Add okta units to a pint registry and handle percent conversion - pint

I have a pint registry that already defines many climate specific units, but I struggle to add a new one for cloud coverage.
I would like to add "okta"[0] as a new unit.
Oktas are an integer scale from 0 to 9.
A conversion from percent to oktas is possible with the formula oktas = round(percent_value * 8 / 100)[1]
I added okta as a new unit in pint with:
my_registry.define(
pint.unit.UnitDefinition("okta", "okta", ("octa", "octas",), pint.converters.ScaleConverter(0.01)
))
But my question is how do I add an auto-conversion from percent to oktas and vice-versa ?
I tried
units.define("okta = percent * 8 / 100") ; it works when using the units.Quantity(10, "okta").to("percent"), but the result is (obviously) not rounded.
units.define("okta = round(percent * 8 / 100)") ; it throws an "UndefinedUnitError: 'round' is not defined in the unit registry" when calling units.Quantity(10, "okta").to("percent").
I also tried to create a "cloudiness" Context and add an add_transformation to it, but without success.
References:
[0] https://en.wikipedia.org/wiki/Okta
[1] at Chapter 2.1.2, on variable "CC" https://knmi-ecad-assets-prd.s3.amazonaws.com/documents/atbd.pdf

Related

How do I fix Unbound Local Error in Python 3

im doing a homework assignment for one of my classes EMT 1111 and Im stuck on this situation at the moment. The question that im trying to answer ask me this question: Write an interactive console program that prompts the user to read in two input values: a number of feet, followed on a separate line by a number of inches. The program should convert this amount to centimeters. Here is a sample run of the program (user input is shown like this):
This program converts feet and inches to centimeters.
Enter number of feet: 5
Enter number of inches: 11
5 ft 11 in = 180.34 cm
Here the coding that I had done so far for this program assignment
centimeters = 2.54
feet_to_inches = feet * 12
print("This program converts feet and inches to centimeters.")
feet = int(input("Enter number of feet: "))
inches = int(input("Enter number of inches: "))
inches_to_centimeters = (feet_to_inches + inches) * centimeters
print = float(input(feet, "ft", inches, "in =",inches_to_centimeters, "cm"))
Every time I keep submitting the code I keep getting an unbound local error. Can someone point the mistake im making so I can fix it
I’m not sure if it’s the reason for the error, but in your last line you use print as a variable name. print is a keyword in python, so you can’t use it as a variable name.
You have a number of issues:
On your 2nd line, you are using feet before it is defined.
On your 9th line, you are using print as a variable instead of a function.
Also on your 9th line, you have what should be printed wrapped in an input function
It's minor, but I would suggest self-descriptive variable names.
So with this in mind, let's refactor your code:
#!/usr/bin/env python3.7
It's a good idea to include a shebang line to make sure you target the correct Python version.
feet_to_inches_multiplier = 12
inches_to_centimeters_multiplier = 2.54
As I said, use self descriptive variables. This way it is more obvious what their intended purpose is.
print("This program converts feet and inches to centimeters.")
This line is fine.
feet = int(input("Enter number of feet: "))
inches = int(input("Enter number of inches: "))
centimeters = (feet * feet_to_inches_multiplier) * inches_to_centimeters_multiplier
Hopefully, you can see the increase in readability here and how the centimeters calculation flows naturally.
print(feet, "ft", inches, "in =", centimeters, "cm")
And this, I assume, is supposed to be a simple print statement.
Here's the output:
This program converts feet and inches to centimeters.
Enter number of feet: 1
Enter number of inches: 1
1 ft 1 in = 30.48 cm
I don't really understand what you want to do but, print() doesn't support the way you're trying to pass those arguments.
For the piece of code provided, the following code may be what you're looking for:
centimeters = 2.54
print("This program converts feet and inches to centimeters.")
feet = int(input("Enter number of feet: "))
feet_to_inches = feet * 12
inches = int(input("Enter number of inches: "))
inches_to_centimeters = (feet_to_inches + inches) * centimeters
print(feet, "ft", inches, "in =", inches_to_centimeters, "cm")
Hope this help you.

CAPL - Converting 4 raw bytes into floating point

CAPL - Vector.
I receive message ID 0x110 which holds current information:
0x3E6978D5 -> 0.228
Currently I can read the data and save into Enviroment Variable to show in Panel using:
putValue(slow_current, this.long(4));
But I don't know how to convert the HEX 4 bytes into float variable, since I cannot use address or casting (float* x = (float *)&vBuffer;)
How to make this conversion in CAPL script? Thanks.
Typically your dbc-file shall contain conversion info from raw value (in your case 4B long) to physical value in form of factor and offset definition:
So your physical value of current shall be calculated as follows:
phys_val = (raw_value * factor) + offset
Note: if you define negative offset then you actually subtracting it in equation above.
But it seems you don't have dbc-file so you need to figure out factor and offset by yourself (if you have 2 example raw values and know their physical equivalent then it shall be as easy as finding linear equation parameters -> y = ax + b).
CAPL shall look like this:
variables
{
float current_phys;
/* adjust below values to your needs */
float factor = 0.001
dword offset = -1000
}
on message 0x110
{
current_phys = (this.long(4) * factor) + offset;
write(current_phys);
}
Alternate solution if you don't want to force transform the value:
You define a sysvar type float(double) and use that sysvar in the panel
(link to it), instead of the envVar
or you change the type of envVar to float(double).
The translation into float will be done automatically
.
Caveat: usually this trick requires that the input number is also 8 bytes as the defined CAPL float range 8 bytes. But you have this by message payload length constraint= 8bytes.
Does not look good, but works:
received msg: 0x3E6978D5
putValue(float4byte,interpretAdFloat(this.long(4)));
float4byte = 0.23
i just reused Vinícius Oliveira solution to avoid creating environment variable. it worked
float floatvalue;
floatvalue = interpretAsFloat(HexValue);
input (HexValue) = 0x3fe20e3a
output(floatvalue() = 1.76606

OneR WEKA - wrong prediction?

I am trying to make a ranking of attributes depending on their predictive power by using OneR in WEKA iteratively. At every run I remove the chosen attribute to see what the next best is.
I have done this for all my attributes and some (3 out of ten attributes) get 'ranked' higher than others, although they have less % correct prediction, a smaller ROC Area average and their rules are less compact.
As I understand, OneR just looks at the frequency tables for the attribute it has and then the class values, so it wouldn't care about whether I take attributes out or not...but I am probably missing something
Would anyone have an idea?
As an alternative you can you use the OneR package (available on CRAN, more information here: OneR - Establishing a New Baseline for Machine Learning Classification Models)
With the option verbose = TRUE you get the accuracy of all attributes, e.g.:
> library(OneR)
> example(OneR)
OneR> data <- optbin(iris)
OneR> model <- OneR(data, verbose = TRUE)
Attribute Accuracy
1 * Petal.Width 96%
2 Petal.Length 95.33%
3 Sepal.Length 74.67%
4 Sepal.Width 55.33%
---
Chosen attribute due to accuracy
and ties method (if applicable): '*'
OneR> summary(model)
Rules:
If Petal.Width = (0.0976,0.791] then Species = setosa
If Petal.Width = (0.791,1.63] then Species = versicolor
If Petal.Width = (1.63,2.5] then Species = virginica
Accuracy:
144 of 150 instances classified correctly (96%)
Contingency table:
Petal.Width
Species (0.0976,0.791] (0.791,1.63] (1.63,2.5] Sum
setosa * 50 0 0 50
versicolor 0 * 48 2 50
virginica 0 4 * 46 50
Sum 50 52 48 150
---
Maximum in each column: '*'
Pearson's Chi-squared test:
X-squared = 266.35, df = 4, p-value < 2.2e-16
(full disclosure: I am the author of this package and I would be very interested in the results you get)
The OneR classifier looks a bit like nearest-neighbor. Given that, the following applies: In the source code of the OneR classifier, it says:
// if this attribute is the best so far, replace the rule
if (noRule || r.m_correct > m_rule.m_correct) {
m_rule = r;
}
Thus, it should be possible (either in 1-R generally or in this implementation) for an attribute to block another, yet be later removed in your process.
Say you have attributes 1,2, and 3 with the distribution 1: 50%, 2: 30%, 3: 20%. In all cases where attribute 1 is best, attribute 3 is second best.
Thus, when attribute 1 is left out, attribute 3 wins with 70%, even though before attribute 2 ranked as "better" than 3 in the comparison of all three.

Crystal Reports - Disable default rounding/Show all decimals

If I create a Formula Field A containing only 1/1000 and then drag it out into the report it will show "0,00" due to default number of decimals is set to 1.00 and default rounding is set to 0.01 for a field of with the type Number.
No problems.
When decimals and rounding are adjusted it will show 0,001.
When I create Formula Field B that only contains {#A} and increase decimals and rounding it will show as "0,001000000000".
But if I use A to create a text, totext({#A}) + ' test', the result will be "0,00 test" and I can not figure out a way to show the correct "0,001 test" without adding totext({#A},3). I don't want to use rounding because the number of decimals in A varies and I don't want to show any zeroes at the end.
I did modify this code (could be used in conditional formatting of decimals for a number field):
If CurrentFieldValue = Int(CurrentFieldValue) Then 0
Else If CurrentFieldValue * 10 = Int(CurrentFieldValue * 10) Then 1
Else If CurrentFieldValue * 100 = Int(CurrentFieldValue * 100) Then 2
Else If CurrentFieldValue * 1000 = Int(CurrentFieldValue * 1000) Then 3
Else If CurrentFieldValue * 10000 = Int(CurrentFieldValue * 10000) Then 4
Else DefaultAttribute
to
If {#A}= Int{#A} Then totext({#A},0)
Else If {#A}* 10 = Int{#A}* 10) Then totext({#A},1)
...
It works but I was hoping I wouldn't need all that extra code, I already have performance issues in my Crystal Reports and I don't want the risk of adding to that.
I just want to use the actual value in {#A} no matter the number of decimals.
I guess this could be caused by both default rounding settings as default number of decimals
And now I realise this might be caused by default number of decimals, not rounding.
If I change A to (1/1000)*6 it will show up as 0,01 unformatted, B will show "0,00600000 test". So it is a rounding problem.
Leave the output of your desired formula as a number.
Right click on the formula and select format field.
In the number tab select Custom Style and click customize.
For rounding option select 0.0000000001
Click the X-2 next to the Decimals option and enter this formula
local numbervar a;
local numbervar b;
for a := 1 to 10 do
(
if mid(strreverse(totext(CurrentFieldValue,10)),a,1) <> "0" then
(b := a;
a := 10);
);
11- b
I have found that the default rounding is defined by your system regional settings. If you increase the number of decimal places from 2 (usual) to say 8, all your problems will be resolved.

How do I convert a decimal number representing time to actual time in Crystal Reports 2008? Ex: "1.5" represents 1:30

I'm trying to edit an existing Crystal Report that shows time allowances for work orders. Budgeted Time / Actual Time / Remaining Time type deal.
These fields show up as not properly converting time from the data field for the report. The person who made the report has some formula for it already but I'm not sure what's it doing.
Formula: Standard Time
Stringvar array Std_Time := split(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""),".");
val(Std_Time[1])*60+val(Std_Time[2])
The field used in the report is Sum of #Standard Time (Number).
How do I fix this so these numbers are properly converted?
The formula that you have posted does the following:
First it converts the datatype of the {WOMNT_CARD.STANDARD_HOURS_DURATION} field to string by using the cstr function, the result is being stripped of commas with the replace function and the resulted string is being split into an array by using the dot character as the delimiter.
So, for the value 1.5 the Std_Time variable will hold the following
Std_Time[1] → 1
Std_Time[2] → 5
Finally it calculates the result by multiplying the first value of the first index with 60 and adds to it the value of the second index. The value 1.5 becomes 1 * 60 + 5 = 65
If the 1.5 must represent 1:30 then the last line must become
val(Std_Time[1]) * 60 + 60 * val(Std_Time[2]) / 10
because 60 * 5 / 10 = 30
or you can use for simplicity just the following
60 * val(replace(cstr({WOMNT_CARD.STANDARD_HOURS_DURATION}),",",""))
since 60 * 1.5 = 90