Sumerics - online samples

General Syntax

Introduction

Sumerics is built upon YAMP and can therefore parse the same statements as YAMP. A simple example is

3 + 2^3

which is evaluated to 11. YAMP recognizes if operators need to be evaluated from left to right or right to left. Therefore statements like

2^2^2^2

get the right result - which is the same as typing

2^(2^(2^2))

since the power operator gets evaluated from right to left. Sumerics knows all arithmetic (+, -, *, /, ...) and logic (==, ~=, > < <=, >=) operators and can even execute factorial statements. The statement

4! == 4 * 3 * 2

results in 1, which is equivalent to true. Imaginary numbers are built in as well and have been assigned to the constant i. It is also possible to stick the i directly to numbers, like

|4 + 3i|

which evaluates the absolute value of the complex number (4, 3) and results in 5. The same can be written with a function, i.e.

abs(4 + 3i)

Whitespaces and new lines are always being ignored. The same is true for tabs and other unsignificant symbols.

Vectors and matrices

A matrix can be written by starting with square brackets. The following statement creates a (row) vector consisting of the numbers 2, 8, 5, 9i and 0.

[2, 8, 5, 9i, 0]

We can produce a column vector by just transposing the row vector:

[2, 8, 5, 9i, 0].'

However, if we initially wanted a column vector then we could also just have initialized the vector like

[2; 8; 5; 9i; 0]

It is also possible to adjungate the vector by using

[2, 8, 5, 9i, 0]'

If we want to get the absolute value of the vector (like the L2-norm), then we could again write

|[2, 8, 5, 9i, 0]|

or we use the abs() function. Creating a full matrix can be done by combining row ; and column , operators, i.e.

[1, 2, 3; 4, 5, 6; 7, 8, 9]

This is a 3x3 matrix. In matrix environments it is sometimes also possible to use whitespaces and newlines as column and row seperators, like

[1 2
3 4]

Please note that negative values like -1 should be separated by commas or brackets.

The range operator

Most of the time one needs a vector with a certain spacing. If we just want to create a vector from 1 to 9 with a spacing of 1, then the following command will certainly help us:

1:9

This gives us a column vector like [1; 2; 3; 4; 5; 6; 7; 8; 9]. We can do the same things as with the matrices (since the range operator just gives us a matrix), i.e.

(1:9)'

adjungates (which is in this case equivalent to transposes) the generated vector. Changing the spacing can be done by specifying another value in the middle. An example would be

1:2:9

which as the same as [1; 3; 5; 7; 9], i.e. all odd entries from 1 to 9. The range operator is quite smart and recognizes patterns like

9:1

This statement does not make sense with a spacing of 1. In this case the spacing will be set to -1. A popular choice is to use the range operator like

0:0.01:2*pi

The query will be evaluated to a vector that contains all elements from 0 to 2π with a spacing of 0.01. If we combine this we can make queries like

x = 0:0.01:2*pi
y = sin(x)

Advanced Syntax

Functions

Functions can be used in various ways. There are two kinds of functions: Functions with one and only one argument and functions with various (0 to many) arguments. Most functions have different behaviors depending on the kind of argument(s) they are receiving. All standard functions (sin(), cos(), ...) are functions of the first kind. Those functions usually react to scalar input like

sin(pi/2)
cos(pi/4)
tan(0.1)

by returning a scalar value. If we insert a matrix like

sin([pi/2, pi, pi/4])
cos(0:0.1:1)
tan([0, 0.5, 1])

then we will get a matrix back. In this case the function has been applied on each member of the given matrix. Functions of the second class show a different behavior. In general there is no fixed pattern for those functions. Popular examples of such functions are

rand(10, 5) //generates a 10 x 5 random matrix with values 0..1
sort([-5, 2, 9, 0, 29]) //sorts the given vector(s)
pwd() //prints the current working directory

Each of those three functions works differently. While the rand() function does also supply overloads for calling the function without any argument (resulting in a scalar) or one argument (resulting in a n x n matrix, where n is the argument), sort() just has this one possible call. The pwd() function accepts no argument at all!

Indices

A quite mighty concept is the usage of variables as functions. A variable that represents a matrix can be used as a function, where the arguments can be seen as indices. This allows us to do the following things:

x = rand(10);
x5 = x(5)
x23 = x(2, 3)
xi = x(4:6, 4:6)
x1all = x(:, 1)
x1to3second = x(6:end, 1:3)

So what is happening there exactly? First of all we are generating a 10 x 10 random matrix and storing the result in the variable x. Now we store the fifth element of the matrix in the variable x5. The fifth element is equivalent to row number 5, column number 1, since YAMP treats rows before columns.

The variable x23 then stores the element in row 2, column 3 of the matrix x. Now the variable xi gets a 3 x 3 submatrix of x, the one going from the rows 4 to 6 and columns 4 to 6. The variable x1all stores the first column vector of the matrix, i.e. all rows and just one column (column index 1). Finally the last variable stores the second half, i.e. rows 6 to 10 of the first 3 columns of x. This results in a 5 x 3 matrix.

The special macro end can be used within matrix indices to denote the length of the corresponding dimension. A simple example:

x = rand(5, 2);
x(2:end, 1)//end = 5
x(7:end)//end = 10
x(2:4, 1:end)//end = 2

Lambda expressions

If you want to write really simply expressions (i.e. functions) in YAMP you can create so called lambda expressions. Basically you just have to tell how the incoming variables (arguments) should be called and what you actually want to do. Lambda expressions do not allow you to make variables optional, so in the end you have to specify each named variable or you cannot invoke your own function.

Let's define a really simple lambda expression:

f = x => x.^2

This function just squares the input (element-wise, i.e. vectors can be squared as well!). We can test this with the following calls:

f(2)//4
f([1,2;3,4])//1,4;9,16

If our own function should receive more arguments we can just seperate them by colons. Here we have to use brackets, to group those arguments. Let's consider an example:

g = (x, y, z) => x .* y + z.^2
h = (x, y) => x' * y

Writing those brackets is just a matter of taste. The first declaration will create a function in the variable g that can be used like g(1, 2, 3) or with matrices that have the same dimensions.

The second example can also be used with scalars or matrices that have the same dimension.

Plotting

Creating plots

Currently there are many different kinds of plots available. The most basic one is a simple 2D plot. The function you would most probably want to call for this is plot(). There are also special cases of this function with some plot properties already pre-set. Let's have a look at some samples:

plot(1:100, rand(100, 3))
semilogy(1:10, 2.^(1:10))
x = 2.^(1:10);
semilogx(x, sqrt(x))
loglog(x, x.^3)

The first one is the standard plot function, which will plot 3 series with 100 points each. Therefore we are setting the x-vector to values with 1 to 100, while the y-values are generated by a uniform random distribution. In the next 2 plot commands (semilogy() and semilogx()) we are plotting with the y-axis or the x-axis set to logarithmic scaling. Finally by using the loglog() function we can get a plot with logarithmic x and y axis.

Another possibility for a 2D plot is the special case of a so-called polar (or radial) plot. In this case the x-axis is periodic with a certain periodicity (usually 2π, but also 360 or something similar could be used). Using such a plot is mostly useful if one wants to display functions which have a kind of periodicity in their argument. This can be used to illustrate the differences between trigonometric functions as well as behaviors for more complex functions like bessel() or the famous Lissajous curves.

x=0:pi/100:2*pi;
polar(x, sin(x))
polar(x, [cos(x), sin(x)])
polar(x, sin(x + pi / 4))
polar(x, sin(x) .* cos(x))

Finally another very useful type of plot is a contour plot. In this kind of plot one can easily spot regions, which have the same value (of a matrix). Usually the input data should be a square matrix, but it does not have to be necessarily. One can now either specify a certain number of levels (which will be the different plateaus, which will be shown in the plot by lines and different colors) or specify the levels exactly.

contour(rand(10))
contour(rand(10), 5)
contour(rand(10), [0.1 0.3 0.8 1.0])

Plot properties

All plots share some properties like the title of the plot or if the labels should actually be shown. Those properties can be changed. Some plots do have some special properties. The contour plot for instance has a property called ColorPalette, which defines the color palette that should be used.

In general all properties of a plot can be changed by using the set() function. Without specifying a plot by using a variable, the last generated plot will be considered for the changes. Here are two simple examples:

a=plot(1:10, rand(10,1))
b=plot(1:10, sin(0.1:0.1:1))
set("title", "Plot with sinus!")
set(a, "title", "Plot with random stuff")

So the set() function requires a string as the property to change and then another argument. In case of the title property the other argument happens to be a string. However, this is not general. Let's have a look at some other examples:

plot(1:10, rand(10,1))
set("gridlines", 1) //here is also "on" allowed
set("showlegend", "off") //here is also 0 allowed
set("minx", 0)
set("maxx", 100)

If we mistype the property we will get a list of all possible properties. If we use the wrong type for the property's value then we will also receive some help on what type to use.

Properties such as the minx and maxx can also be set in one statement. The following example demonstrates this:

plot(0:0.01:1, exp(0:0.01:1))
set("xrange", [-1, 1])
set("yrange", [-3, 3])

Here we use a vector with 2 elements to specify the minimum and the maximum. In the example we set the x-axis to go from -1 to 1 and the y-axis to be shown from -3 to 3. This does not have any affect on the plot values, but just on the display of the plot. If we do not specify the ranges, then YAMP does automatically set the ranges to show all points of the plot. However, this might not be the view you would like to have.

Series properties

Every plot contains one or more series. In case of the contour plot there will be one and only one series. Series also have properties like the plot, where they are contained in. The only difference in setting those properties is that the index of the series has to be specified. Let's consider the following example:

plot(1:10, rand(10,3)) //3 series!
set(1, "color", "red") //changes the color series #1
set(2, "color", "rgb(100, 200, 100)") //changes the color series #2
set(3, "color", "#123AB2") //changes the color series #3
set(:, "lines", "on") //shows the lines on all series
set(1:2, "symbol", "none") //sets the symbol to none for series #1 and #2

Colors can be specified in three different ways. One is to use a known color name (like red, blue, green or also ones like forestgreen, steelblue etc.). The other two possibilities are not new to anyone who is used to style webpages or stylesheets. We have the hexadecimal syntax (6 hex. digits) and the rgb color type with values of 0-255 for each color.

Besides the additional number (or matrix of numbers) before the property (and after the optional plot variable) nothing is different from the plot's properties. We also get some help if we mistype some name or use the wrong type.

The property symbol is interesting, because it is a kind of enumeration and does not accept an arbitrary string. If we do enter a string that is not supported, we will get an error message, which lists all strings that are allowed. In case of the symbol property we are currently limited to the following strings: None, Circle, Square, Diamond, Triangle, Cross, Plus, Star.

Gyrometer experiment

This experiment shows an experiment that can easily be done to show the capabilities of the gyrometer sensor.

Compass coordination

This experiment aims to show the working power of the compass sensor by rotating the Ultrabook™ up to 360 degrees.

Inclinometer experiment

This experiment deals with the three inclinometer sensors which are responsible for detecting changes in the angles.

We rotate a standard office chair and invoke the gyro() function by pressing the enter key at an arbitrary point in time. We could successfully position the UltraBook™ perpendicular to its x-y plane. Therefore the rotation only affected the z-coordinate, i.e. the x-y plane. All other axis have not been rotated (not even slightly) in this experiment.

We fully rotate the UltraBook™ by using our hands. In this case the rotation is not uniform, i.e. at some time the rotation has been performed faster than at other times. Nevertheless we can see that the compass angle performs a full rotation, from 0 to 360 degrees. The compass, orientation and gyrometer sensors are all quite closely related.

The inclinometer is another angle aware sensor. In this experiment we incline the UltraBook™ by lifting the front. In the end we are able to observe some shift in the responsible inclinometer sensor over time. Again this experiment has not been performed with a constant velocity, which is the reason why the line is not straight in the plot.

Example 1

Accurate position measurement via integration of the accelerometer sensor.

N = 50;
dt = 0.1;
measurement = timeseries(acc, N, dt);
time = measurement(:,1);
accelerations = measurement(:, 2:4)';
velocities = int(accelerations)(:, 1:N) * dt;
positions = int(velocities)(:, 1:N) * dt;
plot(time, [accelerations', velocities', positions']);
set(1:3, "label", "Acceleration");
set(4:6, "label", "Velocity");
set(7:9, "label", "Position");

Example 2

Comparison of accuracy of the positions derived from gps() and acc().

N = 50;
dt = 0.1;
start = gps();
measurement = timeseries(acc, N, dt);
end = gps();
accelerations = measurement(:, 2:4)';
velocities = int(accelerations) * dt;
positions = int(velocities) * dt;
delta_gps = |end - start|;
delta_acc = |positions(1:2, N)|;
printf("delta_gps is {0}\ndelta_acc is {1}", delta_gps, delta_acc)

Example 3

Differentiation of gyrometer data (angular velocity) to get angular acceleration.

N = 50;
dt = 0.1;
measurement = timeseries(gyro, N + 1, dt);
time = measurement(1:N, 1);
angular_velocities = measurement(:, 2:4)';
angular_acceleration = diff(angular_velocities) / dt;
angular_positions = int(angular_velocities) * dt;
plot(time, [angular_acceleration', angular_velocities(:, 1:N)', angular_positions(:, 1:N)']);
set(1:3, "label", "Acceleration");
set(4:6, "label", "Velocity");
set(7:9, "label", "Position");

Example 4

Position measurement with orientation corrected using a lambda expression

N = 50;
dt = 0.1;
measf = () => orient() * acc();
measurement = timeseries(measf, N, dt);
time = measurement(:,1);
accelerations = measurement(:, 2:4)';
velocities = int(accelerations)(:, 1:N) * dt;
positions = int(velocities)(:, 1:N) * dt;
plot(time, [accelerations', velocities', positions']);
set(1:3, "label", "Acceleration");
set(4:6, "label", "Velocity");
set(7:9, "label", "Position");

Example 5

Accuracy comparison with orientation corrected using a lambda expression

N = 50;
dt = 0.1;
start = gps();
measf = () => orient() * acc();
measurement = timeseries(measf, N, dt);
end = gps();
accelerations = measurement(:, 2:4)';
velocities = int(accelerations) * dt;
positions = int(velocities) * dt;
delta_gps = |end - start|;
delta_acc = |positions(1:2, N)|;
printf("delta_gps is {0}\ndelta_acc is {1}", delta_gps, delta_acc)

But wait - what about ...

Why is integration of angular_velocities analogous to get angular_positions not correct for large angles?

The reason for this is that the topology of the manifold of orientations is a sphere which leads to errors for large angles.

Sample scripts

A collection of sample scripts to download.

  • CorrelatedDataExample.ys
    An example using the function defined in CorrelatedData.ys for finding correlations between data points. The example uses uniformly generated random data.
  • CorrelatedData2DExample.ys
    An example using the function defined in CorrelatedData2D.ys for finding correlations between 2D data points. The example uses uniformly generated random data and plots them in a surface plot.
  • LissajousFigures.ys
    An example to use the subplot feature for displaying various Lissajous figures.
  • RandomWalkExample.ys
    An example using the function defined in RandomWalk.ys to simulate a random walk using a uniform distribution.
  • GaussianRandomWalkExample.ys
    An example using the function defined in GaussianRandomWalk.ys to simulate a random walk using a normal distribution.
  • YlmPlots.ys
    An example to use the subplot feature for displaying various spherical harmonic functions as 3D surface plots. The spherical harmonics are displayed within θ = -π to π and φ = π to π for the parameters. Each plot presents a different combination for l and m.

About

Sumerics is available on the Intel AppUp® store and provides an unique experience with the latest generation of Ultrabooks™.

The problem is the following: using advanced numerical applications like Matlab is really benefical if one's sitting behind a desktop PC or working on a numerical problem. Once the application is reduced to a small screen without a mouse or keyboard it gets nearly impossible to control. This is where Sumerics jumps in.

The app provides a similar syntax as Matlab. It is built around complex numbers and matrices and embraces the sensor capabilities that the latest generation of Intel® Ultrabooks™ offer us. With the app you can just do standard numerical stuff like solving systems of linear equations, inverting matrices or solving eigenvalue problems.

The function plotter is also capable of understanding touch commands like panning and zooming. The possibility of viewing 3D surface meshgrid and line plots lets you explore multi-parameter functions by using the touchscreen.

Current features

  • Connection to math input panel
  • On screen keyboard
  • Console mode for interaction
  • Editor for scripts
  • Autocomplete in the console and editor
  • Fast Fourier Transformation
  • Obtaining sensor data
  • Using webcam images
  • Gathering audio signals
  • 2D plots
  • 3D plots
  • Polar plots
  • Contour plots
  • Complex plots
  • Panning and zooming in plots
  • Complex numbers
  • Matrices and ranges
  • Indices of matrices and strings
  • Live plots of sensor data
  • Saving and printing plots
  • Touch friendly adjustment to plots
  • Documentation
  • Over 200 functions
  • Useful constants
  • Lambda expressions
  • Fitting of functions
  • Explicitly local variables
  • Powerful physics package
  • Completely asynchronous computation
  • Searchable documentation and workspace
  • Sensor focused for small experiments
  • Plugins

Planned

  • (Online) plugin manager
  • Plot annotations
  • More possibilities for 3D plots

Change log

Version 1.0.2

  • Improved the editor.
  • Added the possibility for gridlines.
  • Improved the scripting language.
  • External functions can now easily be used.
  • Fixed some bugs.

Version 1.0.1

  • Improved the editor.
  • Computations can now be cancelled.
  • Improved the scripting language.
  • Added new functions for fitting polynomials.
  • Fixed some bugs.

Version 1.0.0

  • Improved autocomplete.
  • Improved the YAMP parser (faster, better error handling).
  • Added the possibility for creating complex plots.
  • Added the possibility for creating heatmap plots.
  • Added the possibility for creating 3D surface plots.
  • Added the possibility for creating 3D meshgrid plots.
  • Added the possibility for creating 3D line plots.
  • Added the possibility for creating subplots (a grid of plots).
  • Added the YAMP.Physics plugin.
  • Added the editor.
  • New sensor available: the microphone.
  • New sensor available: the webcam.
  • Included the scripting language for writing YAMP scripts.
  • Improved the documentation.
  • Added UI manipulator functions.
  • Added the ability to view the live plots in the whole window.
  • Hyperlinks for some functions are now available.
  • Searching the help is now possible.
  • Fixed some bugs.

Version 0.9.9

  • Improved autocomplete.
  • Updated the YAMP parser (more functions, string-literals).
  • Added the possibility for creating contour plots.
  • Added the plugins tab.
  • Improved the documentation.

Version 0.9.8

  • Improved the visualization.
  • Added new features to the touch keyboard.
  • Improved the autocomplete.
  • Extended the documentation.
  • Updated the YAMP parser.

Version 0.9.7

  • Improved the documentation.
  • Added a new samples browser, which displays this webpage.
  • Updated the YAMP parser.
  • Integrated a new console.
  • Added autocomplete to the console.
  • Extended the touch keyboard.
  • Improved the plot area with an optional variable view.
  • Added several new commands.
  • Improved the print mode of large matrices and large strings.
  • Included live update of GPS data.

Version 0.9.6

  • Improved the help.
  • Updated the YAMP parser.
  • Small bug fixes (layout update of plots, documentation overview).
  • Option for auto-evaluating math input panel statements.
  • Improved the plot command bar.

Version 0.9.5

  • Initial release.

Contact

Sumerics has been released under the Intel® EULA for Intel AppUp® store applications.

If you have questions concerning the application, found a bug or have a feature in mind then do not bother to write us an e-Mail.

You can reach us by using mail at florian-rappl.de.