casa  5.7.0-16
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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: aips2-request@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 //# $Id: UDFBase.h 21262 2012-09-07 12:38:36Z gervandiepen $
27 
28 #ifndef TABLES_UDFBASE_H
29 #define TABLES_UDFBASE_H
30 
31 //# Includes
32 #include <casacore/casa/aips.h>
38 #include <casacore/casa/OS/Mutex.h>
39 #include <casacore/casa/stdmap.h>
40 
41 
42 namespace casacore {
43 
44  // <summary>
45  // Abstract base class for a user-defined TaQL function
46  // </summary>
47  //
48  // <synopsis>
49  // This class makes it possible to add user-defined functions (UDF) to TaQL.
50  // A UDF has to be implemented in a class derived from this class and can
51  // contain one or more user-defined functions.
52  // <br>A few functions have to be implemented in the class as described below.
53  // In this way TaQL can be extended with arbitrary functions, which can be
54  // normal functions as well as aggregate functions (often used with GROUPBY).
55  //
56  // A UDF is a class derived from this base class. It must contain the
57  // following member functions. See also the example below.
58  // <table border=0>
59  // <tr>
60  // <td><src>makeObject</src></td>
61  // <td>a static function to create an object of the UDF class. This function
62  // needs to be registered.
63  // </td>
64  // </tr>
65  // <tr>
66  // <td><src>setup</src></td>
67  // <td>this virtual function is called after the object has been created.
68  // It should initialize the object using the function arguments that
69  // can be obtained using the function <src>operands()</src>. The setup
70  // function should perform the following:
71  // <ul>
72  // <li>Define the data type of the result using <src>setDataType<src>.
73  // The data type should be derived from the data types of the function
74  // arguments. The possible data types are defined in class
75  // TableExprNodeRep.
76  // Note that a UDF can support multiple data types. For example, a
77  // function like <src>min</src> can be used for Int, Double, or a mix.
78  // Function 'checkDT' in class TableExprNodeMulti can be used to
79  // check the data types of the operands and determine the result
80  // data type.
81  // <li>Define if the function is an aggregate function calculating
82  // an aggregated value in a group (e.g., minimum or mean).
83  // <src>setAggregate</src> can be used to tell so.
84  // <li>Define the dimensionality of the result using <src>setNDim</src>.
85  // A value of 0 means a scalar. A value of -1 means an array with
86  // a dimensionality that can vary from row to row.
87  // <li>Optionally use <src>setShape</src> to define the shape if the
88  // results are arrays with a shape that is the same for all rows.
89  // It will also set ndim if setNDim was not used yet, otherwise
90  // it checks if it ndim matches.
91  // <li>Optionally set the unit of the result using <src>setUnit</src>.
92  // TaQL has full support of units, so UDFs should behave the same.
93  // It is possible to change the unit of the function arguments.
94  // For example:
95  // <ul>
96  // <li>a function like 'sin' can force its argument to be
97  // in radians; TaQL will scale the argument as needed. This can be
98  // done like
99  // <src>TableExprNodeUnit::adaptUnit (operands()[i], "rad");</src>
100  // <li>A function like 'asin' will have a result in radians.
101  // Such a UDF should set its result unit to rad.
102  // <li>A function like 'min' wants its arguments to have the same
103  // unit and will set its result unit to it. It can be done like:
104  // <src>setUnit (TableExprFuncNode::makeEqualUnits
105  // (operands(), 0, operands().size()));</src>
106  // </ul>
107  // See class TableExprFuncNode for more info about these functions.
108  // <li>Optionally define attributes as a Record object. They can be used
109  // by UDFs to tell something more about the type of value.
110  // <li>Optionally define if the result is a constant value using
111  // <src>setConstant</src>. It means that the function is not
112  // dependent on the row number in the table being queried.
113  // This is usually the case if all UDF arguments are constant.
114  // </ul>
115  // </td>
116  // </tr>
117  // <tr>
118  // <td><src>getXXX</src></td>
119  // <td>these are virtual get functions for each possible data type. The
120  // get functions matching the data types set by the setup
121  // function need to be implemented.
122  // The <src>get</src> functions have an argument TableExprId
123  // defining the table row (or record) for which the function has
124  // to be evaluated.
125  // If the UDF is an aggregate functions the TableExprId has to be
126  // upcasted to an TableExprIdAggr object from which all TableExprId
127  // objects in an aggregation group can be retrieved.
128  // <srcblock>
129  // const TableExprIdAggr& aid = TableExprIdAggr::cast (id);
130  // const vector<TableExprId>& ids = aid.result().ids(id.rownr());
131  // </srcblock>
132  // </td>
133  // </tr>
134  // </table>
135  //
136  // A UDF has to be made known to TaQL by adding it to the UDF registry with
137  // its name and 'makeObject' function.
138  // UDFs will usually reside in a shared library that is loaded dynamically.
139  // TaQL will load a UDF in the following way:
140  // <ul>
141  // <li> The UDF name used in TaQL consists of two parts: a library name
142  // and a function name separated by a dot. Both parts need to be given.
143  // Note that the library name can also be seen as a UDF scope, so
144  // different UDFs with equal names can be used from different libraries.
145  // A UDF should be registered with this full name.
146  // <br>The "USING STYLE" clause can be used to define a synonym for
147  // a (long) library name in the TaQLStyle object. The library part
148  // of the UDF will always be looked up in this synonym map.
149  // <li> If a UDF is not found in the registry, it will be tried to load
150  // a shared library using the library name part. The libraries tried
151  // to be loaded are lib<library>.so and libcasa_<library>.so.
152  // On Mac .dylib will be tried. If loaded successfully, a special
153  // function 'register_libname' will be called first. It should
154  // register each UDF in the shared library using UDFBase::register.
155  // </ul>
156  // </synopsis>
157  //
158  // <example>
159  // The following examples show a normal UDF function.
160  // <br>It returns True if the function argument matches 1.
161  // It can be seen that it checks if the argument is an integer scalar.
162  // <srcblock>
163  // class TestUDF: public UDFBase
164  // {
165  // public:
166  // TestUDF() {}
167  // // Registered function to create the UDF object.
168  // // The name of the function is not important here.
169  // static UDFBase* makeObject (const String&)
170  // { return new TestUDF(); }
171  // // Setup and check the details; result is a bool scalar value.
172  // virtual void setup (const Table&, const TaQLStyle&)
173  // {
174  // AlwaysAssert (operands().size() == 1, AipsError);
175  // AlwaysAssert (operands()[0]->dataType() == TableExprNodeRep::NTInt,
176  // AipsError);
177  // AlwaysAssert (operands()[0]->valueType() == TableExprNodeRep::VTScalar,
178  // AipsError);
179  // setDataType (TableExprNodeRep::NTBool);
180  // setNDim (0); // scalar result
181  // setConstant (operands()[0].isConstant()); // constant result?
182  // }
183  // // Get the value for the given id.
184  // // It gets the value of the operand and checks if it is 1.
185  // Bool getBool (const TableExprId& id)
186  // { return operands()[0]->getInt(id) == 1; }
187  // };
188  // </srcblock>
189  // </example>
190 
191  // <example>
192  // The following example shows an aggregate UDF function.
193  // It calculates the sum of the cubes of the values in a group.
194  // <srcblock>
195  // class TestUDFAggr: public UDFBase
196  // {
197  // public:
198  // TestUDFAggr() {}
199  // // Registered function to create the UDF object.
200  // // The name of the function is not important here.
201  // static UDFBase* makeObject (const String&) { return new TestUDFAggr(); }
202  // // Setup and check the details; result is an integer scalar value.
203  // // It aggregates the values of multiple rows.
204  // virtual void setup (const Table&, const TaQLStyle&)
205  // {
206  // AlwaysAssert (operands().size() == 1, AipsError);
207  // AlwaysAssert (operands()[0]->dataType() == TableExprNodeRep::NTInt, AipsError);
208  // AlwaysAssert (operands()[0]->valueType() == TableExprNodeRep::VTScalar, AipsError);
209  // setDataType (TableExprNodeRep::NTInt);
210  // setNDim (0); // scalar
211  // setAggregate (True); // aggregate function
212  // }
213  // // Get the value of a group.
214  // // It aggregates the values of multiple rows.
215  // Int64 getInt (const TableExprId& id)
216  // {
217  // // Cast the id to a TableExprIdAggr object.
218  // const TableExprIdAggr& aid = TableExprIdAggr::cast (id);
219  // // Get the vector of ids for this group.
220  // const vector<TableExprId>& ids = aid.result().ids(id.rownr());
221  // // Get the values for all ids and accumulate them.
222  // Int64 sum3 = 0;
223  // for (vector<TableExprId>::const_iterator it=ids.begin();
224  // it!=ids.end(); ++it){
225  // Int64 v = operands()[0]->getInt(*it);
226  // sum3 += v*v*v;
227  // }
228  // return sum3;
229  // }
230  // };
231  // </srcblock>
232  // </example>
233  // More examples of UDF functions can be found in classes UDFMSCal
234  // and DirectionUDF.
235 
236  class UDFBase
237  {
238  public:
239  // The signature of a global or static member function creating an object
240  // of the UDF.
241  typedef UDFBase* MakeUDFObject (const String& functionName);
242 
243  // Only default constructor is needed.
244  UDFBase();
245 
246  // Destructor.
247  virtual ~UDFBase();
248 
249  // Evaluate the function and return the result.
250  // Their default implementations throw a "not implemented" exception.
251  // <group>
252  virtual Bool getBool (const TableExprId& id);
253  virtual Int64 getInt (const TableExprId& id);
254  virtual Double getDouble (const TableExprId& id);
255  virtual DComplex getDComplex (const TableExprId& id);
256  virtual String getString (const TableExprId& id);
257  virtual TaqlRegex getRegex (const TableExprId& id);
258  virtual MVTime getDate (const TableExprId& id);
259  virtual MArray<Bool> getArrayBool (const TableExprId& id);
260  virtual MArray<Int64> getArrayInt (const TableExprId& id);
261  virtual MArray<Double> getArrayDouble (const TableExprId& id);
262  virtual MArray<DComplex> getArrayDComplex (const TableExprId& id);
263  virtual MArray<String> getArrayString (const TableExprId& id);
264  virtual MArray<MVTime> getArrayDate (const TableExprId& id);
265  // </group>
266 
267  // Get the unit.
268  const String& getUnit() const
269  { return itsUnit; }
270 
271  // Get the attributes.
272  const Record& getAttributes() const
273  { return itsAttributes; }
274 
275  // Get the nodes in the function operands representing an aggregate function.
276  void getAggrNodes (vector<TableExprNodeRep*>& aggr);
277 
278  // Get the nodes in the function operands representing a table column.
279  void getColumnNodes (vector<TableExprNodeRep*>& cols);
280 
281  private:
282  // Set up the function object.
283  virtual void setup (const Table& table,
284  const TaQLStyle&) = 0;
285 
286  protected:
287  // Get the operands.
288  std::vector<TENShPtr>& operands()
289  { return itsOperands; }
290 
291  // Set the data type.
292  // This function must be called by the setup function of the derived class.
294 
295  // Set the dimensionality of the results.
296  // <br> 0 means that the results are scalars.
297  // <br> -1 means that the results are arrays with unknown dimensionality.
298  // <br> >0 means that the results are arrays with that dimensionality.
299  // This function must be called by the setup function of the derived class.
300  void setNDim (Int ndim);
301 
302  // Set the shape of the results if it is fixed and known.
303  void setShape (const IPosition& shape);
304 
305  // Set the unit of the result.
306  // If this function is not called by the setup function of the derived
307  // class, the result has no unit.
308  void setUnit (const String& unit);
309 
310  // Set the attributes of the result.
311  // If this function is not called by the setup function of the derived
312  // class, the result has no attributes.
313  void setAttributes (const Record& attributes);
314 
315  // Define if the result is constant (e.g. if all arguments are constant).
316  // If this function is not called by the setup function of the derived
317  // class, the result is not constant.
318  void setConstant (Bool isConstant);
319 
320  // Define if the UDF is an aggregate function (usually used in GROUPBY).
322 
323  // Let a derived class recreate its column objects in case a selection
324  // has to be applied.
325  // The default implementation does nothing.
326  virtual void recreateColumnObjects (const Vector<uInt>& rownrs);
327 
328  public:
329  // Register the name and construction function of a UDF (thread-safe).
330  // An exception is thrown if this name already exists with a different
331  // construction function.
332  static void registerUDF (const String& name, MakeUDFObject* func);
333 
334  // Initialize the function object.
335  void init (const std::vector<TENShPtr>& arg,
336  const Table& table, const TaQLStyle&);
337 
338  // Get the data type.
340  { return itsDataType; }
341 
342  // Get the dimensionality of the results.
343  // (0=scalar, -1=array with variable ndim, >0=array with fixed ndim
344  Int ndim() const
345  { return itsNDim; }
346 
347  // Get the result shape if the same for all results.
348  const IPosition& shape() const
349  { return itsShape; }
350 
351  // Tell if the UDF gives a constant result.
352  Bool isConstant() const
353  { return itsIsConstant; }
354 
355  // Tell if the UDF is an aggregate function.
357  { return itsIsAggregate; }
358 
359  // Do not apply the selection.
361  { itsApplySelection = False; }
362 
363  // If needed, let the UDF re-create column objects for a selection of rows.
364  // It calls the function recreateColumnObjects.
365  void applySelection (const Vector<uInt>& rownrs);
366 
367  // Create a UDF object (thread-safe).
368  // It looks in the map with fixed function names. If unknown,
369  // it looks if a wildcarded function name is supported (for PyTaQL).
370  static UDFBase* createUDF (const String& name, const TaQLStyle& style);
371 
372  private:
373  //# Data members.
374  std::vector<TENShPtr> itsOperands;
383  //# The registry is used for two purposes:
384  //# 1. It is a map of known function names (lib.func) to funcptr.
385  //# Function name * means that the library can contain any function,
386  //# which is intended for python functions (through PyTaQL).
387  //# 2. The loaded libraries are kept in the map (with 0 funcptr).
388  static map<String, MakeUDFObject*> theirRegistry;
390  };
391 
392 } // end namespace
393 
394 #endif
A Vector of integers, for indexing into Array&lt;T&gt; objects.
Definition: IPosition.h:119
void setUnit(const String &unit)
Set the unit of the result.
virtual MVTime getDate(const TableExprId &id)
virtual MArray< Bool > getArrayBool(const TableExprId &id)
long long Int64
Define the extra non-standard types used by Casacore (like proposed uSize, Size)
Definition: aipsxtype.h:38
int Int
Definition: aipstype.h:50
LatticeExprNode arg(const LatticeExprNode &expr)
void setNDim(Int ndim)
Set the dimensionality of the results.
Bool itsIsAggregate
Definition: UDFBase.h:381
Main interface class to a read/write table.
Definition: Table.h:153
virtual MArray< Double > getArrayDouble(const TableExprId &id)
TableExprNodeRep::NodeDataType itsDataType
Definition: UDFBase.h:375
void init(const std::vector< TENShPtr > &arg, const Table &table, const TaQLStyle &)
Initialize the function object.
UDFBase()
Only default constructor is needed.
void setAggregate(Bool isAggregate)
Define if the UDF is an aggregate function (usually used in GROUPBY).
virtual Bool getBool(const TableExprId &id)
Evaluate the function and return the result.
Abstract base class for a user-defined TaQL function.
Definition: UDFBase.h:236
Bool isAggregate() const
Tell if the UDF is an aggregate function.
Definition: UDFBase.h:356
NodeDataType
Define the data types of a node.
Definition: ExprNodeRep.h:161
virtual MArray< Int64 > getArrayInt(const TableExprId &id)
ABSTRACT CLASSES Abstract class for colors Any implementation of color should be able to provide a hexadecimal form of the if a human readable name(i.e."black").In many places throughout the plotter
virtual MArray< MVTime > getArrayDate(const TableExprId &id)
virtual MArray< DComplex > getArrayDComplex(const TableExprId &id)
const String & getUnit() const
Get the unit.
Definition: UDFBase.h:268
TableExprNodeRep::NodeDataType dataType() const
Get the data type.
Definition: UDFBase.h:339
static map< String, MakeUDFObject * > theirRegistry
Definition: UDFBase.h:388
void getAggrNodes(vector< TableExprNodeRep * > &aggr)
Get the nodes in the function operands representing an aggregate function.
void disableApplySelection()
Do not apply the selection.
Definition: UDFBase.h:360
String itsUnit
Definition: UDFBase.h:378
Int ndim() const
Get the dimensionality of the results.
Definition: UDFBase.h:344
const IPosition & shape() const
Get the result shape if the same for all results.
Definition: UDFBase.h:348
double Double
Definition: aipstype.h:55
void getColumnNodes(vector< TableExprNodeRep * > &cols)
Get the nodes in the function operands representing a table column.
Bool isConstant() const
Tell if the UDF gives a constant result.
Definition: UDFBase.h:352
Class with static members defining the TaQL style.
Definition: TaQLStyle.h:64
std::vector< TENShPtr > itsOperands
Definition: UDFBase.h:374
void setConstant(Bool isConstant)
Define if the result is constant (e.g.
void setAttributes(const Record &attributes)
Set the attributes of the result.
virtual ~UDFBase()
Destructor.
A hierarchical collection of named fields of various types.
Definition: Record.h:180
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
UDFBase * MakeUDFObject(const String &functionName)
The signature of a global or static member function creating an object of the UDF.
Definition: UDFBase.h:241
virtual void recreateColumnObjects(const Vector< uInt > &rownrs)
Let a derived class recreate its column objects in case a selection has to be applied.
virtual Int64 getInt(const TableExprId &id)
static Mutex theirMutex
Definition: UDFBase.h:389
const Bool False
Definition: aipstype.h:44
Bool itsApplySelection
Definition: UDFBase.h:382
virtual MArray< String > getArrayString(const TableExprId &id)
Wrapper around a pthreads mutex.
Definition: Mutex.h:58
Bool itsIsConstant
Definition: UDFBase.h:380
Record itsAttributes
Definition: UDFBase.h:379
IPosition itsShape
Definition: UDFBase.h:377
void setDataType(TableExprNodeRep::NodeDataType)
Set the data type.
void setShape(const IPosition &shape)
Set the shape of the results if it is fixed and known.
The identification of a TaQL selection subject.
Definition: TableExprId.h:97
const Record & getAttributes() const
Get the attributes.
Definition: UDFBase.h:272
Class to handle a Regex or StringDistance.
Definition: ExprNodeRep.h:81
String: the storage and methods of handling collections of characters.
Definition: String.h:223
std::vector< TENShPtr > & operands()
Get the operands.
Definition: UDFBase.h:288
static void registerUDF(const String &name, MakeUDFObject *func)
Register the name and construction function of a UDF (thread-safe).
virtual DComplex getDComplex(const TableExprId &id)
virtual String getString(const TableExprId &id)
Class to handle date/time type conversions and I/O.
Definition: MVTime.h:269
static UDFBase * createUDF(const String &name, const TaQLStyle &style)
Create a UDF object (thread-safe).
virtual Double getDouble(const TableExprId &id)
virtual TaqlRegex getRegex(const TableExprId &id)
virtual void setup(const Table &table, const TaQLStyle &)=0
Set up the function object.
void applySelection(const Vector< uInt > &rownrs)
If needed, let the UDF re-create column objects for a selection of rows.
#define casacore
&lt;X11/Intrinsic.h&gt; #defines true, false, casacore::Bool, and String.
Definition: X11Intrinsic.h:42