Scripting¶
physics_utils features a builtin scripting language for streamlined usage of the module.
Prominent features are writing uncertainties on any number by just putting ~ after it, and
star notation, which allows for easily doing calculations on large sets of data.
Here’s an example of using it:
velocities := [0.312249, 0.343593, 0.365498, 0.688140, 0.205810]
mass := 235.4~0.05
define calc_ke(mass, velocity) as
return mass * velocity ^ 2
end calc_ke
kinetic_energies := calc_ke`(mass, *velocities)
print(kinetic_energies)
"This would then output the following:"
"[22.951±0.005, 27.79±0.006, 31.447±0.007, 111.47±0.02, 9.971±0.002]"
Using the interpreter¶
If you’ve already installed the physics_utils module (if not, see getting started), then you’ll already have this ready to use as well.
To start an interactive session, run python3 -m physics_utils.script, which will start a REPL you can type code into and see the results of immediately. For example:
>>> x := 3.5~0.1 / 7~0.3
>>> sin(x)
0.48±0.02
To run a file, just append the filename to the previous command. I.e., python3 -m physics_utils.script <filename>
Expressions¶
Expressions are code you write which returns something. For instance, comparisons, function calls, or numbers. We’ll go over all the types of expressions here.
Numbers¶
All numbers are stored as MeasuredDatas. Creation of a number is as you’d expect: just writing the number, with an optional decimal.
You can, however, also add an uncertainty to a number by writing ~ followed by the uncertainty, after any number. For instance:
>>> 3
3.0
>>> 10~0.5
10.0±0.5
Arithmetic¶
All the arithmetic operators work about how you’d expect, used in the form expression operator expression, where expression is assumed to be evaluated to a number.
Addition, subtraction, multiplication, and division are all the standard +, -, *, and /. Exponentation is ^. Here are some examples:
>>> 3 + 2
5.0
>>> 5 * 2 + 3
13.0
>>> 7.5~0.1^2
56.0±2.
Comparisons¶
Equality checks are done with =, and not equal !=. For greater than, less than, greater than or equal, and less than or equal, use >, <, >=, or <=.
Logical operators¶
To check if two expressions are true, you can do expression and expression. To check if either expression is true, use expression or expression.
Function calls¶
There are a few ways to call a function, which will all be gone over here.
Normal calls¶
To do a standard function call, just write the function’s name followed by any arguments in parenthesis, seperated by commas, like so: some_function(3, 10).
Prime & star notation¶
Any function which does some operation on data can instead do that operation on collections of data, or collections of collections of collections … of data, using star notation.
For example, if you had a function which calculated a number, you could instead have it calculate a bunch of numbers. When doing so, at least one of the arguments must also be a collection of the standard input, to the same depth as the expected output. The other arguments, however, can be collections up to or less than the depth of the output, or not be collections at all, and just the standard input.
To do this, you put a backtick (`) after the function name, and then put stars (*) before any argument, equaling the depth of input.
This all can sound a bit arcane, so here are some examples:
define calc_momentum(mass, velocity) as
return mass * velocity
end calc_momentum
"If I gathered the mass and velocity of a bunch of different objects,"
"I could calculate the momentum for all of them like so:"
masses := [100, 120, 50]
velocities := [5, 4, 7.5]
calc_momentum`(*masses, *velocities) "would return the following: [500, 480, 375]"
"If, instead, I gathered a bunch of velocities in various trials for an object"
"of constant mass, I could calculate it's momentum for each run like so:"
mass := 70
velocities := [10, 7, 11]
calc_momentum`(mass, *velocities) "would return [700, 490, 770]"
"If I gathered multiple runs for multiple objects of differing masses,"
"I could calculate the momentum for all of them also:"
masses := [3, 4, 5]
velocities := [[5, 10, 3], [2, 10], [12, 7, 9, 15]]
calc_momentum`(*masses, **velocities) "returns [[15, 30, 9], [8, 40], [60, 35, 45, 75]]"
Strings¶
Strings can be made by wrapping any text around double quotation marks. Strings are also used as comments, and can be multiline comments as well,
since newlines have no effect on parsing. For example: "hello world!".
Lists¶
Lists are created by writting square brackets, like so: []. Any default elements in the list can be placed inside the brackets, seperated by commas. For example,
[] "an empty list"
[1, 2, 5] "a list with some elements"
[[5, 2, "Hi!"], 12] "a list with a list inside it"
Methods which are available on python lists, such as .append, .pop, .insert, etc. can all be used.
Accessing list elements¶
List elements can be accessed by wrapping the index of the element you’d like in brackets after the list. For example:
>>> list := [10, 20, 30]
>>> list[0]
10.0
>>> list[2]
30.0
Append operator¶
Along with doing list.append(x), there is also a dedicated append operator, which adds an element to a list, and also returns the list afterwards. It’s denoted by |, and used in the format list | element. Because this returns the list after, successive appends can be easily done like so: list | 1 | 2 | 3 to add 1, 2, and 3 to the list, in that order.
Length operator¶
You can get the length of a list by putting # before the list. For example:
>>> #[1, 2, 3]
3
Parenthesis¶
Any expression can be wrapped in parenthesis. This has no effect, but is useful for forcing an order of operations.
Anonymous functions¶
You can create a function without naming it by writing (parameters) -> expression, where expression is returned when the function is ran. For example:
>>> my_fn := (x, y) -> x + y * 2
>>> my_fn(2, 3)
8.0
>>> ((num) -> num ^ 2) (3)
9.0
Variables¶
If you write a variable name, its value will be returned:
>>> x := 10
>>> x
10.0
There are three built-in variables (counted seperately from built-in functions,) which are true and false, as booleans, and nil, a
none/null type which is inheritly returned by many functions and statements.
Statements¶
Statements are code which do not return anything (that is, immediately), such as if statements, function declarations, and loops.
Variable definitions¶
To define or change variables, the := operator is used, in the format variable_name := expression. Note that the variable name can consist of letters, numbers, and underscores, but cannot start with a number. For example:
>>> x := 10
>>> x
10.0
Uncertainty setting¶
If at any point you want to change the uncertainty on a variable, you can do so using the :~ operator. For example:
>>> x := 3~0.5
>>> x
3.0±0.5
>>> x :~ 1
>>> x
3.0±1.
List element setting¶
You can set the element of a list by wrapping the index of the element in brackets after the list name, and then putting that before the := operator,
followed by the expression to set that value too. For example:
>>> numbers := [1, 2, 3, 4, 5]
>>> numbers
[1.0, 2.0, 3.0, 4.0, 5.0]
>>> numbers[2] := 100
>>> numbers
[1.0, 2.0, 100.0, 4.0, 5.0]
While loops¶
While loops will execute some code as long as some expression is true. They are written in the format while expression loop block end loop,
where as long as expression is true, block is executed. For example:
x := 0
while x < 10 loop
print(x)
x := x + 1
end loop
"This code, when ran, would print the numbers 0 to 9"
For loops¶
There are two types of for loops. The first type loops through a range, and the second type loops through elements in a list.
Range for loop¶
This type of for loop is written in the structure for variable from left_bound to right_bound loop block end loop, where variable is the
name of a variable which loops through the range, left_bound is the least value of the range (inclusive), right_bound is the greatest value
of the range (also inclusive), and block is the code ran. For example:
for i from 1 to 10 loop
print(i)
end loop
"This code would print out the numbers 1 to 10"
List for loop¶
This type of for loop is written as for variable in list loop block end loop, where variable is the current element of the list, list is the list being looped through, and block is the code executed each iteration of the loop. For example,
my_list := [10, 35, 0.5, 12]
sum := 0
for x in my_list loop
sum := sum + x
end loop
"This code sums up all the elements in my_list"
print(sum) "Would output 57.5"
If statements¶
An if statement executes code on a given condition. It can also feature multiple conditions, which only run code if they are true and all previous conditions were false. They can also run code on the case that all conditions ended up being false.
For just running code on a given condition, they are written if expression then block end if, where expression is the condition that must be true for the code block to execute.
For adding other coditions, which could execute if the previous condiitons were false, you add else if expression then block before the end if. To add a condition which
is executed on the case that no conditions were true, add else block right before the end if.
Here are some examples:
if 2 + 3 = 5 then
print("Arithmetic is real!")
end if
age := 20
if age >= 19 then
print("You can drink!")
else
print("You can't drink")
end if
if age < 13 then
print("You're a child")
else if age < 18 then
print("You're a teenager")
else if age < 20 then
print("You're both a teenager and an adult")
else
print("You're an adult")
end if;
Function declarations¶
Functions can be declared by writing define name(parameters) as block end name, where name is the name
of the function, containing letters, numbers, or underscores, but without a number as the first character; parameters
is an optional list of variable names seperated by commas, which will be passed to the function’s code as arguments
when called; and where block is the code of the function.
A function may also contain return statements, which will exit the function when reached. A return statement may also have an expression after it, to have the function return the value of that expression when that return statement is reached.
Some examples:
define avg_list(list) as
sum := 0
for x in list loop
sum := sum + x
end loop
return sum / #list
end avg_list
print(avg_list([3, 5, 10])) "outputs 6.0"
define say_hi() as
print("Hi there!")
end say_hi()
say_hi() "outputs 'Hi there!'"
Import statements¶
Import statements can be used to import python modules in your code. They are written either import module or from module import symbols.
Built-in functions¶
There are a number of built-in functions which can be used without import. They can also be overwritten, if wished.
Trigonometric functions¶
sin, cos, tan, arcsin, and arctan are all builtin functions which perform their respective trigonometric operation
on some radian value provided to them.
print¶
Same as the normal python print. Outputs any arguments provided to it.
exit¶
Stops the interpreter.
Standard deviation¶
std can be used to find the standard deviation on elements in a list.
Averaging¶
avg can be used to find the mean average of a list of data points, and returns the value
with the uncertainty being the standard deviation between the elements.