next up previous contents
Next: Time Series Handling Up: Some Functions and Methods Previous: Plug-in Interface   Contents

General Methods

The following methods can be used for any data object class derived from QdObject. In all cases QSAS works with a pointer class QdObject_var and other pointer classes derived from it. These pointer classes keep track of all references to the actual data object, and when an object is no longer in scope for any pointer the object is deleted. An object placed on the working list is always referenced by a _var pointer held by qsas and will remain accessible until deleted from the working list. Utility functions (see below) are provided to access objects on the Working List by name. It is forbidden to delete a qdos object as it self destructs when no-longer in use. For this reason all reference to an object should be through a _var pointer which is always safe, and creation of a new object must be either using the clone() operation or `new' on a _var pointer (see below).

$\bullet$
virtual bool is_nil(void), returns true if the QdObject_var pointer does not point to a valid QdObject. This will be the case if an object of the requested type cannot be created. e.g.
    #include "Qdos.h"
    QdObject_var obj;
    if( obj.is_nil() )return QPLUG_FAILURE;
Note that this is a method of the _var pointer class itself, and is thus accessed using `.' rather than `-$>$', and is safe even if the QdObject pointed to is NULL.
$\bullet$
bool is_empty(QdObject_var& obj), returns true if an object is a nil pointer, a zero element series, or a timeinterval of zero length. It is a utility call that can be used to trap results from operations that returned an essentially empty object, such as requesting a sub-interval that lies entirely within a data gap(A) e.g.
   #include "qplug_if.h"
   #include "Qdos.h"
   QdScalarSeq_var ts;
   ...
   if( is_empty(ts) ){
      QplugAppendTextDisplay("Operation gave an empty object\n");
      return QPLUG_WARNING;   
   }
Empty objects are trapped by qsas and will not be placed on the working list.
$\bullet$
new QdObject(). The syntax for creating a new QdObject will depend on the derived class being created, and details are provided later. It is important that when a new object is created it is the subject of a _var pointer of the correct class to ensure memory management is not compromised. A simple example is a sequence of Ndata scalar objects,
  #include "qplug_if.h"
  #include "Qdos.h"
  QdRScalarSeq_var out_rad_series  = new QdRScalarSeq(Ndata);
  for(int i=0; i<Ndata; i++){
    out_rad_series[i] = (double) i*0.01;
    // alternatively, out_rad_series[i] = QdRScalar(i*0.01);
  }
Note that this sequence is created as a sequence empty QdRScalar_var pointers, and each element of type QdScalar_var is created by the subsequent code using new with an argument of type double. A distinct QdScalar_var is created each iteration of the loop.
$\bullet$
Factory::clone(QdObject_var& obj) provides a generic method for producing a duplicate of any qdos object using the Factory class. A clone of an object contains a copy of the data, where possible, in the class requested. It always returns an object of the same type as the input object, but this may be assigned to a generic QdObject_var type. The xrefs (attributes) are not copied, and this must be done separately. e.g.
  #include "qplug_if.h"
  #include "QsasUtils.h"
  #include "Qdos.h"
  QdObject_var ts_out = Factory::clone(ts_in);
  if( ts_out.is_nil() ){
    QplugAppendTextDisplay("Unable to clone input sequence\n");
    return QPLUG_FAILURE;
  } 
   QdTimeSeq_var tt_out = 
                (QdTimeSeq_var) Factory::clone(get_timetags(ts_in));
  set_timetags(ts_out,tt_out)
Note that this example creates a new set of time tags for the new object, which would only normally be necessary if the time tags themselves were to be modified in any way.

If the new object must be of a specific type then clone may be used to explicitly return a new object of that type. The above example might have been...

  #include "qplug_if.h"
  #include "QsasUtils.h"
  #include "Qdos.h"

  QdRMatrixSeq_var ts_out = Factory::clone( QdRMatrixSeq_var::narrow(ts_in));
  if( ts_out.is_nil() ){
    QplugAppendTextDisplay("Input object not a Matrix sequence\n");
    return QPLUG_FAILURE;
  }

$\bullet$
QdObject_var::narrow(QdObject_var& obj), will return a _var pointer of the class requested if possible.
  #include "qplug_if.h"
  #include "Qdos.h"
  QdRMatrixSeq_var ts_out = QdRMatrixSeq_var::narrow(ts_in);
  if( ts_out.is_nil() ){
    QplugAppendTextDisplay("Input object not a Matrix sequence\n");
    return QPLUG_FAILURE;
  }
The original object is pointed to by this _var pointer, and differs from clone in that it does not create a new data object. It will succeed only if the target is of the class requested. For example, a QdRMatrix_var cannot be narrowed to a QdRMatrixSeq_var, and vice versa.

$\bullet$
QdObject_var QuGetObjByName(char * name) returns a _var pointer to an object held on the working list as `name'.

  #include "qplug_if.h"
  #include "QdUtils.h"
  #include "Qdos.h"
  QdObject_var obj = QuGetObjByName("B_mag")
  if ( obj.is_nil() ) return QPLUG_FAILURE;

The pointer is NULL if no object of the specified name can be found.(U)

$\bullet$
virtual bool is_sequence(void) returns true if the object is a sequence. This utility call is used to allow a plug-in to conditionally change between a sequence of objects or a single object.
  #include "qplug_if.h"
  #include "Qdos.h"
  QdObject_var obj;
  if(obj->is_sequence()){...}
  else {...}
It is of most use if the plug-in does not at this point need to know what type of objects the sequence contains; it is usually more efficient to narrow to the required sequence or object type directly and test is_nil().

$\bullet$
int sequence_size(void) returns the number of elements in a sequence.
  #include "qplug_if.h"
  #include "Qdos.h"
  QdObject_var obj;
  int Ndata = obj->sequence_size();
This method also works for any QdObject class and returns 1 in the case of a single object. The standard method size() will also work for the number of objects in a sequence, but fails for non-sequence type data objects.

$\bullet$
bool QuConformal (QdObject_var do1, QdObject_var do2), returns true if the input series have the same number of entries and have the same time tags (if time series).
  #include "qplug_if.h"
  #include "QdUtils.h"
  #include "QsasUtils.h"
  #include "Qdos.h"
  using namespace QSAS;
  QdRMatrixSeq_var out_ts;
  if(QuConformal (ts1,ts2)){
    try{
      out_ts = new QdRMatrixSeq(ts1 + ts2);
    }
    catch(Exception &e){
       e.print_msg();
       return QPLUG_FAILURE;   
    }
    QdTimeSeq_var tags = get_timetags(ts1);
    if (!tags.is_nil())  set_timetags(out_ts, tags);      
  }
This utility is only for use with sequence types and returns false if either input is not a sequence. Note that in this example we attach the original time tags to the new output series. If the original series is removed from the working list the time tags remain accessible so long as any object has a xref referencing them.(U)

$\bullet$
bool QarTestConformal (QdObject_var do1, QdObject_var do2)
returns true if the input series have the same number of entries and have the same time tags (if time series), but also returns true if either object has a single entry to permit operations between a sequence and a constant. This test is advised before all arithmetic operations for time series data since the underlying qdos methods only test that the operation is well defined for the inputs. qdos methods do not test metadata, and in particular do not compare time lines.
  #include "qplug_if.h"
  #include "QdUtils.h"
  #include "QsasUtils.h"
  #include "Qdos.h"
  #include "qar.h"
  using namespace QSAS;
  QdRMatrix_var Const = QdRMatrix::narrow(ts2);
  QdRMatrixSeq_var out_ts;
  if(QarTestConformal (ts1,Const)){
    try{
      out_ts = new QdRMatrixSeq(ts1 + Const);
    }
    catch(Exception &e){
       e.print_msg();
       return QPLUG_FAILURE;   
    }
    QdTimeSeq_var tags = get_timetags(ts1);
    if (!tags.is_nil())  set_timetags(out_ts, tags);      
  }
This is a more tolerant test than QuConformal() and will permit operations between a single object and a sequence or between two sequences. If the objects are both time series, the time tags are tested to ensure either the same object is used as TIME_TAGS xref, or that tags are identical to near msec accuracy.


next up previous contents
Next: Time Series Handling Up: Some Functions and Methods Previous: Plug-in Interface   Contents
Anthony Allen 2005-11-07