diff --git a/trg/cdc/dataobjects/include/CDCTriggerTrack.h b/trg/cdc/dataobjects/include/CDCTriggerTrack.h index 9213c0b73b2..a2dd0095bfe 100644 --- a/trg/cdc/dataobjects/include/CDCTriggerTrack.h +++ b/trg/cdc/dataobjects/include/CDCTriggerTrack.h @@ -19,7 +19,7 @@ namespace Belle2 { public: /** default constructor, initializing everything to 0. */ CDCTriggerTrack(): Helix(), m_chi2D(0.), m_chi3D(0.), m_time(0), m_quadrant(-1), m_foundoldtrack(6, false), m_driftthreshold(9, - false), m_valstereobit(false) , m_expert(-1), m_tsvector(9, false), m_qualityvector(0) { } + false), m_valstereobit(false) , m_expert(-1), m_tsvector(9, 0), m_qualityvector(0) { } /** 2D constructor, initializing 3D values to 0. * @param phi0 The angle between the transverse momentum and the x axis and in [-pi, pi]. @@ -45,7 +45,7 @@ namespace Belle2 { m_driftthreshold(driftthreshold), m_valstereobit(valstereobit), m_expert(expert), - m_tsvector(9, false), + m_tsvector(9, 0), m_qualityvector(0) { } CDCTriggerTrack(double phi0, double omega, double chi2, @@ -58,7 +58,7 @@ namespace Belle2 { m_driftthreshold(9, false), m_valstereobit(false), m_expert(-1), - m_tsvector(9, false), + m_tsvector(9, 0), m_qualityvector(0) { } /** 3D constructor @@ -77,7 +77,7 @@ namespace Belle2 { const std::vector& driftthreshold = std::vector(9, false), bool valstereobit = false, int expert = -1, - const std::vector& tsvector = std::vector(9, false), + const std::vector& tsvector = std::vector(9, 0), short time = 0, short quadrant = -1, unsigned qualityvector = 0): Helix(0., phi0, omega, z0, cotTheta), m_chi2D(chi2D), m_chi3D(chi3D), m_time(time), m_quadrant(quadrant), @@ -86,7 +86,9 @@ namespace Belle2 { m_valstereobit(valstereobit), m_expert(expert), m_tsvector(tsvector), - m_qualityvector(qualityvector) { } + m_qualityvector(qualityvector), + m_etf_unpacked(0), + m_etf_recalced(0) { } /** destructor, empty because we don't allocate memory anywhere. */ ~CDCTriggerTrack() { } @@ -106,7 +108,7 @@ namespace Belle2 { return getTransverseMomentum(bField); } /** get the quadrant */ - short getQuadrant() + short getQuadrant() const { return m_quadrant; } @@ -124,7 +126,7 @@ namespace Belle2 { /** return the vector of used Track Segments. * The First bit is the innermost TS, the last bit the outermost. */ - std::vector getTSVector() const {return m_tsvector;} + std::vector getTSVector() const {return m_tsvector;} /** setter and getter for the quality vector. For the setter, the given * uint is xored with the current qualityvector, thus all bits with * a 1 are changed. @@ -134,9 +136,36 @@ namespace Belle2 { m_qualityvector = m_qualityvector ^ newbits; } unsigned getQualityVector() const {return m_qualityvector;} + void setHasETFTime(bool x) {m_hasETFTime = x;} + bool getHasETFTime() const {return m_hasETFTime;} + /** getter and setter functions for etf timing */ + int getETF_unpacked() const {return m_etf_unpacked;} + int getETF_recalced() const {return m_etf_recalced;} + void setETF_unpacked(int x) {m_etf_unpacked = x;} + void setETF_recalced(int x) {m_etf_recalced = x;} + /** setter and getter functions for raw track values */ + void setRawPhi0(const int phi0) + { + m_rawphi0 = phi0; + } + void setRawOmega(const int omega) + { + m_rawomega = omega; + } + void setRawZ(const int z) + { + m_rawz = z; + } + void setRawTheta(const int theta) + { + m_rawtheta = theta; + } + int getRawPhi0() const {return m_rawphi0;} + int getRawOmega() const {return m_rawomega;} + int getRawZ() const {return m_rawz;} + int getRawTheta() const {return m_rawtheta;} protected: - /** chi2 value from 2D fitter */ float m_chi2D; /** chi2 value from 3D fitter */ float m_chi3D; @@ -154,13 +183,33 @@ namespace Belle2 { int m_expert; /** store which track segments were used. * The First bit is the innermost TS, the last bit the outermost. */ - std::vector m_tsvector; + std::vector m_tsvector; /** store bits for different quality flags. * 2^0 : 0 if all axial ts are contained in the related 2dfindertrack; 1 otherwise. + * 2^1 : 0 if hwsim nntrack is less than 1cm in z away from hwtrack; 1 otherwise. + * 2^2 : 0 if all input values for the ID are exactly the same in hw and hwsim; 1 otherwise. + * 2^3 : 0 if all input values for alpa are exactly the same in hw and hwsim; 1 otherwise. + * 2^4 : 1 if dt in hw/hwsim is 0 and in hwsim/hw is 1; 0 otherwise. + * 2^5 : 1 if all inputs in hw are 0 but at least 1 is filled in hwsim; 0 otherwise. + * 2^6 : 1 if all inputs in hwsim are 0 but at least 1 is filled in hw; 0 otherwise. + * 2^7 : 1 if more than 1 etf time was recalculated from hw. this indicates, that an old input + * from a previous track was used in the network. */ unsigned m_qualityvector; + /** unpacked etf time from the unpacker */ + int m_etf_unpacked; + /** etf time recalculated from the hw input */ + int m_etf_recalced; + /** chi2 value from 2D fitter */ + bool m_hasETFTime{0}; + /** values to store the raw network and 2dfinder output */ + int m_rawphi0{0}; + int m_rawomega{0}; + int m_rawz{0}; + int m_rawtheta{0}; //! Needed to make the ROOT object storable - ClassDef(CDCTriggerTrack, 9); + ClassDef(CDCTriggerTrack, 14); + }; } #endif diff --git a/trg/cdc/dataobjects/include/linkdef.h b/trg/cdc/dataobjects/include/linkdef.h index e4c85a68fe3..00f56822e5a 100644 --- a/trg/cdc/dataobjects/include/linkdef.h +++ b/trg/cdc/dataobjects/include/linkdef.h @@ -11,7 +11,7 @@ #pragma link C++ class bitset <639>+; // checksum=0x88f24d, version=2 #pragma link C++ class bitset <256>+; // checksum=0x88f1ea, version=2 #pragma link C++ class Belle2::CDCTriggerSegmentHit+; // checksum=0x89ed4679, version=4 -#pragma link C++ class Belle2::CDCTriggerTrack+; // checksum=0x589cc554, version=9 +#pragma link C++ class Belle2::CDCTriggerTrack+; // checksum=0xdde6f688, version=14 #pragma link C++ class Belle2::CDCTriggerMLP+; // checksum=0x2d137aa, version=7 #pragma link C++ class Belle2::CDCTriggerMLPData+; // checksum=0x48969a58, version=1 #pragma link C++ class Belle2::CDCTriggerMLPInput+; // checksum=0x6fd59940, version=1 diff --git a/trg/cdc/include/NeuroTrigger.h b/trg/cdc/include/NeuroTrigger.h index 2f9cae4b561..b6329dfbcc2 100644 --- a/trg/cdc/include/NeuroTrigger.h +++ b/trg/cdc/include/NeuroTrigger.h @@ -7,7 +7,8 @@ **************************************************************************/ #ifndef NEUROTRIGGER_H #define NEUROTRIGGER_H - +#pragma once +#include #include #include #include @@ -142,6 +143,7 @@ namespace Belle2 { /** set the hit collection and event time to required * and store the hit collection name */ void initializeCollections(std::string hitCollectionName, std::string eventTimeName, const std::string& et_option); + void initializeCollections(std::string hitCollectionName); /** return reference to a neural network */ CDCTriggerMLP& operator[](unsigned index) { return m_MLPs[index]; } @@ -179,6 +181,8 @@ namespace Belle2 { /** Calculate phi position of a hit relative to 2D track * (scaled to number of wires). */ double getRelId(const CDCTriggerSegmentHit& hit); + /** helper function to get the fastest priority time of given ts array */ + int getLowestTime(unsigned isector, RelationVector Hits, bool onlyAxials); /** Read out the event time and store it. * It can be given different options in the et_option ("EventTime option") * parameter. diff --git a/trg/cdc/include/Unpacker.h b/trg/cdc/include/Unpacker.h index 5e0f772a6a8..b8394d59dbe 100644 --- a/trg/cdc/include/Unpacker.h +++ b/trg/cdc/include/Unpacker.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace Belle2 { @@ -254,6 +255,9 @@ namespace Belle2 { double phi0; /// all TS of a 2D track tsOutArray ts; + // hw values of 2dtrack + int hwOmega{0}; + int hwPhi0{0}; }; /// TRG Neuro track struct TRGNeuroTrack { @@ -271,6 +275,9 @@ namespace Belle2 { std::array inputAlpha; /// input TS list of a NN track std::array ts; + /// raw output values of hw network + int hwZ{0}; + int hwTheta{0}; }; struct B2LDataField { B2LDataField( @@ -293,7 +300,6 @@ namespace Belle2 { data = ""; } - // std::cout << "new datafield: " << b2line.name << ": " << b2line.start << ", " << b2line.end << ", " << data << std::endl; name = b2line.name; } @@ -386,6 +392,51 @@ namespace Belle2 { int signal_out = (int16_t (signal_bit.to_ulong() << shift)) >> shift; return signal_out; } + /** function to recalculate the event t0 used in the hardware neurotrigger + * by using the priority times from the track segments and subtracting the relative + * time from the hw network input vector. + */ + int recalcETF(std::string driftinput, std::vector tsvector, CDCTriggerTrack* track) + { + //scale factor to get a value between -1 and 1 + float scale = 1. / (1 << (driftinput.size() - 1) / 9); + int ret = 0; + bool stor = false; + // make a table, with > table; + for (unsigned iSL = 0; iSL < 9; ++iSL) { + // getting the relative drift time in clock cycles (1cc ~ 2ns) + int reldt = static_cast(fabs((mlp_bin_to_signed_int(driftinput.substr((8 - iSL) * driftinput.size() / 9, + driftinput.size() / 9)) * scale * 256))); + int tstime = static_cast(tsvector[iSL]); + // we do not want SLs with no LR info or pts outside of the time window + if (reldt != 0 && reldt < 255) { + for (std::vector& x : table) { + stor = false; + if (x[0] == tstime - reldt) { + x[1]++; + stor = true; + } + } + if (!stor) {table.push_back({tstime - reldt, 1});} + } + + } + // now get the event t0 recalculated most often and return it in the end + int maxi = 0; + for (std::vector& x : table) { + if (x[1] > maxi) { + ret = x[0]; + maxi = x[1]; + } + } + // if there is a "wrong" input in the hardware values, the corresponding error bit is set + if (table.size() > 1) {track->setQualityVector(128);} + return ret; + + } /** * Decode the track segment hit from the bit string @@ -491,6 +542,7 @@ namespace Belle2 { // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits // thus the signed bit is preserved (when right-shifting) int omegafirm = (int16_t (omega << shift)) >> shift; + trackout.hwOmega = omegafirm; //int omegafirm = (int16_t (omega.to_ulong() << shift)) >> shift; // B field is 1.5T const double BField = 1.5e-4; // why is it so small? @@ -502,6 +554,7 @@ namespace Belle2 { int phi = std::stoi(p_phi, 0, 2); + trackout.hwPhi0 = phi; // c.f. https://confluence.desy.de/download/attachments/34033650/output-def.pdf double globalPhi0 = pi() / 4 + pi() / 2 / 80 * (phi + 1) + pi() / 2 * iTracker; // see document above @@ -537,6 +590,7 @@ namespace Belle2 { // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits // thus the signed bit is preserved (when right-shifting) int omegaFirm = (int16_t (omega.to_ulong() << shift)) >> shift; + trackOut.hwOmega = omegaFirm; // B field is 1.5T const double BField = 1.5e-4; // omega in 1/cm @@ -544,6 +598,7 @@ namespace Belle2 { // c.f. https://confluence.desy.de/download/attachments/34033650/output-def.pdf trackOut.omega = Const::speedOfLight * BField / 0.3 / 34 * omegaFirm; int phi0 = std::bitset(trackIn.substr(trackPos[2], trackLens[2])).to_ulong(); + trackOut.hwPhi0 = phi0; trackOut.phi0 = pi() / 4 + pi() / 2 / 80 * (phi0 + 1); for (unsigned i = 0; i < 5; ++i) { trackOut.ts[i] = decodeTSHit(trackIn.substr(trackPos.back() + i * lenTS, lenTS)); @@ -587,6 +642,8 @@ namespace Belle2 { TRGNeuroTrack foundTrack; int theta_raw = mlp_bin_to_signed_int(p_mlpout_theta); int z_raw = mlp_bin_to_signed_int(p_mlpout_z); + foundTrack.hwZ = z_raw; + foundTrack.hwTheta = theta_raw; std::vector unscaledT = neurodb->getMLPs()[0].unscaleTarget({(z_raw * scale_z), (theta_raw * scale_theta)}); foundTrack.z = unscaledT[0]; foundTrack.theta = unscaledT[1]; @@ -971,13 +1028,15 @@ namespace Belle2 { TRGNeuroTrack trkNN = decodeNNTrack_old(strTrack, strSelect); B2DEBUG(15, "make new NN track with , z:" << trkNN.z << ", theta:" << trkNN.theta << ", sector:" << trkNN.sector << ", clock " << foundTime); - double phi0 = track2D->getPhi0(); - double omega = track2D->getOmega(); - std::vector tsvector(9, false); + double phi0 = 0; + double omega = 0; + if (track2D) { + phi0 = track2D->getPhi0(); + omega = track2D->getOmega(); + } + std::vector tsvector(9, 0); for (unsigned iSL = 0; iSL < 9; ++iSL) { - if (trkNN.ts[iSL][3] > 0) { - tsvector[iSL] = true; - } + tsvector[iSL] = trkNN.ts[iSL][2]; // save lr info in tsvector array } CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0., trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(), @@ -1025,7 +1084,8 @@ namespace Belle2 { StoreArray* tsHits, StoreArray* tsHitsAll, StoreArray* storeNNInputs, - const DBObjPtr& neurodb, + StoreObjPtr storeETFTime, + const DBObjPtr neurodb, bool sim13dt) { for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) { @@ -1201,6 +1261,31 @@ namespace Belle2 { iclock); continue; } + B2LDataField p_etftime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etftime")); + if ((p_etftime.name != "None") && (p_etftime.data.size() == 0)) { + B2DEBUG(10, "Could not load Datafield: " << p_etftime.name << " from bitstream. Maybe offset was out of bounds? clock: " << + iclock); + continue; + } + B2LDataField p_etfcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfcc")); + if ((p_etfcc.name != "None") && (p_etfcc.data.size() == 0)) { + B2DEBUG(10, "Could not load Datafield: " << p_etfcc.name << " from bitstream. Maybe offset was out of bounds? clock: " << + iclock); + continue; + } + B2LDataField p_etfqual(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfquality")); + if ((p_etfqual.name != "None") && (p_etfqual.data.size() == 0)) { + B2DEBUG(10, "Could not load Datafield: " << p_etfqual.name << " from bitstream. Maybe offset was out of bounds? clock: " << + iclock); + continue; + } + B2LDataField p_etfval(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfvalid")); + if ((p_etfval.name != "None") && (p_etfval.data.size() == 0)) { + B2DEBUG(10, "Could not load Datafield: " << p_etfval.name << " from bitstream. Maybe offset was out of bounds? clock: " << + iclock); + continue; + } + // B2LDataField (bitsNN, iclock, iTracker, neurodb->getB2FormatLine("")); CDCTriggerTrack* track2D = nullptr; @@ -1228,7 +1313,16 @@ namespace Belle2 { } } B2DEBUG(21, padright(" 2DCC: " + std::to_string(std::stoi(p_2dcc.data, 0, 2)) + ", (" + p_2dcc.data + ")", 100)); + B2DEBUG(21, padright(" ETFCC: " + std::to_string(std::stoi(p_etfcc.data, 0, 2)) + ", (" + p_etfcc.data + ")", 100)); + B2DEBUG(21, padright(" ETFVAL: " + std::to_string(std::stoi(p_etfval.data, 0, 2)) + ", (" + p_etfval.data + ")", 100)); + B2DEBUG(21, padright(" ETFT0: " + std::to_string(std::stoi(p_etftime.data, 0, 2)) + ", (" + p_etftime.data + ")", 100)); + B2DEBUG(21, padright(" ETFQuality: " + std::to_string(std::stoi(p_etfqual.data, 0, 2)) + ", (" + p_etfqual.data + ")", 100)); + bool hasETFTime = false; if (p_nnenable.data == "1") { + if (p_etfval.data == "1") { + storeETFTime->addBinnedEventT0(std::stoi(p_etftime.data, 0, 2), Const::CDC); + hasETFTime = true; + } std::vector foundoldtrack{false}; std::vector driftthreshold{false}; bool valstereobit; @@ -1259,6 +1353,8 @@ namespace Belle2 { p_2dcc.data, sim13dt); track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, iclock, iTracker); + track2D->setRawOmega(trk2D.hwOmega); + track2D->setRawPhi0(trk2D.hwPhi0); B2DEBUG(12, padright(" 2DTrack: (phi=" + std::to_string(trk2D.phi0) + ", omega=" + std::to_string( trk2D.omega) + ", update=" + std::to_string(foundoldtrack[1]) + ")", 100)); @@ -1298,13 +1394,15 @@ namespace Belle2 { double phi0 = track2D->getPhi0(); double omega = track2D->getOmega(); - std::vector tsvector(9, false); + std::vector tsvector(9, 0); + std::vector tstimevector(9, 0); tsstr = ""; // turns false, as soon as there is a ts, which is not contained in the 2dfindertrack bool isin2d = true; for (unsigned iSL = 0; iSL < 9; ++iSL) { + tsvector[iSL] = trkNN.ts[iSL][3]; + tstimevector[iSL] = trkNN.ts[iSL][1]; if (trkNN.ts[iSL][3] > 0) { - tsvector[iSL] = true; unsigned iTS = TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker); tsstr += "(SL" + std::to_string(iSL) + ", " + std::to_string(iTS) + ", " + std::to_string(trkNN.ts[iSL][1]) + ", " + std::to_string( trkNN.ts[iSL][2]) + ", " + std::to_string(trkNN.ts[iSL][3]) + "),\n"; @@ -1328,6 +1426,18 @@ namespace Belle2 { CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0., trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(), track2D->getValidStereoBit(), trkNN.sector, tsvector, iclock, iTracker); + trackNN->setHasETFTime(hasETFTime); + track2D->setHasETFTime(hasETFTime); + trackNN->setRawOmega(track2D->getRawOmega()); + trackNN->setRawPhi0(track2D->getRawPhi0()); + trackNN->setRawTheta(trkNN.hwTheta); + trackNN->setRawZ(trkNN.hwZ); + if (hasETFTime) { + trackNN->setETF_unpacked(std::stoi(p_etftime.data, 0, 2)); + track2D->setETF_unpacked(std::stoi(p_etftime.data, 0, 2)); + } + trackNN->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN)); + track2D->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN)); if (isin2d == false) { trackNN->setQualityVector(1); diff --git a/trg/cdc/modules/dqmneuro/include/CDCTriggerNeuroDQMModule.h b/trg/cdc/modules/dqmneuro/include/CDCTriggerNeuroDQMModule.h index d947ba37378..6b214da872e 100644 --- a/trg/cdc/modules/dqmneuro/include/CDCTriggerNeuroDQMModule.h +++ b/trg/cdc/modules/dqmneuro/include/CDCTriggerNeuroDQMModule.h @@ -11,10 +11,12 @@ #include #include +#include #include #include #include #include +#include #include "TH1F.h" #include "TH2F.h" @@ -159,7 +161,6 @@ namespace Belle2 { } } } - /** Name of the histogram directory in ROOT file */ std::string m_histogramDirectoryName; /** Switch to supress output for dqm online module */ @@ -237,7 +238,8 @@ namespace Belle2 { StoreArray m_simNeuroInputVectorSWTSSW2D; /** StoreArray for neuro tracks using simulated TS and simulated 2D */ StoreArray m_simNeuroTracksSWTSSW2D; - + /** storeobjpointer for event time */ + StoreObjPtr m_eventTime; // histograms for neurotrigger TH1F* m_neuroHWOutZ = nullptr; /**< z distribution of unpacked neuro tracks */ TH1F* m_neuroHWOutCosTheta = nullptr; /**< cos theta distribution of unpacked neuro tracks */ diff --git a/trg/cdc/modules/dqmneuro/src/CDCTriggerNeuroDQMModule.cc b/trg/cdc/modules/dqmneuro/src/CDCTriggerNeuroDQMModule.cc index 3f1b050c098..6e637e9237a 100644 --- a/trg/cdc/modules/dqmneuro/src/CDCTriggerNeuroDQMModule.cc +++ b/trg/cdc/modules/dqmneuro/src/CDCTriggerNeuroDQMModule.cc @@ -81,7 +81,7 @@ CDCTriggerNeuroDQMModule::CDCTriggerNeuroDQMModule() : HistoModule() (double)(- 1.0)); addParam("nSameTS", m_nsamets, "Number of identical track segments to be required for matching between HW and SW Neurotrigger", - (int)(9)); + (int)(0)); } @@ -1264,6 +1264,7 @@ void CDCTriggerNeuroDQMModule::initialize() { // Register histograms (calls back defineHisto) REG_HISTOGRAM + m_eventTime.isRequired("CDCTriggerNeuroETFT0"); if (m_showRecoTracks && m_recoTracksName == "") { m_recoTracksName = "RecoTracks"; } @@ -2497,6 +2498,7 @@ void CDCTriggerNeuroDQMModule::event() if (nsameTS >= m_nsamets) { if (abs(neuroTrack.getZ0() - neuroSimTrack->getZ0()) > 1) { neuroSimTrack->setQualityVector(2); + neuroTrack.setQualityVector(2); } m_neuroDeltaZ->Fill(neuroTrack.getZ0() - neuroSimTrack->getZ0()); double nnHWtheta = neuroTrack.getDirection().Theta() * 180. / M_PI; @@ -2513,12 +2515,32 @@ void CDCTriggerNeuroDQMModule::event() unsigned simSector = neuroSimTrack->getRelatedTo(m_simNeuroInputVectorName)->getSector(); m_neuroDeltaSector->Fill(unpackedSector - simSector); - + bool sameInputId = true; + bool sameInputAlpha = true; + bool scaleErr = false; + bool missingTS = false; + bool timeErr = false; for (unsigned ii = 0; ii < unpackedInput.size(); ii += 3) { m_neuroDeltaInputID->Fill(unpackedInput[ii] - simInput[ii]); m_neuroDeltaInputT->Fill(unpackedInput[ii + 1] - simInput[ii + 1]); m_neuroDeltaInputAlpha->Fill(unpackedInput[ii + 2] - simInput[ii + 2]); + bool hwZero = false; + bool hwSimZero = false; + if (unpackedInput[ii] != simInput[ii]) {sameInputId = false;} + if (unpackedInput[ii + 2] != simInput[ii + 2]) {sameInputAlpha = false;} + if (unpackedInput[ii + 1] != simInput[ii + 1]) {timeErr = true;} + if (unpackedInput[ii + 1] == 0 && fabs(simInput[ii + 1] > 0.99)) {scaleErr = true;} + if (simInput[ii + 1] == 0 && fabs(unpackedInput[ii + 1] > 0.99)) {scaleErr = true;} + if (unpackedInput[ii] == 0 && unpackedInput[ii + 1] == 0 && unpackedInput[ii + 2] == 0) {hwZero = true;} + if (simInput[ii] == 0 && simInput[ii + 1] == 0 && simInput[ii + 2] == 0) {hwSimZero = true;} + if (hwZero != hwSimZero) {missingTS = true;} } + if (!sameInputId) {neuroTrack.setQualityVector(4);} + if (!sameInputAlpha) {neuroTrack.setQualityVector(8);} + if (scaleErr) {neuroTrack.setQualityVector(16);} + if (missingTS) {neuroTrack.setQualityVector(32);} + if (timeErr) {neuroTrack.setQualityVector(64);} + } } } @@ -2959,35 +2981,53 @@ void CDCTriggerNeuroDQMModule::event() std::stringstream strphi; std::stringstream strtheta; std::stringstream strz; + std::stringstream hwomega; + std::stringstream hwphi; + std::stringstream hwtheta; + std::stringstream hwz; strpt << std::fixed << std::setprecision(2) << ltrack.getPt(); stromega << std::fixed << std::setprecision(2) << ltrack.getOmega(); strphi << std::fixed << std::setprecision(2) << (ltrack.getPhi0() * 180. / M_PI); strtheta << std::fixed << std::setprecision(2) << (ltrack.getDirection().Theta() * 180. / M_PI); strz << std::fixed << std::setprecision(2) << ltrack.getZ0(); - std::string trs = " HWNeuroTrack Nr. " + std::to_string(hwntrn) + " (pt, omega, phi, theta, z) = "; - trs += padto(strpt.str(), 6) + ", " + padto(stromega.str(), 6) + ", " + padto(strphi.str(), 6) + ", " + padto(strtheta.str(), - 6) + ", " + padto(strz.str(), 6) + ")"; + hwomega << std::fixed << std::setprecision(0) << ltrack.getRawOmega(); + hwphi << std::fixed << std::setprecision(0) << ltrack.getRawPhi0(); + hwtheta << std::fixed << std::setprecision(0) << ltrack.getRawTheta(); + hwz << std::fixed << std::setprecision(0) << ltrack.getRawZ(); + std::string trs = " HWNeuroTrack Nr. " + std::to_string(hwntrn) + " (pt,om,phi,theta,z)=("; + trs += padto(strpt.str(), 4) + "," + padto(stromega.str(), 6) + "," + padto(strphi.str(), 6) + "," + padto(strtheta.str(), + 6) + "," + padto(strz.str(), 6) + "),(x," + padto(hwomega.str(), 3) + "," + padto(hwphi.str(), 3) + "," + padto(hwtheta.str(), + 3) + "," + padto(hwz.str(), 3) + ")"; B2DEBUG(15, padright(trs, 100)); - std::string infostr = " Found old track: ( "; + std::string infostr = ", Found old track: ( "; for (bool x : ltrack.getFoundOldTrack()) { - infostr += std::to_string(x) + " "; + infostr += std::to_string(x); } infostr += "), "; infostr = padright(infostr, 50); infostr += "Drift threshold: ( "; for (bool x : ltrack.getDriftThreshold()) { - infostr += std::to_string(x) + " "; + infostr += std::to_string(x); } infostr += ")"; infostr += (ltrack.getValidStereoBit()) ? " valid" : " NOT valid"; B2DEBUG(15, padright(infostr, 100)); + std::string infostr2 = " std. ETF vld:"; + infostr2 += std::to_string(m_eventTime.isValid()); + infostr2 += ", ETFT0: "; + infostr2 += std::to_string(m_eventTime->getBinnedEventT0(Const::CDC)); + infostr2 += ", ETF in CC: "; + infostr2 += std::to_string(ltrack.getETF_unpacked()); + infostr2 += ", ETF recalculated: "; + infostr2 += std::to_string(ltrack.getETF_recalced()); + B2DEBUG(15, padright(infostr2, 100)); std::string info2str = " Expert Network Number: " + std::to_string(ltrack.getExpert()); info2str += ", TSVector: ("; - for (bool x : ltrack.getTSVector()) { + for (unsigned x : ltrack.getTSVector()) { info2str += std::to_string(x) + " "; } info2str += ")"; - info2str += ", Q="; + info2str += ", Quality="; info2str += std::to_string(ltrack.getQualityVector()); B2DEBUG(15, padright(info2str, 100)); CDCTriggerTrack* ftrack = ltrack.getRelatedFrom(m_unpackedNeuroInput2DTracksName); @@ -3054,10 +3094,13 @@ void CDCTriggerNeuroDQMModule::event() strphi << std::fixed << std::setprecision(2) << (ltrack.getPhi0() * 180. / M_PI); strtheta << std::fixed << std::setprecision(2) << (ltrack.getDirection().Theta() * 180. / M_PI); strz << std::fixed << std::setprecision(2) << ltrack.getZ0(); - strquality << std::fixed << ltrack.getQualityVector(); - std::string trs = " SWNeuroTrack Nr. " + std::to_string(swntrn) + " (pt, omega, phi, theta, z) = "; - trs += padto(strpt.str(), 6) + ", " + padto(stromega.str(), 6) + ", " + padto(strphi.str(), 6) + ", " + padto(strtheta.str(), - 6) + ", " + padto(strz.str(), 6) + ")" + ", Q=" + strquality.str(); + strquality << std::fixed << ltrack.getQualityVector(); + + std::string trs = " SWNeuroTrack Nr. " + std::to_string(swntrn) + " (pt,om,phi,theta,z)=("; + trs += padto(strpt.str(), 5) + "," + padto(stromega.str(), 5) + "," + padto(strphi.str(), 6) + "," + padto(strtheta.str(), + 6) + ", " + padto(strz.str(), 6) + ")" + + /**,(x," + padto(intomega.str(), 2) + "," + padto(intphi.str(), 3) + "," + padto(inttheta.str(), + 3) + "," + padto(intz.str(), 3) + "),*/ " Q=" + strquality.str(); B2DEBUG(15, padright(trs, 100)); } } diff --git a/trg/cdc/modules/neurotrigger/src/CDCTriggerNeuroModule.cc b/trg/cdc/modules/neurotrigger/src/CDCTriggerNeuroModule.cc index d5260fdcddd..c9e4ce71e0f 100644 --- a/trg/cdc/modules/neurotrigger/src/CDCTriggerNeuroModule.cc +++ b/trg/cdc/modules/neurotrigger/src/CDCTriggerNeuroModule.cc @@ -64,7 +64,7 @@ CDCTriggerNeuroModule::CDCTriggerNeuroModule() : Module() "option on how to obtain the event time. When left blank, the value " "is loaded from the Conditions Database. Possibilities are: " "'etf_only', 'fastestpriority', 'zero', 'etf_or_fastestpriority', " - "'etf_or_zero', 'etf_or_fastest2d', 'fastest2d'.", + "'etf_or_zero', 'etf_or_fastest2d', 'fastest2d', 'etfcc' for the unpacked etf in the corresponding cc, 'etfcc_or_fastestpriority', 'etfcc_or_zero', 'etfhwin' for the recalculated time used in hw input. Last two options are only available for neurotrackinputode.", string("")); addParam("writeMLPinput", m_writeMLPinput, "if true, the MLP input vector will be written to the datastore " @@ -182,9 +182,9 @@ CDCTriggerNeuroModule::event() int thetaIndex = m_NeuroTrigger[isector].thetaIndex(); double cot = (thetaIndex >= 0) ? cos(target[thetaIndex]) / sin(target[thetaIndex]) : 0.; bool valtrack = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getValidStereoBit() : true; - std::vector tsvector; - for (int k = 0; k < 9; k++) { - tsvector.push_back(bool ((chitPattern & (1 << k)) >> k)); + std::vector tsvector(9, 0); + for (unsigned i = 0; i < hitIds.size(); ++i) { + tsvector[m_segmentHits[hitIds[i]]->getISuperLayer()] = m_segmentHits[hitIds[i]]->getLeftRight(); } tsvector = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getTSVector() : tsvector; std::vector driftthreshold; @@ -194,16 +194,19 @@ CDCTriggerNeuroModule::event() int expert = (m_neuroTrackInputMode) ? m_tracks2D[itrack]->getExpert() : isector; short quadrant = 0; double tphi = m_tracks2D[itrack]->getPhi0(); - if (tphi > -1 * M_PI_4 && tphi < 1 * M_PI_4) { quadrant = 0; } - else if (tphi > 1 * M_PI_4 && tphi < 3 * M_PI_4) { quadrant = 1; } - else if (tphi > 3 * M_PI_4 || tphi < -3 * M_PI_4) { quadrant = 2; } - else if (tphi > -3 * M_PI_4 && tphi < -1 * M_PI_4) { quadrant = 3; } - + if (m_neuroTrackInputMode) { + quadrant = m_tracks2D[itrack]->getQuadrant(); + } else { + if (tphi > -1 * M_PI_4 && tphi < 1 * M_PI_4) { quadrant = 0; } + else if (tphi > 1 * M_PI_4 && tphi < 3 * M_PI_4) { quadrant = 1; } + else if (tphi > 3 * M_PI_4 || tphi < -3 * M_PI_4) { quadrant = 2; } + else if (tphi > -3 * M_PI_4 && tphi < -1 * M_PI_4) { quadrant = 3; } + } - const CDCTriggerTrack* NNtrack = + CDCTriggerTrack* NNtrack = m_tracksNN.appendNew(m_tracks2D[itrack]->getPhi0(), m_tracks2D[itrack]->getOmega(), m_tracks2D[itrack]->getChi2D(), @@ -214,10 +217,27 @@ CDCTriggerNeuroModule::event() expert, tsvector, m_tracks2D[itrack]->getTime(), - quadrant //quadrant simulated from phi - - 1, //quadrant not known in simulation + quadrant, //quadrant simulated from phi m_tracks2D[itrack]->getQualityVector() ); + std::stringstream intomega; + std::stringstream intphi; + std::stringstream intz; + std::stringstream inttheta; + intomega << std::fixed << std::setprecision(0) << NNtrack->getOmega() / Const::speedOfLight / 1.5e-4 * 0.3 * 34.; + intphi << std::fixed << std::setprecision(0) << (((NNtrack->getPhi0() - M_PI / 2.*NNtrack->getQuadrant()) - M_PI / 4.) * 2 * + 80 / + M_PI); + std::vector recalcsw(0.); + recalcsw = m_cdctriggerneuroconfig->getMLPs()[0].scaleTarget({static_cast(NNtrack->getZ0()), static_cast(NNtrack->getDirection().Theta())}); + intz << std::fixed << std::setprecision(0) << recalcsw[0] * 4096; + inttheta << std::fixed << std::setprecision(0) << recalcsw[1] * 4096; + + NNtrack->setRawOmega(std::stoi(intomega.str())); + NNtrack->setRawPhi0(std::stoi(intphi.str())); + NNtrack->setRawZ(std::stoi(intz.str())); + NNtrack->setRawTheta(std::stoi(inttheta.str())); + m_tracks2D[itrack]->addRelationTo(NNtrack); if (m_neuroTrackInputMode) { m_tracks2D[itrack]->getRelatedFrom(m_realinputCollectionName)->addRelationTo(NNtrack); diff --git a/trg/cdc/modules/unpacker/include/CDCTriggerUnpackerModule.h b/trg/cdc/modules/unpacker/include/CDCTriggerUnpackerModule.h index 4d8da2cace8..53c0ab0a46a 100644 --- a/trg/cdc/modules/unpacker/include/CDCTriggerUnpackerModule.h +++ b/trg/cdc/modules/unpacker/include/CDCTriggerUnpackerModule.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -313,6 +315,9 @@ namespace Belle2 { /** bitstream of Neuro input and output (including intermediate results) */ StoreArray m_bitsNN; + /** store object for unpacked etf event time from neuro b2link */ + StoreObjPtr m_ETFTime; + /** decoded Neuro tracks */ StoreArray m_NeuroTracks; diff --git a/trg/cdc/modules/unpacker/src/CDCTriggerUnpackerModule.cc b/trg/cdc/modules/unpacker/src/CDCTriggerUnpackerModule.cc index 14431c20a3f..6c4a588f1d9 100644 --- a/trg/cdc/modules/unpacker/src/CDCTriggerUnpackerModule.cc +++ b/trg/cdc/modules/unpacker/src/CDCTriggerUnpackerModule.cc @@ -636,6 +636,7 @@ void CDCTriggerUnpackerModule::initialize() m_NNInput2DFinderTracks.registerInDataStore("CDCTriggerNNInput2DFinderTracks"); m_NeuroTracks.registerInDataStore("CDCTriggerNeuroTracks"); m_NeuroInputs.registerInDataStore("CDCTriggerNeuroTracksInput"); + m_ETFTime.registerInDataStore("CDCTriggerNeuroETFT0"); m_NeuroTracks.registerRelationTo(m_NNInputTSHits); m_NNInput2DFinderTracks.registerRelationTo(m_NNInputTSHits); m_NNInput2DFinderTracks.registerRelationTo(m_NNInputTSHitsAll); @@ -720,7 +721,10 @@ void CDCTriggerUnpackerModule::beginRun() void CDCTriggerUnpackerModule::event() { - + if (m_decodeNeuro == true) { + // needed to unpack neuroinput etf time without problems + if (!m_ETFTime.isValid()) m_ETFTime.create(); + } B2DEBUG(10, padright(" ", 100)); B2DEBUG(10, "----------------------------------------------------------------------------------------------------"); B2DEBUG(10, padright(" ", 100)); @@ -838,7 +842,7 @@ void CDCTriggerUnpackerModule::event() B2DEBUG(99, "now unpack neuro "); if (m_decodeNeuro) { if (m_useDB == true) { - decodeNNIO(&m_bitsNN, &m_NNInput2DFinderTracks, &m_NeuroTracks, &m_NNInputTSHits, &m_NNInputTSHitsAll, &m_NeuroInputs, + decodeNNIO(&m_bitsNN, &m_NNInput2DFinderTracks, &m_NeuroTracks, &m_NNInputTSHits, &m_NNInputTSHitsAll, &m_NeuroInputs, m_ETFTime, m_cdctriggerneuroconfig, m_sim13dt); } else { decodeNNIO_old(&m_bitsNN, &m_NNInput2DFinderTracks, &m_NeuroTracks, &m_NNInputTSHits, &m_NeuroInputs); diff --git a/trg/cdc/scripts/neurotrigger.py b/trg/cdc/scripts/neurotrigger.py index aa099772f20..0c72e67048a 100644 --- a/trg/cdc/scripts/neurotrigger.py +++ b/trg/cdc/scripts/neurotrigger.py @@ -6,7 +6,7 @@ # This file is licensed under LGPL-3.0, see LICENSE.md. # ########################################################################## -import basf2 as b2 +import basf2 from ROOT import Belle2 ################################################################################ @@ -37,33 +37,23 @@ ################################################################################ -class filterTRG(b2.Module): - def initialize(self, branchname=hwneuroinput2dfindertracks): - self.branchname = branchname - self.nullpath = b2.create_path() - - def event(self): - self.return_value(bool(Belle2.PyStoreArray(self.branchname).getEntries() > 0)) - self.if_false(self.nullpath) +def filterTRG(path): + nullpath = basf2.create_path() + mfilter = basf2.register_module("CDCTriggerUnpacker", unpackNeuro=True) + path.add_module(mfilter) + mfilter.if_value('<1', nullpath) -class nnt_eventfilter(b2.Module): - def initialize(self, - tracksegmentsname=hwneuroinputsegmenthits, - twodtracksname=hwneuroinput2dfindertracks, - neurotracksname=hwneurotracks, - recotracksname="RecoTracks" - ): - self.tracksegmentsname = tracksegmentsname - self.twodtracksname = twodtracksname - self.neurotracksname = neurotracksname - self.recotracksname = recotracksname - self.nullpath = b2.create_path() +class nnt_eventfilter(basf2.Module): + def initialize(self): + self.tracksegmentsname = hwneuroinputsegmenthits, + self.twodtracksname = hwneuroinput2dfindertracks, + self.neurotracksname = hwneurotracks, + self.recotracksname = "RecoTracks" + self.nullpath = basf2.create_path() def event(self): - self.return_value(bool(self.hastrginfo() and - self.neurotrack_allgoodquality() - )) + self.return_value(bool(self.neurotrack_allgoodquality())) self.if_false(self.nullpath) def hastrginfo(self): @@ -80,11 +70,11 @@ def neurotrack_allgoodquality(self): def add_neuro_unpacker(path, debug_level=4, debugout=False, **kwargs): # - unpacker = b2.register_module('CDCTriggerUnpacker') + unpacker = basf2.register_module('CDCTriggerUnpacker') if debugout: - unpacker.logging.log_level = b2.LogLevel.DEBUG + unpacker.logging.log_level = basf2.LogLevel.DEBUG unpacker.logging.debug_level = debug_level - unpacker.logging.set_info(b2.LogLevel.DEBUG, b2.LogInfo.LEVEL | b2.LogInfo.MESSAGE) + unpacker.logging.set_info(basf2.LogLevel.DEBUG, basf2.LogInfo.LEVEL | basf2.LogInfo.MESSAGE) # size (number of words) of the Belle2Link header unpacker.param('headerSize', 3) # unpack the data from the 2D tracker and save its Bitstream @@ -120,11 +110,11 @@ def add_neuro_unpacker(path, debug_level=4, debugout=False, **kwargs): def add_neuro_2d_unpackers(path, debug_level=4, debugout=False, **kwargs): # - unpacker = b2.register_module('CDCTriggerUnpacker') + unpacker = basf2.register_module('CDCTriggerUnpacker') if debugout: - unpacker.logging.log_level = b2.LogLevel.DEBUG + unpacker.logging.log_level = basf2.LogLevel.DEBUG unpacker.logging.debug_level = debug_level - unpacker.logging.set_info(b2.LogLevel.DEBUG, b2.LogInfo.LEVEL | b2.LogInfo.MESSAGE) + unpacker.logging.set_info(basf2.LogLevel.DEBUG, basf2.LogInfo.LEVEL | basf2.LogInfo.MESSAGE) # size (number of words) of the Belle2Link header unpacker.param('headerSize', 3) # unpack the data from the 2D tracker and save its Bitstream @@ -160,7 +150,7 @@ def add_neuro_2d_unpackers(path, debug_level=4, debugout=False, **kwargs): def add_neurotrigger_sim(path, nntweightfile=None, debug_level=4, debugout=False, **kwargs): - nnt = b2.register_module('CDCTriggerNeuro') + nnt = basf2.register_module('CDCTriggerNeuro') if 'inputCollectionName' in kwargs: nnt.param('inputCollectionName', kwargs['inputCollectionName']) else: @@ -186,14 +176,16 @@ def add_neurotrigger_sim(path, nntweightfile=None, debug_level=4, debugout=False if 'et_option' in kwargs: nnt.param('et_option', kwargs['et_option']) + if 'EventTimeName' in kwargs: + nnt.param('EventTimeName', kwargs['EventTimeName']) if debugout: - nnt.logging.log_level = b2.LogLevel.DEBUG + nnt.logging.log_level = basf2.LogLevel.DEBUG nnt.logging.debug_level = debug_level path.add_module(nnt) def add_neurotrigger_hw(path, nntweightfile=None, debug_level=4, debugout=False, **kwargs): - nnt = b2.register_module('CDCTriggerNeuro') + nnt = basf2.register_module('CDCTriggerNeuro') if 'inputCollectionName' in kwargs: nnt.param('inputCollectionName', kwargs['inputCollectionName']) else: @@ -224,25 +216,41 @@ def add_neurotrigger_hw(path, nntweightfile=None, debug_level=4, debugout=False, nnt.param('NeuroHWTrackInputMode', True) if 'et_option' in kwargs: nnt.param('et_option', kwargs['et_option']) + else: + nnt.param('et_option', 'etf_or_fastestpriority') + + if 'EventTimeName' in kwargs: + nnt.param('EventTimeName', kwargs['EventTimeName']) + else: + nnt.param('EventTimeName', 'CDCTriggerNeuroETFT0') if debugout: - nnt.logging.log_level = b2.LogLevel.DEBUG + nnt.logging.log_level = basf2.LogLevel.DEBUG nnt.logging.debug_level = debug_level path.add_module(nnt) -def add_neuro_simulation(path): - path.add_module('CDCTriggerTSF', - InnerTSLUTFile=Belle2.FileSystem.findFile("data/trg/cdc/innerLUT_v2.2.coe"), - OuterTSLUTFile=Belle2.FileSystem.findFile("data/trg/cdc/outerLUT_v2.2.coe"), - TSHitCollectionName=simsegmenthits) +def add_neuro_simulation(path, nntweightfile=None, **kwargs): + nnt = basf2.register_module('CDCTriggerNeuro') + tsf = basf2.register_module('CDCTriggerTSF') + if "InnerTSLUTFile" in kwargs: + tsf.param("InnerTSLUTFile", kwargs["InnerTSLUTFile"]) + else: + tsf.param("InnerTSLUTFile", Belle2.FileSystem.findFile("data/trg/cdc/innerLUT_v2.2.coe")) + if "OuterTSLUTFile" in kwargs: + tsf.param("OuterTSLUTFile", kwargs["OuterTSLUTFile"]) + else: + tsf.param("OuterTSLUTFile", Belle2.FileSystem.findFile("data/trg/cdc/outerLUT_v2.2.coe")) + tsf.param("TSHitCollectionName", simsegmenthits) + path.add_module(tsf) path.add_module('CDCTrigger2DFinder', minHits=4, minHitsShort=4, minPt=0.3, hitCollectionName=simsegmenthits, outputCollectionName=sim2dtracks_swts) - path.add_module('CDCTriggerNeuro', - inputCollectionName=sim2dtracks_swts, - outputCollectionName=simneurotracks_swtssw2d, - hitCollectionName=simsegmenthits, - writeMLPinput=True, - fixedPoint=True, - ) + if nntweightfile is not None: + nnt.param('filename', Belle2.FileSystem.findFile(nntweightfile)) + nnt.param('inputCollectionName', sim2dtracks_swts) + nnt.param('outputCollectionName', simneurotracks_swtssw2d) + nnt.param('hitCollectionName', simsegmenthits) + nnt.param('writeMLPinput', True) + nnt.param('fixedPoint', True) + path.add_module(nnt) diff --git a/trg/cdc/scripts/nntd.py b/trg/cdc/scripts/nntd.py new file mode 100644 index 00000000000..1db2743c324 --- /dev/null +++ b/trg/cdc/scripts/nntd.py @@ -0,0 +1,269 @@ +import basf2 +from ROOT import Belle2 +import numpy as np +import pickle + + +class nntd(basf2.Module): + ''' + This class represents a dataset. + ''' + version = 2 # changes, when form of self.array changes + # dict to store the content for each entry in a track vector + varnum = {} + varnum["recoz"] = [0, r'$Z_{Reco}$', r'$[cm]$'] + varnum["recotheta"] = [1, r'$\theta_{Reco}$', r'$[°]$'] + varnum["recophi"] = [2, r'$\phi_{Reco}$', r'$[°]$'] + varnum["recopt"] = [3, r'$P_{t, Reco}$', r'$[GeV]$'] + varnum["neuroz"] = [4, r'$Z_{Neuro}$', r'$[cm]$'] + varnum["neurotheta"] = [5, r'$\theta_{Neuro}$', r'$[°]$'] + varnum["neurophi"] = [6, r'$\phi_{Neuro}$', r'$[°]$'] + varnum["neuropt"] = [7, r'$P_{t, Neuro}$', r'$[GeV]$'] + varnum["neuroval"] = [8, r'Validity', ''] + varnum["neuroqual"] = [9, r'Quality', ''] + varnum["neurots"] = [10, r'TSVector', ''] + varnum["neuroexp"] = [11, r'Expert Number', ''] + varnum["neurodriftth"] = [12, r'Driftthreshold', ''] + varnum["neuroquad"] = [13, r'Quadrant', ''] + varnum["neurofp"] = [14, r'Fastestpriority Eventtime', 'clocks'] + varnum["neuroetf"] = [15, r'ETF Eventtime', 'clocks'] + varnum["twodphi"] = [16, r'$\phi_{2D}$', r'$[°]$'] + varnum["twodpt"] = [17, r'$P_{t, 2D}$', r'$[GeV]$'] + varnum["twodfot"] = [18, r'FoundOldTrack', ''] + varnum["hwneuroz"] = [4, r'$Z_{HWNeuro}$', r'$[cm]$'] + varnum["hwneurotheta"] = [5, r'$\theta_{HWNeuro}$', r'$[°]$'] + varnum["hwneurophi"] = [6, r'$\phi_{HWNeuro}$', r'$[°]$'] + varnum["hwneuropt"] = [7, r'$P_{t, HWNeuro}$', r'$[GeV]$'] + varnum["hwNeuroval"] = [8, r'Validity', ''] + varnum["hwNeuroqual"] = [9, r'Quality', ''] + varnum["hwNeurots"] = [10, r'TSVector', ''] + varnum["hwNeuroexp"] = [11, r'Expert Number', ''] + varnum["hwNeurodriftth"] = [12, r'Driftthreshold', ''] + varnum["hwNeuroquad"] = [13, r'Quadrant', ''] + varnum["hwNeurofp"] = [14, r'Fastestpriority Eventtime', 'clocks'] + varnum["hwNeuroetf"] = [15, r'ETF Eventtime', 'clocks'] + nonelist = [None for i in range(17)] + + def initialize(self): + # TODO: + # check if folder is present or create it + # initialize all plots somehow + # initialize filters somehow, so they can be looped over in the evetn function + # setup histograms + self.data = None # np.array([[[]]]) + self.eventlist = [] + # TODO + # # dict of plots, which should be plotted during the processing and updated every 5000 events. + # self.plotdict = {} + self.recotracksname = "RecoTracks" # recotracksname + self.neurotracksname = "TSimNeuroTracks" # "TRGCDCNeuroTracks" # neurotracksname + self.hwneurotracksname = "CDCTriggerNeuroTracks" # "TRGCDCNeuroTracks" # neurotracksname + self.twodtracksname = "CDCTriggerNNInput2DFinderTracks" # "TRGCDC2DFinderTracks" # twodtracksname + self.etfname = "CDCTriggerNeuroETFT0" + self.tsname = "CDCTriggerNNInputSegmentHits" + + # storearrays + self.recotracks = Belle2.PyStoreArray(self.recotracksname) + self.neurotracks = Belle2.PyStoreArray(self.neurotracksname) + self.hwneurotracks = Belle2.PyStoreArray(self.hwneurotracksname) + self.twodtracks = Belle2.PyStoreArray(self.twodtracksname) + self.ts = Belle2.PyStoreArray(self.tsname) + self.etf = Belle2.PyStoreObj(self.etfname) + + self.varnum = nntd.varnum + self.networkname = None + + def costotheta(self, x): + if isinstance(x, list): + ret = [] + for y in x: + ret.append(self.costotheta(y)) + return ret + else: + ret = None + if not x: + return None + else: + if x < -1 or x > 1: + x = np.round(x) + return 180. / np.pi * np.arccos(x) + + def getrecovals(self, fitres): + ret = [] + if fitres: + ret.append(fitres.getPosition().Z()) + ret.append(self.costotheta(fitres.getMomentum().CosTheta())) + ret.append(fitres.getMomentum().Phi()) + ret.append(fitres.getMomentum().Pt()) + else: + for i in range(4): + ret.append(None) + return ret + + def getneurovals(self, neuro): + ret = [] + if neuro: + ret.append(neuro.getZ0()) + ret.append(self.costotheta(neuro.getCotTheta() / np.sqrt(1 + neuro.getCotTheta()**2))) + ret.append(neuro.getPhi0()) + ret.append(neuro.getPt()) + ret.append(neuro.getValidStereoBit()) + ret.append(neuro.getQualityVector()) + ret.append(None) # int(neuro.getTSVector())) + ret.append(neuro.getExpert()) + ret.append(None) # int(neuro.getDriftThreshold())) + ret.append(neuro.getQuadrant()) + fpt = 9999 + for ts in neuro.getRelationsTo(self.tsname): + if ts.priorityTime() < fpt: + fpt = ts.priorityTime() + if self.etf.hasBinnedEventT0(Belle2.Const.CDC): + eft = self.etf.getBinnedEventT0(Belle2.Const.CDC) + else: + eft = None + ret.append(fpt) + ret.append(eft) + else: + for i in range(12): + ret.append(None) + return ret + + def gettwodvals(self, twod): + ret = [] + if twod: + ret.append(twod.getPhi0()) + ret.append(twod.getPt()) + ret.append(None) # int(twod.getFoundOldTrack())) + else: + for i in range(3): + ret.append(None) + return ret + + def event(self): + # TODO: update the plots every nth time + # if self.showplots != 0: + # if eventnumber % self.showplots = 0: + # show plots + + # loop over events + event = [] + for reco in self.recotracks: + track = reco.getRelatedFrom("Tracks") + if not track: + print("no track found for recotrack") + continue + whishPdg = 211 # pion + fitres = track.getTrackFitResultWithClosestMass(Belle2.Const.ChargedStable(whishPdg)) + if not fitres: + continue + # neuro = reco.getRelatedTo(self.neurotracksname) + event.append([]) + try: + neuro = reco.getRelatedTo(self.neurotracksname) + except BaseException: + neuro = None + try: + hwneuro = reco.getRelatedTo(self.hwneurotracksname) + except BaseException: + hwneuro = None + try: + twod = reco.getRelatedTo(self.twodtracksname) + except BaseException: + twod = None + event[-1] += self.getrecovals(fitres) + event[-1] += self.getneurovals(neuro) + event[-1] += self.gettwodvals(twod) + event[-1] += self.getneurovals(hwneuro) + for neuro in self.neurotracks: + # print("neuroloop") + # print(len(neuro.getRelationsFrom(self.recotracksname))) + if len(neuro.getRelationsFrom(self.recotracksname)) > 0: + # this track is already stored in a recoline + # print("skipping...") + continue + event.append([]) + try: + twod = reco.getRelatedTo(self.twodtracksname) + except BaseException: + twod = None + try: + hwneuro = neuro.getRelatedTo(self.hwneurotracksname) + except BaseException: + twod = None + event[-1] += self.getrecovals(None) + event[-1] += self.getneurovals(neuro) + event[-1] += self.gettwodvals(twod) + event[-1] += self.getneurovals(hwneuro) + for twod in self.twodtracks: + # print("twodloop") + # print(len(twod.getRelationsFrom(self.neurotracksname))) + if len(twod.getRelationsFrom(self.neurotracksname)) > 0: + # print("skipping...") + # this track is already stored in a recoline or twodline + continue + event.append([]) + event[-1] += self.getrecovals(None) + event[-1] += self.getneurovals(None) + event[-1] += self.gettwodvals(twod) + event[-1] += self.getneurovals(None) + + # attach an array for every event + if len(event) > 100: + event = event[0:100] + elif len(event) < 100: + for i in range(100 - len(event)): + event.append(self.getrecovals(None) + self.getneurovals(None) + self.gettwodvals(None) + self.getneurovals(None)) + self.eventlist.append(event) + + def terminate(self): + # self.eventfilters() + # self.makearray(self.eventlist) + # convert eventlist to data array + # initialize histograms and fill them + # both save histograms to file and show them in the plots + pass + + def save(self, filename, netname): + # save the dataset as an array, the corresponding varnum, + # and a description about the dataset into a pickle file + savedict = {} + savedict["eventlist"] = self.eventlist + savedict["varnum"] = self.varnum + savedict["networkname"] = netname + savedict["version"] = nntd.version + f = open(filename, 'wb') + pickle.dump(savedict, f) + f.close() + print('file ' + filename + ' has been saved. ') + + def loadmore(self, filenames): + for x in filenames: + f = open(x, 'rb') + savedict = pickle.load(f) + f.close() + if self.version != savedict["version"]: + print("Error! loaded file was made with different version of nntd! exiting ... ") + exit() + self.networkname = savedict["networkname"] + self.eventlist += savedict["eventlist"] + self.varnum = savedict["varnum"] + print("Loaded file: " + x) + self.makearray(self.eventlist) + + def load(self, filename): + # load a given pickle file + f = open(filename, 'rb') + savedict = pickle.load(f) + f.close() + if self.version != savedict["version"]: + print("Error! loaded file was made with different version of nntd! exiting ... ") + exit() + self.eventlist = savedict["eventlist"] + self.varnum = savedict["varnum"] + self.networkname = savedict["networkname"] + # self.eventfilters() + self.makearray(self.eventlist) + + def makearray(self, evlist): + # TODO: apply filters + self.data = np.array(evlist) diff --git a/trg/cdc/src/NeuroTrigger.cc b/trg/cdc/src/NeuroTrigger.cc index e87331e45bb..43f4ce45984 100644 --- a/trg/cdc/src/NeuroTrigger.cc +++ b/trg/cdc/src/NeuroTrigger.cc @@ -19,6 +19,7 @@ #include #include + using namespace Belle2; using namespace CDC; using namespace std; @@ -387,129 +388,47 @@ NeuroTrigger::getRelId(const CDCTriggerSegmentHit& hit) return relId; } + +int +NeuroTrigger::getLowestTime(unsigned isector, RelationVector Hits, bool onlyAxials = false) +{ + int tlow = 9999; + B2DEBUG(200, "looping over axials:"); + for (unsigned ihit = 0; ihit < Hits.size(); ++ihit) { + // skip hits with negative relation weight (not selected in finder) + if (Hits.weight(ihit) < 0) continue; + unsigned short iSL = Hits[ihit]->getISuperLayer(); + if (iSL % 2 == 1 && onlyAxials) {continue;} + // get shortest time of relevant hits + B2DEBUG(200, " check drifttime: SL" + std::to_string(iSL) + ",ID = " + std::to_string(Hits[ihit]->getSegmentID()) + ", t = " + + std::to_string(Hits[ihit]->priorityTime())); + double relId = getRelId(*Hits[ihit]); + if (m_MLPs[isector].isRelevant(relId, iSL) && + Hits[ihit]->priorityTime() < tlow) { + tlow = Hits[ihit]->priorityTime(); + B2DEBUG(200, " new tlow: " << std::to_string(tlow)); + } + } + return tlow; +} + + void NeuroTrigger::getEventTime(unsigned isector, const CDCTriggerTrack& track, std::string et_option, const bool neuroinputmode = false) { + if (et_option != m_MLPs[isector].get_et_option()) { B2WARNING("Used event time option is different to the one set in the MLP" << LogVar("et_option", et_option) << LogVar("isector", isector) << LogVar("et_option_mlp", m_MLPs[isector].get_et_option())); } - if (et_option == "etf_or_fastestpriority") { - bool hasT0 = m_eventTime->hasBinnedEventT0(Const::CDC); - if (hasT0) { - m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); - m_hasT0 = true; - } else { - m_T0 = 9999; - // find shortest time of related and relevant axial hits - RelationVector axialHits = - track.getRelationsTo(m_hitCollectionName); - for (unsigned ihit = 0; ihit < axialHits.size(); ++ihit) { - // skip hits with negative relation weight (not selected in finder) - if (axialHits.weight(ihit) < 0) continue; - unsigned short iSL = axialHits[ihit]->getISuperLayer(); - // skip stereo hits (should not be related to track, but check anyway) - if ((iSL % 2 == 1) && !neuroinputmode) continue; - // get shortest time of relevant hits - double relId = getRelId(*axialHits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && - axialHits[ihit]->priorityTime() < m_T0) { - m_T0 = axialHits[ihit]->priorityTime(); - } - } - if (!neuroinputmode) { - // find shortest time of relevant stereo hits - StoreArray hits(m_hitCollectionName); - for (int ihit = 0; ihit < hits.getEntries(); ++ihit) { - unsigned short iSL = hits[ihit]->getISuperLayer(); - // skip axial hits - if (iSL % 2 == 0) continue; - // get shortest time of relevant hits - double relId = getRelId(*hits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && hits[ihit]->priorityTime() < m_T0) { - m_T0 = hits[ihit]->priorityTime(); - } - } - } - if (m_T0 < 9999) { - m_hasT0 = true; - } else { - m_T0 = 0; - m_hasT0 = false; - } - } - } else if (et_option == "etf_or_fastest2d") { - bool hasT0 = m_eventTime->hasBinnedEventT0(Const::CDC); - if (hasT0) { - m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); - m_hasT0 = true; - } else { - m_T0 = 9999; - // find shortest time of related and relevant axial hits - RelationVector axialHits = - track.getRelationsTo(m_hitCollectionName); - for (unsigned ihit = 0; ihit < axialHits.size(); ++ihit) { - // skip hits with negative relation weight (not selected in finder) - if (axialHits.weight(ihit) < 0) continue; - unsigned short iSL = axialHits[ihit]->getISuperLayer(); - // skip stereo hits (should not be related to track, but check anyway) - if (iSL % 2 == 1) continue; - // get shortest time of relevant hits - double relId = getRelId(*axialHits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && - axialHits[ihit]->priorityTime() < m_T0) { - m_T0 = axialHits[ihit]->priorityTime(); - } - } - if (m_T0 < 9999) { - m_hasT0 = true; - } else { - m_T0 = 0; - m_hasT0 = false; - } - } - } else if (et_option == "fastestpriority") { + if (et_option == "fastestpriority") { B2DEBUG(200, "et_option is 'fastestpriority'"); m_T0 = 9999; // find shortest time of related and relevant axial hits - RelationVector axialHits = + RelationVector Hits = track.getRelationsTo(m_hitCollectionName); - B2DEBUG(200, "looping over axials:"); - for (unsigned ihit = 0; ihit < axialHits.size(); ++ihit) { - // skip hits with negative relation weight (not selected in finder) - if (axialHits.weight(ihit) < 0) continue; - unsigned short iSL = axialHits[ihit]->getISuperLayer(); - // skip stereo hits (should not be related to track, but check anyway) - if ((iSL % 2 == 1) && !neuroinputmode) continue; - // get shortest time of relevant hits - B2DEBUG(200, " check drifttime: SL" + std::to_string(iSL) + ",ID = " + std::to_string(axialHits[ihit]->getSegmentID()) + ", t = " + - std::to_string(axialHits[ihit]->priorityTime())); - double relId = getRelId(*axialHits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && - axialHits[ihit]->priorityTime() < m_T0) { - m_T0 = axialHits[ihit]->priorityTime(); - B2DEBUG(200, " new t0: " << std::to_string(m_T0)); - } - } - if (!neuroinputmode) { - // find shortest time of relevant stereo hits - StoreArray hits(m_hitCollectionName); - B2DEBUG(200, "looping over stereos:"); - for (int ihit = 0; ihit < hits.getEntries(); ++ihit) { - unsigned short iSL = hits[ihit]->getISuperLayer(); - // skip axial hits - if (iSL % 2 == 0) continue; - // get shortest time of relevant hits - B2DEBUG(200, " check drifttime: SL" + std::to_string(iSL) + ",ID = " + std::to_string(hits[ihit]->getSegmentID()) + ", t = " + - std::to_string(hits[ihit]->priorityTime())); - double relId = getRelId(*hits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && hits[ihit]->priorityTime() < m_T0) { - m_T0 = hits[ihit]->priorityTime(); - B2DEBUG(200, " new t0: " << std::to_string(m_T0)); - } - } - } + m_T0 = getLowestTime(isector, Hits, false); if (m_T0 < 9999) { m_hasT0 = true; } else { @@ -520,21 +439,9 @@ NeuroTrigger::getEventTime(unsigned isector, const CDCTriggerTrack& track, std:: } else if (et_option == "fastest2d") { m_T0 = 9999; // find shortest time of related and relevant axial hits - RelationVector axialHits = + RelationVector Hits = track.getRelationsTo(m_hitCollectionName); - for (unsigned ihit = 0; ihit < axialHits.size(); ++ihit) { - // skip hits with negative relation weight (not selected in finder) - if (axialHits.weight(ihit) < 0) continue; - unsigned short iSL = axialHits[ihit]->getISuperLayer(); - // skip stereo hits (should not be related to track, but check anyway) - if (iSL % 2 == 1) continue; - // get shortest time of relevant hits - double relId = getRelId(*axialHits[ihit]); - if (m_MLPs[isector].isRelevant(relId, iSL) && - axialHits[ihit]->priorityTime() < m_T0) { - m_T0 = axialHits[ihit]->priorityTime(); - } - } + m_T0 = getLowestTime(isector, Hits, true); if (m_T0 < 9999) { m_hasT0 = true; } else { @@ -545,7 +452,7 @@ NeuroTrigger::getEventTime(unsigned isector, const CDCTriggerTrack& track, std:: m_hasT0 = true; m_T0 = 0; } else if (et_option == "etf_only") { - bool hasT0 = m_eventTime->hasBinnedEventT0(Const::CDC); + bool hasT0 = (m_eventTime.isValid()) ? m_eventTime->hasBinnedEventT0(Const::CDC) : false; if (hasT0) { m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); m_hasT0 = true; @@ -554,8 +461,48 @@ NeuroTrigger::getEventTime(unsigned isector, const CDCTriggerTrack& track, std:: m_hasT0 = false; m_T0 = 0; } + } else if (et_option == "etf_or_fastestpriority") { + bool hasT0 = (m_eventTime.isValid()) ? m_eventTime->hasBinnedEventT0(Const::CDC) : false; + if (hasT0) { + m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); + m_hasT0 = true; + } else { + getEventTime(isector, track, "fastestpriority", neuroinputmode); + /** + m_T0 = 9999; + // find shortest time of related and relevant axial hits + RelationVector Hits = + track.getRelationsTo(m_hitCollectionName); + m_T0 = getLowestTime(isector, Hits, false); + if (m_T0 < 9999) { + m_hasT0 = true; + } else { + m_T0 = 0; + m_hasT0 = false; + }*/ + } + } else if (et_option == "etf_or_fastest2d") { + bool hasT0 = (m_eventTime.isValid()) ? m_eventTime->hasBinnedEventT0(Const::CDC) : false; + if (hasT0) { + m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); + m_hasT0 = true; + } else { + getEventTime(isector, track, "fastest2d", neuroinputmode); + /** + m_T0 = 9999; + // find shortest time of related and relevant axial hits + RelationVector Hits = + track.getRelationsTo(m_hitCollectionName); + m_T0 = getLowestTime(isector, Hits, true); + if (m_T0 < 9999) { + m_hasT0 = true; + } else { + m_T0 = 0; + m_hasT0 = false; + }*/ + } } else if (et_option == "etf_or_zero") { - bool hasT0 = m_eventTime->hasBinnedEventT0(Const::CDC); + bool hasT0 = (m_eventTime.isValid()) ? m_eventTime->hasBinnedEventT0(Const::CDC) : false; if (hasT0) { m_T0 = m_eventTime->getBinnedEventT0(Const::CDC); m_hasT0 = true; @@ -563,6 +510,48 @@ NeuroTrigger::getEventTime(unsigned isector, const CDCTriggerTrack& track, std:: m_hasT0 = true; m_T0 = 0; } + } else if (et_option == "etfcc") { + if (!neuroinputmode) { + B2ERROR("cannot use 'etfcc' timing option without hw tracks!"); + } else { + if (track.getHasETFTime()) { + m_T0 = track.getETF_unpacked(); + m_hasT0 = true; + } else { + m_T0 = 0; + m_hasT0 = false; + } + } + } else if (et_option == "etfcc_or_zero") { + if (!neuroinputmode) { + B2ERROR("cannot use 'etfcc' timing option without hw tracks!"); + } else { + if (track.getHasETFTime()) { + m_T0 = track.getETF_unpacked(); + m_hasT0 = true; + } else { + m_T0 = 0; + m_hasT0 = true; + } + } + } else if (et_option == "etfcc_or_fastestpriority") { + if (!neuroinputmode) { + B2ERROR("cannot use 'etfcc' timing option without hw tracks!"); + } else { + if (track.getHasETFTime()) { + m_T0 = track.getETF_unpacked(); + m_hasT0 = true; + } else { + getEventTime(isector, track, "fastestpriority", neuroinputmode); + } + } + } else if (et_option == "etfhwin") { + if (!neuroinputmode) { + B2ERROR("cannot use 'etfcc' timing option without hw tracks!"); + } else { + m_T0 = track.getETF_recalced(); + m_hasT0 = true; + } } else { B2ERROR("No valid parameter for et_option (" << et_option << " )!"); } @@ -680,7 +669,7 @@ unsigned long NeuroTrigger::getCompleteHitPattern(unsigned isector, const CDCTri unsigned long NeuroTrigger::getInputPattern(unsigned isector, const CDCTriggerTrack& track, const bool neurotrackinputmode) { - CDCTriggerMLP& expert = m_MLPs[isector]; + const CDCTriggerMLP& expert = m_MLPs[isector]; unsigned long hitPattern = 0; vector nHits; nHits.assign(9, 0); @@ -762,6 +751,10 @@ NeuroTrigger::selectHitsHWSim(unsigned isector, const CDCTriggerTrack& track) RelationVector allHits = track.getRelationsTo(m_hitCollectionName); B2DEBUG(250, "start hit loop over all related hits"); + //// future: maybe add correction for ts at the time limit + //// loop over all ts and find those smaller 150 + //// determine if there is one over 5120-150 --> yes + //// add 5120 to priotime for (unsigned ihit = 0; ihit < allHits.size(); ++ihit) { // skip hits with negative relation weight (not selected in finder) if (allHits.weight(ihit) < 0) continue; @@ -971,9 +964,10 @@ NeuroTrigger::getInputVector(unsigned isector, const vector& hitIds) unsigned short iSL = m_segmentHits[ihit]->getISuperLayer(); unsigned short iRef = iSL + 9 * nHits[iSL]; ++nHits[iSL]; - int t = (m_hasT0) ? m_segmentHits[ihit]->priorityTime() - m_T0 : 0; + int priot = m_segmentHits[ihit]->priorityTime(); + int t = (m_hasT0) ? priot - m_T0 : 0; if (t < 0) { - t = 0; + t = expert.getTMax(); } else if (t > expert.getTMax()) { t = expert.getTMax(); }