]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - RALICE/icepack/iceconvert/IceF2k.cxx
22-jun-2006 NvE Linear track storage facility introduced in AliSignal to enable
[u/mrichter/AliRoot.git] / RALICE / icepack / iceconvert / IceF2k.cxx
index 19bcb7d00cf9541fba4395960cad73bbd6a2bdf7..6e36e2c30807f9a55d667a9e13c1281b30a5d18a 100644 (file)
 // 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. 
+// to investigate/analyse F2K data using the Ralice/IcePack analysis tools.
+//
+// Note : Sometimes the filtering/reco process which produced the F2K file
+//        may have introduced a shift (i.e. offset) in the hit times w.r.t.
+//        the actual trigger time. The aim of this is to obtain the hit times
+//        centered more or less around zero.
+//        In case of real data, this is recorded in the F2K data itself and
+//        as such will be taken automatically into account by this IceF2k
+//        processor such that all times will be provided again unshifted.
+//        In other words, all times will be w.r.t. the actual trigger time
+//        as recorded in the trigger data device named "Trigger" in the IceEvent
+//        structure.
+//        In case of simulated data this shift is not available in the F2K data.
+//        The offset denoted in the F2K record is related to the time of the
+//        primary interaction to put it well ahead of the detector trigger.
+//        This primary interaction time, however, is irrelevant for the
+//        reconstruction of the recorded hit patterns. 
+//        If a user had introduced a shift in producing the MC data,
+//        very frequently (but not always) a value of -19000 is used.
+//        For the IceF2k processing, the user can manually introduce a
+//        time offset in case of MC data via the memberfunction SetMcToffset().
+//        This user defined offset value will then be used to correct all
+//        the hit times such that they will be provided again unshifted
+//        w.r.t. the actual trigger time as recorded in the device named 
+//        "Trigger" in the IceEvent structure.
+//        By default the MC time offset is set to 0 in the constructor
+//        of this class.
 //
 // Usage example :
 // ---------------
 // q.SetPrintFreq(1);
 //
 // // Split level for the output structures
-// q.SetSplitLevel(2);
+// q.SetSplitLevel(0);
 //
 // // Buffer size for the output structures
 // q.SetBufferSize(32000);
 //
-// // The F2K input filename
-// q.SetInputFile("run7825.f2k");
+// // The F2K input filename(s)
+// q.AddInputFile("run7825.f2k");
 //
 // // Output file for the event structures
 // q.SetOutputFile("events.root");
@@ -117,24 +143,34 @@ ClassImp(IceF2k) // Class implementation to enable ROOT I/O
 IceF2k::IceF2k(const char* name,const char* title) : AliJob(name,title)
 {
 // Default constructor.
-// By default maxevent=-1, split=99, bsize=32000, printfreq=1.
+// By default maxevent=-1, split=0, bsize=32000, printfreq=1.
 
- fSplit=99;
+ fSplit=0;
  fBsize=32000;
  fMaxevt=-1;
  fPrintfreq=1;
- fInfile="";
+ fInfiles=0;
  fOutfile=0;
 
  fPdg=0;
  fOmdb=0;
  fFitdefs=0;
+ fTrigdefs=0;
+ fToffset=0;
+ fMctoffset=0;
+ fMctracks=3;
 }
 ///////////////////////////////////////////////////////////////////////////
 IceF2k::~IceF2k()
 {
 // Default destructor.
 
+ if (fInfiles)
+ {
+  delete fInfiles;
+  fInfiles=0;
+ }
+
  if (fPdg)
  {
   delete fPdg;
@@ -152,6 +188,12 @@ IceF2k::~IceF2k()
   delete fFitdefs;
   fFitdefs=0;
  }
+
+ if (fTrigdefs)
+ {
+  delete fTrigdefs;
+  fTrigdefs=0;
+ }
 }
 ///////////////////////////////////////////////////////////////////////////
 void IceF2k::SetMaxEvents(Int_t n)
@@ -172,7 +214,7 @@ void IceF2k::SetPrintFreq(Int_t 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.
+// split=0 is the default initialisation in the constructor.
  if (split>=0) fSplit=split;
 }
 ///////////////////////////////////////////////////////////////////////////
@@ -183,10 +225,62 @@ void IceF2k::SetBufferSize(Int_t bsize)
  if (bsize>=0) fBsize=bsize;
 }
 ///////////////////////////////////////////////////////////////////////////
+void IceF2k::SetMcToffset(Float_t toffset)
+{
+// Set a user defined time offset for Monte Carlo data.
+// A very frequently (but not always) used value is -19000.
+// See the introductory docs of this class for further details.
+ fMctoffset=toffset;
+}
+///////////////////////////////////////////////////////////////////////////
+void IceF2k::SelectMcTracks(Int_t mode)
+{
+// User selection of MC tracks to be stored in the event structure.
+//
+// mode = 0 : No MC tracks are stored
+//        1 : Only muon and muon-neutrino MC tracks are stored
+//        2 : All lepton MC tracks are stored
+//        3 : All MC tracks (incl. brems, pairprod etc...) are stored
+//
+// By default mode=3 is set in the constructor of this class.
+
+ if (mode<0 || mode >3) return;
+ fMctracks=mode;
+}
+///////////////////////////////////////////////////////////////////////////
 void IceF2k::SetInputFile(TString name)
 {
 // Set the name of the F2K input file.
- fInfile=name;
+// This function has become obsolete but is kept for backward compatibility.
+// The user is advised to use AddInputFile() instead, which allows processing
+// of multiple F2K input files.
+// This function will reset the list of all F2K input files and put the specified
+// filename at the first position.
+// Additional F2K input files can be specified via AddInputFile().
+
+ if (fInfiles) delete fInfiles;
+
+ fInfiles=new TObjArray();
+ fInfiles->SetOwner();
+
+ TObjString* s=new TObjString();
+ s->SetString(name);
+ fInfiles->Add(s);
+}
+///////////////////////////////////////////////////////////////////////////
+void IceF2k::AddInputFile(TString name)
+{
+// Add the name of this F2K input file to the list to be processed.
+
+ if (!fInfiles)
+ {
+  fInfiles=new TObjArray();
+  fInfiles->SetOwner();
+ }
+
+ TObjString* s=new TObjString();
+ s->SetString(name);
+ fInfiles->Add(s);
 }
 ///////////////////////////////////////////////////////////////////////////
 void IceF2k::SetOutputFile(TFile* ofile)
@@ -227,6 +321,12 @@ AliDevice* IceF2k::GetFitdefs()
  return fFitdefs;
 }
 ///////////////////////////////////////////////////////////////////////////
+AliDevice* IceF2k::GetTrigdefs()
+{
+// Provide pointer to the trigger definitions
+ return fTrigdefs;
+}
+///////////////////////////////////////////////////////////////////////////
 void IceF2k::Exec(Option_t* opt)
 {
 // Job to loop over the specified number of events and convert the 
@@ -246,27 +346,19 @@ void IceF2k::Exec(Option_t* opt)
 //    final data structures are written out.
 // 2) The main object in this job environment is an IceEvent* pointer.
 
- if (fInfile=="")
+ if (!fInfiles)
  {
-  cout << " *IceF2k Exec* No data input file specified." << endl;
+  cout << " *IceF2k Exec* No data input file(s) 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)
+ Int_t ninfiles=fInfiles->GetEntries();
+ if (!ninfiles)
  {
-  cout << " *IceF2k Exec* No input file found with name : " << fInfile.Data() << endl;
+  cout << " *IceF2k Exec* No data input file(s) specified." << endl;
   return;
  }
 
- // Initialise the event structure 
- rdmc_init_mevt(&fEvent);
-
- // Read the file header information
- rdmc_rarr(fInput,&fHeader);
-
  TTree* otree=0;
  if (fOutfile)
  {
@@ -296,13 +388,6 @@ void IceF2k::Exec(Option_t* opt)
  fPdg->AddParticle("z_primary","z_primary",0,1,0,0,"none",10003000,0,0);
  fPdg->AddParticle("a_primary","a_primary",0,1,0,0,"none",10003500,0,0);
 
- // Fill the database with geometry, calib. etc... parameters
- // for all the devices
- FillOMdbase();
-
- // Set the fit definitions according to the F2000 header info
- SetFitdefs();
-
  // Initialise the job working environment
  SetMainObject(evt);
  if (fOutfile)
@@ -311,10 +396,18 @@ void IceF2k::Exec(Option_t* opt)
   AddObject(otree);
  }
 
+ TString inputfile;
+
  cout << " ***" << endl;
  cout << " *** Start processing of job " << GetName() << " ***" << endl;
  cout << " ***" << endl;
- cout << " F2K input file : " << fInfile.Data() << endl;
+ for (Int_t i=0; i<ninfiles; i++)
+ {
+  TObjString* sx=(TObjString*)fInfiles->At(i);
+  if (!sx) continue;
+  inputfile=sx->GetString(); 
+  cout << " F2K input file : " << inputfile.Data() << endl;
+ }
  cout << " Maximum number of events to be processed : " << fMaxevt << endl;
  cout << " Print frequency : " << fPrintfreq << endl;
  if (fOutfile)
@@ -324,39 +417,81 @@ void IceF2k::Exec(Option_t* opt)
  }
 
  ListEnvironment();
+
  Int_t nevt=0;
while (!rdmc_revt(fInput,&fHeader,&fEvent))
for (Int_t ifile=0; ifile<ninfiles; ifile++)
  {
-  if (fMaxevt>-1 && nevt>=fMaxevt) break;
+  TObjString* sx=(TObjString*)fInfiles->At(ifile);
+  if (!sx) continue;
+
+  inputfile=sx->GetString(); 
+  if (inputfile=="") continue;
 
-  // Reset the complete Event structure
-  evt->Reset();
+  // Open the input file in the default ascii format (autodetection) for reading 
+  fInput=rdmc_mcopen(inputfile.Data(),"r",RDMC_DEFAULT_ASCII_F);
 
-  evt->SetRunNumber(fEvent.nrun);
-  evt->SetEventNumber(fEvent.enr);
-  evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs);
+  if (!fInput)
+  {
+   cout << " *IceF2k Exec* No input file found with name : " << inputfile.Data() << endl;
+   continue;
+  }
 
-  PutMcTracks();
+  // Initialise the event structure 
+  rdmc_init_mevt(&fEvent);
 
-  PutRecoTracks();
+  // Read the file header information
+  rdmc_rarr(fInput,&fHeader);
 
-  PutHits();
+  // Fill the database with geometry, calib. etc... parameters
+  // for all the devices
+  FillOMdbase();
 
-  // Invoke all available sub-tasks (if any)
-  CleanTasks();
-  ExecuteTasks(opt);
+  // Set the fit definitions according to the F2000 header info
+  SetFitdefs();
 
-  if (fPrintfreq)
+  // Set the trigger definitions according to the F2000 header info
+  SetTrigdefs();
+  while (!rdmc_revt(fInput,&fHeader,&fEvent))
   {
-   if (!(nevt%fPrintfreq)) evt->HeaderData();
-  }
+   if (fMaxevt>-1 && nevt>=fMaxevt) break;
+
+   // Reset the complete Event structure
+   evt->Reset();
+
+   evt->SetRunNumber(fEvent.nrun);
+   evt->SetEventNumber(fEvent.enr);
+   evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs);
 
-  // Write the complete structure to the output Tree
-  if (otree) otree->Fill();
+   // Take trigger offset into account which might have been
+   // introduced during the filtering process.
+   // For simulated data this will be treated separately in PutMcTracks().
+   fToffset=fEvent.t_offset;
 
-  // Update event counter
-  nevt++;
+   PutTrigger();
+
+   PutMcTracks();
+
+   PutRecoTracks();
+
+   PutHits();
+
+   // Invoke all available sub-tasks (if any)
+   CleanTasks();
+   ExecuteTasks(opt);
+
+   if (fPrintfreq)
+   {
+    if (!(nevt%fPrintfreq)) evt->HeaderData();
+   }
+
+   // Write the complete structure to the output Tree
+   if (otree) otree->Fill();
+
+   // Update event counter
+   nevt++;
+  }
+  if (fMaxevt>-1 && nevt>=fMaxevt) break;
  }
 
  // Flush possible memory resident data to the output file
@@ -376,7 +511,15 @@ void IceF2k::FillOMdbase()
 // Fill the database with geometry, calib. etc... parameters 
 // for all the devices.
 
- if (fHeader.nch<=0) return;
+ if (fHeader.nch<=0)
+ {
+  if (fOmdb)
+  {
+   delete fOmdb;
+   fOmdb=0;
+  }
+  return;
+ }
 
  Int_t adccal=fHeader.is_calib.adc;
  Int_t tdccal=fHeader.is_calib.tdc;
@@ -515,8 +658,8 @@ void IceF2k::SetFitdefs()
 {
 // Obtain the names of the variables for each fit procedure from the
 // f2000 header. Each different fit procedure is then stored as a separate
-// hit of an AliDevice object and the various fit variables are stored
-// as separate signal slots of the corresponding hit.
+// "hit" of an AliDevice object and the various fit variables are stored
+// as separate signal slots of the corresponding "hit".
 // Via the GetFitdefs() memberfunction this AliDevice object can be
 // retrieved and stored in the ROOT output file if wanted.
 // The name of the object is FitDefinitions and the stored data can be
@@ -530,26 +673,34 @@ void IceF2k::SetFitdefs()
 //    Position Vector in car coordinates : 0 0 0
 //    Err. in car coordinates : 0 0 0
 //    Owned by device : AliDevice Name : FitDefinitions
-//    Slot : 1 Signal value : 1 name : id
-//    Slot : 2 Signal value : 2 name : rchi2
-//    Slot : 3 Signal value : 3 name : prob
-//    Slot : 4 Signal value : 4 name : sigth
-//    Slot : 5 Signal value : 5 name : covmin
-//    Slot : 6 Signal value : 6 name : covmax
-//    Slot : 7 Signal value : 7 name : cutflag
-//    Slot : 8 Signal value : 8 name : chi2
+//    Slot : 1 Signal value : 0 name : id
+//    Slot : 2 Signal value : 0 name : rchi2
+//    Slot : 3 Signal value : 0 name : prob
+//    Slot : 4 Signal value : 0 name : sigth
+//    Slot : 5 Signal value : 0 name : covmin
+//    Slot : 6 Signal value : 0 name : covmax
+//    Slot : 7 Signal value : 0 name : cutflag
+//    Slot : 8 Signal value : 0 name : chi2
 //  *AliSignal::Data* Id :1
 //    Position Vector in car coordinates : 0 0 0
 //    Err. in car coordinates : 0 0 0
 //    Owned by device : AliDevice Name : FitDefinitions
-//    Slot : 1 Signal value : 1 name : id
-//    Slot : 2 Signal value : 2 name : rchi2
-//    Slot : 3 Signal value : 3 name : prob
+//    Slot : 1 Signal value : 0 name : id
+//    Slot : 2 Signal value : 0 name : rchi2
+//    Slot : 3 Signal value : 0 name : prob
 // etc....  
 //
 // This memberfunction is based on the original idea/code by Adam Bouchta.
 
- if (fHeader.n_fit<=0) return;
+ if (fHeader.n_fit<=0)
+ {
+  if (fFitdefs)
+  {
+   delete fFitdefs;
+   fFitdefs=0;
+  }
+  return;
+ }
 
  if (fFitdefs)
  {
@@ -569,11 +720,12 @@ void IceF2k::SetFitdefs()
  for (Int_t i=0; i<fHeader.n_fit; i++)
  {
   s.SetUniqueID(fHeader.def_fit[i].id);
+  s.SetName(TString(fHeader.def_fit[i].tag));
 
   for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++)
   {
    s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1);
-   s.SetSignal(j+1,j+1);
+   s.SetSignal(0,j+1);
   }
 
   fFitdefs->AddHit(s);
@@ -581,6 +733,85 @@ void IceF2k::SetFitdefs()
  }
 }
 ///////////////////////////////////////////////////////////////////////////
+void IceF2k::SetTrigdefs()
+{
+// Obtain the names of the variables for each trigger procedure from the
+// f2000 header. Each different trigger procedure is then stored as a separate
+// "hit" of an AliDevice object and the various trigger variables are stored
+// as separate signal slots of the corresponding "hit".
+// Via the GetFitdefs() memberfunction this AliDevice object can be
+// retrieved and stored in the ROOT output file if wanted.
+// The name of the object is TrigDefinitions and the stored data can be
+// inspected via the AliDevice::Data() memberfunction and looks as follows :
+//
+//  *AliDevice::Data* Id : 0 Name : TrigDefinitions
+//    Position Vector in car (rad) coordinates : 0 0 0
+//    Err. in car (rad) coordinates : 0 0 0
+//  The following 9 hits are registered : 
+//  *AliSignal::Data* Id : 1 Name : main
+//    Position Vector in car (rad) coordinates : 0 0 0
+//    Err. in car (rad) coordinates : 0 0 0
+//    Owned by device : AliDevice Id : 0 Name : TrigDefinitions
+//     Slot : 1 Signal value : 0 name : trig_pulse_le
+//     Slot : 2 Signal value : 0 name : trig_pulse_tot
+//     Slot : 3 Signal value : 0 name : regi_flag
+//   *AliSignal::Data* Id : 2 Name : amaa
+//     Position Vector in car (rad) coordinates : 0 0 0
+//     Err. in car (rad) coordinates : 0 0 0
+//     Owned by device : AliDevice Id : 0 Name : TrigDefinitions
+//     Slot : 1 Signal value : 0 name : trig_pulse_le
+//     Slot : 2 Signal value : 0 name : trig_pulse_tot
+//     Slot : 3 Signal value : 0 name : regi_flag
+//   *AliSignal::Data* Id : 3 Name : amab10
+//     Position Vector in car (rad) coordinates : 0 0 0
+//     Err. in car (rad) coordinates : 0 0 0
+//     Owned by device : AliDevice Id : 0 Name : TrigDefinitions
+//     Slot : 1 Signal value : 0 name : trig_pulse_le
+//     Slot : 2 Signal value : 0 name : trig_pulse_tot
+//     Slot : 3 Signal value : 0 name : regi_flag
+// etc....  
+
+ if (fHeader.n_trigger<=0)
+ {
+  if (fTrigdefs)
+  {
+   delete fTrigdefs;
+   fTrigdefs=0;
+  }
+  return;
+ }
+
+ if (fTrigdefs)
+ {
+  fTrigdefs->Reset(1);
+ }
+ else
+ {
+  fTrigdefs=new AliDevice();
+ }
+
+ fTrigdefs->SetName("TrigDefinitions");
+ fTrigdefs->SetHitCopy (1);
+
+ AliSignal s;
+ s.Reset();
+
+ for (Int_t i=0; i<fHeader.n_trigger; i++)
+ {
+  s.SetUniqueID(fHeader.def_trig[i].id);
+  s.SetName(TString(fHeader.def_trig[i].tag));
+
+  for (Int_t j=0; j<fHeader.def_trig[i].nwords; j++)
+  {
+   s.SetSlotName(TString(fHeader.def_trig[i].words[j]),j+1);
+   s.SetSignal(0,j+1);
+  }
+
+  fTrigdefs->AddHit(s);
+  s.Reset(1);
+ }
+}
+///////////////////////////////////////////////////////////////////////////
 void IceF2k::PutMcTracks()
 {
 // Get the MC tracks from the F2000 file into the IcePack structure.
@@ -590,6 +821,14 @@ void IceF2k::PutMcTracks()
  IceEvent* evt=(IceEvent*)GetMainObject();
  if (!evt || fEvent.ntrack<=0) return;
 
+ // User defined trigger offset in case of simulated data.
+ // The offset in the F2K file is meant to put the primary interaction
+ // well ahead of the detector trigger.
+ // See the introductory docs of this IceF2k class for further details.
+ fToffset=fMctoffset;
+
+ if (!fMctracks) return;
+
  // Loop over all the tracks and add them to the current event
  AliTrack t;
  Double_t vec[3];
@@ -647,6 +886,16 @@ void IceF2k::PutMcTracks()
    if (idf2k==206) idpdg=-16;
   }
 
+  // Check for the user selected MC track storage
+  if (fMctracks==1) // Store only muon and muon-neutrino tracks
+  {
+   if (abs(idpdg)!=13 && abs(idpdg)!=14) continue;
+  }
+  else if (fMctracks==2) // Store all lepton tracks
+  {
+   if (abs(idpdg)<11 || abs(idpdg)>16) continue;
+  }
+
   t.SetParticleCode(idpdg);
   t.SetName(fPdg->GetParticle(idpdg)->GetName());
   t.SetTitle("MC track");
@@ -760,8 +1009,7 @@ void IceF2k::PutRecoTracks()
   }
 
   t.SetParticleCode(idpdg);
-  t.SetName(fPdg->GetParticle(idpdg)->GetName());
-  t.SetTitle("RECO track");
+  t.SetNameTitle("Sieglinde","RECO track");
   t.SetMass(fPdg->GetParticle(idpdg)->Mass());
   t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
 
@@ -813,6 +1061,7 @@ void IceF2k::PutHits()
  Int_t tid=0;
  AliTrack* tx=0;
  Float_t adc=0;
+ Float_t adcfirst=0; // Adc value of the first hit of an OM
  for (Int_t i=0; i<fEvent.nhits; i++)
  {
   chan=fEvent.h[i].ch+1;
@@ -838,10 +1087,23 @@ void IceF2k::PutHits()
 
   if (!omx) continue;
 
+  adc=fEvent.h[i].amp;
+
+  // Multiple hits in the same OM with the same ADC value
+  // are indicated by "*" in the F2K file.
+  // This corresponds to a value of -2 in the data structure.
+  if (int(adc) == -2)
+  {
+   adc=adcfirst;
+  }
+  else
+  {
+   adcfirst=adc;
+  }
   s.Reset();
   s.SetUniqueID(fEvent.h[i].id);
-  s.SetSignal(fEvent.h[i].amp,1);
-  s.SetSignal(fEvent.h[i].t,2);
+  s.SetSignal(adc,1);
+  s.SetSignal((fEvent.h[i].t-fToffset),2);
   s.SetSignal(fEvent.h[i].tot,3);
 
   omx->AddHit(s);
@@ -875,12 +1137,12 @@ void IceF2k::PutHits()
   {
    tx=evt->GetIdTrack(tid); // Reco tracks
    if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks
-   if (tx) sx->AddLink(tx);
+   if (tx) sx->AddTrack(*tx);
   }
   else
   {
-   if (tid == -2) s.SetNameTitle("N","Noise");
-   if (tid == -3) s.SetNameTitle("A","Afterpulse");
+   if (tid == -2) sx->SetNameTitle("N","Noise");
+   if (tid == -3) sx->SetNameTitle("A","Afterpulse");
   }
  }
 
@@ -916,7 +1178,7 @@ void IceF2k::PutHits()
   if (!omx) continue;
 
   omx->SetSlotName("BASELINE",omx->GetNnames()+1);
-  omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE");
+  omx->SetSignal(-fEvent.wf[iwf].baseline,"BASELINE");
 
   // Fill the waveform histogram
   hname="OM";
@@ -933,7 +1195,7 @@ void IceF2k::PutHits()
 
   for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++)
   {
-   histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin-1]);
+   histo.SetBinContent(jbin,-fEvent.wf[iwf].digi[jbin-1]);
   }
 
   omx->SetWaveform(&histo,omx->GetNwaveforms()+1);
@@ -959,9 +1221,49 @@ void IceF2k::PutHits()
     if (fEvent.fit_uses[k].useid != hypx->GetId()) continue;
     hid=fEvent.fit_uses[k].hitid;
     sx=evt->GetIdHit(hid,"IceAOM");
-    if (sx) sx->AddLink(hypx);
+    if (sx) sx->AddTrack(*hypx);
    }
   }
  }
 }
 ///////////////////////////////////////////////////////////////////////////
+void IceF2k::PutTrigger()
+{
+// Get the trigger info from the F2000 file into the IcePack structure.
+
+ if (!fTrigdefs) return;
+
+ IceEvent* evt=(IceEvent*)GetMainObject();
+ if (!evt || fEvent.ntrig<=0) return;
+
+ AliDevice trig;
+ trig.SetNameTitle("Trigger","Amanda/IceCube event triggers");
+ AliSignal s;
+ TString trigname;
+ TString slotname;
+ Int_t id=0;
+ Int_t nval=0;
+ for (Int_t i=0; i<fEvent.ntrig; i++)
+ {
+  id=fEvent.ptrig[i].id;
+  nval=fEvent.ptrig[i].nval;
+  if (!nval) continue;
+  AliSignal* tdef=fTrigdefs->GetIdHit(id+1);
+  if (!tdef) continue;
+  trigname=tdef->GetName();
+  s.Reset(1);
+  s.SetName(trigname);
+  s.SetUniqueID(id+1);
+  for (Int_t jval=0; jval<fEvent.ptrig[i].nval; jval++)
+  {
+   slotname=tdef->GetSlotName(jval+1);
+   s.SetSlotName(slotname,jval+1);
+   s.SetSignal(fEvent.ptrig[i].val[jval],jval+1);
+  }
+  trig.AddHit(s);
+ }
+
+ // Store the trigger data into the IceEvent structure
+ evt->AddDevice(trig);
+}
+///////////////////////////////////////////////////////////////////////////