ICalculator Class Referenceabstract

Generic calculator for evaluating formulas or manipulating objects based on the OPALS generic filter syntax. More...

#include "ICalculator.hpp"

+ Inheritance diagram for ICalculator:

Classes

struct  EvaluationErrorCallback
 Abstract functor to derive from. More...
 

Public Types

enum  ReadAccess {
  none, coordinates, attributes = coordinates << 1, vectors = coordinates | attributes,
  rasters = attributes << 1, neighbors = rasters << 1, full = (neighbors << 1) - 1
}
 Choose the supported input data types. More...
 
enum  WriteAccess {
  none, coordinates, attributes = coordinates << 1, rasters = attributes << 1,
  full = (rasters << 1) - 1
}
 Choose which types of data may be assigned to. More...
 
enum  DataTypeSuperset { arithmetic, string, unknown }
 The result type of the calculator. More...
 
enum  RasterDataType {
  unknown, uint8, uint16, int16,
  uint32, int32, float32, float64
}
 Copy of GDALDataType, but without complex types. More...
 

Public Member Functions

virtual ICalculatorclone () const =0
 Deep-copy. Use for multi-threading!
 
virtual ICalculatoroperator* (double factor) const =0
 
virtual void geometryChanged (bool *flag=nullptr)=0
 Get notified if an evaluated geometry has been changed. More...
 
virtual void init () const =0
 Initialize internal data. resultDouble calls this implicitly / lazily if some non-const method has been called since the last call to this. More...
 
virtual bool isConstant () const =0
 Returns true iff resultDouble surely does not change any arguments and its return value is always the same, independent of its arguments. More...
 
virtual bool readsRasters () const =0
 returns true iff the calculator reads an input raster.
 
virtual bool readsRastersByIndexOrLimitedSlice () const =0
 returns true iff this reads one or more input raster datasets specified by a single index or by a slice that defines start and/or stop indices.
 
virtual bool readsNeighbors () const =0
 returns true iff the calculator reads a neighbor.
 
virtual unsigned assignmentCount () const =0
 returns the number of (statements that are) assignments.
 
virtual unsigned statementCount () const =0
 returns the number of statements. Empty statements do not count.
 
virtual DataTypeSuperset typeSuperset () const =0
 
virtual void print (std::ostream &) const =0
 
virtual const char * text () const =0
 
Logging of evaluation errors

Set a functor to be called upon evaluation errors, e.g. division by zero, conversion failure to target type. msg describes the problem, and it may contain contextual information. Hence, similar problems may have different messages.

virtual void evaluationErrorCallback (EvaluationErrorCallback *cb=nullptr)=0
 Make this use your functor instance as callback. Its memory remains managed by you.
 
Input rasters

Calculators process zero or more input raster datasets with zero or more bands. Each band has an invalid value, and it may have a name. Named bands may be accessed in the text by name instead of by index. While the number of neighbors may change for each call of resultDouble(), the number of input raster datasets, their band counts, and each band's name and nodata value typically do not change for many consecutive calls of resultDouble(). Hence, this information must be specified beforehand, if input rasters shall be used.

virtual void inputDatasetCount (unsigned nDatasets)=0
 Tells the calculator for how many datasets the argument inRaster of resultDouble() will subsequently provide data, if the respective datasets are used (see inputDatasetSubset()). More...
 
virtual void inputBandCount (unsigned iDataset, unsigned nBands)=0
 Tells the calculator that the iDataset 'th dataset has nBands instead of 1. More...
 
virtual void inputBandName (unsigned iDataset, unsigned iBand, char const *bandName)=0
 Associates a band index with a band name, so the band can be accessed by name in text.
 
virtual void inputBandNoData (unsigned iDataset, unsigned iBand, double noData)=0
 Associates the given value as invalid for the given input raster band. Default: NaN.
 
virtual void inputDatasetSubset (unsigned const *iDatasets=0, unsigned nDatasets=0)=0
 Temporarily restricts the datasets for which inRaster must provide elements to those specified in iDatasets. More...
 
Output raster

text defines the number of output bands, their names and types. Use this information to size outRaster and create the output raster datasets.

virtual unsigned outputBandCount () const =0
 Returns the number of elements that outRaster must point to. More...
 
virtual const char * outputBandName (unsigned iBand) const =0
 Returns the name of the iBand'th output band if specified in text, or otherwise an empty string.
 
virtual RasterDataType outputBandType (unsigned iBand) const =0
 Returns the actual type assumed for the iBand'th output band. If not specified in text, returns the one passed to outputBandTypeDefault, or otherwise RasterDataType::float64.
 
virtual void outputBandNoData (unsigned iBand, double noData)=0
 Sets a value to be written to the iBand'th element of outRaster if invalid (aka NO_DATA). Default: std::numeric_limits<output band type>::max().
 
virtual void clearOutputBandNoData (unsigned iBand)=0
 Clears the NO_DATA value for the iBand'th element of outRaster. Evaluation will throw upon encountering an invalid value!
 
virtual bool hasOutputBandNoData (unsigned iBand) const =0
 Returns true if a NO_DATA value has been set for the iBand'th element of outRaster.
 
virtual double outputBandNoData (unsigned iBand) const =0
 Returns the NO_DATA value for the iBand'th element of outRaster. Throws if none has been set.
 
virtual void outputBandTypeDefault (RasterDataType)=0
 Sets the default data type for output bands, to be used if text does not specify one. Default: RasterDataType::float64.
 
virtual void outputBandStats (unsigned iBand, size_t &nInvalid, size_t &nNoData, size_t &nOverflow) const =0
 Query the statistics of values assigned so far to the iBand'th output band. More...
 
Attribute assignment statistics

Query the statistics of attributes assigned so far.

virtual size_t nAttributeAssignmentStats () const =0
 Query the number of attribute assignment statistics available.
 
virtual void attributeAssignmentStats (unsigned iAttribute, char const *&name, size_t &nInvalid, size_t &nOverflow) const =0
 Query the statistics of values assigned so far to the iAttribute'th attribute. More...
 
Evaluation

Evaluate this with the given geometry, input rasters, neighbors, and output rasters. If this has been created without ReadAccess::rasters, then inRaster will not be accessed and may be NULL. Otherwise, preceding calls to methods in the group for input rasters define the number of elements that inRaster must point to, and the dataset and band that each of its elements is associated with. If this has been created without ReadAccess::neighbors, then neighbors will not be accessed and may be NULL. neighbors must point to nNeighbors elements. If this has been created without WriteAccess::rasters, then outRaster will not be accessed and may be NULL. Otherwise, outRaster must point to outputBandCount() elements.

Returns the result of evaluating the last statement. Assignments always return 1. The following operations yield invalid values:

  • Access to inexistent or null attributes and invalid coordinates (DBL_MAX).
  • Operations on invalid values.
  • Domain errors, e.g. 1/0, acos(2).
  • Conversion of values outside the value range of target types, e.g. uint(-1.), uint8(256.) Returns NaN for invalid results. Hence,
    x
    

returns x if x is valid (i.e. not DBL_MAX, not NaN), NaN otherwise.

3 * sigmaX

returns 3*sigmaX if sigmaX is valid (attribute is part of the layout and not NULL), NaN otherwise.

3 * sigmaX; 5

returns 5.

_val = 3 * sigmaX; sigmaY

Sets _val and returns sigmaY if sigmaY is valid, otherwise NaN. If init() has been called just before, then resultDouble only throws on input raster dataset / band index out-of-range, e.g.:

  • r[1] while only a single input raster dataset has been specified, or
  • r[0][1] while only a single band has been specified for the first input raster dataset.
virtual double resultDouble (IGeometry &geom, double const *inRaster=0, IGeometry const *const *neighbors=0, unsigned nNeighbors=0, double *outRaster=0) const =0
 Evaluate this with a mutable geometry. More...
 
virtual double resultDouble (IGeometry const &geom, double const *inRaster=0, IGeometry const *const *neighbors=0, unsigned nNeighbors=0, double *outRaster=0) const =0
 Evaluate this with a constant geometry. More...
 
- Public Member Functions inherited from ObjectBase
virtual void Delete ()
 

Static Public Member Functions

static void convertOrNaN (double &value, RasterDataType type)
 
static ICalculatorNew ()
 
static ICalculatorNew (const char *text, ReadAccess readAccess, WriteAccess writeAccess)
 

Detailed Description

Generic calculator for evaluating formulas or manipulating objects based on the OPALS generic filter syntax.

Member Enumeration Documentation

◆ DataTypeSuperset

enum DataTypeSuperset
strong

The result type of the calculator.

If custom attributes are to be queried, the result type is unknown beforehand.

◆ RasterDataType

enum RasterDataType
strong

Copy of GDALDataType, but without complex types.

Enumerator
unknown 

Unknown or unspecified type.

uint8 

8 bit unsigned integer

uint16 

16 bit unsigned integer

int16 

16 bit signed integer

uint32 

32 bit unsigned integer

int32 

32 bit signed integer

float32 

32 bit floating point

float64 

64 bit floating point

◆ ReadAccess

enum ReadAccess
strong

Choose the supported input data types.

Enumerator
none 

support querying no data types at all. Hence, only constants and functions: pi atan(.23)

coordinates 

support querying coordinates: x y z

attributes 

support querying attributes: sigmaX _customAttr

vectors 

shortcut: support querying coordinates or attributes

rasters 

support querying input raster data: r[0]

neighbors 

support querying neighbors: n[0]

full 

support querying all input data types

◆ WriteAccess

enum WriteAccess
strong

Choose which types of data may be assigned to.

Enumerator
none 

support no assignments at all

coordinates 

support assignment to coordinates

attributes 

support assignment to attributes

rasters 

support assignment to output raster nodes: [0] [red] [](float32)

full 

support assignment to all output data types

Member Function Documentation

◆ attributeAssignmentStats()

virtual void attributeAssignmentStats ( unsigned  iAttribute,
char const *&  name,
size_t &  nInvalid,
size_t &  nOverflow 
) const
pure virtual

Query the statistics of values assigned so far to the iAttribute'th attribute.

name the name of this attribute nInvalid is the number of times that the value to be assigned has been invalid. nOverflow is the number of times that the value to be assigned has been valid, but outside the domain of this attribute's data type, i.e. too small or too large, or numeric vs. string. nInvalid + nOverflow is the total number of evaluated geometries for which this attribute is now inexistent i.e. the attribute is either not part of the layout, or it is null.

◆ geometryChanged()

virtual void geometryChanged ( bool *  flag = nullptr)
pure virtual

Get notified if an evaluated geometry has been changed.

After each call of resultDouble, this flag will be true only if this has changed the coordinates and/or attributes of geom . An attribute is considered as changed if:

  • a new AddInfo has been assigned, or
  • its layout has been changed (column of same name but different type) or extended (additional column), or
  • an attribute that was null has been set to non-null, or
  • a non-null attribute has been set null, or
  • the value of a non-null attribute has been changed. The memory of flag remains managed by you.

◆ init()

virtual void init ( ) const
pure virtual

Initialize internal data. resultDouble calls this implicitly / lazily if some non-const method has been called since the last call to this.

This does various checks and may throw. Call this explicitly to generate these errors beforehand.

◆ inputBandCount()

virtual void inputBandCount ( unsigned  iDataset,
unsigned  nBands 
)
pure virtual

Tells the calculator that the iDataset 'th dataset has nBands instead of 1.

Hence, with

CalculatorHandle calc = ICalculator::New(...);
calc->inputDatasetCount(3);
calc->inputBandCount(0, 2);
calc->inputBandCount(2, 4);

resultDouble() will expect inRaster to point to 7 elements, where

  • the first 2 elements are associated with the 2 bands of the first dataset,
  • the third element is associated with the only band of the second dataset (because its band count has been left to its default 1), and
  • the trailing 4 elements are associated with the four bands of the third dataset.

◆ inputDatasetCount()

virtual void inputDatasetCount ( unsigned  nDatasets)
pure virtual

Tells the calculator for how many datasets the argument inRaster of resultDouble() will subsequently provide data, if the respective datasets are used (see inputDatasetSubset()).

Datasets by default have a single band. For each dataset, inRaster expects an element for each band, sorted first by dataset and second by band index, in ascending order. Hence, with

CalculatorHandle calc = ICalculator::New(...);
calc->inputDatasetCount(2);

resultDouble() will expect inRaster to point to 2 elements in total: one for the first dataset, followed by another element for the second dataset (since both datasets are single band).

◆ inputDatasetSubset()

virtual void inputDatasetSubset ( unsigned const *  iDatasets = 0,
unsigned  nDatasets = 0 
)
pure virtual

Temporarily restricts the datasets for which inRaster must provide elements to those specified in iDatasets.

Input raster indices (r[<idx>]) and index ranges (mean(r[<iBegin> : <iEnd>])) then index into this reduced list of datasets. iDatasets must point to nDatasets elements. Input band counts, names, and nodata-values of temporarily de-activated datasets are preserved and will be re-used once a dataset gets re-activated by calling inputDatasetSubset another time. Hence, with

CalculatorHandle calc = ICalculator::New(...);
calc->inputDatasetCount(3);
calc->inputBandCount(0, 2);
calc->inputBandName(0, 0, "red");
calc->inputBandCount(2, 4);
std::vector<unsigned> subset = {1, 2};
calc->inputDatasetSubset(subset.data(), subset.size());

resultDouble() expects inRaster to point to 5 elements, where

  • the first element is associated with the only band of the second dataset, and
  • the trailing 4 elements are associated with the four bands of the third dataset.

Because the first dataset has been excluded / de-activated, r[0] now refers to the single-band (second) dataset. If later on,

subset = {0, 1};
calc->inputDatasetSubset(subset.data(), subset.size());

gets executed, resultDouble() expects inRaster to point to 3 elements, where

  • the first 2 elements are associated with the 2 bands of the first dataset, and
  • the third element is associated with the only band of the second dataset.

Again, the first band of the first dataset is associated with the name "red". Because the first dataset has been activated again, r[0] refers to the two-band (first) dataset.

◆ isConstant()

virtual bool isConstant ( ) const
pure virtual

Returns true iff resultDouble surely does not change any arguments and its return value is always the same, independent of its arguments.

Returns true for constants and combinations thereof: New("1")->isConstant() == true New("3 * atan2(0.2, pi)")->isConstant() == true New("2 ? 3 : x")->isConstant() == true New("x = 1")->isConstant() == false New("3 || 4")->isConstant() == true New("0 && 4")->isConstant() == true

Note that the following is correct output, because the validity of x is unknown beforehand and hence, resultDouble may return 0 or NaN. New("0 * x")->isConstant() == false

For operator&& and operator||, this returns certain false negatives, e.g.: New("0 && x")->isConstant() == false New("3 || x")->isConstant() == false

◆ New()

static ICalculator* New ( const char *  text,
ReadAccess  readAccess,
WriteAccess  writeAccess 
)
static

Construct a calculator.

Parameters
textText that defines the calculator.
readAccessChoose which types of data the calculator may query i.e. read from. If supported, make sure to provide inRaster and/or neighbors in calls to resultDouble()! Throws if text would read from an unsupported type.
writeAccessChoose which types of data the calculator may write to i.e. assign to. If supported, make sure to provide outRaster in calls to resultDouble()! Throws if text would assign to an unsupported type.

◆ outputBandCount()

virtual unsigned outputBandCount ( ) const
pure virtual

Returns the number of elements that outRaster must point to.

Hence, returns 0 if this calculator does not write to any output rasters.

◆ outputBandStats()

virtual void outputBandStats ( unsigned  iBand,
size_t &  nInvalid,
size_t &  nNoData,
size_t &  nOverflow 
) const
pure virtual

Query the statistics of values assigned so far to the iBand'th output band.

nInvalid is the number of times that the value to be assigned has been invalid. nNoData is the number of times that the value to be assigned has been valid and could be converted to the band's data type, but happened to be equal to the band's NoData value. nOverflow is the number of times that the value to be assigned has been valid, but outside the domain (i.e. too small or large) of the band's data type or not numeric (i.e. ColumnType::string or ColumnType::cstr).

nInvalid + nNoData + nOverflow is the total number of times that the NoData value has been assigned to outRaster.

◆ resultDouble() [1/2]

virtual double resultDouble ( IGeometry geom,
double const *  inRaster = 0,
IGeometry const *const *  neighbors = 0,
unsigned  nNeighbors = 0,
double *  outRaster = 0 
) const
pure virtual

Evaluate this with a mutable geometry.

The geometry coordinates and/or attributes may get changed only if this has been created with WriteAccess::coordinates and/or WriteAccess::attributes.

◆ resultDouble() [2/2]

virtual double resultDouble ( IGeometry const &  geom,
double const *  inRaster = 0,
IGeometry const *const *  neighbors = 0,
unsigned  nNeighbors = 0,
double *  outRaster = 0 
) const
pure virtual

Evaluate this with a constant geometry.

Throws if this has been created with WriteAccess::coordinates and/or WriteAccess::attributes.