bool ImplantSsdProcessor::Process(RawEvent &event) { using namespace dammIds::implantSsd; if (!EventProcessor::Process(event)) { EndProcess(); return false; } static bool firstTime = true; static LogicProcessor *logProc = NULL; static Correlator &corr = event.GetCorrelator(); static const DetectorSummary *tacSummary = event.GetSummary("generic:tac", true); static DetectorSummary *impSummary = event.GetSummary("ssd:sum", true); static const DetectorSummary *mcpSummary = event.GetSummary("logic:mcp", true); static const DetectorSummary *vetoSummary = event.GetSummary("ssd:veto", true); static const DetectorSummary *boxSummary = event.GetSummary("ssd:box", true); DetectorDriver* driver = DetectorDriver::get(); if (impSummary->GetMult() == 0) { EndProcess(); return false; } if (firstTime) { vector<EventProcessor *> vecProc = driver->GetProcessors("logic"); for (vector< EventProcessor * >::iterator it = vecProc.begin(); it != vecProc.end(); it++) { if ( (*it)->GetName() == "triggerlogic" || (*it)->GetName() == "logic" ) { logProc = reinterpret_cast < LogicProcessor * >(*it); cout << "Implant SSD processor grabbed logic processor" << endl; } } firstTime=false; } EventInfo info; ChanEvent *ch = impSummary->GetMaxEvent(true); info.hasVeto = ( vetoSummary && vetoSummary->GetMult() > 0 ); int location = ch->GetChanID().GetLocation(); if (ch->IsSaturated()) { info.energy = 16000; // arbitrary large number } else { info.energy = ch->GetCalEnergy(); } if (ch->GetTrace().HasValue("position")) { info.position = ch->GetTrace().GetValue("position"); } // else it defaults to nan info.time = ch->GetTime(); info.beamOn = true; // recect noise events if (info.energy < 10 || ch->GetTrace().HasValue("badqdc")) { EndProcess(); return true; } if (logProc) { info.clockCount = logProc->StartCount(2); if (logProc->LogicStatus(3) || logProc->LogicStatus(4) || logProc->LogicStatus(5)) { info.beamOn = true; info.offTime = 0; } else { info.beamOn = false; if (!logProc->LogicStatus(3)) info.offTime = logProc->TimeOff(3, info.time); else if (!logProc->LogicStatus(4)) info.offTime = logProc->TimeOff(4, info.time) + 300e-6; else if (!logProc->LogicStatus(5)) info.offTime = logProc->TimeOff(5, info.time) + 600e-6; } for (int i=0; i < dammIds::logic::MAX_LOGIC; i++) { info.logicBits[i] = (logProc->LogicStatus(i) ? '1' : '0'); } } double digitalTof = NAN; if (mcpSummary) { info.mcpMult = mcpSummary->GetMult(); vector<ChanEvent*> mcpEvents = mcpSummary->GetList(); double dtMin = DBL_MAX; for (vector<ChanEvent*>::iterator it = mcpEvents.begin(); it != mcpEvents.end(); it++) { double dt = info.time - (*it)->GetTime(); plot(D_TDIFF_FOIL_IMPLANT, 500 + dt); if (mcpEvents.size() == 1) { digitalTof = -10.*dt; plot(D_TDIFF_FOIL_IMPLANT_MULT1, 500 + dt); } dtMin = min(dtMin, dt); } if (dtMin != DBL_MAX) info.foilTime= dtMin; } else { info.mcpMult = 0; info.foilTime = NAN; } if (impSummary) { info.impMult = impSummary->GetMult(); } else { info.impMult = 0; } if (boxSummary) { info.boxMult = boxSummary->GetMult(); if (info.boxMult > 0) { const ChanEvent *boxCh = boxSummary->GetMaxEvent(); info.energyBox = boxCh->GetCalEnergy(); //raw? info.boxMax = boxCh->GetChanID().GetLocation(); } else { info.energyBox = 0; info.boxMax = -1; } } else { info.boxMult = 0; } info.tof = NAN; if (tacSummary) { const vector<ChanEvent*> events = tacSummary->GetList(); for (vector<ChanEvent*>::const_iterator it = events.begin(); it != events.end(); it++) { int loc = (*it)->GetChanID().GetLocation(); if (loc == 2) { info.tof = (*it)->GetCalEnergy(); info.hasTof = true; break; } } } else { info.hasTof = true; } Trace &trace = ch->GetTrace(); if (trace.HasValue("filterEnergy2")) { info.pileUp = true; } SetType(info); Correlate(corr, info, location); // TOF spectra update if (tacSummary) { const vector<ChanEvent*> events = tacSummary->GetList(); for (vector<ChanEvent*>::const_iterator it = events.begin(); it != events.end(); it++) { double tof = (*it)->GetCalEnergy(); int ntof = (*it)->GetChanID().GetLocation(); plot(DD_ALL_ENERGY__TOFX + ntof - 1, info.energy, tof); if (!isnan(digitalTof) && digitalTof > 1500. && digitalTof < 2000) plot(DD_ALL_ENERGY__TOFX_GATED + ntof - 1, info.energy, tof); if (info.type == EventInfo::IMPLANT_EVENT) { plot(DD_IMPLANT_ENERGY__TOFX + ntof - 1, info.energy, tof); } else if (info.type == EventInfo::PROTON_EVENT) { plot(DD_VETO_ENERGY__TOFX + ntof - 1, info.energy, tof); } } // TAC channel 0 is missing, so use it for the digital tof if (!isnan(digitalTof)) { plot(DD_ALL_ENERGY__TOFX, info.energy, digitalTof); if (info.type == EventInfo::IMPLANT_EVENT) { plot(DD_IMPLANT_ENERGY__TOFX, info.energy, digitalTof); } else if (info.type == EventInfo::PROTON_EVENT) { plot(DD_VETO_ENERGY__TOFX, info.energy, digitalTof); } } } if (info.type == EventInfo::PROTON_EVENT) { const ChanEvent *chVeto = vetoSummary->GetMaxEvent(); unsigned int posVeto = chVeto->GetChanID().GetLocation(); double vetoEnergy = chVeto->GetCalEnergy(); plot(DD_LOC_VETO__LOC_SSD, posVeto, location); plot(DD_TOTENERGY__ENERGY, vetoEnergy + info.energy, info.energy); } if (info.pileUp) { double trigTime = info.time; info.energy = driver->cali.GetCalEnergy(ch->GetChanID(), trace.GetValue("filterEnergy2")); info.time = trigTime + trace.GetValue("filterTime2") - trace.GetValue("filterTime"); SetType(info); Correlate(corr, info, location); int numPulses = trace.GetValue("numPulses"); if ( numPulses > 2 ) { corr.Flag(location, 1); cout << "Flagging triple event" << endl; for (int i=3; i <= numPulses; i++) { stringstream str; str << "filterEnergy" << i; info.energy = driver->cali.GetCalEnergy(ch->GetChanID(), trace.GetValue(str.str())); str.str(""); // clear it str << "filterTime" << i; info.time = trigTime + trace.GetValue(str.str()) - trace.GetValue("filterTime"); SetType(info); Correlate(corr, info, location); } } // corr.Flag(location, 1); #ifdef VERBOSE cout << "Flagging for pileup" << endl; cout << "fast trace " << fastTracesWritten << " in strip " << location << " : " << trace.GetValue("filterEnergy") << " " << trace.GetValue("filterTime") << " , " << trace.GetValue("filterEnergy2") << " " << trace.GetValue("filterTime2") << endl; cout << " mcp mult " << info.mcpMult << endl; #endif // VERBOSE if (fastTracesWritten < numTraces) { trace.Plot(D_FAST_DECAY_TRACE + fastTracesWritten); fastTracesWritten++; } } if (info.energy > 10000 && !ch->IsSaturated() && !isnan(info.position) ) { corr.Flag(location, info.position); } if (info.energy > 8000 && !trace.empty()) { #ifdef VERBOSE cout << "high energy decay of " << info.energy << "(raw energy " << ch->GetEnergy() << ") with beam " << (info.beamOn ? "present" : "absent") << endl; cout << "Flagging for high energy " << info.energy << " with trace" << endl; #endif //VERBOSE // corr.Flag(location, 1); if (highTracesWritten < numTraces) { trace.Plot(D_HIGH_ENERGY_TRACE + highTracesWritten); highTracesWritten++; } } EndProcess(); // update the processing time return true; }
/** * Process the QDC data involved in top/bottom side for a strip * Note QDC lengths are HARD-CODED at the moment for the plots and to determine the position */ bool PositionProcessor::Process(RawEvent &event) { if (!EventProcessor::Process(event)) return false; static const vector<ChanEvent*> &sumEvents = event.GetSummary("ssd:sum", true)->GetList(); static const vector<ChanEvent*> &digisumEvents = event.GetSummary("ssd:digisum", true)->GetList(); static const vector<ChanEvent*> &topEvents = event.GetSummary("ssd:top", true)->GetList(); static const vector<ChanEvent*> &bottomEvents = event.GetSummary("ssd:bottom", true)->GetList(); vector<ChanEvent *> allEvents; // just add in the digisum events for now allEvents.insert(allEvents.begin(), digisumEvents.begin(), digisumEvents.end()); allEvents.insert(allEvents.begin(), sumEvents.begin(), sumEvents.end()); for (vector<ChanEvent*>::const_iterator it = allEvents.begin(); it != allEvents.end(); ++it) { ChanEvent *sumchan = *it; int location = sumchan->GetChanID().GetLocation(); // Don't waste our time with noise events if ( (*it)->GetEnergy() < 10. || (*it)->GetEnergy() > 16374 ) { using namespace dammIds::position; plot(D_INFO_LOCX + location, INFO_NOISE); plot(D_INFO_LOCX + LOC_SUM , INFO_NOISE); continue; } const ChanEvent *top = FindMatchingEdge(sumchan, topEvents.begin(), topEvents.end()); const ChanEvent *bottom = FindMatchingEdge(sumchan, bottomEvents.begin(), bottomEvents.end()); if (top == NULL || bottom == NULL) { using namespace dammIds::position; if (top == NULL) { // [6] -> Missing top plot(D_INFO_LOCX + location, INFO_MISSING_TOP); plot(D_INFO_LOCX + LOC_SUM, INFO_MISSING_TOP); } if (bottom == NULL) { // [5] -> Missing bottom plot(D_INFO_LOCX + location, INFO_MISSING_BOTTOM); plot(D_INFO_LOCX + LOC_SUM, INFO_MISSING_BOTTOM); } continue; } /* Make sure we get the same match going backwards to insure there is only one in the vector */ if ( FindMatchingEdge(sumchan, topEvents.rbegin(), topEvents.rend()) != top) { using namespace dammIds::position; // [4] -> Multiple top plot(D_INFO_LOCX + location, INFO_MULTIPLE_TOP); plot(D_INFO_LOCX + LOC_SUM, INFO_MULTIPLE_TOP); continue; } if ( FindMatchingEdge(sumchan, bottomEvents.rbegin(), bottomEvents.rend()) != bottom) { using namespace dammIds::position; // [3] -> Multiple bottom plot(D_INFO_LOCX + location, INFO_MULTIPLE_BOTTOM); plot(D_INFO_LOCX + LOC_SUM, INFO_MULTIPLE_BOTTOM); continue; } using namespace dammIds::position; float topQdc[numQdcs]; float bottomQdc[numQdcs]; float topQdcTot = 0; float bottomQdcTot = 0; float position = NAN; topQdc[0] = top->GetQdcValue(0); bottomQdc[0] = bottom->GetQdcValue(0); if (bottomQdc[0] == U_DELIMITER || topQdc[0] == U_DELIMITER) { // This happens naturally for traces which have double triggers // Onboard DSP does not write QDCs in this case #ifdef VERBOSE cout << "SSD strip edges are missing QDC information for location " << location << endl; #endif if (topQdc[0] == U_DELIMITER) { // [2] -> Missing top QDC plot(D_INFO_LOCX + location, INFO_MISSING_TOP_QDC); plot(D_INFO_LOCX + LOC_SUM, INFO_MISSING_TOP_QDC); // Recreate qdc from trace if ( !top->GetTrace().empty() ) { topQdc[0] = accumulate(top->GetTrace().begin(), top->GetTrace().begin() + qdcLen[0], 0); } else { topQdc[0] = 0; } } if (bottomQdc[0] == U_DELIMITER) { // [1] -> Missing bottom QDC plot(D_INFO_LOCX + location, INFO_MISSING_BOTTOM_QDC); plot(D_INFO_LOCX + LOC_SUM, INFO_MISSING_BOTTOM_QDC); // Recreate qdc from trace if ( !bottom->GetTrace().empty() ) { bottomQdc[0] = accumulate(bottom->GetTrace().begin(), bottom->GetTrace().begin() + qdcLen[0], 0); } else { bottomQdc[0] = 0; } } if ( topQdc[0] == 0 || bottomQdc[0] == 0 ) { continue; } } // [0] -> good stuff plot(D_INFO_LOCX + location, INFO_OKAY); plot(D_INFO_LOCX + LOC_SUM, INFO_OKAY); for (int i = 1; i < numQdcs; ++i) { if (top->GetQdcValue(i) == U_DELIMITER) { // Recreate qdc from trace topQdc[i] = accumulate(top->GetTrace().begin() + qdcPos[i-1], top->GetTrace().begin() + qdcPos[i], 0); } else { topQdc[i] = top->GetQdcValue(i); } topQdc[i] -= topQdc[0] * qdcLen[i] / qdcLen[0]; topQdcTot += topQdc[i]; topQdc[i] /= qdcLen[i]; if (bottom->GetQdcValue(i) == U_DELIMITER) { // Recreate qdc from trace bottomQdc[i] = accumulate(bottom->GetTrace().begin() + qdcPos[i-1], bottom->GetTrace().begin() + qdcPos[i], 0); } else { bottomQdc[i] = bottom->GetQdcValue(i); } bottomQdc[i] -= bottomQdc[0] * qdcLen[i] / qdcLen[0]; bottomQdcTot += bottomQdc[i]; bottomQdc[i] /= qdcLen[i]; plot(DD_QDCN__QDCN_LOCX + QDC_JUMP * i + location, topQdc[i] + 10, bottomQdc[i] + 10); plot(DD_QDCN__QDCN_LOCX + QDC_JUMP * i + LOC_SUM, topQdc[i], bottomQdc[i]); float frac = topQdc[i] / (topQdc[i] + bottomQdc[i]) * 1000.; // per mil plot(D_QDCNORMN_LOCX + QDC_JUMP * i + location, frac); plot(D_QDCNORMN_LOCX + QDC_JUMP * i + LOC_SUM, frac); if (i == whichQdc) { position = posScale * (frac - minNormQdc[location]) / (maxNormQdc[location] - minNormQdc[location]); sumchan->GetTrace().InsertValue("position", position); plot(DD_POSITION__ENERGY_LOCX + location, position, sumchan->GetCalEnergy()); plot(DD_POSITION__ENERGY_LOCX + LOC_SUM, position, sumchan->GetCalEnergy()); } if (i == 6 && !sumchan->IsSaturated()) { // compare the long qdc to the energy int qdcSum = topQdc[i] + bottomQdc[i]; // MAGIC NUMBERS HERE, move to qdc.txt if (qdcSum < 1000 && sumchan->GetCalEnergy() > 15000) { sumchan->GetTrace().InsertValue("badqdc", 1); } else if ( !isnan(position) ) { plot(DD_POSITION, location, position); } } } // end loop over qdcs // KM QDC - QDC correlations double ratio[4] = {0}; for (int i = 1; i < 5; ++i) { ratio[i - 1] = topQdc[i] / (bottomQdc[i] + topQdc[i]) * 1000.0; } plot(DD_QDCR2__QDCR1_LOCX + location, ratio[1], ratio[0]); plot(DD_QDCR2__QDCR3_LOCX + location, ratio[1], ratio[2]); plot(DD_QDCR2__QDCR4_LOCX + location, ratio[1], ratio[3]); plot(DD_QDC1R__POS_LOCX + location, ratio[0], position * 10.0 + 200.0); plot(DD_QDC2R__POS_LOCX + location, ratio[1], position * 10.0 + 200.0); plot(DD_QDC3R__POS_LOCX + location, ratio[2], position * 10.0 + 200.0); plot(DD_QDC4R__POS_LOCX + location, ratio[3], position * 10.0 + 200.0); topQdcTot /= totLen; bottomQdcTot /= totLen; plot(DD_QDCTOT__QDCTOT_LOCX + location, topQdcTot, bottomQdcTot); plot(DD_QDCTOT__QDCTOT_LOCX + LOC_SUM, topQdcTot, bottomQdcTot); } // end iteration over sum events // test EndProcess(); return true; }