# A quick tour¶

## First steps¶

In the interactive mode, commands are typed at the prompt. For example,

```
>>> 3 + 3**2
12
```

or

```
>>> print "Hello world"
Hello world
```

Variables can be defined:

```
>>> name = "Mick"
>>> surname = "Dundee"
>>> print name,surname
Mick Dundee
>>> x = 4
>>> y = 2.5
>>> x * y
10.0
```

Iteration is possible:

```
>>> for i in range(10):
... print i, 2.5 * i
...
0 0.0
1 2.5
2 5.0
3 7.5
4 10.0
5 12.5
6 15.0
7 17.5
8 20.0
9 22.5
```

Note

- The prompt changes from
`>>>`

to`...`

when a command is incomplete, allowing multi-line statements to be entered, like the`for`

statement above. - Indentation delimits a block of instructions. In the
`for`

statement above, the second line is indented, making it part of the for-loop body. Any number of lines can be indented to form a block of code.

Conditional statements also use blocks:

```
>>> data = 15
>>> if data > 10:
... print "big"
... else:
... print "small"
...
big
```

## Uncertain numbers¶

`GTC`

uses an *uncertain number* to represent a value that is not precisely known.

Different types of uncertain number are used for real and complex values.

### Uncertain real numbers¶

At least two pieces of information are needed to define an uncertain real number:

- a
value(of the estimate)- a
standard uncertainty(of the value as an estimate of the quantity of interest).

For example, suppose the current flowing in an electrical circuit \(I\) and the voltage across a circuit element \(V\) have been measured.

The estimates (measured values) are \(V \approx 0.1\, \mathrm{V}\) and \(I \approx 15\,\mathrm{mA}\), with standard uncertainties \(u(V) = 1\, \mathrm{mV}\) and \(u(I) = 0.5\,\mathrm{mA}\), respectively.

Uncertain numbers for \(V\) and \(I\) are defined using `ureal`

```
>>> V = ureal(0.1,1E-3)
>>> I = ureal(15E-3,0.5E-3)
```

The resistance can be calculated using Ohm’s law

```
>>> R = V/I
```

Uncertain number attributes

Information about the value (estimate of the quantity of interest) and the associated uncertainty can be obtained from an uncertain number in different ways.

Typing the name of an uncertain number at the prompt displays its Python representation:

>>> R ureal(6.666666666666667, 0.23200681130912335, inf)

The value is

`6.666666666666667`

and the standard uncertainty`0.23200681130912335`

(`inf`

signifies infinite degrees-of-freedom, see note below).Attributes, or corresponding functions, can be used to obtain the value, or the uncertainty, etc,

>>> R.x 6.666666666666667 >>> value(R) 6.666666666666667 >>> R.u 0.23200681130912335 >>> uncertainty(R) 0.23200681130912335

Alternatively, a summary string can be generated showing the value, the uncertainty and the degrees of freedom. Numbers in the string are formatted to show only significant digits:

>>> print R.s 6.67, u=0.23, df=inf >>> summary(R) '6.67, u=0.23, df=inf'

Note

By default, the number of degrees of freedom is infinity (`inf`

): this implies that the standard uncertainty is known exactly.

### Uncertain complex numbers¶

To define an uncertain number for a complex quantity, at least two pieces of information are needed:

- a value (of the estimate)
- an uncertainty (of the value as an estimate of the quantity of interest - different formats may be used, see below)

The same functions, or attributes, mentioned above, can be used to obtain information about uncertain complex numbers.

For example, suppose the alternating current flowing in an electrical circuit \(i\), the voltage across a circuit element \(v\) and the phase of the voltage with respect to the current \(\phi\) have been measured.

The measured values (estimates) are: \(v \approx 4.999\, \mathrm{V}\), \(i \approx 19.661\,\mathrm{mA}\) and \(\phi \approx 1.04446\,\mathrm{rad}\), with standard uncertainties \(u(v) = 0.0032\, \mathrm{V}\), \(u(i) = 0.0095\,\mathrm{mA}\) and \(u(\phi) = 0.00075\,\mathrm{rad}\).

Uncertain numbers for \(v\), \(i\) and \(\phi\) can be defined using `ucomplex`

:

```
>>> v = ucomplex(complex(4.999,0),(0.0032,0))
>>> i = ucomplex(complex(19.661E-3,0),(0.0095E-3,0))
>>> phi = ucomplex(complex(0,1.04446),(0,0.00075))
```

Note that in these definitions the second argument is a pair of numbers [1]. These are the standard uncertainties associated with estimates of the real and imaginary components.

The complex impedance is

```
>>> z = v * exp(phi) / i
```

The value, uncertainty and degrees-of-freedom of `z`

are (in summary form)

```
>>> print z.s
(127.73-219.85j), u=[0.19,0.20], r=0.058, df=inf
```

In this format, the complex value of the estimate is followed by the standard uncertainty in the real and imaginary components. The term `r=0.058`

is the correlation coefficient between the real and imaginary component estimates.

If the magnitude and phase of \(z\) are of interest

```
>>> print magnitude(z).s
254.26, u=0.20, df=inf
>>> print phase(z).s
1.04446, u=0.00075, df=inf
```

Different formats for the uncertainty of uncertain complex numbers

When defining an uncertain complex number, it is possible to specify the uncertainty of a complex value in different ways:

A single number will specify the standard uncertainty of real and imaginary components to the same value,

A 2-element sequence of numbers specifies the standard uncertainties of the real and imaginary components

A 4-element sequence of numbers specifies the elements of the variance-covariance matrix

If

`v`

is such a 4-element sequence then`v[0]`

is the standard variance associated with the real component (the standard uncertainty is`math.sqrt(v[0])`

)`v[3]`

is the standard variance associated with the imaginary component (the standard uncertainty is`math.sqrt(v[3])`

)`v[1]`

and`v[2]`

must be equal, they represent the covariance between the real and imaginary components (the correlation coefficient is`v[1]/math.sqrt(v[0]*v[3])`

)

For example,

```
>>> z = ucomplex(1+1j,1)
>>> uncertainty(z)
standard_uncertainty(real=1.0, imag=1.0)
>>> variance(z)
variance_covariance(rr=1.0, ri=0.0, ir=0.0, ii=1.0)
>>> z = ucomplex(1+1j,(.5,.5))
>>> uncertainty(z)
standard_uncertainty(real=0.5, imag=0.5)
>>> variance(z)
variance_covariance(rr=0.25, ri=0.0, ir=0.0, ii=0.25)
>>> z = ucomplex(1+1j,(.5,0.1,0.1,.5))
>>> uncertainty(z)
standard_uncertainty(real=0.70710678118654757, imag=0.70710678118654757)
>>> z = ucomplex(1+1j,(.5,0.1,0.1,.5))
>>> variance(z)
variance_covariance(rr=0.50000000000000011, ri=0.099999999999999992,
ir=0.099999999999999992, ii=0.50000000000000011)
```

Note

A namedtuple is returned by the functions `uncertainty`

and `variance`

.

The elements of a namedtuple can be accessed by index, or by name. For example,

```
>>> cv = variance(z)
>>> cv
variance_covariance(rr=0.5000000000000001, ri=0.09999999999999999,
ir=0.09999999999999999, ii=0.5000000000000001)
>>> cv[0]
0.50000000000000011
>>> cv.rr
0.50000000000000011
```

## Programming¶

`GTC`

uses the Python programming language. This section gives a very brief introduction to some aspects of the language (see references [2] and [3] for more comprehensive Python tutorials).

### Sequences¶

A sequence is a collection of objects. The two main types of sequence are list and tuple. Tuples cannot be altered (they are read-only) whereas elements may be inserted, changed, sorted, etc, in lists.

For example, a tuple containing the numbers `1`

and `2`

is

```
>>> tup = (1,2)
```

The elements can be accessed by index (sequences are always base-0)

```
>>> print tup[0]
1
```

but cannot not changed

```
>>> tup[1] = 3
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
```

Lists are created using square brackets

```
>>> l = [-8,6,9]
>>> print l[1]
6
```

The elements of both tuples and lists can be iterated over using `for`

loops

```
>>> data = (1.1,3.2,6.7)
>>> for d in data:
... print d**2
...
1.21
10.24
44.89
```

The function `range`

creates a list of integers, which can be useful for iteration

```
>>> for i in range(4):
... print i
...
0
1
2
3
>>> print range(4)
[0, 1, 2, 3]
```

A useful feature allows sequences to be packed, and unpacked, by matching the number of elements on either side of an `=`

sign. For example,

```
>>> a = 1,2,3
>>> a
(1,2,3)
>>> x,y,z = a
>>> y
2
```

### Functions¶

A function is defined by a name followed by a list of arguments in parentheses and a colon. An indented block of code defines the function body. A `return`

statement sends a result back to the calling context.

Here is a function that calculates the surface area of a box, given the length, width and height of the sides

```
def surface(l,w,h):
end_area = 2 * w * h
side_area = 2 * l * h
top_bottom = 2 * w * l
area = end_area + side_area + top_bottom
return area
```

Note

This code snippet would be stored in a file, so the interactive prompt `>>>`

does not appear.

Note

The arguments `l`

, `w`

and `h`

can be ordinary numbers or uncertain numbers.

### Strings and printing¶

When a `print`

statement is used to display an uncertain number, the value will be displayed between question marks. The number of significant digits is determined by the uncertainty

```
>>> x = ureal(1.11111,0.1)
>>> print x
?1.11?
```

However, typing the name of the uncertain number (without using `print`

) produces a more detailed description, called the Python representation:

```
>>> x
ureal(1.111, 0.10000000000000001, inf)
```

There are two ways of formatting data as strings (one described in detail under % formatting in the Python documentation, the other under format str). The % formatting method uses a template string containing format specifiers to determine how data will appear in a resulting string.

For example, the `%s`

format specifier is a placeholder for a string in the output

```
>>> name = 'Jim'
>>> "Hello %s" % name
'Hello Jim'
```

- The format str approach uses the
`format`

method of the string object. :: >>> name = 'Jim' >>> "Hello {}".format(name) 'Hello Jim'

Note

Strings are delimited by apostrophes `'`

or quotation marks `"`

and multi-line strings begin and end with triple delimiters of either kind.

There are format specifiers for display floating point numbers (e.g., `%f`

, `%E`

, `%G`

)

```
>>> p = math.pi
>>> "pi = %f" % p
'pi = 3.141593'
>>> "pi = %E" % p
'pi = 3.141593E+00'
>>> "pi = %G" % p
'pi = 3.14159'
```

alternatively

```
>>> p = math.pi
>>> "pi = {:f}".format(p)
'pi = 3.141593'
>>> "pi = {:E}".format(p)
'pi = 3.141593E+00'
>>> "pi = {:G}".format(p)
'pi = 3.14159'
```

The `G`

format specifier switches automatically to an exponential scientific format when the number becomes too big, or too small (use `E`

to always get the scientific format)

```
>>> bigger = p * 1E6
>>> "pi = %G" % bigger
'pi = 3.14159E+06'
```

Several arguments can inserted in a string using format specifiers. The corresponding data must be contained in a tuple to the right of the `%`

operator. For example,

```
>>> quantity = 'voltage'
>>> value = 1.4
>>> unit = 'V'
>>> "%s = %f (%s)" % (quantity,value,unit)
'voltage = 1.400000 (V)'
>>> "{!s} = {:f} ({!s})".format(quantity,value,unit)
'voltage = 1.400000 (V)'
```

### Operators¶

A few Python operators may be unfamiliar. For example, raising one number to the power of another uses a double asterisk operator

```
>>> 2 ** 4
16
```

Testing for equality uses a double equals operator

```
>>> 2.0 == 2
True
```

Note that a single ‘=’ is used to assign one thing to another, so the following is an error

```
>>> 2.0 = 2
File "<console>", line 1
SyntaxError: can't assign to literal
```

There are quite a few different operators in Python, so it is best to consult the Python Help file, or a Python reference, for further details [4].

### Modules¶

Libraries of functions and classes can be defined in files called modules. Many standard Python modules are included with `GTC`

. For example, math and cmath define basic mathematical operations for real and complex numbers.

`GTC`

has a module structure of its own. The different `GTC`

modules are all accessible by name (or through a shorter alias). For example, the function `reporting.budget`

, which is part of the `reporting`

module (alias `rp`

) is useful for obtaining an uncertainty budget, as this short example shows:

```
x1 = ureal(1,0.1,label='x1')
x2 = ureal(1,0.1,label='x2')
x3 = ureal(1,0.1,label='x3')
x4 = x1 + x2
x5 = x2 + x3
x6 = x4 + x5
print "u(x6) = %G" % uncertainty(x6)
for u_cpt in reporting.budget(x6):
print " %s: %G" % u_cpt
```

The results are

```
u(x6) = 0.244949
x2: 0.2
x1: 0.1
x3: 0.1
```

### Errors¶

When programming errors occur, an `exception`

is raised. This halts execution and generates an error message called a *traceback*.

Example: RuntimeError

An `exception`

is raised when an attempt is made to define an uncertain number with a negative uncertainty

```
>>> x = ureal(1,-1)
Traceback (most recent call last):
File "<console>", line 1, in <module>
RuntimeError: invalid uncertainty: -1
```

The error message is `invalid uncertainty: -1`

and the exception is an instance of a `RuntimeError`

. The problem occurred while executing the `"<console>"`

file, which is actually the `GTC`

command window.

If a file containing the same faulty command had been executed, the error message would look slightly different. Here, executing a file called `simple_error.py`

, containing `x = ureal(1,-1)`

in line 1, we see:

```
C:\>gtc simple_error.py
Traceback (most recent call last):
File "simple_error.py", line 1, in <module>
x = ureal(1,-1)
RuntimeError: invalid uncertainty: -1
```

The first line now refers to the file by name and identifies the code that caused the problem. The `RuntimeError`

error message `invalid uncertainty: -1`

is given at the bottom, as before.

Other types of error

A `RuntimeError`

is just one of a number of built-in Python exceptions. However, the basic structure of traceback messages remain the same.

Here is an example where a `ValueError`

is raised while performing a mathematical operation:

```
>>> x = ureal(-1,1)
>>> sqrt(x)
Traceback (most recent call last):
File "<console>", line 1, in <module>
ValueError: math domain error
```

The exception was raised while executing `sqrt(x)`

and the problem is signaled as a `math domain error`

.

Footnotes

[1] | The parentheses around these numbers are important: they define a type of Python sequence called a tuple. |

[2] | “A Non-Programmer’s Tutorial” <http://en.wikibooks.org/wiki/Non-Programmer’s_Tutorial_for_Python_2.6> |

[3] | A list of beginner guides for non-programmers is available here: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers |

[4] | The Python Help file distributed with `GTC` can be used to quickly check if a symbol is in fact a Python operator. Open the Help file and type the symbol (or symbols) into the index line. If the symbol is part of Python, the Help file will provide some reference information. |