The following reference guide identifies the language syntax, built in variables, functions, and classes that are used to code your simulations in Tychos. Tychos uses the MathNotepad language. We have included documentation here for some of the helpful functions defined in the MathNotepad language. This is not a complete list of all functions available in MathNotepad, just ones that might be commonly used in Tychos for building scenarios as well as defining goals for those scenarios.

Comments are statements that you can insert in your code that do not get interpreted and executed by Tychos. To create a comment, you simply indicate a comment by using a hashtag:

# This is a comment.

To define a variable in Tychos all you need to do is identify a name for the variable. You then type an `=`

sign to assign a value to the variable. The following demonstrates various variable declarations

# Assigns a variable called x the value of 10x = 10# Assign a new variable y the value of the xy = x# Assign x the value of itself plus 1x = x + 1

There are a few variables that are built into Tychos. These variables are:

`t`

— How many seconds has passed since this Scenario was started?`dt`

— Time between frames as seconds, e.g. 0.1 is 1/10th of a second.`frame_count`

— How many frames have passed? e.g. 1, 2, 3...`X`

,`Y`

— These are shortcuts for indexing the first two elements of 2-D matrices, e.g.`my_particle.pos[X]`

These are some common mathematical operators and functions for performing various calculations.

Tychos uses the following operators to perform basic math calculations:

`+`

— Addition`-`

— Subtraction`*`

- Multiplication`/`

- Division`^`

- Exponent`%`

- Modulo

You can also use the following basic math functions:

The `pow(base, power)`

function takes two arguments, raising the `base`

by the `power`

.

# returns number 82 ^ 3

The `sqrt(positive_number)`

function takes a single non negative number and returns the real square root of the number.

# returns number 2sqrt(4)

The `abs(number)`

function returns the absolute value of a number.

# returns number 2abs(-2)

The following functions all use radians as the angle measurement. You can use `pi`

to represent PI.

The `sin(angle)`

function is used to evaluate the trigonometric sine value for a given input angle. The input angle must be provided in radians.

# returns number 1sin(pi/2)

The `cos(angle)`

function is used to evaluate the trigonometric cosine value for a given input angle. The input angle must be provided in radians.

# returns number 1cos(0)

The `tan(angle)`

function is used to evaluate the trigonometric tangent value for a given input angle. The input angle must be provided in radians.

# returns number 1tan(pi/4)

The `asin(value)`

function is used to evaluate the trigonometric arcsine value (inverse sine) for a given input. The output angle is given in radians.

# returns number 1.57asin(1)

The `acos(value)`

function is used to evaluate the trigonometric arccosine value (inverse cosine) for a given input. The output angle is given in radians.

# returns number 0acos(1)

The `atan2(value)`

function is used to evaluate the trigonometric arctangent value (inverse tangent) for a given X and Y input. The output angle is given in radians.

# returns number -0.785atan2(-1, 1)# returns 2.36atan2(1, -1)

The `deg_to_rad(angle)`

function is not part of the MathNotepad language but is provided as a helper function to make the conversion from degree angles to radians easier. The input is an angle measurement in degrees and the output is the angle measurement in radians.

# returns number .785deg_to_rad(45)

The `rad_to_deg(angle)`

function is not part of the MathNotepad language but is provided as a helper function to make the conversion from radian angles to degrees easier. The input is an angle measurement in radians and the output is the angle measurement in degrees.

# returns number 180rad_to_deg(p1)

The following functions provide operations for matrix calculations.

Calculates the dot product of two vectors. The dot product of `x = [a1, a2, a3, ..., an]`

and `y = [b1, b2, b3, ..., bn]`

is defined as:

`dot(x, y) = a1 * b1 + a2 * b2 + a3 * b3 + … + an * bn`

# Work is the dot product of Force (F) and displacement (r)F = [2, 2]r = [3, 3]# returns 12Work = dot(F, r)

Calculates the cross product for two vectors in three dimensional space. The cross product of `x = [a1, a2, a3]`

and `y = [b1, b2, b3]`

is defined as:

`cross(x, y) = [ a2 * b3 - a3 * b2, a3 * b1 - a1 * b3, a1 * b2 - a2 * b1 ]`

If one of the input vectors has a dimension greater than 1, the output vector will be a 1x3 (2-dimensional) matrix.

# Torque is the cross product of Force and moment arm (r)F = [2, 0, 0]r = [0, 2, 0]# returns matrix [0, 0, 4]cross(F, r);

Some other useful functions...

Return a random number larger or equal to min and smaller than max using a uniform distribution. If now min or max are given, then it returns a random value from 0 to 1. If just one value is given, then it returns a random number between 0 and the input value.

random() # returns a random number between 0 and 1random(100) # returns a random number between 0 and 100random(30, 40) # returns a random number between 30 and 40random([2, 3]) # returns a 2x3 matrix with random numbers between 0 and 1

The `drawArrow`

function draws an arrow and is commonly used to illustrate vectors for a particle. drawArrow should be called in the Calculations editor because it only draws the arrow for the current frame. If you call drawArrow() in the Initial State editor, you will not see anything.

`drawArrow(pos=[0,0], size=[1,0], color="black", components=false, thickness=1)`

-> returns and draws an Arrow object

`pos`

— coordinates for the starting point of the arrow as an [X,Y] matrix.`size`

— the vector to illustrate, e.g. [10, 0] will draw an arrow 10 units to the right.`color`

— Optional HTML color value for your arrow, e.g. "red" or "#ff0000".`components`

— Optional flag that determines if vector components are drawn, a value of`true`

displays the components.`thickness`

— Optional stroke value that determines the visual thickness of the arrow.

Example — The illustrations above were drawn using these commands:

# Initial State editorp = Particle([0,0], 10, "green")# Calculations editordrawArrow(p.pos, [20, 20], "purple") # just the diagonal arrowdrawArrow(p.pos, [20, 20], "purple", true) # also draw X and Y components

The `drawLine`

function draws a line and is commonly used to illustrate some connecting member like a string or cable, but could really represent anything you like. `drawLine`

should be called in the Calculations editor because it only draws the line for the current frame. If you call `drawLine`

in the Initial State editor, you will not see anything.

`drawLine(pos=[0,0], pos2=[10,0], color="black", thickess=1)`

-> returns and draws an Line object

`pos`

— coordinates for the starting point of the line as an [X,Y] matrix.`pos2`

— the coordinates of the end point of the line as an [X,Y] matrix.`color`

— Optional HTML color value for the line, e.g. "red" or "#ff0000".`thickness`

— Optional stroke value that determines the visual thickness of the line.

Example — The illustration above was drawn using this command:

# Calculations editordrawLine([0, 0], [20, 20], "purple", 2) # a linedrawLine([0, 0], [10, 20], "green", 10) # another line

This function returns a unit vector representation of the given input vector. Its magnitude is 1 and the direction matches the direction of the input vector. This can be useful if you need just the direction of a vector, but not its magnitude.

`unit_vector(vec)`

-> returns a vector of length 1, and in same direction as `vec`

.

`vec`

- any two dimensional vector as a [X, Y] matrix.

Example:

u = unit_vector([3, 4]) # returns [0.6, 0.8]magnitude(u) # returns 1

This function returns the scaler magnitude of any given vector. This is helpful when you want to know the length of a vector, for example, if you want the magnitude of a vector, but not its direction.

`magnitude(vec)`

-> returns the scaler magnitude of the vector `vec`

.

`vec`

- any two dimensional vector as a [X, Y] matrix.

Example:

magnitude([3, 4]) # returns 5

This function returns a scalar angle measurement. This is helpful when you want to know the direction of a vector, like the direction of a velocity vector, or the direction of a force vector. The default return angle is given in radians, but can also be expressed in degrees.

`direction(vec, units="rad")`

-> returns the scaler angle measurement of the vector `vec`

heading in radian form or in degree form.

`vec`

- any two dimensional vector as a [X, Y] matrix.`units`

- optional`deg`

for degree measurement or the default of`rad`

for radians.

Example:

direction([4, 4]) # returns .785direction([4, 4], "deg") # returns 45

This function returns a two-dimensional matrix representing the cartesian components of a polar coordinate corresponding to the magnitude of the radius and the radial angle.

`polar(radius, angle, units="rad")`

-> returns a two dimensional vector as a [X, Y] matrix.

`radius`

- scalar quantity representing the scalar distance of the radius of the`angle`

- scalar quantity representing the angle measurement of the polar coordinate.`units`

- optional`deg`

for degree measurement or the default of`rad`

for radians.

Example:

polar(10, 45, "deg") # returns [7.07, 7.07]polar(10, PI/4) # returns [7.07, 7.07]

This function actually evaluates a boolean test and then stops the simulation once the boolean test succeeds. This can be useful if you want the simulation to stop when some condition has been met within your simulation.

`stop(test)`

-> returns a either false or true. If true is returned, the simulation stops.

`test`

- a boolean statement that can be evaluated to`true`

or`false`

.

Example:

stop(t > 10) # simulation stops at 10 secondsstop(buggy.pos[X] == 100) # simulation stops when X position of particle equals 100

The following functions currently only support collisions with **Particles**. These are meant to be used as helper functions for easily simulating collisions. We are working on adding more complex functions that work with **Blocks**, but at this time, these functions only work with **Particles.**

This function returns a boolean true/false value when two `Particle`

objects are given as the source and target. It returns false if the two particles are not determined to be *overlapping*, meaning that the distance between their positions is less than the sum of their radii.

`hasCollided(source, target)`

-> returns a boolean `true`

or `false`

.

`source`

-`Particle`

object`angle`

-`Particle`

object

Example:

p1 = Particle([0, 0], 10)p2 = Particle([25, 0], 10)p3 = Particle([-15, 0], 10)hasCollided(p1, p2) # returns falsehasCollided(p1, p3) # returns true

This function returns a two dimensional matrix representing the minimum translation vector (MTV) that would be needed to separate two `Particle`

objects when they overlap. This can be used to simulate collision forces based on the magnitude and direction of the MTV.

`getIntersect(source, target)`

-> returns a two dimensional matrix.

`source`

-`Particle`

object`angle`

-`Particle`

object

Example:

p1 = Particle([0, 0], 10)p2 = Particle([25, 0], 10)p3 = Particle([-15, 0], 10)getIntersect(p1, p2) # returns [0, 0]getIntersect(p1, p3) # returns [5, 0]

The following functions are used to compare two values as being equal or unequal as well as testing if one value is larger or smaller than another. These are very helpful when writing goals for students.

The function tests if two values (x and y) are equal. It returns a boolean value of `true`

or `false`

.

2 + 2 == 3 # returns false2 + 2 == 4 # returns truet == 10 # returns true if t is 10, or false if it is not.equal(2 + 2, 4) # same as 2 + 2 == 4

This function is similar to `equal`

, but it tests element wise whether two matrices are equal. It returns a boolean value of `true`

or `false`

. The code below demonstrates the difference between `equal`

and `deepEqual`

:

p1 = Particle([10, 10])p2 = Particle([10, 0])deepEqual(p1.pos, p2.pos) # returns falseequal(p1.pos, p2.pos) # returns [true, false]

The function tests if one value (a) is larger than another (b). It returns a boolean value of `true`

or `false`

.

2 > 3 # returns false3 > 2 # returns true2 > 2 # returns falselarger(2, 2) # same as 2 > 2

The function tests if one value (a) is smaller than another (b). It returns a boolean value of `true`

or `false`

.

2 < 3 # returns true3 < 2 # returns false2 < 2 # returns falsesmaller(2, 2) # returns false

The function tests if two values (a and b) are unequal. It returns a boolean value of `true`

or `false`

.

2 + 2 != 3 # returns trueunequal(2 + 2, 3) # true -- same as 2 + 2 != 32 + 2 != 4 # returns falset != 10 # returns false if t is 10, or true if it is not.

Comparison operators return `true`

or `false`

but these also evaluate to 1 (true) or 0 (false). This can allow you to conditionally assign a value to a variable depending on the evaluation of the comparison. See the code below as an example:

# If t is larger than 10, then the value of F is [10, 10], otherwise it is 0.F = (t > 10) * [10, 10]

The `if()`

function returns `true_result`

or `false_result`

depending on `test`

.

if(true, 3, 44) # returns 3if(false, 3, 44) # returns 44if(1 > 2, 3, 44) # test is false; therefore returns 44a = 1b = 1if(a == b, "YAY", "darn") # test is true; therefore returns "YAY"

The following operators are used to execute logical AND and OR comparisons for the use of evaluating logical statements.

This is used for performing a logical AND conjunction. For example, "A and B" is true only if A is true and B is true. "A and B" is false if either A or B is false.

A = trueB = trueA and B # returns trueB = falseA and B # returns false

You can use the `and`

operator to test if two comparisons are both true:

x = 2(x < 3) and (x == 2) # returns true(x < 3) and (x != 2) # returns false

This is used for performing a logical OR conjunction. For example, "A or B" is true if A or B is true. "A or B" is false only if A and B are both false.

A = trueB = falseA or B # returns trueA = falseA or B # returns false

You can use the `or`

operator to test if one of two comparisons are true:

x = 2smaller(x, 3) or equal(x, 3) # one is true, so returns true(x < 1) or (x == 3) # both are false, so returns false

Tychos has only a few classes that are used to create the basic simulated objects in the Tychos universe as well as a few tools for analyzing those objects in the simulated world. The two simulated objects in Tychos are the `Particle`

and the `Block`

. The tools that can be used for analyzing the behavior of your simulations are the `Graph`

and the `Meter`

.

A `Particle`

represents a spherical particle in the simulated world and is drawn as a colored circle in the World View. A particle has position, radius and color.

`Particle(pos=[0,0], radius=10, color=default_color)`

-> returns a Particle

`pos`

— The inital position of your particle in [X,Y] coordinates. If you don't specify a position, the default value of [0,0] is used.`radius`

— The radius of the circle that is drawn in the World View to represent this particle.`color`

— The particle will be drawn in this color. Use HTML colors e.g. "#ff3300", "blue".

These attributes may also be modified on the particle after it is created. In particular, one will usually change the `pos`

attribute of a particle in the Calculations editor to show a particle's movement. E.g.

# Initial State editorp = Particle()p_big = Particle([50, 0], 25)p_big.color = "red"p_blue = Particle([100, 0], 10, "green")# Calculations editorp.pos = p.pos + [1, 0.25]

`Particle`

objects can be rotated, but it will have no noticeable affect on the object unless you are using an image as a representation of the `Particle`

.

`particle.rotate(angle=0, center_of_rotation=[0, 0])`

— Rotates the `Particle`

object by a given angle value in degree units. You can also provide an optional matrix that identifies the center of rotation. This method should only be called from the **Calculations** code editor.

`Particle`

objects can also be given a text label. This is similar to the Label object.

`particle.addLabel(text="Hello", color="green")`

— This adds a text label to the `Particle`

object.

Another particle representation in Tychos is the `Block`

. A `Block`

is very similar to a `Partcle`

but it is represented as a colored rectangle in the World View. A block has position, width, height and color. Just as with Particle's, Tychos only uses the width and height attributes for display. You can define how these attributes change given the rules of the simulation that you define.

`Block(pos=[0,0], size=[10, 10], color=default_color)`

-> returns a Block

`pos`

— The inital position of your block in [X,Y] coordinates. If you don't specify a position, the default value of [0,0] is used.`size`

— The width and height of the block that is drawn in the World View to represent the block.`color`

— The block will be drawn in this color. Use HTML colors e.g. "#ff3300", "blue".

These attributes may also be modified on the block after it is created. In particular, one will usually change the `pos`

attribute of a block in the Calculations editor to show a block's movement. E.g.

# Initial State editorb1 = Block([0, 0], [10, 10], "green")b2 = Block([20, 0], [10, 20], "blue")b3 = Block([40, 0], [20, 10], "orange")# Calculations editorb1.pos = b1.pos + [1, 0.25]

You can also rotate a `Block`

object in order to simulate rotational behavior.

`Block.rotate(angle=0, center_of_rotation=[0, 0])`

— Rotates the `Block`

object by a given angle value in degree units. You can also provide an optional matrix that identifies the center of rotation. This method should only be called from the **Calculations** code editor.

Example:

# Initial State editorb1 = Block([-20, 0], [20, 10], "green")b2 = Block([0, 0], [20, 10], "blue")b3 = Block([20, 0], [20, 10], "orange")# Calculations editorb1.rotate(rad_to_deg(-PI/4))b2.rotate(90)b3.rotate(45)

Just as with `Particle`

objects, `Block`

objects can also be represented with an image by setting the image attribute of the object. The text must be a URI link to a graphic file that can be a PNG, SVG, GIF, or JPEG image.

rocket = Block([0, 0], [10, 10], "purple")rocket.image = "https://upload.wikimedia.org/wikipedia/commons/3/3d/Spacecraft.png"

The above image also demonstrates the use of the `direction`

function as well as the `rotate`

method:

`rocket.rotate(direction(rocket.v))`

`Block`

objects can also be given a text label. This is similar to the `Label`

object.

`block.addLabel(text="Hello", color="green")`

— This adds a text label to the `Block`

object.

You can represent a spring in Tychos using the `Spring`

class. A `Spring`

is a visual representation of a common elastic connector that displays a given number of coils that dynamically change shape once the dimensions of the `Spring`

are changed in the **Calculations Pane**.

`Spring(pos1=[0,0], pos2=[100, 0], color=default_color, coils=5, width=10, thickness=1)`

-> returns a `Spring`

object

`pos1`

— The position of one end of the`Spring`

. If you don't specify a position, the default value of [0,0] is used.`pos2`

— The position of one other end of the`Spring`

. If you don't specify a position, the default value of [100,0] is used.`color`

— The block will be drawn in this color. Use HTML colors e.g. "#ff3300", "blue".`coils`

— This is the number of coils represented.`width`

— This is the width of the coils.`thickness`

— This is the stroke weight of the coils.

The code below shows the three different `Spring`

objects above that have different lengths, widths and coil numbers. The `Particle`

objects are shown just for reference.

# Initial State editorp = Particle([0, 0], 2, "green")spring = Spring([0, 20], [0, 0], "black", 20, 2)p = Particle([10, 0], 2, "green")spring = Spring([10, 20], [10, 0], "black", 10, 4)p = Particle([20, 0], 2, "green")spring = Spring([20, 20], [20, 0], "black", 20, 2)

These attributes may also be modified after the `Spring`

is created. In particular, one will usually change the `pos2`

attribute of a Spring in the Calculations editor to show Spring's movement or deformation.

You can add text labels to any scenario using the `Label`

class. A `Label`

has position, width, height and color, similar to a `Block`

, but also has a text value. Just like all Tychos objects, you can define how these attributes change in the simulation.

`Label(pos=[0,0], size=[10, 10], text="Hello", color=default_color)`

-> returns a `Label`

object.

`pos`

— The inital position of your block in [X,Y] coordinates. If you don't specify a position, the default value of [0,0] is used.`size`

— The width and height of the block that is drawn in the World View to represent the block.`text`

- The actual text value of the label.`color`

— The block will be drawn in this color. Use HTML colors e.g. "#ff3300", "blue".

These attributes may also be modified after the `Label`

object is created. Here is an example of how to make several `Label`

objects:

# Initial State editorlabel1 = Label([0, 100], [50, 50], "Cat", "green")label2 = Label([0, 0], [150, 150], "Dog", "red")label3 = Label([0, -100], [50, 50], "Mouse", "blue")

Just as with a `Block`

object or a `Particle`

object, you can rotate a label as shown above:

label3.rotate(PI/4)

Tychos also provides several widgets for displaying data in different ways as well as adding user interactivity so that your simulations can respond to input.

A `Graph`

is a 2-dimensional chart of data that you specify in the Calculations editor. Each Graph that is created will appear on the right side of the World View. Your program needs to add points to the graph with the `plot`

command.

`Graph(title="")`

-> Returns a Graph

`title`

= Optional text that will appear at the top of the graph.

`graph.plot(x, y, color=default_color)`

— Adds a data point to your graph.

Example:

# Initial State editorg = Graph("X Positions vs Time")# Calculations editor# Graphing a particle projectile's Y velocityg.plot(t, particle.pos[X], "blue")g.plot(t, particle.pos[Y], "red")

`graph.integrate(color=default_color)`

— When you call the `plot`

function of a graph, you create a new plot set. You can then integrate this plot set. This is done by referencing the plot set's color. This returns the calculated area based on the** trapezoidal method of approximation**.

Example:

# Initial State editorg = Graph("Y Velocity")# Calculations editor# Graphing a particle projectile's Y velocityg.plot(t, particle.v[Y], "green")g.integrate("green")

A `Meter`

is a numeric display of data that you specify in the Calculations editor. Each Meter that is created will appear on the left side of the World View. Your program needs to tell the Meter what value it needs to display by using the `display`

command.

`Meter(title="", color=default_color)`

-> Returns a Meter

`title`

= Optional text that will appear at the top of the meter.

`meter.display(value, units)`

— Displays the value on the Meter.

`value`

= Numeric value to be displayed.`units`

= String representing the unit label to be displayed.

Example:

# Initial State editormt = Meter("Time")# Calculations editormt.display(t, "s")

A `Gauge`

is an analog display of data that is very similar to a `Meter`

that you specify in the Initial Sate pane. Each `Gauge`

that is created will appear on the left side of the World View. Gauges also need to to be set up with a specific minimum and maximum value for identifying the range of the `Gauge`

. Your program needs to tell the `Gauge`

what value it needs to display by using the `display`

command.

`Gauge(title="", max=100, min=100, color="default_color")`

-> Returns a Gauge

`title`

= Optional text that will appear at the top of the Gauge.`max`

= The maximum value of the Gauge`min`

= The minimum value of the Gauge

`gauge.display(value)`

— Displays the value in the Gauge.

Example:

# Initial State editorg1 = Gauge("Value 1", 200, 0, "orange")g2 = Gauge("Value 2", 100, -100, "purple")g3 = Gauge("Value 3", 100, 0, "blue")# Calculations editorval = 44g1.display(val)g2.display(val)g3.display(val)

The following section describes different user interface elements that can be used to create interactive simulations in Tychos.

A `Toggle`

is an interactive widget that allows you associate a boolean value (true or false) with the state of the `Toggle`

widget.

`Toggle(title="")`

-> Returns a Toggle

`title`

= Optional text that will appear at the top of the Toggle.

`x = toggle.value`

— Returns the current value of the Toggle. This is read/write.

Example:

# Initial State editort1 = Toggle("My Toggle")# Calculations editorisActive = t1.value

A `Slider`

is an interactive widget that allows you to link a value in your scenario to the current value of a horizontal slider.

`Slider(title="", min=0, max=100, step=1)`

-> Returns a Slider

`title`

= Optional text that will appear at the top of the Slider.`min`

= The minimum value of the Slider`max`

= The maximum value of the Slider`step`

= The step increment of the Slider

`x = slider.value`

— Returns the current value of the Slider. This is read/write.

Example:

# Initial State editors1 = Slider("I'm A Slider", 0, 100, 2)# Calculations editorx = s1.value

The `keyboard`

object represents your computers keyboard and has commands to see if any keys are pressed during a simulation.

`keyboard.is_down(key)`

-> `boolean`

— Return 1/0 whether `key`

is currently down

`keyboard.last_pressed(key)`

-> `boolean`

— was `key`

typed? i.e. key was pushed down then released.

The `mouse`

object represents your computer**'**s mouse.

`mouse.pos`

-> `vec`

— Returns two dimensional vector as a [X, Y] matrix representing the position of the mouse in the simulation space.

`mouse.is_down(button_num=0)`

-> `boolean`

— Returns whether the mouse button is pressed. `button_num`

— Which button to check? 0 = primary button, 1 = secondary, etc.

`mouse.is_over(object)`

-> `boolean`

— Returns whether the mouse is positioned over an object that is either a `Particle`

or a `Block`

. `object`

— A simulation object.

You can create a representation of variable values, displayed in the **Data Output** tab, by using various API calls on the built in `table`

object.

`table.setColumns(columns=[])`

- You must first define the column headings for the table in the Initial State pane. The arguments are simply an array of string values representing the column headings of the table.

`table.addRow(row_data=[])`

- Once the table columns have been defined, you then need to define the row data to be added to the table. This is an array of any data type values.

Example:

# Initial State editortable.setColumns(["time", "x value", "y value"])# Calculations editorx = t * 2y = t / 2table.addRow([t, x, y])

The code above would generate this table: