Esempio n. 1
0
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;
}