//_____________________________________________________________________________ void CrateLoc::Load( const THaEvData& evdata ) { // Load one data word from crate/slot/chan address if( evdata.GetNumHits(crate,slot,chan) > 0 ) { data = evdata.GetData(crate,slot,chan,0); } }
//_____________________________________________________________________________ void CrateLocMulti::Load( const THaEvData& evdata ) { // Load all decoded hits from crate/slot/chan address data = 0; for (Int_t i = 0; i < evdata.GetNumHits(crate,slot,chan); ++i) { rdata.push_back( evdata.GetData(crate,slot,chan,i) ); } }
int main(int argc, char* argv[]) { int debug=0; if (argc > 1) debug=1; // CODA file "snippet.dat" is a disk file of CODA data. THaCodaFile datafile; // We could also open the data using a // different constructor: // THaCodaFile datafile("snippet.dat"); TString filename("snippet.dat"); if (datafile.codaOpen(filename) != S_SUCCESS) { cout << "ERROR: Cannot open CODA data" << endl; exit(0); } THaEvData *evdata = new THaCodaDecoder(); // Loop over events int NUMEVT=100; int ievent; for (ievent=0; ievent<NUMEVT; ievent++) { int status = datafile.codaRead(); if ( status != S_SUCCESS ) { if ( status == EOF) { cout << "This is normal end of file. Goodbye !" << endl; } else { cout << hex << "ERROR: codaRread status = " << status << endl; } goto Finish; } // load_evbuffer() must be called each event before you access evdata contents. // If you use the version of load_evbuffer() shown here, // evdata uses its private crate map (recommended). // Alternatively you could use load_evbuffer(int* evbuffer, haCrateMap& map) evdata->LoadEvent( datafile.getEvBuffer() ); cout << "\nEvent type " << dec << evdata->GetEvType() << endl; cout << "Event number " << evdata->GetEvNum() << endl; cout << "Event length " << evdata->GetEvLength() << endl; if (evdata->IsPhysicsTrigger() ) { // triggers 1-14 cout << "Physics trigger " << endl; } if(evdata->IsScalerEvent()) cout << "Scaler `event' " << endl; // Now we want data from a particular crate and slot. // E.g. crates are 1,2,3,13,14,15 (roc numbers), Slots are 1,2,3... // This is like what one might do in a detector decode() routine. int crate = 1; // for example int slot = 24; // Here are raw 32-bit CODA words for this crate and slot cout << "Raw Data Dump for crate "<<dec<<crate<<" slot "<<slot<<endl; int hit; for(hit=0; hit<evdata->GetNumRaw(crate,slot); hit++) { cout<<dec<<"raw["<<hit<<"] = "; cout<<hex<<evdata->GetRawData(crate,slot,hit)<<endl; } // You can alternatively let evdata print out the contents of a crate and slot: evdata->PrintSlotData(crate,slot); if (evdata->IsPhysicsTrigger()) { // Below are interpreted data, device types are ADC, TDC, or scaler. // One needs to know the channel number within the device int channel = 7; // for example cout << "Device type = "; cout << evdata->DevType(crate,slot) << endl; for (hit=0; hit<evdata->GetNumHits(crate,slot,channel); hit++) { cout << "Channel " <<dec<<channel<<" hit # "<<hit<<" "; cout << "data = " << evdata->GetData(crate,slot,channel,hit)<<endl; } // Helicity data cout << "Helicity on left spectrometer "<<evdata->GetHelicity("left")<<endl; cout << "Helicity on right spectrometer "<<evdata->GetHelicity("right")<<endl; cout << "Helicity "<<evdata->GetHelicity()<<endl; } // Scalers: Although the getData methods works if you happen // to know what crate & slot contain scaler data, here is // another way to get scalers directly from evdata for (slot=0; slot<5; slot++) { cout << "\n scaler slot -> " << dec << slot << endl;; for (int chan=0; chan<16; chan++) { cout << "Scaler chan " << chan << " "; cout << evdata->GetScaler("left",slot,chan); cout << " " << evdata->GetScaler(7,slot,chan) << endl; } } } // end of event loop Finish: cout<<"\nAll done; processed "<<dec<<ievent<<" events"<<endl; }
//_____________________________________________________________________________ Int_t THaScintillator::Decode( const THaEvData& evdata ) { // Decode scintillator data, correct TDC times and ADC amplitudes, and copy // the data to the local data members. // This implementation makes the following assumptions about the detector map: // - The first half of the map entries corresponds to ADCs, // the second half, to TDCs. // - The first fNelem detector channels correspond to the PMTs on the // right hand side, the next fNelem channels, to the left hand side. // (Thus channel numbering for each module must be consecutive.) // Loop over all modules defined for this detector for( Int_t i = 0; i < fDetMap->GetSize(); i++ ) { THaDetMap::Module* d = fDetMap->GetModule( i ); bool adc = ( d->model ? fDetMap->IsADC(d) : (i < fDetMap->GetSize()/2) ); // Loop over all channels that have a hit. for( Int_t j = 0; j < evdata.GetNumChan( d->crate, d->slot ); j++) { Int_t chan = evdata.GetNextChan( d->crate, d->slot, j ); if( chan < d->lo || chan > d->hi ) continue; // Not one of my channels #ifdef WITH_DEBUG Int_t nhit = evdata.GetNumHits(d->crate, d->slot, chan); if( nhit > 1 ) if (d->model != 250) Warning( Here("Decode"), "%d hits on %s channel %d/%d/%d", nhit, adc ? "ADC" : "TDC", d->crate, d->slot, chan ); #endif // Get the data. Scintillators are assumed to have only single hit (hit=0) Int_t data = evdata.GetData( d->crate, d->slot, chan, 0 ); // Get the detector channel number, starting at 0 Int_t k = d->first + chan - d->lo - 1; #ifdef WITH_DEBUG if( k<0 || k>NDEST*fNelem ) { // Indicates bad database Warning( Here("Decode()"), "Illegal detector channel: %d", k ); continue; } // cout << "adc,j,k = " <<adc<<","<<j<< ","<<k<< endl; #endif // Copy the data to the local variables. DataDest* dest = fDataDest + k/fNelem; k = k % fNelem; if( adc ) { dest->adc[k] = static_cast<Double_t>( data ); dest->adc_p[k] = data - dest->ped[k]; dest->adc_c[k] = dest->adc_p[k] * dest->gain[k]; (*dest->nahit)++; } else { dest->tdc[k] = static_cast<Double_t>( data ); dest->tdc_c[k] = (data - dest->offset[k])*fTdc2T; (*dest->nthit)++; } } } if ( fDebug > 3 ) { printf("\n\nEvent %d Trigger %d Scintillator %s\n:", evdata.GetEvNum(), evdata.GetEvType(), GetPrefix() ); printf(" paddle Left(TDC ADC ADC_p) Right(TDC ADC ADC_p)\n"); for ( int i=0; i<fNelem; i++ ) { printf(" %2d %5.0f %5.0f %5.0f %5.0f %5.0f %5.0f\n", i+1,fLT[i],fLA[i],fLA_p[i],fRT[i],fRA[i],fRA_p[i]); } } return fLTNhit+fRTNhit; }
//____________________________________________________________________ Int_t THaADCHelicity::Decode( const THaEvData& evdata ) { // Decode Helicity data. // Return 1 if helicity was assigned, 0 if not, -1 if error. // Only the first two channels defined in the detector map are used // here, regardless of how they are defined (consecutive channels // in same module or otherwise). ReadDatabase guarantees that two channels // are present and warns about extra channels. if( !fIsInit ) return -1; Int_t ret = 0; bool gate_high = false; for( Int_t i = 0; i < fNchan; ++i ) { Int_t roc = fAddr[i].roc, slot = fAddr[i].slot, chan = fAddr[i].chan; if ( !evdata.GetNumHits( roc, slot, chan )) continue; Double_t data = static_cast<Double_t>(evdata.GetData( roc, slot, chan, 0 )); if (fDebug >= 3) { cout << "crate "<<roc<<" slot "<<slot<<" chan " <<chan<<" data "<<data<<" "; if (data > fThreshold) cout << " above cut !"; cout << endl; } // Assign gate and helicity bit data. The first data channel is // the helicity bit, the second, the gate. switch(i) { case 0: fADC_hdata = data; break; case 1: fADC_Gate = data; gate_high = fInvertGate ? (data < fThreshold) : (data >= fThreshold); break; } } // Logic: if gate==0 helicity remains unknown. If gate==1 // (or we are ingoring the gate) then helicity is determined by // the helicity bit. if( gate_high || fIgnoreGate ) { fADC_Hel = ( fADC_hdata >= fThreshold ) ? kPlus : kMinus; ret = 1; } // fHelicity may be reassigned by derived classes, so we must keep the ADC // result separately. But within this class, the two are the same. if( fSign >= 0 ) fHelicity = fADC_Hel; else fHelicity = ( fADC_Hel == kPlus ) ? kMinus : kPlus; if (fDebug >= 3) { cout << "ADC helicity info "<<endl << "Gate "<<fADC_Gate<<" helic. bit "<<fADC_hdata << " ADC helicity "<<fADC_Hel << " resulting helicity"<<fHelicity<<endl; } return ret; }
//_____________________________________________________________________________ Int_t THaVDCPlane::Decode( const THaEvData& evData ) { // Converts the raw data into hit information // Logical wire numbers a defined by the detector map. Wire number 0 // corresponds to the first defined channel, etc. // TODO: Support "reversed" detector map modules a la MWDC if (!evData.IsPhysicsTrigger()) return -1; // the event's T0-shift, due to the trigger-type // only an issue when adding in un-retimed trigger types Double_t evtT0=0; if ( fglTrg && fglTrg->Decode(evData)==kOK ) evtT0 = fglTrg->TimeOffset(); Int_t nextHit = 0; bool only_fastest_hit = false, no_negative = false; if( fVDC ) { // If true, add only the first (earliest) hit for each wire only_fastest_hit = fVDC->TestBit(THaVDC::kOnlyFastest); // If true, ignore negative drift times completely no_negative = fVDC->TestBit(THaVDC::kIgnoreNegDrift); } // Loop over all detector modules for this wire plane for (Int_t i = 0; i < fDetMap->GetSize(); i++) { THaDetMap::Module * d = fDetMap->GetModule(i); // Get number of channels with hits Int_t nChan = evData.GetNumChan(d->crate, d->slot); for (Int_t chNdx = 0; chNdx < nChan; chNdx++) { // Use channel index to loop through channels that have hits Int_t chan = evData.GetNextChan(d->crate, d->slot, chNdx); if (chan < d->lo || chan > d->hi) continue; //Not part of this detector // Wire numbers and channels go in the same order ... Int_t wireNum = d->first + chan - d->lo; THaVDCWire* wire = GetWire(wireNum); if( !wire || wire->GetFlag() != 0 ) continue; // Get number of hits for this channel and loop through hits Int_t nHits = evData.GetNumHits(d->crate, d->slot, chan); Int_t max_data = -1; Double_t toff = wire->GetTOffset(); for (Int_t hit = 0; hit < nHits; hit++) { // Now get the TDC data for this hit Int_t data = evData.GetData(d->crate, d->slot, chan, hit); // Convert the TDC value to the drift time. // Being perfectionist, we apply a 1/2 channel correction to the raw // TDC data to compensate for the fact that the TDC truncates, not // rounds, the data. Double_t xdata = static_cast<Double_t>(data) + 0.5; Double_t time = fTDCRes * (toff - xdata) - evtT0; // If requested, ignore hits with negative drift times // (due to noise or miscalibration). Use with care. // If only fastest hit requested, find maximum TDC value and record the // hit after the hit loop is done (see below). // Otherwise just record all hits. if( !no_negative || time > 0.0 ) { if( only_fastest_hit ) { if( data > max_data ) max_data = data; } else new( (*fHits)[nextHit++] ) THaVDCHit( wire, data, time ); } // Count all hits and wires with hits // fNWiresHit++; } // End hit loop // If we are only interested in the hit with the largest TDC value // (shortest drift time), it is recorded here. if( only_fastest_hit && max_data>0 ) { Double_t xdata = static_cast<Double_t>(max_data) + 0.5; Double_t time = fTDCRes * (toff - xdata) - evtT0; new( (*fHits)[nextHit++] ) THaVDCHit( wire, max_data, time ); } } // End channel index loop } // End slot loop // Sort the hits in order of increasing wire number and (for the same wire // number) increasing time (NOT rawtime) fHits->Sort(); if ( fDebug > 3 ) { printf("\nVDC %s:\n",GetPrefix()); int ncol=4; for (int i=0; i<ncol; i++) { printf(" Wire TDC "); } printf("\n"); for (int i=0; i<(nextHit+ncol-1)/ncol; i++ ) { for (int c=0; c<ncol; c++) { int ind = c*nextHit/ncol+i; if (ind < nextHit) { THaVDCHit* hit = static_cast<THaVDCHit*>(fHits->At(ind)); printf(" %3d %5d ",hit->GetWireNum(),hit->GetRawTime()); } else { // printf("\n"); break; } } printf("\n"); } } return 0; }