///////////////////////////////////////////////////////////// // Provide tests of the event input and output. This also tests many of the // associated classes. ///////////////////////////////////////////////////////////// #include #include #include #include #include #include "ICOMETEvent.hxx" #include "ICOMETInput.hxx" #include "ICOMETOutput.hxx" #include "IMCHit.hxx" #include "IMultiHit.hxx" #include "IG4VHit.hxx" #include "IG4HitSegment.hxx" #include "IAlgorithmResult.hxx" #include "IHandleHack.hxx" #include "IReconBase.hxx" #include "IReconCluster.hxx" #include "IReconShower.hxx" #include "IReconTrack.hxx" #include "COMETGeomId.hxx" #include "ICTHGeomId.hxx" #include "ICDCGeomId.hxx" namespace { class ITestG4VHit : public COMET::IG4HitSegment { public: ITestG4VHit() {}; virtual ~ITestG4VHit() {}; void SetPrimaryId(int i) {fPrimaryId = i;} void SetEnergyDeposit(double d) {fEnergyDeposit = d;} }; int gIndexNumber = 1; std::string IndexNumber(int i=-1) { std::stringstream tmp; if (i<0) tmp << gIndexNumber++; else tmp << i; return tmp.str(); } void CreateIG4Hits(COMET::IDataVector& truth, const char* name) { if (!truth.FindDatum("g4Hits")) { truth.push_back(new COMET::IDataVector("g4Hits")); } // Create the hit container and add it to the event. COMET::IG4HitContainer* hits = new COMET::IG4HitContainer(name); truth.Get("g4Hits")->push_back(hits); // Create hits for the event. for (int i = 1; i< 6; ++i) { ITestG4VHit* hit = new ITestG4VHit(); hit->SetPrimaryId(i); hit->SetEnergyDeposit(10.0 + 1.0*i); hits->push_back(hit); } } void CreateTruth(COMET::ICOMETEvent& event) { event.push_back(new COMET::IDataVector("truth")); COMET::IHandle truth = event.Get("truth"); CreateIG4Hits(*truth,"CTH"); CreateIG4Hits(*truth,"CDC"); } /// Create "real" MC hits using G4Hit information directly void CreateHits(COMET::ICOMETEvent& event, std::string name) { std::string g4Name = "truth/g4Hits/" + name; COMET::IHandle g4Hits = event.Get(g4Name); if (!g4Hits) return; std::string containerTitle("Hits for the " + name + " detector"); COMET::IHitSelection *hits = new COMET::IHitSelection(name.c_str(), containerTitle.c_str()); event.Get("hits")->push_back(hits); for (COMET::IG4HitContainer::iterator g4Hit = g4Hits->begin(); g4Hit != g4Hits->end(); ++g4Hit) { COMET::IWritableMCHit mcHit; COMET::IG4HitSegment* hitSeg = dynamic_cast(*g4Hit); mcHit.SetGeomID(COMET::GeomId::CTH::Counter(1,0,1,0)); mcHit.SetCharge(hitSeg->GetPrimaryId()); mcHit.SetTime(hitSeg->GetPrimaryId()); mcHit.GetContributors().push_back(hitSeg); mcHit.GetContributors().push_back(NULL); hits->push_back(COMET::IHandle(new COMET::IMCHit(mcHit))); } } void CreateWaveform(COMET::ICOMETEvent& event, std::string name) { std::string g4Name = "truth/g4Hits/" + name; COMET::IHandle g4Hits = event.Get(g4Name); if (!g4Hits) return; std::string containerTitle("Hits for the " + name + " detector"); COMET::IHitSelection *hits = new COMET::IHitSelection(name.c_str(), containerTitle.c_str()); event.Get("hits")->push_back(hits); // Create maxWaveforms worth of TMultiHits. int maxWaveforms = 20; std::vector< COMET::IHandle > wave(600); for (int i = 0; i< maxWaveforms; ++i) { // Create a waveform. wave.clear(); for (int j = 0; j<512; ++j) { COMET::IWritableMCHit tmpHit; tmpHit.SetGeomID(COMET::GeomId::CDC::WireId(1,3,3)); tmpHit.SetCharge(1.0); tmpHit.SetTime(j); wave.push_back(COMET::IHandle(new COMET::IMCHit(tmpHit))); } hits->push_back( COMET::IHandle(new COMET::IMultiHit(wave.begin(),wave.end()))); } } void CreateResults(COMET::ICOMETEvent& event) { // Create a simple algorithm result. COMET::IAlgorithmResult *result = new COMET::IAlgorithmResult("firstResult", "Test Result"); COMET::IHandle hits = event.GetHitSelection("CTH"); COMET::IHitSelection *newHits = new COMET::IHitSelection("newHits"); std::copy(hits->begin(), hits->end(), std::back_inserter(*newHits)); result->AddHitSelection(newHits); event.AddFit(result); // Create a second algorithm result. result = new COMET::IAlgorithmResult("secondResult", "Test Result"); hits = event.GetHitSelection("CTH"); COMET::IHitSelection* moreHits = new COMET::IHitSelection("moreHits"); std::copy(hits->begin(),hits->end(),std::back_inserter(*moreHits)); result->AddHitSelection(moreHits); event.AddFit(result); /// Create an COMET::IAlgorithmResult with reconstruction objects. COMETDebug("Create Recon Object"); result = new COMET::IAlgorithmResult("reconResult", "Test Recon Object Result"); COMET::IReconObjectContainer* recObjs = new COMET::IReconObjectContainer("reconObjects"); result->AddResultsContainer(recObjs); // Add a cluster. COMET::IHandle cluster(new COMET::IReconCluster); COMET::IHandle clusterState = cluster->GetState(); clusterState->SetEDeposit(10.0); recObjs->push_back(cluster); // Add a shower. COMET::IHandle shower(new COMET::IReconShower); recObjs->push_back(shower); // Add a track. COMET::IHandle track(new COMET::IReconTrack); recObjs->push_back(track); event.AddFit(result); } void CreateTemporary(COMET::ICOMETEvent& event) { COMET::IDatum* d1 = new COMET::IDatum("temporaryObject"); event.AddDatum(d1); } void FillEvent(COMET::ICOMETEvent& event) { CreateTruth(event); CreateHits(event,"CTH"); CreateWaveform(event,"CDC"); CreateResults(event); CreateTemporary(event); } } namespace tut { struct baseEventIO { static std::vector outputEvents; static std::vector inputEvents; baseEventIO() { // Run before each test. const char* fileName = "./tutEventIO.root"; // Write events to an output file and save them in a local vector. try { if (outputEvents.size()<1) { COMET::ICOMETOutput* output = new COMET::ICOMETOutput(fileName,"RECREATE"); for (int i=0; i<5; ++i) { COMET::ICOMETEvent* event = new COMET::ICOMETEvent(); event->SetRunId(1); event->SetEventId(i); COMETTrace("Write event"); outputEvents.push_back(event); FillEvent(*event); output->WriteEvent(*event); } output->Close(); delete output; } } catch (std::exception& e) { COMETError("Error writing output file"); COMETError("exception: " << e.what()); return; } // Read the same events from the file and save them in another // local vector. try { if (inputEvents.size()<1) { // Read the event back. COMET::ICOMETInput* input = new COMET::ICOMETInput(fileName,"OLD"); for (COMET::ICOMETEvent* event = input->FirstEvent(); !input->EndOfFile(); event = input->NextEvent()) { COMETTrace("Read event"); inputEvents.push_back(event); } input->Close(); delete input; } } catch (std::exception& e) { COMETError("Error reading input file"); COMETError("exception: " << e.what()); return; } } ~baseEventIO() { // Run after each test. } }; std::vector baseEventIO::outputEvents; std::vector baseEventIO::inputEvents; void EventIO_Finalization(void) { // Delete the events saved in the input and output event vectors. for (std::vector::iterator e = baseEventIO::outputEvents.begin(); e != baseEventIO::outputEvents.end(); ++e) delete (*e); for (std::vector::iterator e = baseEventIO::inputEvents.begin(); e != baseEventIO::inputEvents.end(); ++e) delete (*e); if (!COMET::CleanHandleRegistry()) { std::cout << "tutEventIO:: EVENT HANDLES NOT DELETED" << std::endl; } } // Declare the test group. typedef test_group::object testEventIO; test_group groupEventIO("EventIO", EventIO_Finalization); // Test that events were actual written, and then read back in. template<> template<> void testEventIO::test<1> () { ensure("Event IO events written", (0 template<> void testEventIO::test<2> () { std::vector::iterator out = baseEventIO::outputEvents.begin(); std::vector::iterator in = baseEventIO::inputEvents.begin(); for (;out != baseEventIO::outputEvents.end(); ++out, ++in) { ensure_equals("Input and output event IDs match", (*in)->GetEventId(), (*out)->GetEventId()); ensure_equals("Input and output run IDs match", (*in)->GetRunId(), (*out)->GetRunId()); } } // Test that the basic event structure was created. template<> template<> void testEventIO::test<3> () { std::vector::iterator out = baseEventIO::outputEvents.begin(); std::vector::iterator in = baseEventIO::inputEvents.begin(); for (;out != baseEventIO::outputEvents.end(); ++out, ++in) { COMET::IHandle outHits=(*out)->Get("~/hits"); COMET::IHandle inHits=(*in)->Get("~/hits"); ensure("Hits vector exists in output event",outHits); ensure("Hits vector exists in input event",inHits); COMET::IHandle outFits=(*out)->Get("~/fits"); COMET::IHandle inFits=(*in)->Get("~/fits"); ensure("Fits vector exists in output event",outFits); ensure("Fits vector exists in input event",inFits); } } // Test the input IG4Hits match the output IG4Hits. template<> template<> void testEventIO::test<4> () { std::vector::iterator out = baseEventIO::outputEvents.begin(); std::vector::iterator in = baseEventIO::inputEvents.begin(); for (;out != baseEventIO::outputEvents.end(); ++out, ++in) { COMET::IHandle outCTH = (*out)->Get("~/truth/g4Hits/CTH"); COMET::IHandle inCTH = (*in)->Get("~/truth/g4Hits/CTH"); ensure("CTH G4 hit container exists in output event",outCTH); ensure("CTH G4 hit container exists in input event",inCTH); ensure_equals("CTH G4 hit containers are same length", outCTH->size() , inCTH->size()); COMET::IG4HitContainer::iterator outHits = outCTH->begin(); COMET::IG4HitContainer::iterator inHits = inCTH->begin(); for (;outHits != outCTH->end(); ++outHits, ++inHits) { ensure("Output COMET::IG4VHit pointer exists", (*outHits)); ensure("Input COMET::IG4VHit pointer exists", (*inHits)); const COMET::IG4HitSegment *inSeg = dynamic_cast(*inHits); const COMET::IG4HitSegment *outSeg = dynamic_cast(*outHits); ensure("Output is a IG4HitSegment", outSeg); ensure("Input is a IG4HitSegment", inSeg); ensure_equals("CTH data fields match", inSeg->GetPrimaryId(), outSeg->GetPrimaryId()); } } } // Check that the hits match in the output and input objects. template<> template<> void testEventIO::test<5> () { std::vector::iterator out = baseEventIO::outputEvents.begin(); std::vector::iterator in = baseEventIO::inputEvents.begin(); for (;out != baseEventIO::outputEvents.end(); ++out, ++in) { COMET::IHandle outCTH = (*out)->Get("~/hits/CTH"); COMET::IHandle inCTH = (*in)->Get("~/hits/CTH"); ensure("CTH hit selection exists in output event",outCTH); ensure("CTH hit selection exists in input event",inCTH); COMET::IHitSelection::iterator out = outCTH->begin(); COMET::IHitSelection::iterator in = inCTH->begin(); //FIXME //for (;out != outCTH->end(); ++out, ++in) { // COMET::IHandle outHit = (*out); // COMET::IHandle outMCHit = outHit; // COMET::IHandle inHit = (*in); // COMET::IHandle inMCHit = inHit; //ch//eck below here // ensure_greaterthan("CTH hit GeomId filled", // inHit->GetGeomID().AsInt(), 0); // ensure_equals("CTH hit GeomIds match", // inHit->GetGeomID(), outHit->GetGeomID()); // ensure_equals("CTH hit charges match", // inHit->GetCharge(), outHit->GetCharge()); // ensure_equals("CTH hit times match", // inHit->GetTime(), outHit->GetTime()); // ensure_equals("CTH MC and regular hit GeomIds match", // inHit->GetGeomID(), outMCHit->GetGeomID()); // ensure_equals("CTH MC and regular hit charges match", // inHit->GetCharge(), outMCHit->GetCharge()); // ensure_equals("CTH MC and regular hit times match", // inHit->GetTime(), outMCHit->GetTime()); // ensure_equals("CTH MC hit GeomIds match", // inMCHit->GetGeomID(), // outMCHit->GetGeomID()); // ensure_equals("CTH MC hit charges match", // inMCHit->GetCharge(), outMCHit->GetCharge()); // ensure_equals("CTH MC hit times match", // inMCHit->GetTime(), outMCHit->GetTime()); // const COMET::IMCHit::ContributorContainer& inContrib // = inMCHit->GetContributors(); // const COMET::IMCHit::ContributorContainer& outContrib // = outMCHit->GetContributors(); // ensure_greaterthan("CTH contributors exist", // inContrib.size(), // (unsigned) 0); // ensure_equals("CTH number of contributors match", // inContrib.size(), outContrib.size()); // COMET::IG4VHit* inG4VHit = inContrib[0]; // COMET::IG4VHit* outG4VHit = inContrib[0]; // ensure("CTH input COMET::IG4VHit exists", inG4VHit); // ensure("CTH output COMET::IG4VHit exists", outG4VHit); // COMET::IG4HitSegment* inG4HitSegment // = dynamic_cast(inG4VHit); // COMET::IG4HitSegment* outG4HitSegment // = dynamic_cast(outG4VHit); // ensure("CTH input contributor is a COMET::IG4HitSegment", // inG4HitSegment); // ensure("CTH output contributor is a COMET::IG4HitSegment", // outG4HitSegment); // ensure_equals("CTH primary particle identifiers match", // inG4HitSegment->GetPrimaryId(), // outG4HitSegment->GetPrimaryId()); // ensure_greaterthan("CTH primary particle identifiers not zero", // inG4HitSegment->GetPrimaryId(),0); // ensure_distance("CTH energy deposits match", // inG4HitSegment->GetEnergyDeposit(), // outG4HitSegment->GetEnergyDeposit(), 0.001); // double inPrim = 10.0 + 1.0*inG4HitSegment->GetPrimaryId(); // ensure_distance("CTH energy deposits match id", // inG4HitSegment->GetEnergyDeposit(), // inPrim, 0.0001); // ensure_greaterthan("CTH energy deposit not zero", // inG4HitSegment->GetEnergyDeposit(),5.0); // inG4VHit = inContrib[1]; // outG4VHit = inContrib[1]; // ensure("CTH NULL COMET::TG4VHits are saved",inG4VHit == NULL); // ensure("CTH NULL COMET::TG4VHits are saved",outG4VHit == NULL); //} } } // Check that the hit selections in different COMET::IAlgorithmResult objects // share the same hits. template<> template<> void testEventIO::test<6> () { std::vector::iterator out = baseEventIO::outputEvents.begin(); std::vector::iterator in = baseEventIO::inputEvents.begin(); for (;out != baseEventIO::outputEvents.end(); ++out, ++in) { COMET::IHandle r1 = (*in)->GetFit("firstResult"); COMET::IHandle r2 = (*in)->GetFit("secondResult"); ensure("The first algorithm result exists in input",r1); ensure("The second algorithm result exists in input",r2); COMET::IHandle h1 = r1->GetHitSelection(); COMET::IHandle h2 = r2->GetHitSelection(); ensure("The first hit selection was found",h1); ensure("There are hits in the first hit selection", h1->size()>0); ensure("The second hit selection was found",h2); ensure_equals("The selections have the same number of hits", h2->size(), h1->size()); COMET::IHitSelection::iterator hit1 = h1->begin(); COMET::IHitSelection::iterator hit2 = h2->begin(); for (; hit1 != h1->end(); ++hit1, ++hit2) { ensure("First hit handle is valid", *hit1); ensure("Second hit handle is valid", *hit2); ensure_equals("Hit pointers match", GetPointer(*hit1), GetPointer(*hit2)); } } } // Test that a simple COMET::IAlgorithmResult object was correctly saved. template<> template<> void testEventIO::test<7> () { for (std::vector::iterator in = baseEventIO::inputEvents.begin(); in != baseEventIO::inputEvents.end(); ++in) { COMET::IHandle s = (*in)->GetFit("reconResult"); ensure("The algorithm result exists in input",s); COMET::IHandle d = s->GetResultsContainer(); ensure("The default recon objects were found",d); ensure_equals("Recon object container length",d->size(), (unsigned) 3); // Check object 0 COMET::IHandle elem = (*d)[0]; ensure("State 0 is valid", elem); COMET::IHandle cluster = elem; ensure("State 0 is a valid cluster", cluster); COMET::IHandle track = elem; ensure("State 0 is not a valid track", !track); COMET::IHandle clusterState = cluster->GetState(); ensure("State 0 cluster has a cluster state",clusterState); COMET::IHandle trackState = cluster->GetState(); ensure("State 0 cluster does not have a track state",!trackState); ensure_distance("State 0 cluster state values are saved", clusterState->GetEDeposit(),10.0,0.001); // Check object 1 elem = (*d)[1]; ensure("State 1 is valid", elem); COMET::IHandle shower = elem; ensure("State 1 is a valid shower", shower); track = elem; ensure("State 1 is not a valid track", !track); COMET::IHandle showerState = shower->GetState(); ensure("State 1 shower has a shower state",showerState); trackState = shower->GetState(); ensure("State 1 shower does not have a track state",!trackState); // Check object 2 elem = (*d)[2]; ensure("State 2 is valid", elem); track = elem; ensure("State 2 is a valid track", track); cluster = elem; ensure("State 2 is not a valid cluster", !cluster); trackState = track->GetState(); ensure("State 2 track has a track state",trackState); clusterState = track->GetState(); ensure("State 2 track does not have a cluster state",!clusterState); } } // Test that a temporary objects are not saved in output file. template<> template<> void testEventIO::test<8> () { for (std::vector::iterator out = baseEventIO::outputEvents.begin(); out != baseEventIO::outputEvents.end(); ++out) { COMET::IHandle tmp = (*out)->Get("temporaryObject"); ensure("Temporary object exists in output",tmp); } for (std::vector::iterator in = baseEventIO::inputEvents.begin(); in != baseEventIO::inputEvents.end(); ++in) { COMET::IHandle tmp = (*in)->Get("temporaryObject"); ensure("Temporary object does not exist in input",tmp); } } // Test that a simple COMET::IAlgorithmResult object was correctly in the // output object. template<> template<> void testEventIO::test<9> () { for (std::vector::iterator in = baseEventIO::outputEvents.begin(); in != baseEventIO::outputEvents.end(); ++in) { COMET::IHandle s = (*in)->GetFit("reconResult"); ensure("The algorithm result exists in input",s); COMET::IHandle d = s->GetResultsContainer(); ensure("The default recon objects were found",d); ensure_equals("Recon object container length",d->size(), (unsigned) 3); // Check object 0 COMET::IHandle elem = (*d)[0]; ensure("State 0 is valid", elem); COMET::IHandle cluster = elem; ensure("State 0 is a valid cluster", cluster); COMET::IHandle track = elem; ensure("State 0 is not a valid track", !track); COMET::IHandle clusterState = cluster->GetState(); ensure("State 0 cluster has a cluster state",clusterState); COMET::IHandle trackState = cluster->GetState(); ensure("State 0 cluster does not have a track state",!trackState); ensure_distance("State 0 cluster state values are saved", clusterState->GetEDeposit(),10.0,0.001); // Check object 1 elem = (*d)[1]; ensure("State 1 is valid", elem); COMET::IHandle shower = elem; ensure("State 1 is a valid shower", shower); track = elem; ensure("State 1 is not a valid track", !track); COMET::IHandle showerState = shower->GetState(); ensure("State 1 shower has a shower state",showerState); trackState = shower->GetState(); ensure("State 1 shower does not have a track state",!trackState); // Check object 2 elem = (*d)[2]; ensure("State 2 is valid", elem); track = elem; ensure("State 2 is a valid track", track); cluster = elem; ensure("State 2 is not a valid cluster", !cluster); trackState = track->GetState(); ensure("State 2 track has a track state",trackState); clusterState = track->GetState(); ensure("State 2 track does not have a cluster state",!clusterState); } } };