casacore
Loading...
Searching...
No Matches
UDFBase.h
Go to the documentation of this file.
1// # UDFBase.h: Abstract base class for a user-defined TaQL function
2// # Copyright (C) 2010
3// # Associated Universities, Inc. Washington DC, USA.
4// #
5// # This library is free software; you can redistribute it and/or modify it
6// # under the terms of the GNU Library General Public License as published by
7// # the Free Software Foundation; either version 2 of the License, or (at your
8// # option) any later version.
9// #
10// # This library is distributed in the hope that it will be useful, but WITHOUT
11// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13// # License for more details.
14// #
15// # You should have received a copy of the GNU Library General Public License
16// # along with this library; if not, write to the Free Software Foundation,
17// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18// #
19// # Correspondence concerning AIPS++ should be addressed as follows:
20// # Internet email: casa-feedback@nrao.edu.
21// # Postal address: AIPS++ Project Office
22// # National Radio Astronomy Observatory
23// # 520 Edgemont Road
24// # Charlottesville, VA 22903-2475 USA
25
26#ifndef TABLES_UDFBASE_H
27#define TABLES_UDFBASE_H
28
29// # Includes
30#include <casacore/casa/aips.h>
31#include <casacore/tables/TaQL/ExprNodeRep.h>
32#include <casacore/tables/Tables/Table.h>
33#include <casacore/tables/TaQL/TaQLStyle.h>
34#include <casacore/casa/Containers/Record.h>
35#include <casacore/casa/Containers/Block.h>
36#include <casacore/casa/stdmap.h>
37
38namespace casacore {
39
40// <summary>
41// Abstract base class for a user-defined TaQL function
42// </summary>
43//
44// <synopsis>
45// This class makes it possible to add user-defined functions (UDF) to TaQL.
46// A UDF has to be implemented in a class derived from this class and can
47// contain one or more user-defined functions.
48// <br>A few functions have to be implemented in the class as described below.
49// In this way TaQL can be extended with arbitrary functions, which can be
50// normal functions as well as aggregate functions (often used with GROUPBY).
51//
52// A UDF is a class derived from this base class. It must contain the
53// following member functions. See also the example below.
54// <table border=0>
55// <tr>
56// <td><src>makeObject</src></td>
57// <td>a static function to create an object of the UDF class. This function
58// needs to be registered.
59// </td>
60// </tr>
61// <tr>
62// <td><src>setup</src></td>
63// <td>this virtual function is called after the object has been created.
64// It should initialize the object using the function arguments that
65// can be obtained using the function <src>operands()</src>. The setup
66// function should perform the following:
67// <ul>
68// <li>Define the data type of the result using <src>setDataType<src>.
69// The data type should be derived from the data types of the function
70// arguments. The possible data types are defined in class
71// TableExprNodeRep.
72// Note that a UDF can support multiple data types. For example, a
73// function like <src>min</src> can be used for Int, Double, or a mix.
74// Function 'checkDT' in class TableExprNodeMulti can be used to
75// check the data types of the operands and determine the result
76// data type.
77// <li>Define if the function is an aggregate function calculating
78// an aggregated value in a group (e.g., minimum or mean).
79// <src>setAggregate</src> can be used to tell so.
80// <li>Define the dimensionality of the result using <src>setNDim</src>.
81// A value of 0 means a scalar. A value of -1 means an array with
82// a dimensionality that can vary from row to row.
83// <li>Optionally use <src>setShape</src> to define the shape if the
84// results are arrays with a shape that is the same for all rows.
85// It will also set ndim if setNDim was not used yet, otherwise
86// it checks if it ndim matches.
87// <li>Optionally set the unit of the result using <src>setUnit</src>.
88// TaQL has full support of units, so UDFs should behave the same.
89// It is possible to change the unit of the function arguments.
90// For example:
91// <ul>
92// <li>a function like 'sin' can force its argument to be
93// in radians; TaQL will scale the argument as needed. This can be
94// done like
95// <src>TableExprNodeUnit::adaptUnit (operands()[i], "rad");</src>
96// <li>A function like 'asin' will have a result in radians.
97// Such a UDF should set its result unit to rad.
98// <li>A function like 'min' wants its arguments to have the same
99// unit and will set its result unit to it. It can be done like:
100// <src>setUnit (TableExprFuncNode::makeEqualUnits
101// (operands(), 0, operands().size()));</src>
102// </ul>
103// See class TableExprFuncNode for more info about these functions.
104// <li>Optionally define attributes as a Record object. They can be used
105// by UDFs to tell something more about the type of value.
106// <li>Optionally define if the result is a constant value using
107// <src>setConstant</src>. It means that the function is not
108// dependent on the row number in the table being queried.
109// This is usually the case if all UDF arguments are constant.
110// </ul>
111// </td>
112// </tr>
113// <tr>
114// <td><src>getXXX</src></td>
115// <td>these are virtual get functions for each possible data type. The
116// get functions matching the data types set by the setup
117// function need to be implemented.
118// The <src>get</src> functions have an argument TableExprId
119// defining the table row (or record) for which the function has
120// to be evaluated.
121// If the UDF is an aggregate functions the TableExprId has to be
122// upcasted to an TableExprIdAggr object from which all TableExprId
123// objects in an aggregation group can be retrieved.
124// <srcblock>
125// const TableExprIdAggr& aid = TableExprIdAggr::cast (id);
126// const vector<TableExprId>& ids = aid.result().ids(id.rownr());
127// </srcblock>
128// </td>
129// </tr>
130// </table>
131//
132// A UDF has to be made known to TaQL by adding it to the UDF registry with
133// its name and 'makeObject' function.
134// UDFs will usually reside in a shared library that is loaded dynamically.
135// TaQL will load a UDF in the following way:
136// <ul>
137// <li> The UDF name used in TaQL consists of two parts: a library name
138// and a function name separated by a dot. Both parts need to be given.
139// Note that the library name can also be seen as a UDF scope, so
140// different UDFs with equal names can be used from different libraries.
141// A UDF should be registered with this full name.
142// <br>The "USING STYLE" clause can be used to define a synonym for
143// a (long) library name in the TaQLStyle object. The library part
144// of the UDF will always be looked up in this synonym map.
145// <li> If a UDF is not found in the registry, it will be tried to load
146// a shared library using the library name part. The libraries tried
147// to be loaded are lib<library>.so and libcasa_<library>.so.
148// On Mac .dylib will be tried. If loaded successfully, a special
149// function 'register_libname' will be called first. It should
150// register each UDF in the shared library using UDFBase::register.
151// </ul>
152// </synopsis>
153//
154// <example>
155// The following examples show a normal UDF function.
156// <br>It returns True if the function argument matches 1.
157// It can be seen that it checks if the argument is an integer scalar.
158// <srcblock>
159// class TestUDF: public UDFBase
160// {
161// public:
162// TestUDF() {}
163// // Registered function to create the UDF object.
164// // The name of the function is not important here.
165// static UDFBase* makeObject (const String&)
166// { return new TestUDF(); }
167// // Setup and check the details; result is a bool scalar value.
168// virtual void setup (const Table&, const TaQLStyle&)
169// {
170// AlwaysAssert (operands().size() == 1, AipsError);
171// AlwaysAssert (operands()[0]->dataType() == TableExprNodeRep::NTInt,
172// AipsError);
173// AlwaysAssert (operands()[0]->valueType() == TableExprNodeRep::VTScalar,
174// AipsError);
175// setDataType (TableExprNodeRep::NTBool);
176// setNDim (0); // scalar result
177// setConstant (operands()[0].isConstant()); // constant result?
178// }
179// // Get the value for the given id.
180// // It gets the value of the operand and checks if it is 1.
181// Bool getBool (const TableExprId& id)
182// { return operands()[0]->getInt(id) == 1; }
183// };
184// </srcblock>
185// </example>
186
187// <example>
188// The following example shows an aggregate UDF function.
189// It calculates the sum of the cubes of the values in a group.
190// <srcblock>
191// class TestUDFAggr: public UDFBase
192// {
193// public:
194// TestUDFAggr() {}
195// // Registered function to create the UDF object.
196// // The name of the function is not important here.
197// static UDFBase* makeObject (const String&) { return new TestUDFAggr(); }
198// // Setup and check the details; result is an integer scalar value.
199// // It aggregates the values of multiple rows.
200// virtual void setup (const Table&, const TaQLStyle&)
201// {
202// AlwaysAssert (operands().size() == 1, AipsError);
203// AlwaysAssert (operands()[0]->dataType() == TableExprNodeRep::NTInt, AipsError);
204// AlwaysAssert (operands()[0]->valueType() == TableExprNodeRep::VTScalar, AipsError);
205// setDataType (TableExprNodeRep::NTInt);
206// setNDim (0); // scalar
207// setAggregate (True); // aggregate function
208// }
209// // Get the value of a group.
210// // It aggregates the values of multiple rows.
211// Int64 getInt (const TableExprId& id)
212// {
213// // Cast the id to a TableExprIdAggr object.
214// const TableExprIdAggr& aid = TableExprIdAggr::cast (id);
215// // Get the vector of ids for this group.
216// const vector<TableExprId>& ids = aid.result().ids(id.rownr());
217// // Get the values for all ids and accumulate them.
218// Int64 sum3 = 0;
219// for (vector<TableExprId>::const_iterator it=ids.begin();
220// it!=ids.end(); ++it){
221// Int64 v = operands()[0]->getInt(*it);
222// sum3 += v*v*v;
223// }
224// return sum3;
225// }
226// };
227// </srcblock>
228// </example>
229// More examples of UDF functions can be found in classes UDFMSCal
230// and DirectionUDF.
231
232class UDFBase {
233 public:
234 // The signature of a global or static member function creating an object
235 // of the UDF.
236 typedef UDFBase* MakeUDFObject(const String& functionName);
237
238 // Only default constructor is needed.
240
241 // Destructor.
242 virtual ~UDFBase();
243
244 // Evaluate the function and return the result.
245 // Their default implementations throw a "not implemented" exception.
246 // <group>
247 virtual Bool getBool(const TableExprId& id);
248 virtual Int64 getInt(const TableExprId& id);
249 virtual Double getDouble(const TableExprId& id);
250 virtual DComplex getDComplex(const TableExprId& id);
251 virtual String getString(const TableExprId& id);
252 virtual TaqlRegex getRegex(const TableExprId& id);
253 virtual MVTime getDate(const TableExprId& id);
260 // </group>
261
262 // Get the unit.
263 const String& getUnit() const { return itsUnit; }
264
265 // Get the attributes.
266 const Record& getAttributes() const { return itsAttributes; }
267
268 // Flatten the node tree by adding the node and its children to the vector.
269 virtual void flattenTree(std::vector<TableExprNodeRep*>&);
270
271 private:
272 // Set up the function object.
273 virtual void setup(const Table& table, const TaQLStyle&) = 0;
274
275 protected:
276 // Get the operands.
277 std::vector<TENShPtr>& operands() { return itsOperands; }
278
279 // Set the data type.
280 // This function must be called by the setup function of the derived class.
282
283 // Set the dimensionality of the results.
284 // <br> 0 means that the results are scalars.
285 // <br> -1 means that the results are arrays with unknown dimensionality.
286 // <br> >0 means that the results are arrays with that dimensionality.
287 // This function must be called by the setup function of the derived class.
289
290 // Set the shape of the results if it is fixed and known.
292
293 // Set the unit of the result.
294 // If this function is not called by the setup function of the derived
295 // class, the result has no unit.
296 void setUnit(const String& unit);
297
298 // Set the attributes of the result.
299 // If this function is not called by the setup function of the derived
300 // class, the result has no attributes.
301 void setAttributes(const Record& attributes);
302
303 // Define if the result is constant (e.g. if all arguments are constant).
304 // If this function is not called by the setup function of the derived
305 // class, the result is not constant.
307
308 // Define if the UDF is an aggregate function (usually used in GROUPBY).
310
311 // Let a derived class recreate its column objects in case a selection
312 // has to be applied.
313 // The default implementation does nothing.
314 virtual void recreateColumnObjects(const Vector<rownr_t>& rownrs);
315
316 public:
317 // Register the name and construction function of a UDF (thread-safe).
318 // An exception is thrown if this name already exists with a different
319 // construction function.
320 static void registerUDF(const String& name, MakeUDFObject* func);
321
322 // Initialize the function object.
323 void init(const std::vector<TENShPtr>& arg, const TableExprInfo& tableInfo, const TaQLStyle&);
324
325 // Get the data type.
327
328 // Get the dimensionality of the results.
329 // (0=scalar, -1=array with variable ndim, >0=array with fixed ndim
330 Int ndim() const { return itsNDim; }
331
332 // Get the result shape if the same for all results.
333 const IPosition& shape() const { return itsShape; }
334
335 // Tell if the UDF gives a constant result.
336 Bool isConstant() const { return itsIsConstant; }
337
338 // Tell if the UDF is an aggregate function.
339 Bool isAggregate() const { return itsIsAggregate; }
340
341 // Do not apply the selection.
343
344 // If needed, let the UDF re-create column objects for a selection of rows.
345 // It calls the function recreateColumnObjects.
346 void applySelection(const Vector<rownr_t>& rownrs);
347
348 // Create a UDF object (thread-safe).
349 // It looks in the map with fixed function names. If unknown,
350 // it looks if a wildcarded function name is supported (for PyTaQL).
351 static UDFBase* createUDF(const String& name, const TaQLStyle& style);
352
353 private:
354 // # Data members.
355 std::vector<TENShPtr> itsOperands;
364 // # The registry is used for two purposes:
365 // # 1. It is a map of known function names (lib.func) to funcptr.
366 // # Function name * means that the library can contain any function,
367 // # which is intended for python functions (through PyTaQL).
368 // # 2. The loaded libraries are kept in the map (with 0 funcptr).
370 static std::recursive_mutex theirMutex;
371};
372
373} // namespace casacore
374
375#endif
String: the storage and methods of handling collections of characters.
Definition String.h:355
Class to connect a Table and its alias name.
NodeDataType
Define the data types of a node.
virtual MArray< MVTime > getArrayDate(const TableExprId &id)
virtual MArray< Int64 > getArrayInt(const TableExprId &id)
virtual Double getDouble(const TableExprId &id)
const Record & getAttributes() const
Get the attributes.
Definition UDFBase.h:266
const String & getUnit() const
Get the unit.
Definition UDFBase.h:263
IPosition itsShape
Definition UDFBase.h:358
TableExprNodeRep::NodeDataType itsDataType
Definition UDFBase.h:356
void setAttributes(const Record &attributes)
Set the attributes of the result.
void init(const std::vector< TENShPtr > &arg, const TableExprInfo &tableInfo, const TaQLStyle &)
Initialize the function object.
std::vector< TENShPtr > & operands()
Get the operands.
Definition UDFBase.h:277
void setDataType(TableExprNodeRep::NodeDataType)
Set the data type.
virtual Int64 getInt(const TableExprId &id)
TableExprNodeRep::NodeDataType dataType() const
Get the data type.
Definition UDFBase.h:326
virtual MVTime getDate(const TableExprId &id)
Bool itsApplySelection
Definition UDFBase.h:363
virtual TaqlRegex getRegex(const TableExprId &id)
UDFBase * MakeUDFObject(const String &functionName)
The signature of a global or static member function creating an object of the UDF.
Definition UDFBase.h:236
void applySelection(const Vector< rownr_t > &rownrs)
If needed, let the UDF re-create column objects for a selection of rows.
Int ndim() const
Get the dimensionality of the results.
Definition UDFBase.h:330
void setAggregate(Bool isAggregate)
Define if the UDF is an aggregate function (usually used in GROUPBY).
Bool isAggregate() const
Tell if the UDF is an aggregate function.
Definition UDFBase.h:339
void setUnit(const String &unit)
Set the unit of the result.
virtual void recreateColumnObjects(const Vector< rownr_t > &rownrs)
Let a derived class recreate its column objects in case a selection has to be applied.
std::vector< TENShPtr > itsOperands
Definition UDFBase.h:355
virtual MArray< DComplex > getArrayDComplex(const TableExprId &id)
UDFBase()
Only default constructor is needed.
static UDFBase * createUDF(const String &name, const TaQLStyle &style)
Create a UDF object (thread-safe).
virtual Bool getBool(const TableExprId &id)
Evaluate the function and return the result.
virtual DComplex getDComplex(const TableExprId &id)
void setConstant(Bool isConstant)
Define if the result is constant (e.g.
const IPosition & shape() const
Get the result shape if the same for all results.
Definition UDFBase.h:333
void setNDim(Int ndim)
Set the dimensionality of the results.
virtual void flattenTree(std::vector< TableExprNodeRep * > &)
Flatten the node tree by adding the node and its children to the vector.
static std::recursive_mutex theirMutex
Definition UDFBase.h:370
virtual MArray< Double > getArrayDouble(const TableExprId &id)
virtual ~UDFBase()
Destructor.
Record itsAttributes
Definition UDFBase.h:360
static map< String, MakeUDFObject * > theirRegistry
Definition UDFBase.h:369
Bool isConstant() const
Tell if the UDF gives a constant result.
Definition UDFBase.h:336
void disableApplySelection()
Do not apply the selection.
Definition UDFBase.h:342
virtual String getString(const TableExprId &id)
static void registerUDF(const String &name, MakeUDFObject *func)
Register the name and construction function of a UDF (thread-safe).
virtual MArray< String > getArrayString(const TableExprId &id)
void setShape(const IPosition &shape)
Set the shape of the results if it is fixed and known.
virtual MArray< Bool > getArrayBool(const TableExprId &id)
virtual void setup(const Table &table, const TaQLStyle &)=0
Set up the function object.
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
LatticeExprNode arg(const LatticeExprNode &expr)
long long Int64
Define the extra non-standard types used by Casacore (like proposed uSize, Size).
Definition aipsxtype.h:36
String name() const
Return the name of the field.
int Int
Definition aipstype.h:48
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
double Double
Definition aipstype.h:53