X-Git-Url: http://git.uio.no/git/?p=u%2Fmrichter%2FAliRoot.git;a=blobdiff_plain;f=RALICE%2Ficepack%2Ficeconvert%2FIceF2k.cxx;h=2fef202e3ee4c9c75eca7985b0cdce46ec45964a;hp=887d4fe36e514a066663476b99cb748eee73a21d;hb=216d1d911d5f43db34b51f991cbb06bfe12ecbe6;hpb=f60271ca17d635bd65a3f2e05b535da268b7dfe7;ds=sidebyside diff --git a/RALICE/icepack/iceconvert/IceF2k.cxx b/RALICE/icepack/iceconvert/IceF2k.cxx index 887d4fe36e5..2fef202e3ee 100644 --- a/RALICE/icepack/iceconvert/IceF2k.cxx +++ b/RALICE/icepack/iceconvert/IceF2k.cxx @@ -18,6 +18,16 @@ /////////////////////////////////////////////////////////////////////////// // Class IceF2k // Conversion of Amanda F2K data into IceEvent physics event structures. +// This class is derived from AliJob providing a task-based processing +// structure on an event-by-event basis. +// The main object in the job environment is an IceEvent* pointer. +// In case the user has provided sub-tasks, these will be executed +// on an event-by-event basis after the IceEvent structure has been filled +// with the F2K data and before the final structures are written out. +// Note that the data structures are only written out if an outputfile has +// been specified via the SetOutputFile memberfunction. +// In case no outputfile has been specified, this class provides a facility +// to investigate/analyse F2K data using the Ralice/IcePack analysis tools. // // Usage example : // --------------- @@ -26,27 +36,50 @@ // gSystem->Load("icepack"); // gSystem->Load("iceconvert"); // -// // Output file for the event structures -// TFile* ofile=new TFile("events.root","RECREATE","F2K data in IceEvent structure"); -// TTree* otree=new TTree("T","Data of an Amanda run"); +// IceF2k q("IceF2k","F2K to IcePack data structure conversion"); // // // Limit the number of entries for testing -// Int_t nentries=300; +// q.SetMaxEvents(10); // // // Print frequency to produce a short summary print every printfreq events -// Int_t printfreq=10; +// q.SetPrintFreq(1); // // // Split level for the output structures -// Int_t split=2; +// q.SetSplitLevel(2); // // // Buffer size for the output structures -// Int_t bsize=32000; +// q.SetBufferSize(32000); +// +// // The F2K input filename +// q.SetInputFile("run7825.f2k"); +// +// // Output file for the event structures +// TFile* ofile=new TFile("events.root","RECREATE","F2K data in IceEvent structure"); +// q.SetOutputFile(ofile); +// +// /////////////////////////////////////////////////////////////////// +// // Here the user can specify his/her sub-tasks to be executed +// // on an event-by-event basis after the IceEvent structure +// // has been filled and before the data is written out. +// // Sub-tasks (i.e. a user classes derived from TTask) are entered +// // as follows : +// // +// // MyXtalk task1("task1","Cross talk correction"); +// // MyClean task2("task2","Hit cleaning"); +// // q.Add(&task1); +// // q.Add(&task2); +// // +// // The sub-tasks will be executed in the order as they are entered. +// /////////////////////////////////////////////////////////////////// // -// IceF2k q("run8000.f2k",split,bsize); -// q.Loop(otree,nentries,printfreq); +// // Perform the conversion and execute subtasks (if any) +// // on an event-by-event basis +// q.ExecuteJob(); // // // Select various objects to be added to the output file // +// ofile->cd(); // Switch to the output file directory +// // AliObjMatrix* omdb=q.GetOMdbase(); // if (omdb) omdb->Write(); // @@ -56,9 +89,11 @@ // TDatabasePDG* pdg=q.GetPDG(); // if (pdg) pdg->Write(); // -// // Close output file +// // Flush the output file. +// // The output file is not explicitly closed here +// // to allow ineractive investigation of the data tree +// // when this macro is run in an interactive ROOT/CINT session. // ofile->Write(); -// ofile->Close(); // //--- Author: Nick van Eijndhoven 11-mar-2005 Utrecht University //- Modified: NvE $Date$ Utrecht University @@ -69,46 +104,27 @@ ClassImp(IceF2k) // Class implementation to enable ROOT I/O -IceF2k::IceF2k(char* fname,Int_t split,Int_t bsize) +IceF2k::IceF2k(const char* name,const char* title) : AliJob(name,title) { // Default constructor. -// Initialise the input file and data structres to be converted. -// Also the required split level and buffer size of the output tree -// can be specified in this constructor. -// By default tree=0, split=0 and bsize=32000. +// By default maxevent=-1, split=99, bsize=32000, printfreq=1. - fSplit=split; - fBsize=bsize; + fSplit=99; + fBsize=32000; + fMaxevt=-1; + fPrintfreq=1; + fInfile=""; + fOutfile=0; fPdg=0; fOmdb=0; fFitdefs=0; - - if (!fname) - { - cout << " *IceF2k ctor* No data input file specified." << endl; - return; - } - - // Open the input file in the default ascii format (autodetection) for reading - fInput=rdmc_mcopen(fname,"r",RDMC_DEFAULT_ASCII_F); - - if (!fInput) - { - cout << " *IceF2k ctor* No input file found with name : " << fname << endl; - return; - } - - // Initialise the event structure - rdmc_init_mevt(&fEvent); - - // Read the file header information - rdmc_rarr(fInput,&fHeader); } /////////////////////////////////////////////////////////////////////////// IceF2k::~IceF2k() { // Default destructor. + if (fPdg) { delete fPdg; @@ -128,6 +144,47 @@ IceF2k::~IceF2k() } } /////////////////////////////////////////////////////////////////////////// +void IceF2k::SetMaxEvents(Int_t n) +{ +// Set the maximum number of events to be processed. +// n=-1 implies processing of the complete input file, which is the default +// initialisation in the constructor. + fMaxevt=n; +} +/////////////////////////////////////////////////////////////////////////// +void IceF2k::SetPrintFreq(Int_t f) +{ +// Set the printfrequency to produce info every f events. +// f=1 is the default initialisation in the constructor. + if (f>=0) fPrintfreq=f; +} +/////////////////////////////////////////////////////////////////////////// +void IceF2k::SetSplitLevel(Int_t split) +{ +// Set the split level for the ROOT data file. +// split=99 is the default initialisation in the constructor. + if (split>=0) fSplit=split; +} +/////////////////////////////////////////////////////////////////////////// +void IceF2k::SetBufferSize(Int_t bsize) +{ +// Set the buffer size for the ROOT data file. +// bsize=32000 is the default initialisation in the constructor. + if (bsize>=0) fBsize=bsize; +} +/////////////////////////////////////////////////////////////////////////// +void IceF2k::SetInputFile(TString name) +{ +// Set the name of the F2K input file. + fInfile=name; +} +/////////////////////////////////////////////////////////////////////////// +void IceF2k::SetOutputFile(TFile* ofile) +{ +// Set the output file for the ROOT data. + fOutfile=ofile; +} +/////////////////////////////////////////////////////////////////////////// TDatabasePDG* IceF2k::GetPDG() { // Provide pointer to the PDG database @@ -146,28 +203,59 @@ AliDevice* IceF2k::GetFitdefs() return fFitdefs; } /////////////////////////////////////////////////////////////////////////// -void IceF2k::Loop(TTree* otree,Int_t nentries,Int_t printfreq) +void IceF2k::Exec(Option_t* opt) { -// Loop over the specified number of entries and convert the +// Job to loop over the specified number of events and convert the // F2K data into the IceEvent structure. -// The output will be written on the output tree specified as "otree". -// If otree=0, a default standard output tree will be created. -// If nentries<0 (default) all the entries of the input file +// If maxevents<0 (default) all the entries of the input file // will be processed. // Every "printfreq" events a short event summary will be printed. // The default value is printfreq=1. +// The output will be written on a standard output tree named "T". +// +// Notes : +// ------- +// 1) This class is derived from AliJob, allowing a task based processing. +// After the conversion of an F2K event into an IceEvent structure, +// the processing of all available sub-tasks (if any) is invoked. +// This provides an event-by-event (sub)task processing before the +// final data structures are written out. +// 2) The main object in this job environment is an IceEvent* pointer. + + if (fInfile=="") + { + cout << " *IceF2k Exec* No data input file specified." << endl; + return; + } + + // Open the input file in the default ascii format (autodetection) for reading + fInput=rdmc_mcopen(fInfile.Data(),"r",RDMC_DEFAULT_ASCII_F); + + if (!fInput) + { + cout << " *IceF2k Exec* No input file found with name : " << fInfile.Data() << endl; + return; + } - if (!fInput || fSplit<0) return; + // Initialise the event structure + rdmc_init_mevt(&fEvent); - if (!otree) otree=new TTree("T","F2K Data"); + // Read the file header information + rdmc_rarr(fInput,&fHeader); - IceEvent* evt=new IceEvent(); + TTree* otree=0; + if (fOutfile) + { + otree=new TTree("T","F2K Data converted to IceEvent structures"); + otree->SetDirectory(fOutfile); + } + IceEvent* evt=new IceEvent(); evt->SetTrackCopy(1); evt->SetDevCopy(1); // Branch in the tree for the event structure - otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit); + if (otree) otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit); // Create the particle database and extend it with some F2000 specific definitions if (!fPdg) fPdg=new TDatabasePDG(); @@ -191,9 +279,32 @@ void IceF2k::Loop(TTree* otree,Int_t nentries,Int_t printfreq) // Set the fit definitions according to the F2000 header info SetFitdefs(); - for (Int_t jentry=0; jentryGetName() << endl; + cout << " Output characteristics : splitlevel = " << fSplit << " buffersize = " << fBsize << endl; + } + + ListEnvironment(); + + Int_t nevt=0; + while (!rdmc_revt(fInput,&fHeader,&fEvent)) + { + if (fMaxevt>-1 && nevt>=fMaxevt) break; // Reset the complete Event structure evt->Reset(); @@ -202,22 +313,34 @@ void IceF2k::Loop(TTree* otree,Int_t nentries,Int_t printfreq) evt->SetEventNumber(fEvent.enr); evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs); - PutMcTracks(evt); + PutMcTracks(); + + PutRecoTracks(); - PutRecoTracks(evt); + PutHits(); - PutHits(evt); + // Invoke all available sub-tasks (if any) + ExecuteTasks(opt); - if (!(jentry%printfreq)) + if (fPrintfreq) { - evt->HeaderData(); + if (!(nevt%fPrintfreq)) evt->HeaderData(); } // Write the complete structure to the output Tree - otree->Fill(); + if (otree) otree->Fill(); + + // Update event counter + nevt++; } - if (evt) delete evt; + // Remove the IceEvent object from the environment + // and delete it as well + if (evt) + { + RemoveObject(evt); + delete evt; + } } /////////////////////////////////////////////////////////////////////////// void IceF2k::FillOMdbase() @@ -227,6 +350,35 @@ void IceF2k::FillOMdbase() if (fHeader.nch<=0) return; + Int_t geocal=fHeader.is_calib.geo; + Int_t adccal=fHeader.is_calib.adc; + Int_t tdccal=fHeader.is_calib.tdc; + Int_t totcal=fHeader.is_calib.tot; + Int_t utccal=fHeader.is_calib.utc; + + TF1 fadccal("fadccal","(x-[1])*[0]"); + TF1 fadcdecal("fadcdecal","(x/[0])+[1]"); + fadccal.SetParName(0,"BETA-ADC"); + fadccal.SetParName(1,"PED-ADC"); + fadcdecal.SetParName(0,"BETA-ADC"); + fadcdecal.SetParName(1,"PED-ADC"); + + TF1 ftdccal("ftdccal","(x*[0])-[1]-([0]-1.)*32767.-[2]/sqrt([3])"); + TF1 ftdcdecal("ftdcdecal","(x+([0]-1.)*32767.+[1]+[2]/sqrt([3]))/[0]"); + ftdccal.SetParName(0,"BETA-TDC"); + ftdccal.SetParName(1,"T0"); + ftdccal.SetParName(2,"ALPHA-TDC"); + ftdccal.SetParName(3,"ADC-SLEW"); + ftdcdecal.SetParName(0,"BETA-TDC"); + ftdcdecal.SetParName(1,"T0"); + ftdcdecal.SetParName(2,"ALPHA-TDC"); + ftdcdecal.SetParName(3,"ADC-SLEW"); + + TF1 ftotcal("ftotcal","x*[0]"); + TF1 ftotdecal("ftotdecal","x/[0]"); + ftotcal.SetParName(0,"BETA-TOT"); + ftotdecal.SetParName(0,"BETA-TOT"); + if (fOmdb) { fOmdb->Reset(); @@ -244,25 +396,91 @@ void IceF2k::FillOMdbase() { dev=new IceAOM(); dev->SetUniqueID(i+1); - dev->SetSlotName("TYPE",1); - dev->SetSlotName("ORIENT",2); - dev->SetSlotName("T0",3); - dev->SetSlotName("ALPHA",4); - dev->SetSlotName("KADC",5); - dev->SetSlotName("KTOT",6); - dev->SetSlotName("KTDC",7); + + dev->SetSlotName("ADC",1); + dev->SetSlotName("LE",2); + dev->SetSlotName("TOT",3); + + dev->SetSlotName("TYPE",4); + dev->SetSlotName("ORIENT",5); + dev->SetSlotName("THRESH",6); + dev->SetSlotName("SENSIT",7); + dev->SetSlotName("BETA-TDC",8); + dev->SetSlotName("T0",9); + dev->SetSlotName("ALPHA-TDC",10); + dev->SetSlotName("PED-ADC",11); + dev->SetSlotName("BETA-ADC",12); + dev->SetSlotName("KAPPA-ADC",13); + dev->SetSlotName("PED-TOT",14); + dev->SetSlotName("BETA-TOT",15); + dev->SetSlotName("KAPPA-TOT",16); pos[0]=fHeader.x[i]; pos[1]=fHeader.y[i]; pos[2]=fHeader.z[i]; dev->SetPosition(pos,"car"); - dev->SetSignal(fHeader.type[i],1); - dev->SetSignal((Float_t)fHeader.costh[i],2); - dev->SetSignal(fHeader.cal[i].t_0,3); - dev->SetSignal(fHeader.cal[i].alpha_t,4); - dev->SetSignal(fHeader.cal[i].beta_a,5); - dev->SetSignal(fHeader.cal[i].beta_tot,6); - dev->SetSignal(fHeader.cal[i].beta_t,7); + + fadccal.SetParameter(0,fHeader.cal[i].beta_a); + fadccal.SetParameter(1,fHeader.cal[i].ped); + fadcdecal.SetParameter(0,fHeader.cal[i].beta_a); + if (!fHeader.cal[i].beta_a) fadcdecal.SetParameter(0,1); + fadcdecal.SetParameter(1,fHeader.cal[i].ped); + + ftdccal.SetParameter(0,fHeader.cal[i].beta_t); + ftdccal.SetParameter(1,fHeader.cal[i].t_0); + ftdccal.SetParameter(2,fHeader.cal[i].alpha_t); + ftdccal.SetParameter(3,1.e20); + ftdcdecal.SetParameter(0,fHeader.cal[i].beta_t); + if (!fHeader.cal[i].beta_t) ftdcdecal.SetParameter(0,1); + ftdcdecal.SetParameter(1,fHeader.cal[i].t_0); + ftdcdecal.SetParameter(2,fHeader.cal[i].alpha_t); + ftdcdecal.SetParameter(3,1.e20); + + ftotcal.SetParameter(0,fHeader.cal[i].beta_tot); + ftotdecal.SetParameter(0,fHeader.cal[i].beta_tot); + if (!fHeader.cal[i].beta_tot) ftotdecal.SetParameter(0,1); + + if (adccal) + { + dev->SetDecalFunction(&fadcdecal,1); + } + else + { + dev->SetCalFunction(&fadccal,1); + } + + if (tdccal) + { + dev->SetDecalFunction(&ftdcdecal,2); + } + else + { + dev->SetCalFunction(&ftdccal,2); + } + + if (totcal) + { + dev->SetDecalFunction(&ftotdecal,3); + } + else + { + dev->SetCalFunction(&ftotcal,3); + } + + dev->SetSignal(fHeader.type[i],4); + dev->SetSignal((Float_t)fHeader.costh[i],5); + dev->SetSignal(fHeader.thresh[i],6); + dev->SetSignal(fHeader.sensit[i],7); + dev->SetSignal(fHeader.cal[i].beta_t,8); + dev->SetSignal(fHeader.cal[i].t_0,9); + dev->SetSignal(fHeader.cal[i].alpha_t,10); + dev->SetSignal(fHeader.cal[i].ped,11); + dev->SetSignal(fHeader.cal[i].beta_a,12); + dev->SetSignal(fHeader.cal[i].kappa,13); + dev->SetSignal(fHeader.cal[i].ped_tot,14); + dev->SetSignal(fHeader.cal[i].beta_tot,15); + dev->SetSignal(fHeader.cal[i].kappa_tot,16); + fOmdb->EnterObject(i+1,1,dev); } } @@ -337,12 +555,13 @@ void IceF2k::SetFitdefs() } } /////////////////////////////////////////////////////////////////////////// -void IceF2k::PutMcTracks(IceEvent* evt) +void IceF2k::PutMcTracks() { // Get the MC tracks from the F2000 file into the IcePack structure. // Note : MC tracks are given negative track id's in the event structure. // This memberfunction is based on the original code by Adam Bouchta. + IceEvent* evt=(IceEvent*)GetMainObject(); if (!evt || fEvent.ntrack<=0) return; // Loop over all the tracks and add them to the current event @@ -439,12 +658,13 @@ void IceF2k::PutMcTracks(IceEvent* evt) } } /////////////////////////////////////////////////////////////////////////// -void IceF2k::PutRecoTracks(IceEvent* evt) +void IceF2k::PutRecoTracks() { // Get the reconstructed tracks from the F2000 file into the IcePack structure. // Note : Reco tracks are given positive track id's in the event structure. // This memberfunction is based on the original code by Adam Bouchta. + IceEvent* evt=(IceEvent*)GetMainObject(); if (!evt || fEvent.nfit<=0) return; // Loop over all the tracks and add them to the current event @@ -545,11 +765,12 @@ void IceF2k::PutRecoTracks(IceEvent* evt) } } /////////////////////////////////////////////////////////////////////////// -void IceF2k::PutHits(IceEvent* evt) +void IceF2k::PutHits() { // Get the hit and waveform info from the F2000 file into the IcePack structure. // This memberfunction is based on the original code by Adam Bouchta. + IceEvent* evt=(IceEvent*)GetMainObject(); if (!evt) return; // Loop over all the hits and add them to the current event @@ -565,6 +786,7 @@ void IceF2k::PutHits(IceEvent* evt) AliSignal* sx=0; Int_t tid=0; AliTrack* tx=0; + Float_t adc=0; for (Int_t i=0; iGetHit(omx->GetNhits()); if (!sx) continue; + // ADC dependent TDC (de)calibration function for this hit + TF1* fcal=omx->GetCalFunction("LE"); + TF1* fdecal=omx->GetDecalFunction("LE"); + if (fcal) sx->SetCalFunction(fcal,2); + if (fdecal) sx->SetDecalFunction(fdecal,2); + fcal=sx->GetCalFunction(2); + fdecal=sx->GetDecalFunction(2); + adc=sx->GetSignal(1,-4); + if (adc>0) + { + if (fcal) fcal->SetParameter(3,adc); + if (fdecal) fdecal->SetParameter(3,adc); + } + else + { + if (fcal) fcal->SetParameter(3,0); + if (fdecal) fdecal->SetParameter(3,0); + } + // Bi-directional link between this hit and the track that caused the ADC value. // This F2K info is probably only present for MC tracks. tid=fEvent.h[i].ma; @@ -666,7 +907,7 @@ void IceF2k::PutHits(IceEvent* evt) for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++) { - histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin]); + histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin-1]); } omx->SetWaveform(&histo,omx->GetNwaveforms()+1);