14-nov-2007 NvE Copy constructor and Clone() memberfunction introduced in AliObjMatrix.
[u/mrichter/AliRoot.git] / RALICE / icepack / iceconvert / IceDB2Root.cxx
1 /*******************************************************************************
2  * Copyright(c) 2003, IceCube Experiment at the South Pole. All rights reserved.
3  *
4  * Author: The IceCube RALICE-based Offline Project.
5  * Contributors are mentioned in the code where appropriate.
6  *
7  * Permission to use, copy, modify and distribute this software and its
8  * documentation strictly for non-commercial purposes is hereby granted
9  * without fee, provided that the above copyright notice appears in all
10  * copies and that both the copyright notice and this permission notice
11  * appear in the supporting documentation.
12  * The authors make no claims about the suitability of this software for
13  * any purpose. It is provided "as is" without express or implied warranty.
14  *******************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class IceDB2Root
20 // Extraction of Amanda and IceCube calibration data from the IceCube database.
21 // Calibration data are stored into an AliObjMatrix containing the complete OM 
22 // position, calibration, Xtalk etc... database.
23 // Various AliObjMatrix objects are created and (optionally) stored in a single 
24 // output file.
25 // The names of the AliObjMatrix objects indicate the type of database they
26 // contain.
27 // For example :
28 // The name "MuDaq-OMDBASE" indicates the database info for MuDaq data,
29 // whereas TWRDaq calibration data is in the object named "TWRDaq-OMDBASE".
30 // In addition a PDG particle database, extended with some specific Amanda
31 // entries, is provided as well.
32 // This class is derived from AliJob providing task-based processing.
33 // Note that the data structures are only written out if an outputfile has
34 // been specified via the SetOutputFile memberfunction.
35 // In case no outputfile has been specified, this class provides a facility
36 // to investigate/use the dbase data directly in subsequent (sub)tasks.
37 //
38 // The OM database information in the AliObjMatrix has the following structure :
39 //
40 // (j,1)    : Pointer to OM with identifier "j"
41 // (j,k+1)  : Pointer to a TF1* being the probability function for Xtalk
42 //            with OM "j" as transmitter and OM "k" as receiver.
43 //
44 // The latter is only available for MuDaq and TWRDaq databases.
45 //
46 // The geometry information is directly available from the OM pointer
47 // in the form of its position and data words like "ORIENT" for orientation etc...
48 // Just use the OM memberfunction Data() to obtain a full overview. 
49 //
50 // Note : Position coordinates are indicated in meters and times are in nanoseconds,
51 //        in accordance with the convention used previously for Amanda.
52 //
53 // From the OM pointer also the various (de)calibration functions for
54 // ADC, LE and TOT can be obtained as TF1* pointers.
55 // The actual values of the calibration constants are stored as parameters
56 // of these (de)calibration functions and can be investigated via the
57 // usual TF1::Print() or TF1::GetParameter() facilities.
58 // The last two parameters of the Xtalk probability function have no effect
59 // on the evaluated probability value. However, these two parameters provide
60 // the minimum and maximum allowed LE differences between the transmitter
61 // and receiver hits, respectively (as can be seen from the parameter names).
62 //
63 // The (de)calibration of signals and/or determination of the Xtalk probability
64 // can be performed via the standard TF1::Eval(x) functionality, where "x"
65 // represents the input argument of the function (e.g. an uncalibrated ADC value).
66 //
67 // In general the database is not directly accessed by the user in performing
68 // physics analysis, since all the necessary information is contained in the
69 // event data itself and available via the GetSignal() memberfunction of the hits.
70 // However, specific tasks like e.g. calibration, Xtalk correction,
71 // bad module removal, noise hit removal etc... might need explicit database access.
72 // So, at the end of the example below some functionality is indicated for clarity.
73 // The user may use exactly the same procedures to obtain explicit access to the calibration
74 // functions etc... from the various OMs and/or hits within the actual event data which he/she
75 // is analysing.
76 //
77 // The PDG particle database is a standard ROOT TDatabasePDG object
78 // with the following extensions :
79 //
80 // Name        PDG code
81 // ----        --------
82 // brems       10001001
83 // deltae      10001002
84 // pairprod    10001003
85 // nucl_int    10001004
86 // mu_pair     10001005
87 // hadrons     10001006
88 // fiberlaser  10002100
89 // n2laser     10002101
90 // yaglaser    10002201
91 // z_primary   10003000
92 // a_primary   10003500
93 // 
94 // Usage example :
95 // ---------------
96 //
97 // gSystem->Load("ralice");
98 // gSystem->Load("icepack");
99 // gSystem->Load("iceconvert");
100 //
101 // IceDB2Root q("IceDB2Root","DB to IcePack data structure conversion");
102 //
103 // // Output file for the event structures
104 // q.SetOutputFile("cal2005.root");
105 // q.SetUT(2005,7,1);
106 //
107 // ///////////////////////////////////////////////////////////////////
108 // // Here the user can specify his/her sub-tasks to be executed
109 // // after the database structures have been filled and before the
110 // // data is written out.
111 // // Sub-tasks (i.e. a user classes derived from TTask) are entered
112 // // as follows :
113 // //
114 // //    MyTask1 task1("task1","Some modifications to specific OMs");
115 // //    MyTask2 task2("task2","Removal of specific OMs");
116 // //    MyTask3 task3("task3","Add private objects to the output file");
117 // //    q.Add(&task1);
118 // //    q.Add(&task2);
119 // //    q.Add(&task3);
120 // //
121 // // The sub-tasks will be executed in the order as they are entered.
122 // ///////////////////////////////////////////////////////////////////
123 //
124 // // Perform the conversion and execute subtasks (if any)
125 // q.ExecuteJob();
126 //
127 // // Outline of dbase usage for (de)calibration and Xtalk
128 //
129 // AliObjMatrix* omdb=q.GetOMdbase("MuDaq");
130 // IceAOM* om=(IceAOM*)omdb->GetObject(9,1); // Pointer to OM 9
131 // om->Data(); // Overview of generic module parameters
132 // TF1* fcal=0;   // Calibration function
133 // TF1* fdecal=0; // De-calibration function
134 // fcal=om->GetCalFunction("ADC");
135 // Float_t adc=248; // Uncalibrated ADC
136 // Float_t cadc=0;  // Calibrated ADC
137 // if (fcal) cadc=fcal->Eval(adc);
138 // fcal=om->GetCalFunction("TOT");
139 // Float_t tot=1538; // Uncalibrated TOT
140 // Float_t ctot=0;   // Calibrated TOT
141 // if (fcal) ctot=fcal->Eval(tot);
142 // fdecal=om->GetDecalFunction("LE");
143 // Float_t le=21697; // Uncalibrated LE
144 // Float_t cle=0;    // Calibrated LE
145 // if (fcal) cle=fcal->Eval(le);
146 //
147 // // Xtalk probability between (trans) OM 90 and (rec) OM 113
148 // // for a transmitter signal of uncalibrated amplitude "adc".
149 // TF1* fxtalkp=(TF1*)omdb->GetObject(90,113+1);
150 // Float_t prob=0;
151 // adc=378;
152 // if (fxtalkp) prob=fxtalkp->Eval(adc);
153 //
154 //--- Author: Garmt de Vries-Uiterweerd 06-jun-2007 Utrecht University
155 //- Modified: GdVU $Date$ Utrecht University
156 ///////////////////////////////////////////////////////////////////////////
157  
158 #include "IceDB2Root.h"
159 #include "Riostream.h"
160
161 ClassImp(IceDB2Root) // Class implementation to enable ROOT I/O
162
163 IceDB2Root::IceDB2Root(const char* name,const char* title) : AliJob(name,title)
164 {
165 // Default constructor.
166  fDBName="mysql://icedb.umh.ac.be/I3OmDb";
167  fUser="www";
168  fPassword="";
169  fRootFileName="";
170  fOutfile=0;
171
172  fPdg=0;
173  fMuDaqdb=0;
174  fTWRDaqdb=0;
175  fJEBTDaqdb=0;
176  fJEBADaqdb=0;
177 }
178 ///////////////////////////////////////////////////////////////////////////
179 IceDB2Root::~IceDB2Root()
180 {
181 // Default destructor.
182
183  if (fPdg)
184  {
185   delete fPdg;
186   fPdg=0;
187  }
188
189  if (fMuDaqdb)
190  {
191   delete fMuDaqdb;
192   fMuDaqdb=0;
193  }
194
195  if (fTWRDaqdb)
196  {
197   delete fTWRDaqdb;
198   fTWRDaqdb=0;
199  }
200
201  if (fJEBTDaqdb)
202  {
203   delete fJEBTDaqdb;
204   fJEBTDaqdb=0;
205  }
206
207  if (fJEBADaqdb)
208  {
209   delete fJEBADaqdb;
210   fJEBADaqdb=0;
211  }
212 }
213 ///////////////////////////////////////////////////////////////////////////
214 void IceDB2Root::SetDatabase(TString name, TString user, TString password)
215 {
216 // Set the name of the database, and username/password needed to access it.
217  fDBName=name;
218  fUser=user;
219  fPassword=password;
220 }
221 ///////////////////////////////////////////////////////////////////////////
222 void IceDB2Root::SetOutputFile(TString name)
223 {
224 // Set the name of the ROOT output file.
225  fRootFileName=name;
226 }
227 ///////////////////////////////////////////////////////////////////////////
228 AliTimestamp IceDB2Root::GetTime()
229 {
230 // Return time for which the calibration is done.
231  return fTime;
232 }
233 ///////////////////////////////////////////////////////////////////////////
234 void IceDB2Root::SetUT(Int_t y, Int_t m, Int_t d, Int_t hh, Int_t mm, Int_t ss)
235 {
236 // Set time for which calibration is done. Input parameters are the same as 
237 // for AliTimestamp::SetUT. Default value for hh, mm and ss is 0.
238  fTime.SetUT(y,m,d,hh,mm,ss);
239 }
240 ///////////////////////////////////////////////////////////////////////////
241 TDatabasePDG* IceDB2Root::GetPDG()
242 {
243 // Provide pointer to the PDG database
244  return fPdg;
245 }
246 ///////////////////////////////////////////////////////////////////////////
247 AliObjMatrix* IceDB2Root::GetOMdbase(TString name)
248 {
249 // Provide pointer to the requested OM geometry, calib. etc... database.
250 // Options for the "name" specification are : MuDaq, TWRDaq, JEBTDaq, JEBADaq.
251 // For backward compatibility the default is name="MuDaq".
252
253  if (name=="MuDaq") return fMuDaqdb;
254  if (name=="TWRDaq") return fTWRDaqdb;
255  if (name=="JEBTDaq") return fJEBTDaqdb;
256  if (name=="JEBADaq") return fJEBADaqdb;
257  return 0;
258 }
259 ///////////////////////////////////////////////////////////////////////////
260 void IceDB2Root::Exec(Option_t* opt)
261 {
262 // Job to extract calibration data from database into the IcePack structure.
263 //
264 // Notes :
265 // -------
266 // 1) This class is derived from AliJob, allowing a task based processing.
267 //    After conversion of the (ascii) dbase data into the IcePack structure,
268 //    the processing of all available sub-tasks (if any) is invoked.
269 //    This provides a facility to investigate/use the dbase data in
270 //    subsequent (sub)tasks processing before the final data structures
271 //    are written out.
272 //
273 // 2) Creation of a TFolder via the argument of the ExecuteJob statement
274 //    makes all created database objects accessible to subsequent tasks
275 //    via the TFolder::FindObject facility.
276
277  if (fOutfile)
278  {
279   delete fOutfile;
280   fOutfile=0;
281  }
282  if (fRootFileName != "")
283  {
284   fOutfile=new TFile(fRootFileName.Data(),"RECREATE","Calibration data in IcePack structure");
285  }
286
287  // Create the particle database and extend it with some F2000 specific definitions
288  if (fPdg) delete fPdg;
289  fPdg=new TDatabasePDG();
290  fPdg->SetNameTitle("PDG-DBASE","The extended PDG particle database");
291  Double_t me=fPdg->GetParticle(11)->Mass();
292  fPdg->AddParticle("brems"   ,"brems"   ,0,1,0,0,"none",10001001,0,0);
293  fPdg->AddParticle("deltae"  ,"deltae"  ,me,1,0,-3,"Lepton",10001002,0,0);
294  fPdg->AddParticle("pairprod","pairprod",0,1,0,0,"none",10001003,0,0);
295  fPdg->AddParticle("nucl_int","nucl_Int",0,1,0,0,"none",10001004,0,0);
296  fPdg->AddParticle("mu_pair" ,"mu_pair" ,0,1,0,0,"none",10001005,0,0);
297  fPdg->AddParticle("hadrons" ,"hadrons" ,0,1,0,0,"none",10001006,0,0);
298  fPdg->AddParticle("fiberlaser","fiberlaser",0,1,0,0,"none",10002100,0,0);
299  fPdg->AddParticle("n2laser"   ,"n2laser"   ,0,1,0,0,"none",10002101,0,0);
300  fPdg->AddParticle("yaglaser"  ,"yaglaser"  ,0,1,0,0,"none",10002201,0,0);
301  fPdg->AddParticle("z_primary","z_primary",0,1,0,0,"none",10003000,0,0);
302  fPdg->AddParticle("a_primary","a_primary",0,1,0,0,"none",10003500,0,0);
303
304  // Initialise the job working environment
305  AddObject(fPdg);
306  if (fOutfile) AddObject(fOutfile);
307
308  cout << " ***" << endl;
309  cout << " *** Start processing of job " << GetName() << " ***" << endl;
310  cout << " ***" << endl;
311  cout << " Database : " << fDBName.Data() << endl;
312  if (fOutfile) cout << " ROOT output file : " << fOutfile->GetName() << endl;
313
314  // Get all the data
315  GetMuDaqData();
316  if (fMuDaqdb) AddObject(fMuDaqdb);
317
318  GetTWRDaqData();
319  if (fTWRDaqdb) AddObject(fTWRDaqdb);
320
321  GetJEBTDaqData();
322  if (fJEBTDaqdb) AddObject(fJEBTDaqdb);
323
324  GetJEBADaqData();
325  if (fJEBADaqdb) AddObject(fJEBADaqdb);
326
327  ListEnvironment();
328
329  // Invoke all available sub-tasks (if any)
330  CleanTasks();
331  ExecuteTasks(opt);
332
333  // Write the datastructures to the output file
334  if (fOutfile)
335  {
336   fOutfile->cd();
337   if (fMuDaqdb) fMuDaqdb->Write();
338   if (fTWRDaqdb) fTWRDaqdb->Write();
339   if (fJEBTDaqdb) fJEBTDaqdb->Write();
340   if (fJEBADaqdb) fJEBADaqdb->Write();
341   if (fPdg) fPdg->Write();
342  }
343
344  // Flush remaining memory resident data to the output file
345  if (fOutfile) fOutfile->Write();
346 }
347 ///////////////////////////////////////////////////////////////////////////
348 void IceDB2Root::GetMuDaqData()
349 {
350 // Obtain all the MuDaq geometry, calibration and Xtalk data.
351
352  // Connect to the DB server
353  TSQLServer* server=TSQLServer::Connect(fDBName.Data(),fUser.Data(),fPassword.Data()); 
354  if (!server)
355  {
356   cout << " *IceDB2Root GetMuDaqData* Database " << fDBName.Data() << " could not be accessed." << endl;
357   return;
358  }
359
360  // The MuDaq OM database object
361  if (fMuDaqdb)
362  {
363   fMuDaqdb->Reset();
364  }
365  else
366  {
367   fMuDaqdb=new AliObjMatrix();
368   fMuDaqdb->SetNameTitle("MuDaq-OMDBASE","The MuDaq OM geometry, calib. etc... database");
369   fMuDaqdb->SetOwner();
370  }
371
372  // Prescription of the various (de)calibration functions
373  TF1 fadccal("fadccal","(x-[1])*[0]");
374  TF1 fadcdecal("fadcdecal","(x/[0])+[1]");
375  fadccal.SetParName(0,"BETA-ADC");
376  fadccal.SetParName(1,"PED-ADC");
377  fadcdecal.SetParName(0,"BETA-ADC");
378  fadcdecal.SetParName(1,"PED-ADC");
379
380  TF1 ftdccal("ftdccal","(x*[0])-[1]-([0]-1.)*32767.-[2]/sqrt([3])");
381  TF1 ftdcdecal("ftdcdecal","(x+([0]-1.)*32767.+[1]+[2]/sqrt([3]))/[0]");
382  ftdccal.SetParName(0,"BETA-TDC");
383  ftdccal.SetParName(1,"T0");
384  ftdccal.SetParName(2,"ALPHA-TDC");
385  ftdccal.SetParName(3,"ADC-SLEW");
386  ftdcdecal.SetParName(0,"BETA-TDC");
387  ftdcdecal.SetParName(1,"T0");
388  ftdcdecal.SetParName(2,"ALPHA-TDC");
389  ftdcdecal.SetParName(3,"ADC-SLEW");
390
391  TF1 ftotcal("ftotcal","x*[0]");
392  TF1 ftotdecal("ftotdecal","x/[0]");
393  ftotcal.SetParName(0,"BETA-TOT");
394  ftotdecal.SetParName(0,"BETA-TOT");
395
396  // The cross talk probability function
397  TF1 fxtalkp("fxtalkp","(1.+[2]-[2]+[3]-[3])/(1.+exp(([0]-x)/[1]))");
398  fxtalkp.SetParName(0,"C");
399  fxtalkp.SetParName(1,"B");
400  fxtalkp.SetParName(2,"dLE-min");
401  fxtalkp.SetParName(3,"dLE-max");
402
403  // The basic OM contents
404  IceAOM om;
405
406  // Slots to hold the various (de)calibration functions
407  om.AddNamedSlot("ADC");
408  om.AddNamedSlot("LE");
409  om.AddNamedSlot("TOT");
410  // Slots with hardware parameters
411  om.AddNamedSlot("TYPE"); // -1=unknown 0=std_coax 1=std_twisted/std_hybrid 2=desy_hybrid 3=uci_fiber 4=lbl_dom 5=dAOM_ld 6=dAOM_led 9=desy_active_fiber
412  om.AddNamedSlot("ORIENT");
413  om.AddNamedSlot("THRESH");
414  om.AddNamedSlot("SENSIT");
415  om.AddNamedSlot("READOUT"); // 0=unknown 1=electrical 2=optical 3=digital
416
417  // Default values
418  Float_t type=-1;
419  om.SetSignal(type,"TYPE");
420  Float_t costh=0;
421  om.SetSignal(costh,"ORIENT");
422  Float_t thresh=0;
423  om.SetSignal(thresh,"THRES");
424  Float_t sensit=1;
425  om.SetSignal(sensit,"SENSIT");
426  Float_t readout=0;
427  om.SetSignal(readout,"READOUT");
428
429  // Variables needed
430  TSQLStatement* st;
431  IceAOM* omx=0;
432  Int_t omid;
433  Double_t pos[3]={0,0,0};
434  Float_t ped, beta, alpha;
435  Int_t jtrans,jrec;
436  Float_t c, b, dlemin, dlemax;
437  TF1* fcal=0;
438  TF1* fdecal=0;
439  AliTimestamp validitystart, validityend;
440  Int_t revision[682];
441
442  // Difference between Amanda and IceCube coordinates
443  Float_t dx=-339.8;
444  Float_t dy=-117.4;
445  Float_t dz=-224.6;
446
447  // Get positions of Amanda OMs in Amanda coordinates
448  for(omid=0; omid<=681; omid++) revision[omid]=0;
449  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, X, Y, Z, AmandaOm.TypeId, Orientation FROM GeometryOm INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE GeometryOm.StringId=AmandaOm.StringId AND GeometryOm.TubeId=AmandaOm.TubeId AND GeometryOm.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=2;");
450  if (!st)
451  {
452   cout << " *IceDB2Root GetMuDaqData* Positions could not be read from DB" << endl;
453  }
454  else {
455   st->Process();
456   st->StoreResult();
457   while(st->NextResultRow())
458   {
459    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
460    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
461    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
462    omid=st->GetInt(3);
463    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
464    {
465     revision[omid]=st->GetInt(2);
466     // Get OM, create a new one if necessary
467     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
468     if (!omx)
469     {
470      omx=new IceAOM(om);
471      omx->SetUniqueID(omid);
472      fMuDaqdb->EnterObject(omid,1,omx);
473     }
474     // Enter calibration values
475     pos[0]=st->GetDouble(4)+dx;
476     pos[1]=st->GetDouble(5)+dy;
477     pos[2]=st->GetDouble(6)+dz;
478     omx->SetPosition(pos,"car");
479     type=(Float_t)st->GetInt(7);
480     omx->SetSignal(type,"TYPE");
481     costh=(Float_t)st->GetInt(8);
482     omx->SetSignal(costh,"ORIENT");
483    }
484   }
485  }
486
487  // Get sensitivity/threshold of Amanda OMs
488  for(omid=0; omid<=681; omid++) revision[omid]=0;
489  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id, sc_sensit, sc_thresh FROM AmandaStatusOm INNER JOIN CalibrationDetail WHERE AmandaStatusOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=804;");
490  if (!st)
491  {
492   cout << " *IceDB2Root GetMuDaqData* Sensitivity/threshold could not be read from DB" << endl;
493  }
494  else {
495   st->Process();
496   st->StoreResult();
497   while(st->NextResultRow())
498   {
499    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
500    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
501    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
502    omid=st->GetInt(3);
503    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
504    {
505     revision[omid]=st->GetInt(2);
506     // Get OM, create a new one if necessary
507     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
508     if (!omx)
509     {
510      omx=new IceAOM(om);
511      omx->SetUniqueID(omid);
512      fMuDaqdb->EnterObject(omid,1,omx);
513     }
514     // Enter calibration values
515     thresh=(Float_t)st->GetDouble(4);
516     sensit=(Float_t)st->GetDouble(5);
517     omx->SetSignal(thresh,"THRES");
518     omx->SetSignal(sensit,"SENSIT");
519    }
520   }
521  }
522
523  // Get readout types of Amanda OMs
524  for(omid=0; omid<=681; omid++) revision[omid]=0;
525  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, CableType FROM AmandaTWRCableType INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE AmandaTWRCableType.StringId=AmandaOm.StringId AND AmandaTWRCableType.TubeId=AmandaOm.TubeId AND AmandaTWRCableType.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=853;");
526  if (!st)
527  {
528   cout << " *IceDB2Root GetMuDaqData* Readout types could not be read from DB" << endl;
529  }
530  else {
531   st->Process();
532   st->StoreResult();
533   while(st->NextResultRow())
534   {
535    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
536    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
537    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
538    omid=st->GetInt(3);
539    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
540    {
541     revision[omid]=st->GetInt(2);
542     // Get OM, create a new one if necessary
543     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
544     if (!omx)
545     {
546      omx=new IceAOM(om);
547      omx->SetUniqueID(omid);
548      fMuDaqdb->EnterObject(omid,1,omx);
549     }
550     // Enter calibration values
551     if(st->GetUInt(4) == 0) readout=1;        // Electrical
552     else if(st->GetUInt(4) == 10) readout=2;  // Optical
553     else readout=0;                           // Unknown
554     omx->SetSignal(readout,"READOUT");
555    }
556   }
557  }
558
559  // Get muDAQ amplitude calibration constants
560  for(omid=0; omid<=681; omid++) revision[omid]=0;
561  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id, ac_pedestal, ac_spepeak FROM AmandaAmplOm INNER JOIN CalibrationDetail WHERE AmandaAmplOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=802;");
562  if (!st)
563  {
564   cout << " *IceDB2Root GetMuDaqData* Amplitude calibrations could not be read from DB" << endl;
565  }
566  else {
567   st->Process();
568   st->StoreResult();
569   while(st->NextResultRow())
570   {
571    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
572    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
573    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
574    omid=st->GetInt(3);
575    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
576    {
577     revision[omid]=st->GetInt(2);
578     // Get OM, create a new one if necessary
579     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
580     if (!omx)
581     {
582      omx=new IceAOM(om);
583      omx->SetUniqueID(omid);
584      fMuDaqdb->EnterObject(omid,1,omx);
585     }
586     // Set calibration functions
587     omx->SetCalFunction(&fadccal,1);
588     omx->SetDecalFunction(&fadcdecal,1);
589     // Get calibration values
590     ped=(Float_t)st->GetDouble(4);
591     if (st->GetDouble(5)>0) beta=(Float_t)(1/st->GetDouble(5));
592     else beta=-999999;
593     // Flag amplitude slots of bad OMs as dead and don't provide amplitude (de)calib functions
594     if (ped<-1e5 || beta<=0)
595     {
596      omx->SetDead(1);
597      omx->SetCalFunction(0,1);
598      omx->SetDecalFunction(0,1);
599     }
600     // Set calibration function parameters
601     fcal=omx->GetCalFunction(1);
602     fdecal=omx->GetDecalFunction(1);
603     if (fcal)
604     {
605      fcal->SetParameter(0,beta);
606      fcal->SetParameter(1,ped);
607     }
608     if (fdecal)
609     {
610      fdecal->SetParameter(0,beta);
611      if (!beta) fdecal->SetParameter(0,1);
612      fdecal->SetParameter(1,ped);
613     }
614    }
615   }
616  }
617
618  // Get muDAQ time calibration constants
619  for(omid=0; omid<=681; omid++) revision[omid]=0;
620  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id, tc_tzero, tc_beta_t, tc_alpha_t FROM AmandaTimeOm INNER JOIN CalibrationDetail WHERE AmandaTimeOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=805;");
621  if (!st)
622  {
623   cout << " *IceDB2Root GetMuDaqData* Time calibrations could not be read from DB" << endl;
624  }
625  else {
626   st->Process();
627   st->StoreResult();
628   while(st->NextResultRow())
629   {
630    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
631    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
632    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
633    omid=st->GetInt(3);
634    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
635    {
636     revision[omid]=st->GetInt(2);
637     // Get OM, create a new one if necessary
638     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
639     if (!omx)
640     {
641      omx=new IceAOM(om);
642      omx->SetUniqueID(omid);
643      fMuDaqdb->EnterObject(omid,1,omx);
644     }
645     // Set calibration functions
646     omx->SetCalFunction(&ftdccal,2);
647     omx->SetDecalFunction(&ftdcdecal,2);
648     omx->SetCalFunction(&ftotcal,3);
649     omx->SetDecalFunction(&ftotdecal,3);
650     // Get calibration values
651     ped=(Float_t)st->GetDouble(4);
652     beta=(Float_t)st->GetDouble(5);
653     alpha=(Float_t)st->GetDouble(6);
654     // Flag time slots of bad OMs as dead and don't provide time (de)calib functions
655     if (ped<-1e5 || beta<=0 || alpha<0)
656     {
657      omx->SetDead(2);
658      omx->SetDead(3);
659      omx->SetCalFunction(0,2);
660      omx->SetDecalFunction(0,2);
661      omx->SetCalFunction(0,3);
662      omx->SetDecalFunction(0,3);
663     }
664     // Set calibration function parameters
665     fcal=omx->GetCalFunction(2);
666     fdecal=omx->GetDecalFunction(2);
667     if (fcal)
668     {
669      fcal->SetParameter(0,beta);
670      fcal->SetParameter(1,ped);
671      fcal->SetParameter(2,alpha);
672      fcal->SetParameter(3,1.e20);
673     }
674     if (fdecal)
675     {
676      fdecal->SetParameter(0,beta);
677      if (!beta) fdecal->SetParameter(0,1);
678      fdecal->SetParameter(1,ped);
679      fdecal->SetParameter(2,alpha);
680      fdecal->SetParameter(3,1.e20);
681     }
682     fcal=omx->GetCalFunction(3);
683     fdecal=omx->GetDecalFunction(3);
684     if (fcal)
685     {
686      fcal->SetParameter(0,beta);
687     }
688     if (fdecal)
689     {
690      fdecal->SetParameter(0,beta);
691     }
692    }
693   }
694  }
695
696  // Get Xtalk probability constants
697  for(omid=0; omid<=681; omid++) revision[omid]=0;
698  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_talker_id, om_receiver_id, threshold, width, timelow, timehigh FROM AmandaXtalkOm INNER JOIN CalibrationDetail WHERE AmandaXtalkOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=807;");
699  if (!st)
700  {
701   cout << " *IceDB2Root GetMuDaqData* Xtalk probability constants could not be read from DB" << endl;
702  }
703  else {
704   st->Process();
705   st->StoreResult();
706   while(st->NextResultRow())
707   {
708    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
709    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
710    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
711    jtrans=st->GetInt(3);
712    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[jtrans])
713    {
714     revision[jtrans]=st->GetInt(2);
715     jrec=st->GetInt(4);
716     // Get transmitter OM, create a new one if necessary
717     omx=(IceAOM*)fMuDaqdb->GetObject(jtrans,1);
718     if (!omx)
719     {
720      omx=new IceAOM(om);
721      omx->SetUniqueID(jtrans);
722      fMuDaqdb->EnterObject(jtrans,1,omx);
723     }
724     // Get calibration values
725     c=(Float_t)st->GetDouble(5);
726     b=(Float_t)st->GetDouble(6);
727     dlemin=(Float_t)st->GetDouble(7);
728     dlemax=(Float_t)st->GetDouble(8);
729     // Make Xtalk probability function and set parameters
730     TF1* fx=new TF1(fxtalkp);
731     fx->SetParameter(0,c);
732     if (b) fx->SetParameter(1,b);
733     else fx->SetParameter(1,1);
734     fx->SetParameter(2,dlemin);
735     fx->SetParameter(3,dlemax);
736     fMuDaqdb->EnterObject(jtrans,jrec+1,fx);
737    }
738   }
739  }
740
741  // Flag OMs in bad OM list as dead
742  for(omid=0; omid<=681; omid++) revision[omid]=0;
743  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id FROM AmandaBadOm INNER JOIN CalibrationDetail WHERE AmandaBadOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=803;");
744  if (!st)
745  {
746   cout << " *IceDB2Root GetMuDaqData* Bad OM list could not be read from DB" << endl;
747  }
748  else {
749   st->Process();
750   st->StoreResult();
751   while(st->NextResultRow())
752   {
753    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
754    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
755    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
756    omid=st->GetInt(3);
757    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
758    {
759     revision[omid]=st->GetInt(2);
760     // Get OM, create a new one if necessary
761     omx=(IceAOM*)fMuDaqdb->GetObject(omid,1);
762     if (!omx)
763     {
764      omx=new IceAOM(om);
765      omx->SetUniqueID(omid);
766      fMuDaqdb->EnterObject(omid,1,omx);
767     }
768     // Flag OMs as dead
769     omx->SetDead(1);
770     omx->SetCalFunction(0,1);
771     omx->SetDecalFunction(0,1);
772     omx->SetDead(2);
773     omx->SetCalFunction(0,2);
774     omx->SetDecalFunction(0,2);
775     omx->SetDead(3);
776     omx->SetCalFunction(0,3);
777     omx->SetDecalFunction(0,3);
778    }
779   }
780  }
781
782 }
783 ///////////////////////////////////////////////////////////////////////////
784 void IceDB2Root::GetTWRDaqData()
785 {
786 // Obtain all the TWRDaq geometry, calibration and Xtalk data.
787
788  // Connect to the DB server
789  TSQLServer* server=TSQLServer::Connect(fDBName.Data(),fUser.Data(),fPassword.Data()); 
790  if (!server)
791  {
792   cout << " *IceDB2Root GetTWRDaqData* Database " << fDBName.Data() << " could not be accessed." << endl;
793   return;
794  }
795
796  // The TWRDaq OM database object
797  if (fTWRDaqdb)
798  {
799   fTWRDaqdb->Reset();
800  }
801  else
802  {
803   fTWRDaqdb=new AliObjMatrix();
804   fTWRDaqdb->SetNameTitle("TWRDaq-OMDBASE","The TWRDaq OM geometry, calib. etc... database");
805   fTWRDaqdb->SetOwner();
806  }
807
808  // Prescription of the various (de)calibration functions
809
810  // Conversion of adc to charge in nC
811  // Volt per digit = 5/4096    Assumed capacitance = 20 pF
812  // Charge (in nC) is adc*(5./4096.)*0.02
813  // The database calibration constant is the amount of nC per photon electron (nC/PE)
814  TF1 fadccal("fadccal","x*(5./4096.)/(50.*[0])");
815  TF1 fadcdecal("fadcdecal","x*(50.*[0])/(5./4096.)");
816  fadccal.SetParName(0,"nC/PE");
817  fadcdecal.SetParName(0,"nC/PE");
818
819  TF1 ftdccal("ftdccal","x-[0]");
820  TF1 ftdcdecal("ftdcdecal","x+[0]");
821  ftdccal.SetParName(0,"T0");
822  ftdcdecal.SetParName(0,"T0");
823
824  TF1 ftotcal("ftotcal","x");
825  TF1 ftotdecal("ftotdecal","x");
826
827  // The cross talk probability function
828  TF1 fxtalkp("fxtalkp","(1.+[2]-[2]+[3]-[3])/(1.+exp(([0]-x)/[1]))");
829  fxtalkp.SetParName(0,"C");
830  fxtalkp.SetParName(1,"B");
831  fxtalkp.SetParName(2,"dLE-min");
832  fxtalkp.SetParName(3,"dLE-max");
833
834  // The basic OM contents
835  IceAOM om;
836
837  // Slots to hold the various (de)calibration functions
838  om.AddNamedSlot("ADC");
839  om.AddNamedSlot("LE");
840  om.AddNamedSlot("TOT");
841  // Slots with hardware parameters
842  om.AddNamedSlot("TYPE"); // -1=unknown 0=std_coax 1=std_twisted/std_hybrid 2=desy_hybrid 3=uci_fiber 4=lbl_dom 5=dAOM_ld 6=dAOM_led 9=desy_active_fiber
843  om.AddNamedSlot("ORIENT");
844  om.AddNamedSlot("THRESH");
845  om.AddNamedSlot("SENSIT");
846  om.AddNamedSlot("READOUT"); // 0=unknown 1=electrical 2=optical 3=digital
847  om.AddNamedSlot("BINSIZE");
848  om.AddNamedSlot("EXTSTOP");
849
850  // Default values
851  Float_t type=-1;
852  om.SetSignal(type,"TYPE");
853  Float_t costh=0;
854  om.SetSignal(costh,"ORIENT");
855  Float_t thresh=0;
856  om.SetSignal(thresh,"THRESH");
857  Float_t sensit=1;
858  om.SetSignal(sensit,"SENSIT");
859  Float_t readout=0;
860  om.SetSignal(readout,"READOUT");
861  Float_t binsize=0;
862  om.SetSignal(binsize,"BINSIZE");
863  Float_t stopdelay=0;
864  om.SetSignal(stopdelay,"EXTSTOP");
865
866  // Variables needed
867  TSQLStatement* st;
868  IceAOM* omx=0;
869  Int_t omid;
870  Double_t pos[3]={0,0,0};
871  Float_t peArea, twrT0;
872  Int_t jtrans,jrec;
873  Float_t c, b, dlemin, dlemax;
874  TF1* fcal=0;
875  TF1* fdecal=0;
876  AliTimestamp validitystart, validityend;
877  Int_t revision[682];
878
879  // Get positions of Amanda OMs in IceCube coordinates
880  for(omid=0; omid<=681; omid++) revision[omid]=0;
881  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, X, Y, Z, AmandaOm.TypeId, Orientation FROM GeometryOm INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE GeometryOm.StringId=AmandaOm.StringId AND GeometryOm.TubeId=AmandaOm.TubeId AND GeometryOm.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=2;");
882  if (!st)
883  {
884   cout << " *IceDB2Root GetTWRDaqData* Positions could not be read from DB" << endl;
885  }
886  else {
887   st->Process();
888   st->StoreResult();
889   while(st->NextResultRow())
890   {
891    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
892    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
893    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
894    omid=st->GetInt(3);
895    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
896    {
897     revision[omid]=st->GetInt(2);
898     // Get OM, create a new one if necessary
899     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
900     if (!omx)
901     {
902      omx=new IceAOM(om);
903      omx->SetUniqueID(omid);
904      fTWRDaqdb->EnterObject(omid,1,omx);
905     }
906     // Enter calibration values
907     pos[0]=st->GetDouble(4);
908     pos[1]=st->GetDouble(5);
909     pos[2]=st->GetDouble(6);
910     omx->SetPosition(pos,"car");
911     type=(Float_t)st->GetInt(7);
912     omx->SetSignal(type,"TYPE");
913     costh=(Float_t)st->GetInt(8);
914     omx->SetSignal(costh,"ORIENT");
915    }
916   }
917  }
918
919  // Get sensitivity/threshold of Amanda OMs
920  for(omid=0; omid<=681; omid++) revision[omid]=0;
921  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id, sc_sensit, sc_thresh FROM AmandaStatusOm INNER JOIN CalibrationDetail WHERE AmandaStatusOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=804;");
922  if (!st)
923  {
924   cout << " *IceDB2Root GetTWRDaqData* Sensitivity/threshold could not be read from DB" << endl;
925  }
926  else {
927   st->Process();
928   st->StoreResult();
929   while(st->NextResultRow())
930   {
931    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
932    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
933    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
934    omid=st->GetInt(3);
935    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
936    {
937     revision[omid]=st->GetInt(2);
938     // Get OM, create a new one if necessary
939     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
940     if (!omx)
941     {
942      omx=new IceAOM(om);
943      omx->SetUniqueID(omid);
944      fTWRDaqdb->EnterObject(omid,1,omx);
945     }
946     // Enter calibration values
947     thresh=(Float_t)st->GetDouble(4);
948     sensit=(Float_t)st->GetDouble(5);
949     omx->SetSignal(thresh,"THRESH");
950     omx->SetSignal(sensit,"SENSIT");
951    }
952   }
953  }
954
955  // Get readout types of Amanda OMs
956  for(omid=0; omid<=681; omid++) revision[omid]=0;
957  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, CableType FROM AmandaTWRCableType INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE AmandaTWRCableType.StringId=AmandaOm.StringId AND AmandaTWRCableType.TubeId=AmandaOm.TubeId AND AmandaTWRCableType.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=853;");
958  if (!st)
959  {
960   cout << " *IceDB2Root GetTWRDaqData* Readout types could not be read from DB" << endl;
961  }
962  else {
963   st->Process();
964   st->StoreResult();
965   while(st->NextResultRow())
966   {
967    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
968    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
969    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
970    omid=st->GetInt(3);
971    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
972    {
973     revision[omid]=st->GetInt(2);
974     // Get OM, create a new one if necessary
975     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
976     if (!omx)
977     {
978      omx=new IceAOM(om);
979      omx->SetUniqueID(omid);
980      fTWRDaqdb->EnterObject(omid,1,omx);
981     }
982     // Enter calibration values
983     if(st->GetUInt(4) == 0) readout=1;        // Electrical
984     else if(st->GetUInt(4) == 10) readout=2;  // Optical
985     else readout=0;                           // Unknown
986     omx->SetSignal(readout,"READOUT");
987    }
988   }
989  }
990
991  // Get bin sizes and stop delays types of TWRs
992  for(omid=0; omid<=681; omid++) revision[omid]=0;
993  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, BinSize, StopDelay FROM AmandaTWRStandard INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE AmandaTWRStandard.StringId=AmandaOm.StringId AND AmandaTWRStandard.TubeId=AmandaOm.TubeId AND AmandaTWRStandard.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=852;");
994  if (!st)
995  {
996   cout << " *IceDB2Root GetTWRDaqData* Bin size and stop delays could not be read from DB" << endl;
997  }
998  else {
999   st->Process();
1000   st->StoreResult();
1001   while(st->NextResultRow())
1002   {
1003    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1004    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1005    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1006    omid=st->GetInt(3);
1007    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1008    {
1009     revision[omid]=st->GetInt(2);
1010     // Get OM, create a new one if necessary
1011     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
1012     if (!omx)
1013     {
1014      omx=new IceAOM(om);
1015      omx->SetUniqueID(omid);
1016      fTWRDaqdb->EnterObject(omid,1,omx);
1017     }
1018     // Enter calibration values
1019     binsize=(Float_t)st->GetInt(4);
1020     stopdelay=(Float_t)st->GetInt(5);
1021     omx->SetSignal(binsize,"BINSIZE");
1022     omx->SetSignal(stopdelay,"EXTSTOP");
1023    }
1024   }
1025  }
1026
1027  // Get TWRDaq amplitude and time calibration constants
1028  for(omid=0; omid<=681; omid++) revision[omid]=0;
1029  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, OmId, peArea, twrT0 FROM AmandaTWRCalibration INNER JOIN AmandaOm INNER JOIN CalibrationDetail WHERE AmandaTWRCalibration.StringId=AmandaOm.StringId AND AmandaTWRCalibration.TubeId=AmandaOm.TubeId AND AmandaTWRCalibration.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=854;");
1030  if (!st)
1031  {
1032   cout << " *IceDB2Root GetTWRDaqData* Bin size and stop delays could not be read from DB" << endl;
1033  }
1034  else {
1035   st->Process();
1036   st->StoreResult();
1037   while(st->NextResultRow())
1038   {
1039    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1040    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1041    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1042    omid=st->GetInt(3);
1043    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1044    {
1045     revision[omid]=st->GetInt(2);
1046     // Get OM, create a new one if necessary
1047     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
1048     if (!omx)
1049     {
1050      omx=new IceAOM(om);
1051      omx->SetUniqueID(omid);
1052      fTWRDaqdb->EnterObject(omid,1,omx);
1053     }
1054     // Set calibration functions
1055     omx->SetCalFunction(&fadccal,1);
1056     omx->SetDecalFunction(&fadcdecal,1);
1057     omx->SetCalFunction(&ftdccal,2);
1058     omx->SetDecalFunction(&ftdcdecal,2);
1059     omx->SetCalFunction(&ftotcal,3);
1060     omx->SetDecalFunction(&ftotdecal,3);
1061     // Get calibration values
1062     peArea=(Float_t)st->GetDouble(4);
1063     twrT0=(Float_t)st->GetDouble(5);
1064     // Flag amplitude slots of bad OMs as dead and don't provide amplitude (de)calib functions
1065     if (peArea<=0 || omx->GetSignal("BINSIZE")<=0)
1066     {
1067      omx->SetDead(1);
1068      omx->SetCalFunction(0,1);
1069      omx->SetDecalFunction(0,1);
1070     }
1071     // Set amplitude calibration function parameters
1072     fcal=omx->GetCalFunction(1);
1073     fdecal=omx->GetDecalFunction(1);
1074     if (fcal)
1075     {
1076      // peArea as read from the DB is the factor that converts the integrated
1077      // area under the peak to the number of pe, that is, the sum over all bins
1078      // of ADC*binsize. In IcePack, we simply add up the bin contents of the
1079      // peak, without multiplying by binsize. Hence, the calibration factor is 
1080      // peArea/binsize, rather than peArea.
1081      fcal->SetParameter(0,peArea/omx->GetSignal("BINSIZE"));
1082     }
1083     if (fdecal)
1084     {
1085      fdecal->SetParameter(0,peArea/omx->GetSignal("BINSIZE"));
1086      if (!peArea) fdecal->SetParameter(0,1);
1087     }
1088     // Flag LE slots of bad OMs as dead and don't provide time (de)calib functions
1089     if (twrT0<=0)
1090     {
1091      omx->SetDead(2);
1092      omx->SetCalFunction(0,2);
1093      omx->SetDecalFunction(0,2);
1094     }
1095     // Set time calibration function parameters
1096     fcal=omx->GetCalFunction(2);
1097     fdecal=omx->GetDecalFunction(2);
1098     if (fcal)
1099     {
1100      fcal->SetParameter(0,twrT0);
1101     }
1102     if (fdecal)
1103     {
1104      fdecal->SetParameter(0,twrT0);
1105     }
1106    }
1107   }
1108  }
1109
1110  // Get Xtalk probability constants
1111  for(omid=0; omid<=681; omid++) revision[omid]=0;
1112  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_talker_id, om_receiver_id, threshold, width, timelow, timehigh FROM AmandaXtalkOm INNER JOIN CalibrationDetail WHERE AmandaXtalkOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=807;");
1113  if (!st)
1114  {
1115   cout << " *IceDB2Root GetTWRDaqData* Xtalk probability constants could not be read from DB" << endl;
1116  }
1117  else {
1118   st->Process();
1119   st->StoreResult();
1120   while(st->NextResultRow())
1121   {
1122    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1123    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1124    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1125    jtrans=st->GetInt(3);
1126    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1127    {
1128     revision[jtrans]=st->GetInt(2);
1129     jrec=st->GetInt(4);
1130     // Get transmitter OM, create a new one if necessary
1131     omx=(IceAOM*)fTWRDaqdb->GetObject(jtrans,1);
1132     if (!omx)
1133     {
1134      omx=new IceAOM(om);
1135      omx->SetUniqueID(jtrans);
1136      fTWRDaqdb->EnterObject(jtrans,1,omx);
1137     }
1138     // Get calibration values
1139     c=(Float_t)st->GetDouble(5);
1140     b=(Float_t)st->GetDouble(6);
1141     dlemin=(Float_t)st->GetDouble(7);
1142     dlemax=(Float_t)st->GetDouble(8);
1143     // Make Xtalk probability function and set parameters
1144     TF1* fx=new TF1(fxtalkp);
1145     fx->SetParameter(0,c);
1146     if (b) fx->SetParameter(1,b);
1147     else fx->SetParameter(1,1);
1148     fx->SetParameter(2,dlemin);
1149     fx->SetParameter(3,dlemax);
1150     fTWRDaqdb->EnterObject(jtrans,jrec+1,fx);
1151    }
1152   }
1153  }
1154
1155  // Flag OMs in bad OM list as dead
1156  for(omid=0; omid<=681; omid++) revision[omid]=0;
1157  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, om_id FROM AmandaBadOm INNER JOIN CalibrationDetail WHERE AmandaBadOm.ca_id=CalibrationDetail.CaId AND CalibrationDetail.TypeId=803;");
1158  if (!st)
1159  {
1160   cout << " *IceDB2Root GetTWRDaqData* Bad OM list could not be read from DB" << endl;
1161  }
1162  else {
1163   st->Process();
1164   st->StoreResult();
1165   while(st->NextResultRow())
1166   {
1167    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1168    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1169    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1170    omid=st->GetInt(3);
1171    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1172    {
1173     revision[omid]=st->GetInt(2);
1174     // Get OM, create a new one if necessary
1175     omx=(IceAOM*)fTWRDaqdb->GetObject(omid,1);
1176     if (!omx)
1177     {
1178      omx=new IceAOM(om);
1179      omx->SetUniqueID(omid);
1180      fTWRDaqdb->EnterObject(omid,1,omx);
1181     }
1182     // Flag OMs as dead
1183     omx->SetDead(1);
1184     omx->SetCalFunction(0,1);
1185     omx->SetDecalFunction(0,1);
1186     omx->SetDead(2);
1187     omx->SetCalFunction(0,2);
1188     omx->SetDecalFunction(0,2);
1189     omx->SetDead(3);
1190     omx->SetCalFunction(0,3);
1191     omx->SetDecalFunction(0,3);
1192    }
1193   }
1194  }
1195  
1196 }
1197 ///////////////////////////////////////////////////////////////////////////
1198 void IceDB2Root::GetJEBTDaqData()
1199 {
1200 // Obtain all the JEB TWRDaq geometry, calibration and Xtalk data.
1201 // For the time being, the JEBTDaq database is just a copy of the
1202 // TWRDaq database. If different calibrations are needed in the 
1203 // future, this member function can be updated accordingly.
1204
1205  // The JEBTDaq OM database object
1206  if (fJEBTDaqdb)
1207  {
1208   delete fJEBTDaqdb;
1209   fJEBTDaqdb=0;
1210  }
1211
1212  // Copy TWRDaq database to JEBTDaq database via the Clone() function
1213  if(!fTWRDaqdb) GetTWRDaqData();
1214  if(fTWRDaqdb)
1215  {
1216   fJEBTDaqdb=(AliObjMatrix*)fTWRDaqdb->Clone();
1217   fJEBTDaqdb->SetNameTitle("JEBTDaq-OMDBASE","The JEBTDaq OM geometry, calib. etc... database");
1218  }
1219 }
1220 ///////////////////////////////////////////////////////////////////////////
1221 void IceDB2Root::GetJEBADaqData()
1222 {
1223 // Obtain all the JEB ATWDDaq geometry, calibration.
1224
1225  // Connect to the DB server
1226  TSQLServer* server=TSQLServer::Connect(fDBName.Data(),fUser.Data(),fPassword.Data()); 
1227  if (!server)
1228  {
1229   cout << " *IceDB2Root GetJEBADaqData* Database " << fDBName.Data() << " could not be accessed." << endl;
1230   return;
1231  }
1232
1233  // The JEBADaq OM database object
1234  if (fJEBADaqdb)
1235  {
1236   fJEBADaqdb->Reset();
1237  }
1238  else
1239  {
1240   fJEBADaqdb=new AliObjMatrix();
1241   fJEBADaqdb->SetNameTitle("JEBADaq-OMDBASE","The JEBADaq OM geometry, calib. etc... database");
1242   fJEBADaqdb->SetOwner();
1243  }
1244
1245  // Prescription of the various (de)calibration functions
1246  TF1 fadccal("fadccal","x*[0]");
1247  TF1 fadcdecal("fadcdecal","x/[0]");
1248  fadccal.SetParName(0,"ADC-SLOPE");
1249  fadcdecal.SetParName(0,"ADC-SLOPE");
1250
1251  TF1 ftdccal("ftdccal","x");
1252  TF1 ftdcdecal("ftdcdecal","x");
1253
1254  TF1 ftotcal("ftotcal","x");
1255  TF1 ftotdecal("ftotdecal","x");
1256
1257  // The basic OM contents
1258  IceDOM om;
1259
1260  // Slots to hold the various (de)calibration functions
1261  om.AddNamedSlot("ADC");
1262  om.AddNamedSlot("LE");
1263  om.AddNamedSlot("TOT");
1264  // Slots with hardware parameters
1265  om.AddNamedSlot("ORIENT");
1266
1267  // Default values
1268  Float_t costh=0;
1269  om.SetSignal(costh,"ORIENT");
1270
1271  // Variables needed
1272  TSQLStatement* st;
1273  IceDOM* omx=0;
1274  Int_t omid;
1275  Double_t pos[3]={0,0,0};
1276  Float_t peArea;
1277  TF1* fcal=0;
1278  TF1* fdecal=0;
1279  AliTimestamp validitystart, validityend;
1280  const Int_t maxomid=8064;
1281  Int_t revision[maxomid+1];
1282
1283  // Get positions of IceCube DOMs in IceCube coordinates
1284  for(omid=0; omid<=maxomid; omid++) revision[omid]=0;
1285  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, StringId, TubeId, X, Y, Z, Orientation FROM GeometryOm INNER JOIN CalibrationDetail WHERE StringId>0 AND GeometryOm.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=2;");
1286  if (!st)
1287  {
1288   cout << " *IceDB2Root GetJEBADaqData* Positions could not be read from DB" << endl;
1289  }
1290  else {
1291   st->Process();
1292   st->StoreResult();
1293   while(st->NextResultRow())
1294   {
1295    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1296    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1297    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1298    omid=om.GetOMId(st->GetInt(3),st->GetInt(4));
1299    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1300    {
1301     revision[omid]=st->GetInt(2);
1302     // Get OM, create a new one if necessary
1303     omx=(IceDOM*)fJEBADaqdb->GetObject(omid,1);
1304     if (!omx)
1305     {
1306      omx=new IceDOM(om);
1307      omx->SetUniqueID(omid);
1308      fJEBADaqdb->EnterObject(omid,1,omx);
1309     }
1310     // Enter calibration values
1311     pos[0]=st->GetDouble(5);
1312     pos[1]=st->GetDouble(6);
1313     pos[2]=st->GetDouble(7);
1314     omx->SetPosition(pos,"car");
1315     costh=(Float_t)st->GetInt(8);
1316     omx->SetSignal(costh,"ORIENT");
1317    }
1318   }
1319  }
1320
1321  // Get JEBADaq amplitude calibration constants
1322  //// TODO: Insert correct table and field names and use correct calibration type
1323  for(omid=0; omid<=maxomid; omid++) revision[omid]=0;
1324  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, StringId, TubeId, XXXpeArea FROM XXXampl INNER JOIN CalibrationDetail WHERE StringId>0 AND XXXampl.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=XXX;");
1325  if (!st)
1326  {
1327   cout << " *IceDB2Root GetJEBADaqData* Amplitude calibrations could not be read from DB" << endl;
1328  }
1329  else {
1330   st->Process();
1331   st->StoreResult();
1332   while(st->NextResultRow())
1333   {
1334    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1335    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1336    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1337    omid=om.GetOMId(st->GetInt(3),st->GetInt(4));
1338    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1339    {
1340     revision[omid]=st->GetInt(2);
1341     // Get OM, create a new one if necessary
1342     omx=(IceDOM*)fJEBADaqdb->GetObject(omid,1);
1343     if (!omx)
1344     {
1345      omx=new IceDOM(om);
1346      omx->SetUniqueID(omid);
1347      fJEBADaqdb->EnterObject(omid,1,omx);
1348     }
1349     // Set calibration functions
1350     omx->SetCalFunction(&fadccal,1);
1351     omx->SetDecalFunction(&fadcdecal,1);
1352     // Get calibration values
1353     peArea=(Float_t)st->GetDouble(5);
1354     // Flag amplitude slots of bad OMs as dead and don't provide amplitude (de)calib functions
1355     //// TODO: Set correct conditions
1356     if (peArea<=0)
1357     {
1358      omx->SetDead(1);
1359      omx->SetCalFunction(0,1);
1360      omx->SetDecalFunction(0,1);
1361     }
1362     // Set calibration function parameters
1363     fcal=omx->GetCalFunction(1);
1364     fdecal=omx->GetDecalFunction(1);
1365     if (fcal)
1366     {
1367      fcal->SetParameter(0,peArea);
1368     }
1369     if (fdecal)
1370     {
1371      fdecal->SetParameter(0,peArea);
1372      if (!peArea) fdecal->SetParameter(0,1);
1373     }
1374    }
1375   }
1376  }
1377
1378  /*
1379  // Flag OMs in bad OM list as dead
1380  for(omid=0; omid<=maxomid; omid++) revision[omid]=0;
1381  st=server->Statement("SELECT ValidityStartDate, ValidityEndDate, RevisionId, StringId, TubeId FROM XXXBadOm INNER JOIN CalibrationDetail WHERE StringId>0 AND XXXBadOm.CaId=CalibrationDetail.CaId AND CalibrationDetail.TypeId=XXX;");
1382  if (!st)
1383  {
1384   cout << " *IceDB2Root GetJEBADaqData* Bad OM list could not be read from DB" << endl;
1385  }
1386  else {
1387   st->Process();
1388   st->StoreResult();
1389   while(st->NextResultRow())
1390   {
1391    // Only get calibrations with correct validity range, and update with latest revision in case of several valid calibrations
1392    validitystart.SetUT(st->GetYear(0),st->GetMonth(0),st->GetDay(0),st->GetHour(0),st->GetMinute(0),st->GetSecond(0));
1393    validityend.SetUT(st->GetYear(1),st->GetMonth(1),st->GetDay(1),st->GetHour(1),st->GetMinute(1),st->GetSecond(1));
1394    omid=om.GetOMId(st->GetInt(3),st->GetInt(4));
1395    if(validitystart.GetDifference(fTime,"d",1)>0 && validityend.GetDifference(fTime,"d",1)<0 && st->GetInt(2) > revision[omid])
1396    {
1397     revision[omid]=st->GetInt(2);
1398     // Get OM, create a new one if necessary
1399     omx=(IceDOM*)fJEBADaqdb->GetObject(omid,1);
1400     if (!omx)
1401     {
1402      omx=new IceDOM(om);
1403      omx->SetUniqueID(omid);
1404      fJEBADaqdb->EnterObject(omid,1,omx);
1405     }
1406     // Flag OMs as dead
1407     omx->SetDead(1);
1408     omx->SetCalFunction(0,1);
1409     omx->SetDecalFunction(0,1);
1410     omx->SetDead(2);
1411     omx->SetCalFunction(0,2);
1412     omx->SetDecalFunction(0,2);
1413     omx->SetDead(3);
1414     omx->SetCalFunction(0,3);
1415     omx->SetDecalFunction(0,3);
1416    }
1417   }
1418  }
1419  */
1420
1421 }
1422 ///////////////////////////////////////////////////////////////////////////