Important classes
pcot.document.Document, and an overview
- PCOT keeps all its user data in a pcot.document.Document:
This contains:
- a pcot.documentsettings.DocumentSettings object
- a pcot.inputs.inp.InputManager object handling the inputs
- a pcot.document.UndoRedoStore which uses the serialisation/deserialisation system to handle an undo stack
- A dictionary of pcot.macros.XFormMacro objects - the user macros
- most importantly a pcot.xform.XFormGraph - a set of nodes of type pcot.xform.XForm connected together to do things.
- Each XForm points to a pcot.xform.XFormType singleton which controls its behaviour.
- Nodes (XForms) communicate by passing pcot.datum.Datum objects.
- Each Datum points to a pcot.datumtype.Type subclass singleton providing serialisation, copy, and display facilities.
- They also have values - two common value classes are pcot.imagecube.ImageCube for images, and pcot.value.Value objects for other arrays and scalars.
- ImageCubes can generate SubImageCube objects which are subsets of the image covered by ROIs and with bad pixels masked out ("bad" according to the data quality bits).
pcot.xform.XFormGraph
This represents the graph of nodes which take data from inputs and perform operations on them. There is one inside the document, and instances of macros also contain their own graphs (and the macro itself contains a "template" graph from which these are created).
A graph contains:
- A set of pcot.xform.XForm objects (usually called nodes)
connected together by their
inputs
fields, which are tuples of (source node, index of output). - A graph runs by finding those nodes which have no inputs and performing them; the entire graph will be recursively traversed.
- Nodes are only run if their inputs have data (if their parent nodes have run).
pcot.xform.XForm
- All nodes are of the same type. Polymorphism - different nodes behaving
differently - is accomplished through each node having a reference to
a pcot.xform.XFormType object in its
type
member that controls its behaviour. - Nodes communicate by passing pcot.datum.Datum objects.
- When a node runs its
perform
method- It reads the inputs by deferencing the
inputs
fields and getting the input node and index of the output of that node, and reading the Datum stored in that output. - It processes the data and stores the results in its
outputs
field as Datum objects. - It then performs its "child" nodes.
- It reads the inputs by deferencing the
pcot.datum.Datum
This is the fundamental data type, used both for communicating between nodes and handling values in the expr node. A Datum has
- a type, which is a pcot.datumtypes.Type object
- a value, whose type depends on the type field
- a source indicating where the data came from
If the value is None
, the Datum is null. There is a constant
Datum.null
for null data.
pcot.datumtypes.Type
The DatumType object provides methods for serialisation, copying, and display. Each is a singleton. It's easy to create custom DatumTypes. The most commonly used builtins are:
- Datum.IMG: contains an ImageCube
- Datum.NUMBER: contains a Value
(these names are for the singleton objects, not their types - for example,
Datum.IMG
has the type pcot.datumtypes.ImgType
.)
pcot.imagecube.ImageCube
This is the fundamental image type, consisting of
- image data - 2D (H x W) if there is only one band (channel), 3D otherwise (H x W x D). Type is float32.
- uncertainty data, same shape and type as image data. This is the standard deviation of each pixel.
- DQ data. This a 16-bit bitfield for each pixel. Some of these are considered errors - these are called "bad" DQ bits (e.g. no uncertainty, saturated, results from a division by zero).
- regions of interest
- annotations that have been added to the image
- mapping used to render the image as RGB
- sources for each band
pcot.imagecube.SubImageCube
These objects can be generated by calling the subimg() method on an ImageCube. They are the subset of an image covered by the regions of interest it has, along with a mask for those regions. Additionally, "bad" parts of the image (which can be different in different bands) can be masked out.
Operations on images are typically done on these subimages, and then modifyWithSub is called on the imagecube to return a copy of that imagecube with the modified subimage spliced in. Useful subimage methods include:
- masked(): return the masked nominal image data
- maskedUncertainty(): return the masked uncertainty data
- maskedDQ(): return the masked DQ bits
All these return numpy masked arrays.
pcot.value.Value
This is the fundamental numeric type, consisting of
- nominal value
- uncertainty value (standard deviation)
- DQ bits
It's usually used for scalars but can also hold array data - internally ImageCubes (or parts of them) are converted into array Values for maths. If it does hold array data, the three elements must be the same shape. It's possible to create 1D vectors in an expr node using square brackets, and some functions and operations return such vectors.
This type supports mathematical operations which propagate uncertainty and DQ.
More on how Values work here
Note: You may wonder why ImageCube and SubImageCube don't use Value internally. The answer is simply historical reasons: they were created a very long time before Value, and refactoring now could cause huge problems.