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