Modifications by H. Tydesio:
[u/mrichter/AliRoot.git] / ITS / ITSSPDPHYSda.cxx
1 /*
2 Contact: henrik.tydesjo@cern.ch
3 Link: tydes.home.cern.ch/tydes/doc/CalibrationOverview/CalibrationAlgorithms/
4 Run Type: PHYSICS
5 DA Type: MON
6 Number of events needed: Depending on muliplicity per event
7 Input Files: spd_physics_params ,  ./calibResults/DeadReferenceTmp/* ,  ./calibResults/DeadToFXS/*
8 Output Files: ./calibResults/NoisyReference/* ,  ./calibResults/DeadReference/* ,  ./calibResults/NoisyToFXS/* ,  ./calibResults/DeadReferenceTmp/*,./calibResults/DeadToFXS/*
9 Trigger types used: PHYSICS
10 */
11
12 ////////////////////////////////////////////////////////////////////////////////
13 // This program can be compiled in two modes.                                 //
14 //                                                                            //
15 // 1. Online. With the DAQ DA framework. This is the default operating mode.  //
16 //                                                                            //
17 // 2. Offline. Without the DAQ DA framework. Define the SPD_DA_OFF            //
18 //    environment var. Call this program with the name of the executable      //
19 //    followed by the runNr and the data files to process.                    //
20 //                                                                            //
21 ////////////////////////////////////////////////////////////////////////////////
22
23 #ifndef SPD_DA_OFF
24 extern "C" {
25 #include "daqDA.h"
26 }
27 #endif
28 #include "event.h"
29 #include "monitor.h"
30 #include "AliRawReaderDate.h"
31 #include "AliITSRawStreamSPD.h"
32 #include "AliITSOnlineSPDphys.h"
33 #include "AliITSOnlineSPDphysAnalyzer.h"
34 #include "AliITSOnlineCalibrationSPDhandler.h"
35 #include "AliLog.h"
36 #include <iostream>
37 #include <fstream>
38 //#include <time.h>
39 #include <TROOT.h>
40 #include <TPluginManager.h>
41 #include <TObjArray.h>
42 #include <TObjString.h>
43 #include <TString.h>
44
45
46 int main(int argc, char **argv) {
47   if (argc<2) {
48     printf("Wrong number of arguments\n");
49     return -1;
50   }
51
52   // directory structure, hard coded
53   char *saveDirDead          = "./calibResults/Dead";             // may NOT delete content
54   char *saveDirDeadToFXS     = "./calibResults/DeadToFXS";        //     may delete content
55   char *saveDirDeadRef       = "./calibResults/DeadReference";    //     may delete content
56   char *saveDirDeadRefTmp    = "./calibResults/DeadReferenceTmp"; // may NOT delete content
57   char *saveDirNoisyToFXS    = "./calibResults/NoisyToFXS";       //     may delete content
58   char *saveDirNoisyRef      = "./calibResults/NoisyReference";   //     may delete content
59   char *saveDirIdsToFXS      = "./calibResults/IdsToFXS";         //     may delete content
60   char *configFilesDir       = "./configFiles";                   //     may delete content
61   // make sure the directory structure is put up correctly:
62   system("mkdir ./calibResults >& /dev/null");
63   system("mkdir ./calibResults/Dead >& /dev/null");
64   system("mkdir ./calibResults/DeadToFXS >& /dev/null");
65   system("mkdir ./calibResults/DeadReference >& /dev/null");
66   system("mkdir ./calibResults/DeadReferenceTmp >& /dev/null");
67   system("mkdir ./calibResults/NoisyToFXS >& /dev/null");
68   system("mkdir ./calibResults/NoisyReference >& /dev/null");
69   system("mkdir ./calibResults/IdsToFXS >& /dev/null");
70   system("mkdir ./configFiles >& /dev/null");
71   // parameters config file
72   TString paramsFileName = Form("%s/physics_params.txt",configFilesDir);
73
74   // This line is needed in case of a stand-alone application w/o
75   // $ROOTSYS/etc/system.rootrc file
76   gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
77                                         "*",
78                                         "TStreamerInfo",
79                                         "RIO",
80                                         "TStreamerInfo()");
81
82   // turn off annoying warning messages
83   new AliLog;
84   AliLog::Instance()->SetGlobalDebugLevel(-20);
85
86
87   // ********* STEP 0: Get configuration files from db (if there are any) , then read parameters*********
88   UInt_t nrTuningParams = 0;
89   TObjArray paramNames;  paramNames.SetOwner(kTRUE);
90   TObjArray paramVals;  paramVals.SetOwner(kTRUE);
91   
92   // tuning parameters:
93   Int_t par_status = 0;
94 #ifndef SPD_DA_OFF
95   TString idp = "spd_physics_params";
96   par_status=daqDA_DB_getFile(idp.Data(),paramsFileName.Data());
97   if (par_status) {
98     printf("Failed to get config file %s: status=%d. Using default tuning parameters.\n",idp.Data(),par_status);
99   }
100 #endif
101   if (par_status==0) {
102     ifstream paramsFile;
103     paramsFile.open(paramsFileName.Data(), ifstream::in);
104     if (paramsFile.fail()) {
105       printf("No config file (%s) present. Using default tuning parameters.\n",paramsFileName.Data());
106     }
107     else {
108       while(1) {
109         Char_t paramN[50];
110         Char_t paramV[50];
111         paramsFile >> paramN;
112         if (paramsFile.eof()) break;
113         paramsFile >> paramV;
114         paramNames.AddAtAndExpand(new TObjString(paramN),nrTuningParams);
115         paramVals.AddAtAndExpand(new TObjString(paramV),nrTuningParams);
116         nrTuningParams++;
117         if (paramsFile.eof()) break;
118       }
119       paramsFile.close();
120     }
121   }
122   //  for (UInt_t i=0; i<nrTuningParams; i++) {
123   //  //    printf("Entry %d: N=%s , V=%s\n",i,((TString*)paramNames.At(i))->Data(),((TString*)paramVals.At(i))->Data());
124   //    printf("Entry %d: N=%s , V=%s\n",i,((TObjString*)paramNames.At(i))->GetString().Data(),((TObjString*)paramVals.At(i))->GetString().Data());
125   //  }
126
127
128
129
130
131   // create calibration handler (needed already at step 1 in order to fill which eq,hs,chips are active
132   AliITSOnlineCalibrationSPDhandler* handler = new AliITSOnlineCalibrationSPDhandler();
133   // Read silent=dead+inactive info from previous calibrations
134   handler->SetFileLocation(saveDirDead);
135   handler->ReadSilentFromFiles();
136   printf("Nr dead pixels before: %d\n",handler->GetNrDead());
137
138
139
140
141   // ********* STEP 1: Produce phys container files (Reference Data). ***********************************
142
143 #ifndef SPD_DA_OFF
144   if (getenv("DATE_RUN_NUMBER")==0) {
145     printf("DATE_RUN_NUMBER not properly set.\n");
146     return -1;
147   }
148   int runNr = atoi(getenv("DATE_RUN_NUMBER"));
149 #else
150   int runNr = atoi(argv[1]);
151   int startSeg = 2;
152 #endif
153
154
155   // container objects
156   AliITSOnlineSPDphys *physObj[20];
157   Bool_t bPhysInit[20];
158   for (UInt_t eq=0; eq<20; eq++) {
159     physObj[eq]=NULL;
160     bPhysInit[eq]=kFALSE;
161   }
162
163
164   // loop over run segments in case of offline mode
165 #ifdef SPD_DA_OFF
166   for (int segNr=startSeg; segNr<argc; segNr++) {
167 #endif
168
169     int status;
170
171     /* define data source : */  
172 #ifndef SPD_DA_OFF
173     status=monitorSetDataSource( argv[1] ); // should be "^SPD" in order to get full detector online
174 #else
175     status=monitorSetDataSource( argv[segNr] );
176 #endif
177     if (status!=0) {
178       printf("monitorSetDataSource() failed : %s\n",monitorDecodeError(status));
179       return -1;
180     }
181     /* declare monitoring program */
182     status=monitorDeclareMp("ITS_SPD_PHYS");
183     if (status!=0) {
184       printf("monitorDeclareMp() failed : %s\n",monitorDecodeError(status));
185       return -1;
186     }
187     /* define wait event timeout - 1s max */
188     monitorSetNowait();
189     monitorSetNoWaitNetworkTimeout(1000);
190
191
192     UInt_t eventNr=0;
193
194     /* main loop (infinite) */
195     for(;;) {
196
197       struct eventHeaderStruct *event;
198       eventTypeType eventT;
199
200       /* check shutdown condition */
201 #ifndef SPD_DA_OFF
202       if (daqDA_checkShutdown()) {break;}
203 #endif
204
205       /* get next event (blocking call until timeout) */
206       status=monitorGetEventDynamic((void **)&event);
207       if (status==MON_ERR_EOF) {
208         printf ("End of File detected\n");
209         break; /* end of monitoring file has been reached */
210       }
211
212       if (status!=0) {
213         printf("monitorGetEventDynamic() failed : %s\n",monitorDecodeError(status));
214         break;
215       }
216
217       /* retry if got no event */
218       if (event==NULL) {
219         continue;
220       }
221
222       eventT=event->eventType;
223       if (eventT == PHYSICS_EVENT){
224
225         //      printf("eventNr %d\n",eventNr);
226
227         AliRawReader *reader = new AliRawReaderDate((void*)event);
228         AliITSRawStreamSPD *str = new AliITSRawStreamSPD(reader);
229
230         while (str->Next()) {
231
232           Int_t eq = reader->GetDDLID();
233           // check that this hs is active in handler object
234           if (!(handler->IsActiveEq(eq))) {
235             printf("Info: Found Eq (%d) , previously inactive\n",eq);
236             handler->ActivateEq(eq);
237           }
238           if (eq>=0 && eq<20) {
239             if (!bPhysInit[eq]) { // this code is duplicated for the moment... (see also below)
240               TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eq);
241               physObj[eq] = new AliITSOnlineSPDphys(fileName.Data());
242               physObj[eq]->AddRunNr(runNr);
243               physObj[eq]->SetEqNr(eq);
244               bPhysInit[eq]=kTRUE;
245             }
246
247             UInt_t hs = str->GetHalfStaveNr();
248             // check that this hs is active in handler object
249             if (!(handler->IsActiveHS(eq,hs))) {
250               printf("Info: Found HS (%d,%d) , previously inactive\n",eq,hs);
251               handler->ActivateHS(eq,hs);
252             }
253             UInt_t chip = str->GetChipAddr();
254             // check that this chip is active in handler object
255             if (!(handler->IsActiveChip(eq,hs,chip))) {
256               printf("Info: Found Chip (%d,%d,%d) , previously inactive\n",eq,hs,chip);
257               handler->ActivateChip(eq,hs,chip);
258             }
259             physObj[eq]->IncrementHits(hs,chip,str->GetChipCol(),str->GetChipRow());
260             
261           }
262         }
263
264
265         // check which eq and hs are active, for first event only
266         if (eventNr==0) {
267           for (UInt_t eq=0; eq<20; eq++) {
268             // activate Eq and HSs in handler object
269             if (str->IsActiveEq(eq)) {
270               handler->ActivateEq(eq);
271               for (UInt_t hs=0; hs<6; hs++) {
272                 if (str->IsActiveHS(eq,hs)) {
273                   handler->ActivateHS(eq,hs);
274                   for (UInt_t chip=0; chip<10; chip++) {
275                     if (str->IsActiveChip(eq,hs,chip)) {
276                       handler->ActivateChip(eq,hs,chip);
277                     }
278                     else {
279                       handler->ActivateChip(eq,hs,chip,kFALSE);
280                     }
281                   }
282                 }
283                 else {
284                   handler->ActivateHS(eq,hs,kFALSE);
285                 }
286               }
287               if (!bPhysInit[eq]) { // this code is duplicated for the moment... (see also above)
288                 TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eq);
289                 physObj[eq] = new AliITSOnlineSPDphys(fileName.Data());
290                 physObj[eq]->AddRunNr(runNr);
291                 physObj[eq]->SetEqNr(eq);
292                 bPhysInit[eq]=kTRUE;
293               }
294             }
295             else {
296               handler->ActivateEq(eq,kFALSE);
297             }
298           }
299         }
300
301
302         for (UInt_t eq=0; eq<20; eq++) {
303           if (bPhysInit[eq]) {
304             physObj[eq]->IncrementNrEvents();
305           }
306         }
307
308         delete str;
309         delete reader;
310
311         eventNr++;
312
313       }
314
315       /* free resources */
316       free(event);
317
318     }
319     
320
321 #ifdef SPD_DA_OFF
322     printf("progress: %d\n",(unsigned int)( ((Float_t)(segNr-startSeg+1))/(argc-startSeg)*50 ));
323   }
324 #endif
325   
326   // clean up phys objects (also saves them)
327   for (UInt_t eq=0; eq<20; eq++) {
328     if (physObj[eq]!=NULL) delete physObj[eq];
329   }
330
331
332
333
334
335   // ********* STEP 2: Analyze phys container files. ************************************************
336
337   //  time_t timeStamp = time(NULL);
338   //  printf("*** Start step2 , %d\n",time(NULL) - timeStamp);
339
340   // clear noisyToFXS dir:
341   TString command;
342   command = Form("cd %s; rm -f *",saveDirNoisyToFXS);
343   system(command.Data());
344   // clear deadToFXS dir:
345   command = Form("cd %s; rm -f *",saveDirDeadToFXS);
346   system(command.Data());
347
348
349   UInt_t firstRunNrDead = runNr;
350
351
352   UInt_t nrEnoughStatNoisy = 0;
353   UInt_t nrEqActiveNoisy = 0;
354   Bool_t eqActiveNoisy[20];
355
356   // *** *** *** start loop over equipments (eq_id)
357   for (UInt_t eq=0; eq<20; eq++) {
358     eqActiveNoisy[eq] = kFALSE;
359
360     // create analyzer for this eq
361     TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eq);
362     AliITSOnlineSPDphysAnalyzer *noisyAnalyzer = new AliITSOnlineSPDphysAnalyzer(fileName.Data(),handler);
363
364     // check data in container
365     if (noisyAnalyzer->GetEqNr() != eq) {
366       if (noisyAnalyzer->GetEqNr() != 999) {
367         printf("Error: Mismatching EqId in Container data and filename (%d!=%d). Skipping.\n",
368                noisyAnalyzer->GetEqNr(),eq);
369       }
370       delete noisyAnalyzer;
371       continue;
372     }
373
374     nrEqActiveNoisy++;
375     eqActiveNoisy[eq] = kTRUE;
376
377     // configure analyzer with tuning parameters etc:
378     for (UInt_t i=0; i<nrTuningParams; i++) {
379       noisyAnalyzer->SetParam(((TObjString*)paramNames.At(i))->GetString().Data(),((TObjString*)paramVals.At(i))->GetString().Data());
380     }
381
382     printf("SPD phys STEP 2: Noisy search for eq %d\n",eq);  
383
384     // search for noisy pixels:
385     nrEnoughStatNoisy += noisyAnalyzer->ProcessNoisyPixels();
386
387     // copy this phys obj to temporary dead reference dir to process after noisy search
388     TString fileNameDead = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eq);
389     AliITSOnlineSPDphys* physObj = new AliITSOnlineSPDphys(fileNameDead.Data());
390     physObj->AddPhys(noisyAnalyzer->GetOnlinePhys());
391     if (physObj->GetNrRuns()>0) {
392       UInt_t firstRunNr = physObj->GetRunNr(0);
393       if (firstRunNrDead>firstRunNr) {
394         firstRunNrDead=firstRunNr;
395       }
396     }
397     // remove noisy pixels from dead hitmap
398     for (UInt_t hs=0; hs<6; hs++) {
399       for (UInt_t chip=0; chip<10; chip++) {
400         for (UInt_t ind=0; ind<handler->GetNrNoisyC(eq,hs,chip); ind++) {
401           UInt_t col  = handler->GetNoisyColAtC(eq,hs,chip,ind);
402           UInt_t row  = handler->GetNoisyRowAtC(eq,hs,chip,ind);
403           physObj->AddHits(hs,chip,col,row,-noisyAnalyzer->GetOnlinePhys()->GetHits(hs,chip,col,row));
404         }
405       }
406     }
407
408     delete physObj;
409     delete noisyAnalyzer;
410
411 #ifndef SPD_DA_OFF
412     daqDA_progressReport((unsigned int)((eq+1)*2.5));
413 #else
414     printf("progress: %d\n",(unsigned int)(50+(eq+1)*1.25));
415 #endif
416   }
417   // *** *** *** end loop over equipments (eq_id)
418
419   printf("Noisy search finished. %d noisy pixels found. %d chips had enough statistics.\n",
420          handler->GetNrNoisy(),nrEnoughStatNoisy);
421   handler->SetFileLocation(saveDirNoisyToFXS);
422   handler->WriteNoisyToFiles();
423
424
425
426
427
428
429
430   UInt_t nrEnoughStatChips = 0;
431   UInt_t nrDeadChips = 0;
432   UInt_t nrInefficientChips = 0;
433   UInt_t nrEqActiveDead = 0;
434   Bool_t eqActiveDead[20];
435
436   // *** *** *** start loop over equipments (eq_id)
437   for (UInt_t eq=0; eq<20; eq++) {
438     eqActiveDead[eq] = kFALSE;
439
440     // setup analyzer for dead search
441     TString fileNameDead = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eq);
442     AliITSOnlineSPDphys* physObj = new AliITSOnlineSPDphys(fileNameDead.Data());
443     AliITSOnlineSPDphysAnalyzer* deadAnalyzer = new AliITSOnlineSPDphysAnalyzer(physObj,handler);
444     // check data in container
445     if (deadAnalyzer->GetEqNr() != eq) {
446       if (deadAnalyzer->GetEqNr() != 999) {
447         printf("Error: Mismatching EqId in Dead Container data and filename (%d!=%d). Skipping.\n",
448                deadAnalyzer->GetEqNr(),eq);
449       }
450       delete deadAnalyzer;
451       nrDeadChips+=60; // since this eq is inactive...
452       continue;
453     }
454
455     nrEqActiveDead++;
456     eqActiveDead[eq] = kTRUE;
457
458     // configure analyzer with tuning parameters etc:
459     for (UInt_t i=0; i<nrTuningParams; i++) {
460       deadAnalyzer->SetParam(((TObjString*)paramNames.At(i))->GetString().Data(),((TObjString*)paramVals.At(i))->GetString().Data());
461     }
462
463     printf("SPD phys STEP 2: Dead search for eq %d\n",eq);  
464
465     // search for dead pixels:
466     nrEnoughStatChips += deadAnalyzer->ProcessDeadPixels();
467     nrDeadChips += deadAnalyzer->GetNrDeadChips();
468     nrInefficientChips += deadAnalyzer->GetNrInefficientChips();
469
470     delete deadAnalyzer;
471
472
473 #ifndef SPD_DA_OFF
474     daqDA_progressReport((unsigned int)(50+(eq+1)*2.5));
475 #else
476     printf("progress: %d\n",(unsigned int)(75+(eq+1)*1.25));
477 #endif
478   }
479   // *** *** *** end loop over equipments (eq_id)
480
481
482
483   
484   printf("Dead search finished.\n");
485   printf("%d single dead pixels , %d dead or inactive pixels in total.\n",handler->GetNrDead(),handler->GetNrSilent());
486   printf("%d chips had enough statistics. %d chips are dead. %d chips are inefficient.\n",nrEnoughStatChips,nrDeadChips,nrInefficientChips);
487   handler->SetFileLocation(saveDirDead);
488   handler->WriteSilentToFilesAlways();
489   handler->SetFileLocation(saveDirDeadToFXS);
490   handler->WriteSilentToFilesAlways();
491
492
493   printf("Opening id list file\n");
494   TString idsFXSFileName = Form("%s/FXSids_run_%d.txt",saveDirIdsToFXS,runNr);
495   ofstream idsFXSfile;
496   idsFXSfile.open(idsFXSFileName.Data());
497
498
499   // send (dead) reference data for this run to FXS - only if there is no chip in category "needsMoreStat"
500   if (nrEnoughStatChips+nrDeadChips+nrInefficientChips == 1200) {
501     printf("Dead calibration is complete.\n");    // calibration is complete
502     printf("Preparing dead reference data\n");
503     // send reference data for dead pixels to FXS
504     TString tarFiles = "";
505     for (UInt_t eq=0; eq<20; eq++) {
506       if (eqActiveDead[eq]) {
507         printf("Preparing dead pixels for eq %d\n",eq);
508         // move file to ref dir
509         TString fileName = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eq);
510         TString newFileName = Form("%s/SPDphys_dead_run_%d_%d_eq_%d.root",saveDirDeadRef,firstRunNrDead,runNr,eq);
511         TString command = Form("mv -f %s %s",fileName.Data(),newFileName.Data());
512         system(command.Data());
513
514         tarFiles.Append(Form("SPDphys_dead_run_%d_%d_eq_%d.root ",firstRunNrDead,runNr,eq));
515       }
516     }
517     TString send_command = Form("cd %s; tar -cf ref_phys_dead.tar %s",saveDirDeadRef,tarFiles.Data());
518     system(send_command.Data());
519     TString fileName = Form("%s/ref_phys_dead.tar",saveDirDeadRef);
520     TString id = "SPD_ref_phys_dead";
521 #ifndef SPD_DA_OFF
522     status = daqDA_FES_storeFile(fileName.Data(),id.Data());
523     if (status!=0) {
524       printf("Failed to export file %s , status %d\n",fileName.Data(),status);
525       return -1;
526     }
527 #endif
528     idsFXSfile << Form("%s\n",id.Data());
529   }
530
531
532
533   // send (noisy) reference data for this run to FXS
534   printf("Preparing noisy reference data\n");
535   TString tarFiles = "";
536   for (UInt_t eq=0; eq<20; eq++) {
537     if (eqActiveNoisy[eq]) {
538       tarFiles.Append(Form("SPDphys_run_%d_eq_%d.root ",runNr,eq));
539     }
540   }
541   TString send_command = Form("cd %s; tar -cf ref_phys.tar %s",saveDirNoisyRef,tarFiles.Data());
542   system(send_command.Data());
543   TString fileName = Form("%s/ref_phys.tar",saveDirNoisyRef);
544   TString id = "SPD_ref_phys";
545 #ifndef SPD_DA_OFF
546   status = daqDA_FES_storeFile(fileName.Data(),id.Data());
547   if (status!=0) {
548     printf("Failed to export file %s , status %d\n",fileName.Data(),status);
549     return -1;
550   }
551 #endif
552   idsFXSfile << Form("%s\n",id.Data());
553
554
555
556
557   // send dead pixels to FXS
558   printf("Preparing dead files\n");
559   // send a tared file of all the dead files
560   send_command = Form("cd %s; tar -cf dead_phys.tar *",saveDirDeadToFXS);
561   //  printf("\n\n%s\n\n",command.Data());
562   system(send_command.Data());
563   fileName = Form("%s/dead_phys.tar",saveDirDeadToFXS);
564   id = "SPD_phys_dead";
565 #ifndef SPD_DA_OFF
566   Int_t send_status = daqDA_FES_storeFile(fileName.Data(),id.Data());
567   if (send_status!=0) {
568     printf("Failed to export file %s , status %d\n",fileName.Data(),send_status);
569     return -1;
570   }
571 #endif
572   idsFXSfile << Form("%s\n",id.Data());
573
574
575
576   // send noisy pixels to FXS
577   if (handler->GetNrNoisy()>0) { // there must be at least one file created
578     printf("Preparing noisy files\n");
579     // send a tared file of all the noisy files
580     TString command = Form("cd %s; tar -cf noisy_phys.tar *",saveDirNoisyToFXS);
581     //    printf("\n\n%s\n\n",command.Data());
582     system(command.Data());
583     TString fileName = Form("%s/noisy_phys.tar",saveDirNoisyToFXS);
584     TString id = "SPD_phys_noisy";
585 #ifndef SPD_DA_OFF
586     status = daqDA_FES_storeFile(fileName.Data(),id.Data());
587     if (status!=0) {
588       printf("Failed to export file %s , status %d\n",fileName.Data(),status);
589       return -1;
590     }
591 #endif
592     idsFXSfile << Form("%s\n",id.Data());
593   }
594
595
596
597   // send ids file to FXS
598   idsFXSfile.close();
599   id = "SPD_id_list";
600 #ifndef SPD_DA_OFF
601   status = daqDA_FES_storeFile(idsFXSFileName.Data(),id.Data());
602   if (status!=0) {
603     printf("Failed to export file %s , status %d\n",idsFXSFileName.Data(),status);
604     return -1;
605   }
606 #endif
607
608
609
610
611   delete handler;
612
613   //  printf("*** End step2 , %d\n",time(NULL) - timeStamp);
614
615
616   return 0;
617 }