// ---------------------------------------------------------------------- // // HepNtuple-read.cc - implementation of generic HepNtuple; routine // associated with reading data already stored. // // // HepNtuple a generic Ntuple. // Its final implementation is defined by a manager class/ // histogram subclass. HepNtuple provides methods for filling an Ntuple // histogram and retreiving information from and about it. // // The following methods are in this file // destinationAt // destinationVia (functions and methods) // blockDestinations #include "HepTuple/HepNtuple.h" #include "HepTuple/Column.h" #include "HepTuple/ColumnT.h" #include "HepTuple/Block.h" #include "HepTuple/TupleNameTag.h" #include "ZMtools/pretendToUse.h" #include USING( std::string ) ZM_BEGIN_NAMESPACE( zmht ) /* namespace zmht { */ // ---------------------------------------------------------------------- // getColumnT // // Static function that return a columnT corresponding to nametag and // set it to be the current column in hep // // It will throw an exception if the nametag is wrong and return NULL // if the column does not exist and/or is of the wrong type // ---------------------------------------------------------------------- template static ColumnT* getColumnT(const string& nametag,HepNtuple *hep,T fortype) { // Declare a nametag as specified. Check if the syntax is valid, // throw an exception and return false if it isn't. TupleNameTag tag; hep->parseNameTag( tag, nametag); if ( !tag.isValid() ) { ZMthrow ( ZMxHepUnknownColumn (string("Improper form for column name tag: ") +nametag) ); return NULL; } // Declare a pointer to the column with the given nametag. Column * c = hep->findColumn(nametag); if ( !c ) { ZMthrow ( ZMxHepUnknownColumn (string("No column with the tag: ") +nametag+" in "+hep->title()) ); return NULL; } // Make sure we have a proper type match and bail out if not. if (!c->checkType(T())) { ZMthrow( ZMxHepTypeMismatch( (string("Improper type for column name tag: ") +nametag) ) ); return NULL; } ColumnT * ct = (ColumnT *) c; // Tell the manager that this is the "current column" ... hep->setCurrentColumn(c); return ct; } #ifdef NEVER // The following is necessary because of a what seems to be a bug in gcc // It was unable to know that it should instantiate a template function // used inside a template function (addNewColumnF in newColumnF). #define getColumnT_User_MACRO(TYPE) \ static void getColumnT_User (TYPE f) { \ TYPE a = 0; \ getColumnT(string("Dummy Name"),(HepNtuple*)NULL,a);\ } getColumnT_User_MACRO ( Int1 ) getColumnT_User_MACRO ( Int2 ) getColumnT_User_MACRO ( Int4 ) #ifdef Int8 getColumnT_User_MACRO ( Int8 ) #endif getColumnT_User_MACRO ( Float4 ) getColumnT_User_MACRO ( Float8 ) #ifdef Float16 getColumnT_User_MACRO ( Float16 ) #endif getColumnT_User_MACRO ( bool) getColumnT_User_MACRO ( void*) // Added 1 Dec. 2001 JMM void HepNtuple::silenceCompiler() { { void (*p)(signed char) = getColumnT_User; pretendToUse(p); } { void (*p)(short int) = getColumnT_User; pretendToUse(p); } { void (*p)(int) = getColumnT_User; pretendToUse(p); } #ifdef Int8 { void (*p)(long int) = getColumnT_User; pretendToUse(p); } #endif { void (*p)(float) = getColumnT_User; pretendToUse(p); } { void (*p)(double) = getColumnT_User; pretendToUse(p); } #ifdef Float16 { void (*p)(long double) = getColumnT_User; pretendToUse(p); } #endif { void (*p)(bool) = getColumnT_User; pretendToUse(p); } { void (*p)(void*) = getColumnT_User; pretendToUse(p); } } #endif // ---------------------------------------------------------------------- // destinationAt // // Set the destination variable when one row of the column is read // back // ---------------------------------------------------------------------- template static bool destinationAtTmpl ( const string& nametag, T* address, HepNtuple* hep) { ColumnT *ct = getColumnT( nametag, hep, T() ); if ( ct == NULL ) { return false; } return ct->setDestinationVariable(address); } #define destinationAtMacro(TYPE) \ HepNtuple& \ HepNtuple::destinationAt( const string& nametag, TYPE* address) { \ if (isValid()) { \ isValid(destinationAtTmpl(string(nametag),address,this)); \ } \ return *this; \ } destinationAtMacro ( Int1 ) destinationAtMacro ( Int2 ) destinationAtMacro ( Int4 ) #ifdef Int8 destinationAtMacro ( Int8 ) #endif destinationAtMacro ( Float4 ) destinationAtMacro ( Float8 ) #ifdef Float16 destinationAtMacro ( Float16 ) #endif destinationAtMacro ( bool ) destinationAtMacro ( void* ) // ---------------------------------------------------------------------- // destinationVia // // Set the destination method used when one row of the column is read // back // ---------------------------------------------------------------------- template static bool destinationViaTmpl ( const string& nametag, ZMsetMethod* method, HepNtuple* hep) { ColumnT *ct = getColumnT( nametag, hep, T() ); if ( ct == NULL ) { return false; } return ct->setDestinationMethod(method); } #define destinationViaMacro(TYPE) \ HepNtuple& \ HepNtuple::destinationVia( const string& nametag, ZMsetMethod* method) { \ if ( isValid() ) { \ isValid(destinationViaTmpl(string(nametag),method,this)); \ } \ return *this; \ } destinationViaMacro ( Int1 ) destinationViaMacro ( Int2 ) destinationViaMacro ( Int4 ) #ifdef Int8 destinationViaMacro ( Int8 ) #endif destinationViaMacro ( Float4 ) destinationViaMacro ( Float8 ) #ifdef Float16 destinationViaMacro ( Float16 ) #endif destinationViaMacro ( bool ) destinationViaMacro ( void* ) // ---------------------------------------------------------------------- // destinationVia // // Set the destination function used when one row of the column is read // back // ---------------------------------------------------------------------- template static bool destinationViaFuncTmpl ( const string& nametag, void (* setMethod) (T), HepNtuple* hep) { ColumnT *ct = getColumnT( nametag, hep, T() ); if ( ct == NULL ) { return false; } return ct->setDestinationFunction(setMethod); } #define destinationViaFuncMacro(TYPE) \ HepNtuple& \ HepNtuple::destinationVia( const string& nametag, void (* setMethod) (TYPE)) { \ if ( isValid() ) { \ isValid(destinationViaFuncTmpl(string(nametag),setMethod,this)); \ } \ return *this; \ } destinationViaFuncMacro ( Int1 ) destinationViaFuncMacro ( Int2 ) destinationViaFuncMacro ( Int4 ) #ifdef Int8 destinationViaFuncMacro ( Int8 ) #endif destinationViaFuncMacro ( Float4 ) destinationViaFuncMacro ( Float8 ) #ifdef Float16 destinationViaFuncMacro ( Float16 ) #endif destinationViaFuncMacro ( bool ) destinationViaFuncMacro ( void* ) // ************************************************************************* // // bool blockDestinations (const string& blockName, const string& format, // HepAList addresses); // ************************************************************************* // bool HepNtuple::blockDestinations(const string& blockName, const string& format, std::STL_VECTOR(void*) addresses) { if ( ! isValid() ) { return false; } // Get The Block .. throw an exception if we do not find it. Block *bk = findBlock(blockName); if ( bk == NULL ) { ZMthrow ( ZMxHepUnknownBlock (string("Could not find indicated block (")+ string(blockName)+ string(")to set destinations") ) ); return false; } // Verify that the format is the same std::STL_VECTOR(ColumnAttribs*) list(parseFormat(format)); string newFormat = bk->AttribsToChform(list); std::string::size_type i; for (i=0; i < list.size(); i++ ) delete list[i]; if ( bk->format() == newFormat ) { ZMthrow( ZMxHepBadFormat(string( "Real format and expected format do not match in blockDestination", ZMexERROR))); return false; } // Fill each column with the addresses i = 0; for ( Block::columnsVec::const_iterator iterateCol (bk->columns().begin()); iterateCol != bk->columns().end() && i < addresses.size(); iterateCol++, i++ ) { (*iterateCol)->setDestinationVariable( addresses[i] ); } return true; } // ************************************************************************* // // int readRow (int irow); // ************************************************************************* // // Read contents of all blocks for this row, into the destination // variables established. All destination variables established // will be filled; this need not be the whole row but must include at // least one variable. // Will return number of BLOCKS filled. int HepNtuple::readRow ( int irow ) { if ( !mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return 0; } if ( !isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return 0; } if ( (irow > nrows()) || (irow < 1)) { ZMthrow(ZMxHepOutOfRangeValue("Row number required out of range")); return 0; } bool allHaveDestination = true; Block *bk; for ( blocksMap::iterator iterateBlock = blocks.begin(); iterateBlock != blocks.end(); iterateBlock++ ) { bk = (*iterateBlock).second; allHaveDestination &= bk->hasSomeDestination(); } if ( allHaveDestination ) { if ( ! readWholeRow(irow) ) { return 0; } return nBlocks(); } else { int count = 0; for ( blocksMap::iterator iterateBlock = blocks.begin(); iterateBlock != blocks.end(); iterateBlock++ ) { bk = (*iterateBlock).second; if ( bk->hasSomeDestination() ) { if ( readBlock(bk,irow) != 0 ) { count ++; } } } return count; } } // ************************************************************************* // // int readBlock (int irow, const string& blockName); // ************************************************************************* // // Read contents of specified block for this row, into the destination // variables established. All destination variables pertaining to this block // will be filled; this need not be the whole block as written to the Ntuple // but must include at least one variable. // Will return the number of columns filled. int HepNtuple::readBlock ( int irow, const string& blockName ) { // Integrity tests if ( !mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return 0; } if ( !isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return 0; } if ( (irow > nrows()) || (irow < 1)) { ZMthrow(ZMxHepOutOfRangeValue("Row number required out of range")); return 0; } Block *bk = findBlock(blockName); if ( bk == NULL ) { ZMthrow(ZMxHepUnknownBlock(string("Block not found :")+blockName)); return 0; } return readBlock(bk,irow); } int HepNtuple::readBlock(Block *bk, int irow) { // Integrity tests if ( !mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return 0; } if ( !isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return 0; } bool allHaveDestination = true; Column *col; for ( Block::columnsVec::const_iterator iterateCol(bk->columns().begin()); iterateCol != bk->columns().end(); iterateCol++ ) { allHaveDestination &= (*iterateCol)->hasDestination(); } if ( allHaveDestination ) { if ( ! readWholeBlock(bk,irow) ) { return 0; } return bk->nColumns(); } else { int count = 0; for ( Block::columnsVec::const_iterator iterateCol(bk->columns().begin()); iterateCol != bk->columns().end(); iterateCol++ ) { col = (*iterateCol); if ( col ->hasDestination() ) { if ( readSingleColumn(col,irow) != 0 ) { count ++; } } } return count; } } // ************************************************************************* // // int readColumn (int irow, const string& nametag, float* value); // ************************************************************************* // // Direct read of the value of a column, into *value. In the case of an // array of columns the nametag[] should include the specification of which // element was wanted, e.g. "mycols(3,5)". #define readColumn_MACRO(TYPE) \ bool HepNtuple::readColumn(int irow, const string& nametag, TYPE* value) { \ if ( isValid()) { \ return readColumnF(irow,nametag,value,this); \ } \ return false; \ } template static bool readColumnF(int irow, const string& nametag, T* value,HepNtuple *tuple) { // Integrity tests if ( !tuple->mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return false; } if ( !tuple->isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return false; } if ( (irow > tuple->nrows()) || (irow < 1)) { ZMthrow(ZMxHepOutOfRangeValue("Row number required out of range")); return 0; } // the nametag can have array indices attached to them ... TupleNameTag tag; tuple->parseNameTag( tag, nametag, true); if ( ! tag.isValid() ) { ZMthrow( ZMxHepUnknownColumn( "Tag Ill formed" )); return 0; } Column * c = tuple->findColumn(tag.tag()); if ( !c ) { ZMthrow ( ZMxHepUnknownColumn (string("Attempt to read data for undefined column: ")+nametag) ); return false; } if (!c->checkType(T())) { ZMthrow(ZMxHepTypeMismatch("Read with wrong type")); return false; } // ColumnT * ct = (ColumnT *) c; if ( tag.indices().empty() ) { return tuple->readSingleColumn( c, irow, (void*)value ); } else { bool res = tuple->readSingleColumn( c, tag.indices(), irow, (void*)value ); return res; } } readColumn_MACRO ( Int1 ) readColumn_MACRO ( Int2 ) readColumn_MACRO ( Int4 ) #ifdef Int8 readColumn_MACRO ( Int8 ) #endif readColumn_MACRO ( Float4 ) readColumn_MACRO ( Float8 ) #ifdef Float16 readColumn_MACRO ( Float16 ) #endif readColumn_MACRO ( bool ) readColumn_MACRO ( void* ) // ************************************************************************* // // int bulkReadColumn (int irow, int nrows, // const string& nametag, float destination[]); // ************************************************************************* // // Retrieve data from one column (which may be one element of an array of // columns) for a whole range of rows. Data not captured for a row will // be reflected by the default value being placed in that slot of the // destination array. // Bulk reads of a column may be particularly efficient for column-wise // storage strategies, and gain no practical efficiency for row-wise. // The destination must be an array big enough to hold nrows floats. // The return value is the number of values placed; normally nrows, unless // the end of the Ntuple is reached before getting nrows rows. #define bulkReadColumn_MACRO(T) \ int HepNtuple::bulkReadColumn ( int irow, int nrows, const string& nametag, \ T *destination) { \ if ( isValid() ) { \ return bulkReadColumnF(irow,nrows,nametag,destination,this); \ } \ return 0; \ } template static int bulkReadColumnF ( int irow, int nrows, const string& nametag, T *destination, HepNtuple* tuple) { // Integrity tests if ( !tuple->mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return false; } if ( !tuple->isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return false; } if ( (irow > tuple->nrows()) || (irow < 1) ) { ZMthrow(ZMxHepOutOfRangeValue("Row number required out of range")); return 0; } // the nametag can have array indices attached to them ... TupleNameTag tag; tuple->parseNameTag( tag, nametag, true); if ( ! tag.isValid() ) { ZMthrow( ZMxHepUnknownColumn( "Tag ill formed" )); return 0; } Column * c = tuple->findColumn(tag.tag()); if ( !c ) { ZMthrow ( ZMxHepUnknownColumn (string("Attempt to read data for undefined column: ")+nametag) ); return 0; } if (!c->checkType(T())) { ZMthrow(ZMxHepTypeMismatch("Read with wrong type")); return 0; } int read; if ( tag.indices().length() == 0 ) { read = tuple->readWholeColumn( c, irow, nrows, (char*)destination, sizeof(T) ); } else { read = tuple->readWholeColumn( c, tag.indices(), irow, nrows, (char*)destination, sizeof(T) ); } return read; } bulkReadColumn_MACRO ( Int1 ) bulkReadColumn_MACRO ( Int2 ) bulkReadColumn_MACRO ( Int4 ) #ifdef Int8 bulkReadColumn_MACRO ( Int8 ) #endif bulkReadColumn_MACRO ( Float4 ) bulkReadColumn_MACRO ( Float8 ) #ifdef Float16 bulkReadColumn_MACRO ( Float16 ) #endif bulkReadColumn_MACRO ( bool ) bulkReadColumn_MACRO ( void* ) // ************************************************************************* // // int readWholeColumn(Column* col, const string& indices, // int start_row, int nrows, char * dest, std::string::size_type size); // ************************************************************************* // // Instruct the manager to read a whole column and store it into val // which is assume to be array of the same type as the column and of size // nrows. This function are called from bulkReadColumn // The manager independent implementation loop over the equivalent // readSingleColumn function int HepNtuple::readWholeColumn(Column* col, const string& indices, int start_row, int n_rows, char * dest, std::string::size_type size) { int i; int status = true; int end = start_row + n_rows; for (i=start_row; i < end && (i <= nrows()) ; i++ , dest += size ) { status &= readSingleColumn( col, indices, i, (void*) (dest) ); } return i-start_row; } // ************************************************************************* // // int readWholeColumn(Column* col, // int start_row, int nrows, char * val, std::string::size_type size); // ************************************************************************* // // Instruct the manager to read a whole column and store it into val // which is assume to be array of the same type as the column and of size // nrows. This function are called from bulkReadColumn // The manager independent implementation loop over the equivalent // readSingleColumn function int HepNtuple::readWholeColumn(Column* col, int start_row, int n_rows, char * dest, std::string::size_type size) { int i; int end = start_row + n_rows; int status = true; for (i=start_row; i < end && (i <= nrows()) ; i++ , dest += size ) { status &= readSingleColumn( col, i, (void*) (dest) ); } return i-start_row; } // ************************************************************************* // // int readColumnArray (int irow, const string& nametag, float values[]); // ************************************************************************* // // Direct read of the value of a column, into an array at values[]. // The nametag[] should be that of the array of columns. // The user must provide a large enough array at value[] to fit the array // of columns. // The method returns the number of data elements actually captured which, // in the case of indexed arrays, will be the value of its index variable // (and may be less than the maximum number of columns possible). #define readColumnArray_MACRO(T) \ int HepNtuple::readColumnArray ( int irow, const string& nametag,\ T *destination) { \ if ( isValid() ) { \ return readColumnArrayF(irow,nametag,destination,this); \ } \ return 0; \ } template static int readColumnArrayF ( int irow, const string& nametag, T *destination, HepNtuple* tuple) { // Integrity tests if ( !tuple->mayUse() ) { ZMthrow(ZMxHepUnmanagedItem("attempt to read an unmanaged ntuple")); return false; } if ( !tuple->isValid() ) { ZMthrow(ZMxHepVacuousItem("attempt to read an invalidated ntuple")); return false; } if ( (irow > tuple->nrows()) || (irow < 1) ) { ZMthrow(ZMxHepOutOfRangeValue("Row number required out of range")); return 0; } Column * c = tuple->findColumn(nametag); if ( !c ) { ZMthrow ( ZMxHepUnknownColumn (string("Attempt to read data for undefined column: ")+nametag) ); return 0; } if (!c->checkType(T())) { ZMthrow(ZMxHepTypeMismatch("Read with wrong type")); return 0; } // ColumnT * ct = (ColumnT *) c; return tuple->readSingleColumn( c, irow, (void*) destination ); } readColumnArray_MACRO ( Int1 ) readColumnArray_MACRO ( Int2 ) readColumnArray_MACRO ( Int4 ) #ifdef Int8 readColumnArray_MACRO ( Int8 ) #endif readColumnArray_MACRO ( Float4 ) readColumnArray_MACRO ( Float8 ) #ifdef Float16 readColumnArray_MACRO ( Float16 ) #endif readColumnArray_MACRO ( bool ) readColumnArray_MACRO ( void* ) ZM_END_NAMESPACE( zmht ) /* } // namespace zmht */