////////////////////////////////////////////////////////////// // $Id: IOADatabase.cxx,v 1.53 2012/03/07 02:09:48 mcgrew Exp $ // // Implement the class COMET::IOADatabase which provides the user interface // to the calibrations and geometry databases. This class is a // singleton. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ICOMETEvent.hxx" #include "IFieldDescription.hxx" #include "IOADatabase.hxx" #include "IEventFolder.hxx" #include "IDigitManager.hxx" #include "IGeomIdManager.hxx" #include "ISHA1.hxx" ClassImp(COMET::IOADatabase); /// The static member pointer to the singleton. COMET::IOADatabase* COMET::IOADatabase::fOADatabase = NULL; namespace { typedef std::pair < std::time_t , COMET::ISHAHashValue> HashValue; typedef std::vector< HashValue > Hash; bool hashCompare(const HashValue& lhs, const HashValue& rhs) { return lhs.first < rhs.first; } /// Implement a default IGeometryLookup class. This is used unless another /// one is explicitly registered. class IDefaultGeometryLookup: public COMET::IOADatabase::IGeometryLookup { Hash fHashs; public: virtual ~IDefaultGeometryLookup() {} // Open the context file and read the list of geometries. IDefaultGeometryLookup() { // Generate the name of the file. std::string geometryName(gSystem->Getenv("OAEVENTROOT")); geometryName += "/"; geometryName += gSystem->Getenv("OAEVENTCONFIG"); geometryName += "/GEOMETRY.LIST" ; // Attache the file to a stream. std::ifstream geoContext(geometryName.c_str()); std::string line; while (std::getline(geoContext,line)) { std::size_t comment = line.find("#"); std::string tmp = line; if (comment != std::string::npos) tmp.erase(comment); // The minimum valid date, time and hash is 22 characters. if (tmp.size()<20) continue; std::istringstream parser(tmp); int yr, mn, da, hr, m; unsigned int hash0 = 0; unsigned int hash1 = 0; unsigned int hash2 = 0; unsigned int hash3 = 0; unsigned int hash4 = 0; char c; parser >> yr >> c >> mn >> c >> da; if (parser.fail()) { COMETError("Could not parse date: "<< line); continue; } parser >> hr >> c >> m; if (parser.fail()) { COMETError("Could not parse time: "<< line); continue; } parser >> std::hex >> hash0; if (parser.fail()) { COMETError("Could not parse hash: "<< line); continue; } parser >> c >> std::hex >> hash1; if (c != '-' || parser.fail()) { COMETError("Could not parse hash: "<< line); continue; } parser >> c >> std::hex >> hash2; if (c != '-' || parser.fail()) { COMETError("Could not parse hash: "<< line); continue; } parser >> c >> std::hex >> hash3; if (c != '-' || parser.fail()) { COMETError("Could not parse hash: "<< line); continue; } parser >> c >> std::hex >> hash4; if (c != '-' || parser.fail()) { COMETError("Could not parse hash: "<< line); continue; } yr -= 1900; TTimeStamp cTime(yr, mn, da, hr, m, 0 /*s*/, 0 /*ns*/, true /* Apply shift */,-9*60*60 /*JST*/); fHashs.push_back( Hash::value_type(cTime.GetSec(), COMET::ISHAHashValue(hash0, hash1, hash2, hash3, hash4))); } std::sort(fHashs.begin(),fHashs.end(),hashCompare); COMETVerbose("Available Geometries:"); for (Hash::iterator h = fHashs.begin(); h != fHashs.end(); ++h) { COMETVerbose(" First valid date: " << TTimeStamp(h->first).AsString("c") << " UTC -- Hash code: " << std::hex << std::setw(8) << std::showbase << h->second); } } // Return the geometry matching the event context. virtual COMET::ISHAHashValue GetHash( const COMET::ICOMETEvent* const event) { if (fHashs.empty()) return COMET::ISHAHashValue(); // If no event so no default geometry. if (!event) return COMET::ISHAHashValue(); // Check to see if there is a hash code for this event. COMET::ISHAHashValue hc = event->GetGeometryHash(); if (hc.Valid()) return hc; // Find the first context after the event context Hash::iterator h; for (h = fHashs.begin(); h != fHashs.end(); ++h) { if (h->first >= event->GetContext().GetTimeStamp()) break; } // Before the first context, so use the front. if (h == fHashs.begin()) return fHashs.front().second; // After the last context, so use the last. else if (h == fHashs.end()) return fHashs.back().second; // Use the context before the current. return (--h)->second; } }; // Create a private geometry lookup. IDefaultGeometryLookup* gDefaultGeometryLookup = NULL; } /// The private constructor for the database COMET::IOADatabase::IOADatabase() { fCurrentInputFile = NULL; fParticleData = NULL; fDigits = NULL; fGeomId = NULL; fGeometryLookup = NULL; fAlignmentLookup = NULL; fEMFieldDescription=NULL; } COMET::IOADatabase& COMET::IOADatabase::Get(void) { if (!fOADatabase) { COMETVerbose("Create a new COMET::IOADatabase object"); fOADatabase = new COMET::IOADatabase; } return *fOADatabase; } TGeoManager* COMET::IOADatabase::UpdateGeometry(COMET::ICOMETEvent* event) { // If an event wasn't provided, then try getting the current event. if (!event) event = COMET::IEventFolder::GetCurrentEvent(); return GeomId().UpdateGeometry(event); } TGeoManager* COMET::IOADatabase::GetGeometry() { return GeomId().GetGeometry(); } void COMET::IOADatabase::SetCurrentInputFile(TFile* input) { fCurrentInputFile = input; } void COMET::IOADatabase::SetGeometryOverride(const std::string& geomFile) { GeomId().SetGeometryFileOverride(""); GeomId().SetGeometryHashOverride(COMET::ISHAHashValue()); if (geomFile != "") GeomId().SetGeometryFileOverride(geomFile); } void COMET::IOADatabase::SetGeometryOverride(const COMET::ISHAHashValue& hc) { GeomId().SetGeometryFileOverride(""); GeomId().SetGeometryHashOverride(hc); } void COMET::IOADatabase::SetGeometryOverride(TGeoManager * geometry) { GeomId().SetGeometryPointerOverride(geometry); } void COMET::IOADatabase::RegisterGeometryCallback( COMET::IOADatabase::IGeometryChange* callback) { fGeometryCallbacks.insert(callback); } void COMET::IOADatabase::RemoveGeometryCallback( COMET::IOADatabase::IGeometryChange* callback) { fGeometryCallbacks.erase(callback); } void COMET::IOADatabase::ClearGeometryCallbacks() { fGeometryCallbacks.clear(); } void COMET::IOADatabase::ApplyGeometryCallbacks(const COMET::ICOMETEvent* event) { for (std::set::iterator c = fGeometryCallbacks.begin(); c != fGeometryCallbacks.end(); ++c) { if (!(*c)) continue; (*c)->Callback(event); } } COMET::IOADatabase::IGeometryLookup* COMET::IOADatabase::RegisterGeometryLookup( COMET::IOADatabase::IGeometryLookup* lookup) { COMET::IOADatabase::IGeometryLookup* old = fGeometryLookup; if (!lookup) { if (!gDefaultGeometryLookup) { gDefaultGeometryLookup = new IDefaultGeometryLookup; } fGeometryLookup = gDefaultGeometryLookup; } else fGeometryLookup = lookup; return old; } COMET::ISHAHashValue COMET::IOADatabase::FindEventGeometry( const COMET::ICOMETEvent *const event) const { ISHAHashValue hashValue; if (!fGeometryLookup) { if (!gDefaultGeometryLookup) { gDefaultGeometryLookup = new IDefaultGeometryLookup; } const_cast(this)->fGeometryLookup = gDefaultGeometryLookup; } try { hashValue = fGeometryLookup->GetHash(event); } catch (...) { hashValue = ISHAHashValue(); } return hashValue; } COMET::IOADatabase::IAlignmentLookup* COMET::IOADatabase::RegisterAlignmentLookup( COMET::IOADatabase::IAlignmentLookup* lookup) { COMET::IOADatabase::IAlignmentLookup* old = fAlignmentLookup; fAlignmentLookup = lookup; return old; } void COMET::IOADatabase::AlignGeometry(const COMET::ICOMETEvent* const event) { GeomId().ApplyAlignment(event); } COMET::IAlignmentId COMET::IOADatabase::ApplyAlignmentLookup( const COMET::ICOMETEvent* const event) { COMET::IAlignmentId id; GeomId().GetGeometry(); TObjArray* physicalNodes = gGeoManager->GetListOfPhysicalNodes(); if (physicalNodes) { COMETNamedInfo("Geometry","Clear existing physical nodes: " << physicalNodes->GetEntries()); gGeoManager->ClearPhysicalNodes(true); } if (fAlignmentLookup) { // Save the current geometry state. COMETInfo("Apply alignment to event"); gGeoManager->PushPath(); // Let alignment code know that the alignment is starting. id = fAlignmentLookup->StartAlignment(event); if (!id.Valid()) COMETNamedInfo("Geometry", "No alignment should be apply"); gGeoManager->UnlockGeometry(); int alignmentCount = 0; // Apply alignment to each geometry element. IGeometryId geomId; while (TGeoMatrix* align = fAlignmentLookup->Align(event,geomId)) { std::string path = geomId.GetName(); TGeoPhysicalNode* pNode = gGeoManager->MakePhysicalNode(path.c_str()); TGeoMatrix* orig = pNode->GetNode()->GetMatrix(); TGeoHMatrix* h = dynamic_cast(orig->MakeClone()); if (h) { h->Multiply(align); if (pNode->IsAligned()) { pNode->Align(h); delete orig; } else { pNode->Align(h); } ++ alignmentCount; } } if (alignmentCount > 0) { COMETInfo("Applied " << alignmentCount << " alignment matrices."); } gGeoManager->PopPath(); gGeoManager->RefreshPhysicalNodes(true); if (id.Valid() && !alignmentCount) { COMETError("Invalid alignment applied to geometry"); throw EBadAlignment(); } if (!id.Valid() && alignmentCount) { COMETError("Invalid alignment applied to geometry"); throw EBadAlignment(); } } // There isn't an alignment id, so create one. This is the hash of an // empty string. if (!id.Valid()) { COMETNamedDebug("Geometry","No alignment id, so create an empty one"); ISHA1 sha; unsigned int message[5]; if (sha.Result(message)) { id = IAlignmentId(message); } else { COMETError("ISHA1 Calculation failed"); } } return id; } bool COMET::IOADatabase::CheckAlignment(const COMET::ICOMETEvent* const event) { if (!fAlignmentLookup) return false; return fAlignmentLookup->CheckAlignment(event); } TDatabasePDG& COMET::IOADatabase::ParticleData(void) { if (!fParticleData) { fParticleData = TDatabasePDG::Instance(); } return *fParticleData; } COMET::IPackageSet& COMET::IOADatabase::PackageSet(void) { return fPackageSet; } COMET::IDigitManager& COMET::IOADatabase::Digits(void) { if (!fDigits) { fDigits = new COMET::IDigitManager(); } return *fDigits; } COMET::IGeomIdManager& COMET::IOADatabase::GeomId(void) { if (!fGeomId) { fGeomId = new COMET::IGeomIdManager(); } return *fGeomId; } COMET::IFieldDescription* COMET::IOADatabase::EMFieldDescription(const ICOMETEvent* /*event*/){ // Do we already have a description if(fEMFieldDescription ) return fEMFieldDescription; // Which file will we read the geometry from? TDirectory* originalDir=TDirectory::CurrentDirectory(); TFile* inputFile=CurrentInputFile(); if(!fEMFieldDescriptionOverride.empty() && (!inputFile || fEMFieldDescriptionOverride!=inputFile->GetName())){ inputFile=TFile::Open(fEMFieldDescriptionOverride.c_str(),"read"); if(!inputFile || inputFile->IsZombie()){ COMETError("Cannot find override file for EM Field description, '"<GetListOfKeys()); TKey *key; while ((key = (TKey*)next())) { if (strcmp(key->GetClassName(),"COMET::IFieldDescription") != 0) continue; fEMFieldDescription = (COMET::IFieldDescription*)key->ReadObj()->Clone(); break; } if(!fEMFieldDescription){ COMETError("File, '"<GetName()<<"' doesn't contain an instance of IFieldDescription"); originalDir->cd(); throw ENoEMFieldDescription(); } originalDir->cd(); return fEMFieldDescription; } TDirectory* COMET::IOADatabase::GetInputFileDirectory() const { if (!fCurrentInputFile){ COMETError("Input file is not found !!"); throw ENoInputFile(); } return fCurrentInputFile->GetDirectory(""); }