Version 3 (modified by 14 years ago) ( diff ) | ,
---|
How To Implement New Filler
Concept
The Filler is only responsible for filling Scantable. It does not have a direct access to the data file. Retrieving various information from the data is done by Reader class, which is separated from the Filler. The Filler has appropriate Reader object that depends on type of the data file. The Filler does the following things:
- set target Scantable
- open data file (via Reader object)
- get information from the Reader object
- fill Scantable
- close data file (via Reader object)
The target Scantable must be prepared outside the Filler and should be passed to the Filler at the beginning of filling process. It should be empty.
The filling process goes on row-by-row manner. It means that the filling is actually an iteration process over all rows. The process contains:
- get information for one row from the Reader object
- fill row
- add row to Scantable
Design
The FillerBase class is defined as the above description. All Filler classes must inherit this class. Constructor of the class takes Scantable object as its argument. The Scantable given will be filled by the Filler. The FillerBase is an abstract class that have three pure abstract methods:
- open() --- open data file (via Reader object)
- fill() --- get information from the Reader object, and fill Scantable
- close() --- close data file (via Reader object)
These methods must be implemented in the derived classes.
The FillerBase is designed to fill Scantable in row-by-row manner. To do this, it has an attribute that represents a single row of the main table in Scantable. The fill() method should 1) fill that row and 2) add that row to target Scantable over all rows. The FillerBase implements common methods that help to implement fill() method.
- setHeader() --- fill header
- 'setter' methods for cells --- fill certain cells in the current row
- setIndex() --- fill SCANNO, CYCLENO, IFNO, POLNO, and BEAMNO
- setSpectrum() --- fill SPECTRA, FLAGTRA, and TSYS
- setFlagrow() --- fill FLAGROW
- setDirection() --- fill DIRECTION, AZIMUTH, and ELEVATION
- setTime() --- fill TIME and INTERVAL
- setReferenceBeam() --- fill REFBEAMNO
- setSource() --- fill SRCNAME, SRCTYPE, FIELDNAME, SRCDIRECTION, SRCPROPERMOTION, and SRCVELOCITY
- setScanRate() --- fill SCANRATE
- setOpacity() --- fill OPACITY
- setFrequency() --- add row to FREQUENCIES subtable if necessary, and fill FREQ_ID
- setMolecule() --- add row to MOLECULES subtable if necessary, and fill MOLECULE_ID
- setFocus() --- add row to FOCUS subtable if necessary, and fill FOCUS_ID
- setWeather() --- add row to WEATHER subtable if necessary, and fill WEATHER_ID
- setTcal() --- add row to TCAL subtable if necessary, and fill TCAL_ID
- commitRow() --- add row to Scantable
The 'setter' methods including setHeader() method take some arguments that is used to fill corresponding cells. Some arguments have their default values. It means that the corresponding cell is an optional one that may not be given explicitly. On the other hand, cells without default values are mandatory. Their values must be given explicitly.
Implementation
To define new filler, you should go through the following steps:
1. define your filler as a derived class of FillerBase
class MyFiller : public FillerBase { ... };
2. define constructor
Default constructor and copy constructor should be disabled from outside. So, they should be explicitly declared in the private section. The only public constructor is the one that takes Scantable object as its argument.
class MyFiller : public FillerBase { public: MyFiller( CountedPtr<Scantable> stable ); ... private: MyFiller(); MyFiller( const MyFiller& ); MyFiller &operator=( const MyFiller& ); ... };
You probably need to have Reader object as an attribute.
class MyFiller : public FillerBase { public: MyFiller( CountedPtr<Scantable> stable ); ... private: CountedPtr<MyReader> reader_; MyFiller(); MyFiller( const MyFiller& ); MyFiller &operator=( const MyFiller& ); ... };
At least, the constructor must call the constructor of FillerBase class.
MyFiller::MyFiller( CountedPtr<Scantable> stable ) : FillerBase( stable ) { ... }
The constructor of FillerBase class sets Scantable object given as a target.
3. implement open() method
You must implement open() method that gets an access to the data file. In almost case, it will be realized by the open() method of Reader object. You can call setHeader() to fill header of target Scantable.
bool MyFiller::open( const string &filename ) { ... // open file if ( reader_->open( filename ) ) { return False ; } ... // get header information ... // set header setHeader( header ) ; }
The header variable must be set in the method.
4. implement fill() method
You must implement fill() method that performs 1) to fill row and 2) to add row to target Scantable. As mentioned above, a lot of useful methods are available.
void MyFiller::fill() { // get row information // e.g. reader_->read(...) ; ... // loop on all rows for ( int i = 0 ; i < nrow ; i++ ) { // fill row setIndex( ... ) ; setSpectrum( ... ) ; setFlagrow( ... ) ; setDirection( ... ) ; setTime( ... ) ; setReferenceBeam( ... ) ; setSource( ... ) ; setScanRate( ... ) ; setOpacity( ... ) ; setFrequency( ... ) ; setMolecule( ... ) ; setFocus( ... ) ; setWeather( ... ) ; setTcal( ... ) ; // add row commitRow() ; } }
5. implement close() method
You must implement close() method. Normally, it just closes the file.
void MyFiller::close() { if ( reader_.null() != False ) { reader_ = 0 ; } table_ = 0 ; }
In this example, the method doesn't close the file explicitly. Instead, the file is closed when the Reader object is destructed.
Miscellaneous
See existing Filler implementation (PKSFiller, NROFiller) for more detail.