diff --git a/src/cpp/include/UTIL/CheckCollections.h b/src/cpp/include/UTIL/CheckCollections.h index 28cfc6f39..03b3b1621 100644 --- a/src/cpp/include/UTIL/CheckCollections.h +++ b/src/cpp/include/UTIL/CheckCollections.h @@ -30,16 +30,20 @@ namespace UTIL { virtual ~CheckCollections() = default ; /** Checks the file for missing collections - can be called repeadedly on different files. + The quiet flag makes this function not produce any output. */ - void checkFile( const std::string& fileName ) ; + void checkFile( const std::string& fileName, bool quiet=false) ; /** Checks all files for missing collections. + The quiet flag makes this function not produce any output. */ - void checkFiles( const std::vector& fileNames ) ; + void checkFiles( const std::vector& fileNames, bool quiet=false) ; - /** dump result of check to stream */ - void print( std::ostream& os ) const ; + /** dump result of check to stream. The minimal flag reduces the output of + * this function. + */ + void print( std::ostream& os ,bool minimal=false) const ; /** Returns the collections that are not present in all events checked with checkFiles() with their names and types. diff --git a/src/cpp/include/pre-generated/EVENT/LCObject.h b/src/cpp/include/pre-generated/EVENT/LCObject.h index 6b2e0ea93..67b6fbb19 100644 --- a/src/cpp/include/pre-generated/EVENT/LCObject.h +++ b/src/cpp/include/pre-generated/EVENT/LCObject.h @@ -33,6 +33,10 @@ class LCObject : public LCRTRelations { /// Destructor. virtual ~LCObject() { /* nop */; } + LCObject() = default ; + LCObject(LCObject const&) = default ; + LCObject& operator=(LCObject const&) = default ; + /** Returns an object id for internal (debugging) use in LCIO. */ virtual int id() const = 0; diff --git a/src/cpp/src/EXAMPLE/check_missing_cols.cc b/src/cpp/src/EXAMPLE/check_missing_cols.cc index d265a03de..f3f900373 100644 --- a/src/cpp/src/EXAMPLE/check_missing_cols.cc +++ b/src/cpp/src/EXAMPLE/check_missing_cols.cc @@ -14,35 +14,45 @@ static std::vector FILEN ; int main(int argc, char** argv ){ // read file names from command line (only argument) + bool minimal = false ; if( argc < 2) { - std::cout << " usage: check_missing_cols [[input-file2],...]" << std::endl << std::endl ; + std::cout << " usage: check_missing_cols [--minimal] [[input-file2],...]" << std::endl << std::endl ; exit(1) ; } for(int i=1 ; i < argc ; i++){ + if (argv[i] == std::string("--minimal")){ + minimal = true ; + continue ; + } + FILEN.push_back( argv[i] ) ; } int nFiles = argc-1 ; + if (minimal == true){ + nFiles --; + } - MT::LCReader lcReader(0) ; - - std::cout << "patch_events: will open and read from files: " << std::endl ; - - for(int i=0 ; i < nFiles ; i++){ - - lcReader.open( FILEN[i] ) ; - - std::cout << std::endl << " " << FILEN[i] - << " [ nEvt = " << lcReader.getNumberOfEvents() << " ] " - << std::endl ; + if (minimal == false){ + MT::LCReader lcReader(0) ; - lcReader.close() ; - } - + std::cout << "patch_events: will open and read from files: " << std::endl ; + + for(int i=0 ; i < nFiles ; i++){ + + lcReader.open( FILEN[i] ) ; + + std::cout << std::endl << " " << FILEN[i] + << " [ nEvt = " << lcReader.getNumberOfEvents() << " ] " + << std::endl ; + + lcReader.close() ; + } + } UTIL::CheckCollections colCheck ; - colCheck.checkFiles( FILEN ) ; + colCheck.checkFiles( FILEN ,minimal) ; - colCheck.print( std::cout ) ; + colCheck.print( std::cout ,minimal) ; return 0 ; diff --git a/src/cpp/src/UTIL/CheckCollections.cc b/src/cpp/src/UTIL/CheckCollections.cc index 66c21b28c..2c58c7b1d 100644 --- a/src/cpp/src/UTIL/CheckCollections.cc +++ b/src/cpp/src/UTIL/CheckCollections.cc @@ -9,18 +9,16 @@ namespace UTIL{ - void CheckCollections::checkFiles( const std::vector& fileNames ){ + void CheckCollections::checkFiles( const std::vector& fileNames, bool quiet){ for( auto n : fileNames ) - checkFile( n ) ; + checkFile( n ,quiet) ; } - void CheckCollections::checkFile( const std::string& fileName ){ - - MT::LCReader lcReader(0) ; + void CheckCollections::checkFile( const std::string& fileName, bool quiet){ + MT::LCReader lcReader(MT::LCReader::directAccess) ; lcReader.open( fileName ) ; - //----------- the event loop ----------- while( const auto evt = lcReader.readNextEventHeader() ) { @@ -33,8 +31,33 @@ namespace UTIL{ if( it == _map.end() ){ auto col = evt->getCollection( name ) ; - - const auto[ itx, inserted] = _map.emplace( name, std::make_pair( col->getTypeName() , 0 ) ) ; + // If the type of a collection is LCRelation we want to read the entire + // collections instead of just the header to get the 'ToType' and + // 'FromType'. setReadCollectionNames({name}) allows reading of only + // certain collections by name instead of an entire event. This flag has to + // be unset after reading in order for the reading of the headers to + // function properly. + std::string typeString; + if (col->getTypeName() == "LCRelation"){ + lcReader.setReadCollectionNames({name}); + auto fullEvt = lcReader.readEvent(evt->getRunNumber(), evt->getEventNumber()); + lcReader.setReadCollectionNames({}); + + auto fullcol = fullEvt->getCollection( name ) ; + const auto& params = fullcol->getParameters(); + const auto& fromType = params.getStringVal("FromType"); + const auto& toType = params.getStringVal("ToType"); + if (quiet == false){ + if (fromType == ""|| toType == ""){ + std::cout<< "WARNING! : Relation " << name <<" does not have the 'FromType' and 'ToType' set."<getTypeName(); + } + const auto[ itx, inserted] = _map.emplace( name, std::make_pair( std::move(typeString) , 0 ) ) ; it = itx ; } @@ -68,49 +91,87 @@ namespace UTIL{ return s ; } - void CheckCollections::patchCollections(EVENT::LCEvent* evt ) const { + // Obtain the from and to type from the encoded "LCRelation[From,To]" + std::tuple getToFromType(const std::string_view fullType) { + auto delim = fullType.find(','); + constexpr auto prefixLen = 11u; // length of "LCRelation[" - for(auto c : _patchCols ){ + return {fullType.substr(prefixLen, delim - prefixLen), + fullType.substr(delim + 1, fullType.size() - delim - 2)}; // need to strip final "]" as well + } - try{ + void CheckCollections::patchCollections(EVENT::LCEvent* evt ) const { - evt->getCollection( c.first ) ; + for(const auto& c : _patchCols ){ + try{ + auto* coll = evt->getCollection( c.first ) ; + // For LCRelations we still have to check whether the FromType and + // ToType are set and correct in case they are not + if (coll->getTypeName() == "LCRelation") { + auto& params = coll->parameters(); + if (params.getStringVal("FromType").empty() || params.getStringVal("ToType").empty()) { + const auto [from, to] = getToFromType(c.second); + params.setValue("FromType", std::string(from)); + params.setValue("ToType", std::string(to)); + } + } } catch( EVENT::DataNotAvailableException& e) { - - evt->addCollection( new IMPL::LCCollectionVec(c.second), c.first ) ; + //10 is the length of the String LCRelation after which the bracket is and the "ToType" and "FromType" start. + if (c.second.size() > 10 && c.second[10] == '[') { + auto relationColl = new IMPL::LCCollectionVec("LCRelation"); + auto& params = relationColl->parameters(); + + const auto [from, to] = getToFromType(c.second); + params.setValue("FromType", std::string(from)); + params.setValue("ToType", std::string(to)); + evt->addCollection( relationColl, c.first ) ; + } else { + evt->addCollection( new IMPL::LCCollectionVec(c.second), c.first ) ; + } } } } - void CheckCollections::print( std::ostream& os ) const { + void CheckCollections::print( std::ostream& os ,bool minimal) const { unsigned width = 50 ; - + if (minimal == false){ os << " ================================================================ " << std::endl ; os << std::endl << " " << _nEvents << " events read " << std::endl ; os << " collections that are not in all events : [# events where col is present]" << std::endl ; os << " ================================================================ " << std::endl ; - - for(auto e : _map ){ - - if( e.second.second != _nEvents ) - os << " " << std::setw(width) << std::left << e.first << " " <