bool PspmtProcessor::PreProcess(RawEvent &event) { if (!EventProcessor::PreProcess(event)) return false; static const vector<ChanEvent *> &pspmtEvents = sumMap["pspmt"]->GetList(); data_.Clear(); double q1 = 0, q2 = 0, q3 = 0, q4 = 0, qd = 0; double qdc1 = 0, qdc2 = 0, qdc3 = 0, qdc4 = 0, qdcd = 0; double tre1 = 0, tre2 = 0, tre3 = 0, tre4 = 0, tred = 0; double qright = 0, qleft = 0, qtop = 0, qbottom = 0, qsum = 0; double xright = 0, xleft = 0, ytop = 0, ybottom = 0; double qtre_r = 0, qtre_l = 0, qtre_t = 0, qtre_b = 0, qtre_s = 0; double xtre_r = 0, xtre_l = 0, ytre_t = 0, ytre_b = 0; double qqdc_r = 0, qqdc_l = 0, qqdc_t = 0, qqdc_b = 0, qqdc_s = 0; //double xqdc_r=0,xqdc_l=0,yqdc_t=0,yqdc_b=0; double pxright = 0, pxleft = 0, pytop = 0, pybottom = 0; double pxtre_r = 0, pxtre_l = 0, pytre_t = 0, pytre_b = 0; // tentatively local params // double threshold = 260; double slope = 0.0606; double intercept = 10.13; ////////////////////////////// static int traceNum; double f = 0.1; for (vector<ChanEvent *>::const_iterator it = pspmtEvents.begin(); it != pspmtEvents.end(); it++) { ChanEvent *chan = *it; string subtype = chan->GetChanID().GetSubtype(); int ch = chan->GetChanID().GetLocation(); double calEnergy = chan->GetCalibratedEnergy(); //double pspmtTime = chan->GetTime(); Trace trace = chan->GetTrace(); double trace_energy; //double trace_time; //double baseline; double qdc; //int num = trace.GetValue("numPulses"); if (!trace.GetFilteredEnergies().empty()) { traceNum++; //trace_time = trace.GetValue("filterTime"); trace_energy = trace.GetFilteredEnergies().front(); //baseline = trace.GetValue("baseline"); qdc = trace.GetQdc(); if (ch == 0) { qdc1 = qdc; tre1 = trace_energy; histo.Plot(D_QDC_TRACE1, qdc1); histo.Plot(D_ENERGY_TRACE1, tre1); } else if (ch == 1) { qdc2 = qdc; tre2 = trace_energy; histo.Plot(D_QDC_TRACE2, qdc2); histo.Plot(D_ENERGY_TRACE2, tre2); } else if (ch == 2) { qdc3 = qdc; tre3 = trace_energy; histo.Plot(D_QDC_TRACE3, qdc3); histo.Plot(D_ENERGY_TRACE3, tre3); } else if (ch == 3) { qdc4 = qdc; tre4 = trace_energy; histo.Plot(D_QDC_TRACE4, qdc4); histo.Plot(D_ENERGY_TRACE4, tre4); } else if (ch == 4) { qdcd = qdc; tred = trace_energy; histo.Plot(D_QDC_TRACED, qdcd); histo.Plot(D_ENERGY_TRACED, tred); } } if (ch == 0) { q1 = calEnergy; histo.Plot(D_RAW1, q1); } else if (ch == 1) { q2 = calEnergy; histo.Plot(D_RAW2, q2); } else if (ch == 2) { q3 = calEnergy; histo.Plot(D_RAW3, q3); } else if (ch == 3) { q4 = calEnergy; histo.Plot(D_RAW4, q4); } else if (ch == 4) { qd = calEnergy; histo.Plot(D_RAWD, qd); } if (q1 > 0 && q2 > 0 && q3 > 0 && q4 > 0) { qtop = (q1 + q2) / 2; qleft = (q2 + q3) / 2; qbottom = (q3 + q4) / 2; qright = (q4 + q1) / 2; qsum = (q1 + q2 + q3 + q4) / 2; xright = (qright / qsum) * 512 + 100; xleft = (qleft / qsum) * 512 + 100; ytop = (qtop / qsum) * 512 + 100; ybottom = (qbottom / qsum) * 512 + 100; histo.Plot(D_SUM, qsum); } if (tre1 > 0 && tre2 > 0 && tre3 > 0 && tre4 > 0) { qtre_t = (tre1 + tre2) / 2; qtre_l = (tre2 + tre3) / 2; qtre_b = (tre3 + tre4) / 2; qtre_r = (tre4 + tre1) / 2; qtre_s = (tre1 + tre2 + tre3 + tre4) / 2; xtre_r = (qtre_r / qtre_s) * 512 + 100; xtre_l = (qtre_l / qtre_s) * 512 + 100; ytre_t = (qtre_t / qtre_s) * 512 + 100; ytre_b = (qtre_b / qtre_s) * 512 + 100; pxtre_r = trunc(slope * xtre_l - intercept); pxtre_l = trunc(slope * xtre_r - intercept); pytre_t = trunc(slope * ytre_t - intercept); pytre_b = trunc(slope * ytre_b - intercept); histo.Plot(D_ENERGY_TRACESUM, qtre_s); if (tre1 > threshold && tre2 > threshold && tre3 > threshold && tre4 > threshold) { histo.Plot(DD_POS1_RAW_TRACE, xtre_r, ytre_t); histo.Plot(DD_POS2_RAW_TRACE, xtre_l, ytre_b); histo.Plot(DD_POS1_TRACE, pxtre_r, pytre_t); histo.Plot(DD_POS2_TRACE, pxtre_l, pytre_b); } } if (qdc1 > 0 && qdc2 > 0 && qdc3 > 0 && qdc4 > 0) { qqdc_t = (qdc1 + qdc2) / 2; qqdc_l = (qdc2 + qdc3) / 2; qqdc_b = (qdc3 + qdc4) / 2; qqdc_r = (qdc4 + qdc1) / 2; qqdc_s = (qqdc_t + qqdc_l + qqdc_b + qqdc_r) / 2; // xqdc_r=(qqdc_r/qqdc_s)*512+100; // xqdc_l=(qqdc_l/qqdc_s)*512+100; // yqdc_t=(qqdc_t/qqdc_s)*512+100; // yqdc_b=(qqdc_b/qqdc_s)*512+100; histo.Plot(D_ENERGY_TRACESUM, qqdc_s); } if (q1 > threshold && q2 > threshold && q3 > threshold && q4 > threshold) { pxleft = trunc(slope * xleft - intercept); pxright = trunc(slope * xright - intercept); pytop = trunc(slope * ytop - intercept); pybottom = trunc(slope * ybottom - intercept); histo.Plot(DD_POS1_RAW, xright, ytop); histo.Plot(DD_POS2_RAW, xleft, ybottom); histo.Plot(DD_POS1, pxright, pytop); histo.Plot(DD_POS2, pxleft, pybottom); if (xright > 341 && xright < 356 && ytop > 200 && ytop < 211) { histo.Plot(D_TEMP0, f * q1); histo.Plot(D_TEMP1, f * q2); histo.Plot(D_TEMP2, f * q3); histo.Plot(D_TEMP3, f * q4); histo.Plot(D_TEMP4, f * qd); } for (vector<unsigned int>::iterator ittr = trace.begin(); ittr != trace.end(); ittr++) histo.Plot(DD_SINGLE_TRACE, ittr - trace.begin(), traceNum, *ittr); } } // end of channel event EndProcess(); return (true); }
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; }