Site navigation:

Contents

The Point and Pointset classes are essentially enhanced Numpy array classes. The primary goal of these two classes is to free the user from dealing with explicit array indices when manipulating scientific or numerically-computed data which are commonly most naturally referenced by names. We believe the "index free" array is a liberating substrate for users, that permits construction of sophisticated computations without the tedious book-keeping of arbitrary integer array indices. This comes at little cost to efficiency, especially as regular arrays can easily be extracted from a Pointset or reassembled into one, so that data porting to other applications is easy.

Pointsets may either be parameterized by an independent variable -- in which case they are *callable* with values of that variable, or they may be non-parameterized -- in which case they are not callable. In either case they can be referenced by array index, or in other ways (see below).

The display of point and pointset contents uses a numerical precision of 8 significant figures. This cannot be changed by the user, who should extract a subset of the pointset as an array in order to see the values at full precision. Of course, arithmetic comparisons using pointset values use full precision.

**Attributes of Pointsets**

- coordnames
- coordarray
- coordtype (A numeric type, float or int)
- indepvarname
- indepvararray (stored variables in rows, as per display output)
- indepvartype (A numeric type, float or int)
- dimension
- _parameterized (Boolean) [
*Please note the leading underscore. An alternative is to call the*isparameterized(p)*function on the pointset*p]

Individual values of a Point or Pointset can be set using their 'set' method.

A further feature of Points and Pointsets is their inherent point labelling system, which can be queried and manipulated much like a dictionary, as a way to organize sophisticated access to array data. For instance, this becomes especially useful when exploring the bifurcation sets of a dynamical system using PyCont.

In a Pointset, denoted `w`, labels are stored by *index*. To see which point is labelled at index `i`, look at `w[i]`. To find out which index corresponds to an independent variable value `t`, call `w.find(t)` (parameterized pointsets only). If the value of `t` is not in the pointset then a *pair* will be returned that indicates where `t` lies with respect to existing independent variable values in `w`.

To see which points in a pointset possess a given string label `s`, use `w.bylabel(s)`.

Labels should be added and removed using the `addlabel` and `removelabel` methods.

Additionally, a pointset may be given a name, which resides in the attribute `name`.

The displayed order of point or pointset coordinates is *alphabetical*. This is the only supported ordering of coordinates, and also provides the ordering for exported arrays from these objects.

A point can be called and referenced by coordinate name or index.

A point can be removed, appended, or inserted into a pointset using the methods `remove`, `append` and `insert`. Note that, unlike with lists, you can append either an individual point or a pointset object. A method named `extend` is also provided, and has identical functionality to `append`.

A parameterized pointset can be called at a specific independent variable value (or set of values), with an additional argument to select coordinates in the output. A pointset can be referenced by point index (returning a point), a set of indices (returning a pointset corresponding to points at those indices), or by coordinate name (returning a pointset containing only that coordinate at all point indices). The `bylabel` method also allows points to be selected based on their label.

Both points and pointsets can have their values set in the same ways that both a dictionary and a list can be.

The full range of possibilities in the point and pointset interface can be seen by running the `Points.py` file as a script and reading the examples in the output.

Pointsets can be reversed *in place* using the `reverse` method.

Basic arithmetic and comparison operations can be performed on Points and Pointsets, in much the same way as can be done with arrays. The ordering and test of equality for points is defined according to the choice of norm for the points. By default, this is L2 norm, although this can be changed using the 'norm' key in the argument dictionary at initialization to be values from 1 to Inf. Comparison of both points and pointsets using the usual arithmetic operators will compare objects point-wise based on their norms.

To compare two points or pointsets, coordinate for coordinate, use the `comparePointCoords` function (which also accepts appropriately keyed dictionaries). The comparison can be made stricter using the optional `fussy` boolean argument, in which case the norm and coordinate type are also checked for equality, provided only points and pointsets are passed to the function.

Points can be compared to single values, returning a Boolean array that indicate matching coordinates (ordered). Similarly, Pointsets can be compared to Points, returning a Boolean array indicating matching positions. This functionality is much like that of Numpy arrays.

Unlabelled points and unlabelled non-parameterized pointsets can be created by calling the appropriate class constructor with a dictionary mapping coordinate name keys to numeric or array/list values.

Points and pointsets can have their *values* (i.e. not including the independent variable, if present) turned into a dictionary by calling the in-built function `dict` with the point or pointset as argument. A `todict` method is also implemented.

The `Point` class is defined to closely resemble a mapping object class such as `dict` (although it is not a subtype of `dict`). `Pointset` is a subclass of `Point`, although it acts more like a list than a dictionary. Most natural operations for dictionaries and lists apply equally to the respective subclasses.

See the file `/tests/test_pointsets.py` for the code for the following demo.

>>> x = Point({'coorddict': {'x0': [1.123456789], 'x1': [-0.4], 'x2': [4000]}, 'coordtype': float}) >>> x x0: 1.123456789 x1: -0.4 x2: 4000.0 >>> x.toarray() array([ 1.12345679e+00 -4.00000000e-01 4.00000000e+03]) >>> x.dimension 3 >>> x.coordnames ['x0', 'x1', 'x2'] >>> x.coordtype>>> x('x1') # returns a float -0.4 >>> x(['x1','x0']) # returns another Point x0: 1.123456789 x1: -0.4 >>> x([0,1]) x0: 1.123456789 x1: -0.4 >>> x[1] = -0.45 #Changing x entries is done by x[index] = value: >>> x[['x0', 'x1']] = [4.11103, -0.56]) #The index can also be a name, a list of names, or even a dictionary >>> y = Point({'y': 4}) # y is a 1D point (with integer type) >>> print y y: 4.0 >>> y(0) 4.0 >>> type(y(0)) >>> y([0]) y: 4.0 >>> y.toarray() 4.0

In the following, `v` is a 'singleton' pointset (only one entry)

>>> v = Pointset({'coorddict': {'x0': 0.2, 'x1': -1.2}, 'indepvardict': {'t': 0.01}, 'coordtype': float64, 'indepvartype': float64 }) >>> print v Pointset(parameterized) >>> print v(0.01) # a Point object x0: 0.2 x1: -1.2 >>> print v(0.01, 0) # also a Point object (index 0 only = 'x0') x0: 0.2 >>> print v(0.01, 'x0') # alternative to using index, use the name directly x0: 0.2

In the following, Pointset `k` shows a different way to specify a single-point Pointset:

>>> k = Pointset({'coordarray': array(0.1), 'coordnames': 'k0', 'indepvarname': 't', 'indepvararray': array(0.0)}) >>> print k.toarray() [ 0.1] >>> print k['t'] [ 0.] >>> print k(0.0) k0: 0.1 >>> print k Pointset(parameterized)

In the following, `u` is a non-parameterized Pointset:

>>> u = Pointset({'coordarray': array([10., 20., 30., 40.])}) >>> u.toarray() [ 10. 20. 30. 40.] >>> isparameterized(u) False >>> print u Pointset(non-parameterized)

In the following, `w` shows alternative declaration syntax, and other forms of calling:

>>> wp = Pointset({'coordarray': array([[4.456, 2.34634, 7.3431, 5.443], [-10.0336, -5.2235, -3.23221, -0.01], [3e5, 3.1e5, 3.3e5, 2.8e5]], float64), 'coordnames': ['x0', 'x1', 'x2'], 'indepvarname': 't', 'indepvararray': array([0.0, 1.0, 2.0, 3.0], float64)}) >>> wp.dimension 3 >>> print wp(0.0) x0: 4.456 x1: -10.0336 x2: 300000.0 >>> type(wp(0.0))>>> print wp(1.0)(0) 2.34634 >>> print wp(2.0, 'x1') x1: -3.23221 >>> print wp(2.0, ['x2', 'x1']) x1: -3.23221 x2: 330000.0 >>> type(wp(2.0, ['x1', 'x2'])) >>> print wp[['x1','x0']] Pointset (parameterized) >>> wp.info(1) Pointset (parameterized) Independent variable: t: [ 0. 1. 2. 3.] Coordinates: x0: [ 4.456 2.34634 7.3431 5.443 ] x1: [ -1.00336000e+01 -5.22350000e+00 -3.23221000e+00 -1.00000000e-02] x2: [ 300000. 310000. 330000. 280000.] Labels by index: Empty >>> wp(1.0).info(1) x0: 2.34634 x1: -5.2235 x2: 310000.0 >>> wp['t'] [ 0. 1. 2. 3.] >>> # Call several 't' values at once (explicit values only -- no ellipses): >>> wp([1., 2.]) Pointset (parameterized) >>> # Extract a coordinate (only by name) as a regular array: >>> w_x0 = wp['x0'] >>> print w_x0 [ 4.456 2.34634 7.3431 5.443 ] >>> # Extract a point of w as a regular array: >>> w_at_1 = wp(1.).toarray() >>> print w_at_1 [ 2.34634000e+00 -5.22350000e+00 3.10000000e+05] >>> # Many forms to access individual values or sub-arrays: >>> wp(1., 'x1') x1: -5.2235 >>> wp(1.)('x1') -5.2235 >>> wp(1., 1)) x1: -5.2235 >>> wp([1.,3.], 1) Pointset (parameterized) >>> wp([1.,3.])('x1') [-5.2235 -0.01 ] >>> wp(1.)([0,1]) x0: 2.34634 x1: -5.2235 >>> wp([1.])(1., [0,1]) x0: 2.34634 x1: -5.2235 >>> # ... because wp([1.]) is a Pointset and wp(1.) is a Point #This is why wp(1.).toarray() shows a different array shape to wp([1.]).toarray(): >>> wp(1.).toarray().shape (3,) >>> wp([1.]).toarray().shape (3, 1) >>> # Change a point in w using wp[indepvar_value] = point: # Old value at t=1.0: >>> wp(1.0) x0: 2.34634 x1: -5.2235 x2: 310000.0 >>> wp[1] = x >>> # w has now been updated for the meshpoint at t=1.0 => # New value at t=1.0: >>> wp(1.0) x0: 4.11103 x1: -0.56 x2: 4000.0 >>> # We can test equality between arrays, as expected: >>> w_at_1 != wp(1.).toarray() [ True True True] >>> # We can also compare with a Pointset object: >>> wp(1.) != w_at_1 [ True True True] >>> # But we can't put an array on the left-hand side if a Point or Pointset is on the right. >>> # To demonstrate appending a Point and Pointset to another Pointset: >>> vw.labels 1: {c: {}} >>> wp.append(vw) >>> wp.labels 5: {c: {}} >>> wp.toarray() [[ 4.45600000e+00 4.11103000e+00 7.34310000e+00 5.44300000e+00 1.00000000e-01 1.50000000e-01 2.00000000e+00] [ -1.00336000e+01 -5.60000000e-01 -3.23221000e+00 -1.00000000e-02 1.00000000e+02 1.02000000e+02 -3.00000000e+02] [ 3.00000000e+05 4.00000000e+03 3.30000000e+05 2.80000000e+05 2.00000000e-01 1.00000000e-01 -9.99700000e-01]] >>> wp(4.5) x0: 0.1 x1: 100.0 x2: 0.2 >>> wp[[3,6]] Pointset (parameterized) >>> wp[3:5] Pointset (parameterized) >>> wp[2:] Pointset (parameterized) >>> wp[wp.findIndex(4.5)] x0: 0.1 x1: 100.0 x2: 0.2 >>> wp.labels 5: {c: {}} >>> # Labels test: >>> wp.labels[3] {'a': {'bif': 'SN'}} >>> wp_part.labels 0: {a: {keys=bif}} >>> # wp_ins object created to insert into wp: >>> wp.insert(wp_ins) # returns a new Pointset Pointset (parameterized) >>> # To demonstrate building a Pointset from a list of Point objects: >>> pointlist = [] >>> for t in wp['t']: pointlist.append(wp(t)) >>> w_reconstructed = pointsToPointset(pointlist, 't', wp['t']) >>> # And to demonstrate that this yields an identical object: >>> w_reconstructed == w [ True True True True True True True True True True True] >>> # (ensure that any independent variable values to append are well-ordered) >>> # Test of non-parameterized use of pointsToPointset: # (Adding two additional labels to wnp) >>> wnp[:] # can use index slicing, etc. as expected Pointset (non-parameterized) >>> # Can iterate over points and pointsets: >>> for p in wnp.bylabel('a'): print p x0: 4.456 x1: -10.0336 x2: 300000.0 Labels: a ({'bif': 'SN'}) Labels: b ({}) x0: 7.3431 x1: -3.23221 x2: 330000.0 Labels: a ({'bif': 'H'})

- pointsToPointset(pointlist, indepvarname='', indepvararray=None, indepvartype=float, norm=2):
- arrayToPointset(a, vnames=None, ia=None, iname=""):
- exportPointset (thepointset, infodict, separator=' ', precision=12, varvaldir='col', ext='', append=False):
- export_pointset_to_CSV (filename, pts):
- importPointset (xFileName, t=None, indices=None, sep=" ", preamblelines=0):
- mergePointsets (pts1, pts2):
- padPointset (pts, pinterval, value_dict, eps=None):
- comparePointCoords (p1, p2, fussy=False):
- makeNonParameterized (p):

Generate a Pointset from a list of Point objects (or a singleton Point). Include a name for the independent variable if constructing a parameterized pointset. The independent variable should be a coordinate of the Points passed, otherwise it can be passed as the optional third argument.

Convert an array to a non-parameterized Pointset. The inclusion of an optional independent variable array creates a parameterized Pointset. Coordinate (and independent variable) names are optional: the defaults are the array indices (and 't' for the independent variable).

Export a pointset to a set of ASCII whitespace- (or user-defined character-) separated data files. Option to list each variable's data in rows ('across') or in columns ('down'). Existing files of the same names will be overwritten, unless the 'append' boolean option is set.

NB. If the file extension argument 'ext' is present without a leading dot, one will be added. infodict should consist of: keys = filenames, values = tuples of pointset variable names to export.

Simple export that ignores all metadata in pts, including name, tags, norm, etc. Data is arranged by row only. Independent variable is first column, if it exists in pts.

Import ASCII format files containing data points. If the first row contains string names then the output will be a pointset, otherwise a numeric array. A dictionary is returned, with keys 'vararray' will point to the data. The 't' argument can specify one of several things:

string: filename to read single-column of time values (same length as xFileName)

sequence type: time values (same length as xFileName)

integer: column in xFileName to treat as time data

If used, this leads to and an additional key in the return dictionary where 't' points to the independent variable array.

Specific columns can be selected for the variable data array by specifying a list of column indices in argument 'indices'.

The separator used in the ASCII file can be specified by argument 'sep' (defaults to single whitespace character). preamblelines (positive integer) specifies how many lines to skip before starting to read data (in case of preceding text) -- default 0.

Merges two pointsets into a new pointset, preserving (merging) any metadata in each. In particular, if each have different accuracy tolerances, the larger of the two will be used. If each have different 'checklevel' values, the larger of the two will be used. Point labels will be merged. Names will also be merged. If both are parameterized, their independent variable arrays must be identical. If only one is parameterized, the result will be too. The two pointsets must be identical in length. The norm associated with each pointset must be the same.

Pad a pointset pts with values from value_dict over the interval given by pinterval (pair). For each side of the interval outside of the current independent variable domain of pts, two new points are added, one at the outer limit of the interval, and one a distance eps (default the abseps setting of pts) from the existing closest point in pts.

Compare two Points, Pointsets, or dictionary of point data, coordinate-wise. If p1 or p2 are Pointsets, their independent variable values, if present, are *not* compared. fussy option causes point norm order and coordinate types to be checked too (requires both arguments to be Points or Pointsets).

Return a new Pointset stripped of its parameterization.