KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
GTGanilData.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 * GTGanilData.cpp - Main Header to ROOTGAnilTape
3 * -------------------
4 * begin : Thu Jun 14 2001
5 * copyright : (C) 2001 by Garp
6 * email : patois@ganil.fr
7 ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "Riostream.h"
17 #include "KVConfig.h"
18 #ifdef CCIN2P3_XRD
19 #include "TSystem.h"
20 #endif
21 // ganil_tape lib headers
22 
24 
25 #include <ERR_GAN.H>
26 #include <gan_tape_erreur.h>
27 #include <gan_tape_general.h>
28 #include <gan_tape_param.h>
29 #include <gan_tape_test.h>
30 #include <gan_tape_alloc.h>
31 #include <gan_tape_mount.h>
32 #include <gan_tape_file.h>
33 #include <acq_mt_fct_ganil.h>
34 #include <acq_ebyedat_get_next_event.h>
35 #include <gan_tape_get_parametres.h>
36 extern "C" {
37  typedef struct SCALE {
38  UNSINT32 Length; /* Nb bytes utils suivant ce mot */
39  UNSINT32 Nb_channel;
40  UNSINT32 Acq_status;
41  UNSINT32 Reserve[2];
42  union JBUS_SCALE {
43  scale_struct UnScale[NB_MAX_CHANNEL];
44  UNSINT16 Info_jbus [NB_MAX_JBUS];
46  } scale;
47 }
48 
49 
50 #include "GTGanilData.h"
51 
54 
55 using namespace std;
56 
58 
59 
60 
61 
65 {
66  // Default constructor
67 
68  InitDefault();
69 }
70 
71 
72 
75 
77 {
78  // Create the reading class over the given file with all defaults values
79 
80  InitDefault();
81  SetFileName(filename);
82 }
83 
84 
85 
89 
90 void GTGanilData::SetFileName(const TString filename)
91 {
92  //Set the name of the file to read (use if default ctor is used to create object).
93  //We check if 'filename' begins with "rfio:"; if so, we remove it
94 
95  fFileName = filename;
96  if (filename.BeginsWith("rfio:")) fFileName.Remove(0, 5);
97  strncpy(fDevice->DevName, fFileName, MAX_CARACTERES);
98 }
99 
100 
101 
103 
105 {
106  if (fScaler)delete fScaler;
107  if (fDataParameters)delete fDataParameters;
108  if (fDevice)delete fDevice;
109  if (fBuffer)delete fBuffer;
110  if (fStructEvent)delete[] fStructEvent;
111  if (fDataArray) delete[] fDataArray;
112  if (fEventBrut) delete[] fEventBrut;
113  if (fEventCtrl) delete[] fEventCtrl;
114 }
115 
116 
117 
118 
126 
127 void GTGanilData::InitDefault(const Int_t argc, char** argv)
128 {
129  // PRIVATE
130  // Called by every constructors.
131  // Init parameters to default values
132  // Data are taken first from command line,
133  // Second from environment variables
134  // if none works, takes defaults values.
135 #ifdef CCIN2P3_XRD
136  //if we are using version of GanTape compiled with Xrootd support
137  //we need to load the ROOT XrdPosix library now
138  gSystem->Load("libXrdPosix");
139 #endif
140  fStatus = ACQ_OK;
141  fDataParameters = new GTDataParameters();
142  fEventNumber = -1;
143  fEventCount = 0;
144  fIsCtrl = false;
145  fIsScalerBuffer = false;
146  fDataArray = 0;
147 
148  fDevice = new gan_tape_desc;
149  fBuffer = new in2p3_buffer_struct;
150  fStructEvent = new char[STRUCTEVENTSIZE];
151 
152  fScalerTree = NULL; // By default, no scaler tree
153  fScaler = new GTScalers; // Scaler class
154 
155  val_ret DeRetour; // Union to communicate with ganil_tape lib routines
156  // Getting Logical Unit ID number
157  fStatus = acq_get_param_env(lun_id, &DeRetour, argc, argv);
158  if (DeRetour.Val_INT >= 0) fLun = DeRetour.Val_INT;
159  else fLun = 10; // Random
160  fDevice->Lun = fLun;
161  // Getting tape/file name
162  fStatus = acq_get_param_env(device_id, &DeRetour, argc, argv);
163  strncpy(fDevice->DevName, DeRetour.Val_CAR, MAX_CARACTERES);
164  fFileName = DeRetour.Val_CAR;
165 
166  // GLOBAL VARIABLES ASSIGNED HERE
167  fStatus = acq_get_param_env(autoswbuf_id, &DeRetour, argc, argv);
168  AutoswBuf = DeRetour.Val_BOL;
169 
170  fStatus = acq_get_param_env(swbufon_id, &DeRetour, argc, argv);
171  Swbufon = DeRetour.Val_BOL;
172 
173  // Variable/fix length events
174  fStatus = acq_get_param_env(ctrlform_id, &DeRetour, argc, argv);
175  fCtrlForm = DeRetour.Val_INT;
176 
177  fStatus = acq_get_param_env(density_id, &DeRetour, argc, argv);
178  fDensity = DeRetour.Val_INT;
179 
180  fStatus = acq_get_param_env(bufsize_id, &DeRetour, argc, argv);
181  fBufSize = DeRetour.Val_INT;
182  // GLOBAL VARIABLES ASSIGNED HERE
183  BufSize = fBufSize;
184 
185  fStatus = acq_get_param_env(evbsize_id, &DeRetour, argc, argv);
186  fEvbsize = DeRetour.Val_INT;
187 
188  fStatus = acq_get_param_env(evcsize_id, &DeRetour, argc, argv);
189  fEvcsize = DeRetour.Val_INT;
190 
191  fEventBrut = new UShort_t[fEvbsize];
192  fEventCtrl = new UShort_t[fEvcsize];
193 
194  // calculate size of CTRL_EVNT header to be subtracted from size of event
195  // returned by acq_ebyedat_get_next_event in order to calculate number of
196  // label-value parameter pairs
197  fCTRLEVNT_HD = sizeof(CTRL_EVENT) / 2 - 1;
198 }
199 
200 
201 
204 
206 {
207  // Print every class parameters, for now a simple dump.
208  DumpParameterName();
209 }
210 
211 
212 
216 
218 {
219  // Not implemented.
220  // ...
221 }
222 
223 
224 
231 
233 {
234  // Open the data file (could be on a tape) with a few checks.
235  // Use IsOpen() to check whether the file is opened successfully.
236  // After successfully opening the file, we call ReadParameters()
237  // to fill the parameter list from the first data buffer
238  // which *has to* be a parameter buffer.
239 
240  Int_t structEvent_size = STRUCTEVENTSIZE; // bidon
241 
242  fStatus = acq_dev_is_alloc_c(*fDevice); // Allocation test
243  if (fStatus == ACQ_OK) fAllocated = true;
244  else {
245  gan_tape_erreur(fStatus, "test d'allocation");
246  return;
247  }
248 
249  fStatus = acq_mt_alloc_c(*fDevice); // Allocation
250  if (fStatus != ACQ_OK) {
251  if (fStatus == ACQ_NOTALLOC)
252  cout << "This tape drive is already in use !" << endl;
253  gan_tape_erreur(fStatus, "allocation");
254  return;
255  }
256 
257  fStatus = acq_mt_mount_c(*fDevice, fDensity, fBufSize);
258  if (fStatus != ACQ_OK) { // There might be some imprecisions here
259  if (fStatus == ACQ_ALREADYMOUNT)
260  cout << "The tape you want to use is already mounted" << endl;
261  gan_tape_erreur(fStatus, "mount");
262  return;
263  }
264 
265  fStatus = acq_mt_open_c(fDevice, o_read, &fLun);
266  if (fStatus != ACQ_OK) { // There might be some imprecisions here
267  gan_tape_erreur(fStatus, "open");
268  return;
269  }
270  fRunNumber = 0;
271  Char_t Date[21];
272  fStatus = acq_mt_ini_run_c(fLun, fBuffer, fBufSize, &fRunNumber,
273  fStructEvent, structEvent_size, Date);
274  fDateStart = Date;
275 
276  if (fStatus != ACQ_OK) {
277  gan_tape_erreur(fStatus, "Init Run");
278  return;
279  }
280  cout << "Run " << fRunNumber << " opened" << endl;
281  ReadParameters();
282  return;
283 }
284 
285 
286 
287 
292 
294 {
295  // PRIVATE
296  // Read the data parameters from the current buffer, put it in the
297  // parameter list.
298 
299  do {
300  ReadBuffer();
301  if (strcmp(fHeader, PARAM_Id) == 0)
302  fDataArraySize = fDataParameters->Fill(fBuffer->les_donnees.cas.Buf_param);
303  }
304  while (strcmp(fHeader, PARAM_Id) == 0);
305 
306  fDataArray = new UShort_t[fDataArraySize + 1]; // Data buffer is allocated
307  for (Int_t i = 1; i <= fDataArraySize; i++) {
308  fDataArray[i] = (Short_t) - 1;
309  }
310 }
311 
312 
313 
316 
317 void GTGanilData::Connect(const Int_t index, UShort_t** p) const
318 {
319  // Connect a pointer to a data to the defined index in the Data Array
320 
321  if ((index < 1) || (index > fDataArraySize)) {
322  cout << "Invalid connexion:" << index << ". Valid only in 1<=index<="
323  << fDataArraySize << endl;
324  return;
325  }
326  *p = &(fDataArray[index]);
327 }
328 
329 
330 
333 
334 Bool_t GTGanilData::Connect(const TString parName, UShort_t** p) const
335 {
336  // Connect a pointer to a data to a given parameter name in the Data Array
337 
338  Int_t index = fDataParameters->GetIndex(parName);
339  if (index < 0) {
340  //parameter not found
341  return kFALSE;
342  }
343  Connect(index, p);
344  return kTRUE;
345 }
346 
347 
348 
384 
386 {
387  // Read an event on tape/file and put in into the event array
388  // return true until read fails
389  //
390  // If scaler buffer management (fWhatScaler) has been set to
391  // kSkipScaler, kDumpScaler or kAutoWriteScaler, then every time this method
392  // returns kTRUE a new event has been read (and perhaps 1 or more scaler buffers
393  // were read and dealt with internally).
394  // In this case, a loop over all events will look like this:
395  //
396  // while( my_gtganildata->Next() ){
397  // // new event read from file
398  // my_gtganilData->GetFiredDataParameters()->ls(); // or whatever
399  // }
400  //
401  // If fWhatScaler = kReportScaler then this method also returns kTRUE after
402  // reading a scaler buffer (no new event read), so that the user can do
403  // something with the scalers.
404  // In this case, a loop over all events including treatment of scaler buffers
405  // will look like this:
406  //
407  // while( my_gtganildata->Next() ){
408  // if( my_gtganildata->IsScalerBuffer() ){
409  // // scaler buffer read from file
410  // GTScalers* scalers = my_gtganildata->GetScalers();
411  // // N.B. GTGanilData::GetScalers() also resets the IsScalerBuffer()
412  // // flag ready for next event/buffer, so even if you don't
413  // // do anything with the scalers, you should call it
414  // }
415  // else
416  // {
417  // // new event read from file
418  // my_gtganilData->GetFiredDataParameters()->ls(); // or whatever
419  // }
420  // }
421 
422  if (fEventNumber == -1) ReadBuffer();
423  if (fStatus) return (false); // Maybe more to say here
424  TString _heads(fHeader);
425  _heads.ToUpper();
426  if (_heads.Contains("ENDRUN")) {
427  //we have reached the end of the file
428  return (false);
429  }
430  if (strcmp(fHeader, SCALER_Id) == 0) {
431  switch (fWhatScaler) {
432  case kSkipScaler:
433  return (Next()); // Skip
434  case kDumpScaler:
435  fScaler->Fill((scale*) & (fBuffer->les_donnees.cas.scale));
436  fScaler->DumpScalers();
437  return (Next());
438 
439  case kReportScaler:
440  fScaler->Fill((scale*) & (fBuffer->les_donnees.cas.scale));
441  fIsScalerBuffer = true;
442  return kTRUE;
443 
444  case kAutoWriteScaler: {
445  fScaler->Fill((scale*) & (fBuffer->les_donnees.cas.scale));
446  fScaler->DumpScalers();
447  fScalerTree->Fill();
448  return (Next());
449  }
450  break;
451  default:
452  cout << "GTGanilData::Next: unexpected value for fWhatScaler" << endl;
453  }
454  }
455  if (strcmp(fHeader, EVENTDB_Id) == 0) {
456  fIsScalerBuffer = false;
457  fIsCtrl = false;
458  fEventCount++;
459  return (ReadNextEvent());
460  }
461  else if (strcmp(fHeader, EVENTCT_Id) == 0) {
462  fIsScalerBuffer = false;
463  fIsCtrl = true;
464  fEventCount++;
465  return (ReadNextEvent());
466  }
467  else if (strcmp(fHeader, EBYEDAT_Id) == 0) {
468  fIsScalerBuffer = false;
469  fIsCtrl = false;
470  fEventCount++;
471  return (ReadNextEvent_EBYEDAT());
472  }
473  cout << "Unknown header in GTGanilData::Next:" << fHeader << endl;
474  return (true);
475 }
476 
477 
478 
483 
484 void GTGanilData::MakeTree(const TString filename, UInt_t nEvents)
485 {
486  // Automatically create and fill a tree created from ganil data.
487  // Can be use to convert a ganil tape or file to a ROOT file.
488  // The number of actual converted events is set with the nEvents parameter.
489 
490  TString theFilename;
491  if (filename == "")
492  theFilename = fFileName + ".root";
493  else theFilename = filename;
494  TFile theTreeFile(theFilename, "recreate");
495  TTree theTree("AutoTree", "Automatic filled Tree");
496  for (Int_t i = 1; i <= fDataArraySize; i++) {
497  TString parName = fDataParameters->GetParName(i);
498  TString parType = parName + "/s";
499  theTree.Branch(parName, &(fDataArray[i]), parType);
500  }
501 
502  while (Next()) {
503  theTree.Fill();
504  nEvents--;
505  if (nEvents <= 0) break;
506  }
507  theTree.Write();
508 }
509 
510 
511 
512 
516 
518 {
519  // PRIVATE
520  // Utility routine to read events from buffers.
521 
522  if (!fIsCtrl) {
523  fStatus = get_next_event(fBuffer, fBufSize,
524  (short*)fEventBrut, fEvbsize, &fEventNumber);
525  if (fStatus == ACQ_OK) {
526  fStatus = s_evctrl((short*)fEventBrut, (short*)fEventCtrl,
527  fStructEvent, &fCtrlForm);
528  if (fStatus == GR_OK)
529  return (EventUnravelling((CTRL_EVENT*)fEventCtrl));
530  else {
531  puts("\n>>> Erreur de reconstruction");
532  return (false);
533  }
534  }
535  else if (fStatus == ACQ_ENDOFBUFFER) {
536  fEventNumber = -1;
537  return (Next());
538  }
539  else {
540  gan_tape_erreur(fStatus, "obtention d'evenement");
541  return (false);
542  }
543  }
544  else {
545  fStatus = get_next_event(fBuffer, fBufSize, (short*)fEventCtrl,
546  fEvcsize, &fEventNumber);
547  if (fStatus == ACQ_OK) {
548  return (EventUnravelling((CTRL_EVENT*)fEventCtrl));
549  }
550  else if (fStatus == ACQ_ENDOFBUFFER) {
551  fEventNumber = -1;
552  return (Next());
553  }
554  else {
555  gan_tape_erreur(fStatus, "obtention d'evenement");
556  return (false);
557  }
558  }
559 }
560 
561 
562 
567 
569 {
570  // PRIVATE
571  // Utility routine to read EBYEDAT events from buffers.
572  //Shamelessly copied from Luc Legeard's GEvent
573  if (!fIsCtrl) {
574  UNSINT16* ebyeEventCtrl;
575  fStatus = acq_ebyedat_get_next_event((UNSINT16*)fBuffer, &ebyeEventCtrl, &fEventNumber, EVCT_VAR);
576  if (fStatus == ACQ_OK) return (EventUnravelling((CTRL_EVENT*)ebyeEventCtrl));
577  else if (fStatus == ACQ_ENDOFBUFFER) {
578  fEventNumber = -1;
579  return (Next());
580  }
581  else {
582  cout << " in ReadNextEvent__EBEYEDAT error status: " << fStatus << " n";
583  return (false);
584  }
585  }
586  else {
587  fStatus = ACQ_BADEVENTFORM;
588  }
589  return (false);
590 }
591 
592 
596 
598 {
599  // PRIVATE
600  // Read a single buffer from file
601 
602  fStatus = acq_mt_read_c(fLun, fBuffer->Buffer, &fBufSize);
603  //if ( fStatus != ACQ_OK )
604  //cout << "Not OK"<<endl; // Maybe stuff to do to handle the error
605 
606  strncpy(fHeader, fBuffer->les_donnees.Ident, 8);
607  fHeader[8] = '\0';
608 }
609 
610 
611 
619 
620 bool GTGanilData::EventUnravelling(CTRL_EVENT* pCtrlEvent)
621 {
622  // PRIVATE
623  // If mode is variable length event, we have to reconstruct the Data buffer
624  // from the given event.
625  // WARNING: temporary the default: we dont check that it's really the case
626  // Before reading event, all parameters have their value set to -1 (65535 - fDataArray is UShort_t)
627  // Parameters which are not fired in the event will have value -1 (65535 - cast back to Short_t for real value)
628 
629  Short_t* brutData = &(pCtrlEvent->ct_par);
630 
631  Int_t eventLength = pCtrlEvent->ct_len - fCTRLEVNT_HD;
632  //printf("EventUnravelling : eventLength=%d sizeof(CTRL_EVENT)=%d\n",eventLength,sizeof(CTRL_EVENT));
633 
634  for (Int_t i = 1; i <= fDataArraySize; i++) {
635  fDataArray[i] = (Short_t) - 1;
636  }
637 
638  for (Int_t i = 0; i < eventLength; i += 2) {
639  //cout << dec << i+1 << " -- " << hex << brutData[i] << " = " << brutData[i+1] << endl;
640  if (brutData[i] <= fDataArraySize && brutData[i] >= 1) {
641  fDataArray[brutData[i]] = brutData[i + 1];
642  }
643  else { // More on error handling would be cool
644  /* cout << "Index overflow : Parameter index "<<i<<" is "<<brutData[i]<<
645  " but fDataArraySize is " << fDataArraySize<<endl;
646  return(false);
647  */
648  }
649  }
650  return (true);
651 }
652 
653 
654 
655 
656 
657 
660 
661 void GTGanilData::DumpEvent(void) const
662 {
663  // Dump parameter index, name and value for the current event.
664 
665  cout << "--------- DUMPING EVENT ----------------------------" << endl;
666  cout << "------- number:" << fEventCount << endl;
667  for (Int_t i = 1; i <= fDataArraySize; i++) {
668  if ((Short_t)fDataArray[i] > -1) cout << "index :" << i << " " << fDataParameters->GetParName(i) << " : " << fDataArray[i] << endl;
669  }
670  cout << "--------- END ----------------------------" << endl;
671 }
672 
673 
674 
677 
679 {
680  // Dump parameter index and name
681 
682  cout << "--------- DUMPING PARAMETERS ----------------------------" << endl;
683  cout << "------- number:" << fEventCount << endl;
684  for (Int_t i = 1; i <= fDataArraySize; i++) {
685  // WARNING : index start at one, the first value is boggus
686  cout << "index :" << i << " " << fDataParameters->GetParName(i) << endl;
687  }
688  cout << "--------- END ----------------------------" << endl;
689 }
690 
691 
692 
706 
708 {
709  // Set scaler buffers management. It can be:
710  // GTGanilData::kSkipScaler : Skip scaler buffers
711  // GTGanilData::kDumpScaler : Dump all scaler buffers on stdout
712  // GTGanilData::kAutoWriteScaler : Automatic scaler buffer management, all scalers written in a TTree
713  // To use this, the current TFile (i.e. gFile) must be writable.
714  // i.e. you should do TFile file("somefile.root", "create")
715  // and then toto.SetScalerBuffersManagement(GTGanilData::kReportScaler)
716  // GTGanilData::kReportScaler : when Next() encounters a scaler buffer, the IsScalerBuffer()
717  // flag is set to kTRUE and the data can be retrieved by
718  // calling GetScalers() (returns a pointer to a GScalers object).
719  // WARNING: this option changes the logic of a loop over all events
720  // in the file (see GTGanilData::Next()).
721 
722  fWhatScaler = sc;
723 
724  if (fWhatScaler == kAutoWriteScaler) {
725  if (gFile && gFile->IsWritable()) {
726  fScalerTree = new TTree("Scalers", "Automatic filled scalers");
727  fScalerTree->Branch("scalers", fScaler, 8000, 99);
728  }
729  else {
730  cout << "Error in <GTGanilData::SetScalerBuffersManagement> : ";
731  cout << "You must open a writable TFile before calling SetScalerBuffersManagement(kAutoWriteScaler)" << endl;
732  fWhatScaler = kSkipScaler;
733  }
734  }
735 }
736 
737 
738 
739 
742 
744 {
745  //Returns current run number
746  return fRunNumber;
747 }
748 
749 
750 
751 
753 
755 {
756  return (fStatus == ACQ_OK && fLun);
757 }
758 
759 
760 
761 
764 
766 {
767  //Not used
768 }
769 
770 
int Int_t
unsigned int UInt_t
std::string fBuffer
bool AutoswBuf
Definition: GTGanilData.cpp:52
Int_t BufSize
Definition: GTGanilData.cpp:53
bool Swbufon
Definition: GTGanilData.cpp:52
struct SCALE scale
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
unsigned short UShort_t
char Char_t
const Bool_t kFALSE
bool Bool_t
short Short_t
const Bool_t kTRUE
#define gFile
virtual void ReadBuffer(char *&buffer)
R__EXTERN TSystem * gSystem
Read GANIL formatted tapes or files.
Definition: GTGanilData.h:63
bool ReadNextEvent(void)
void ReadBuffer(void)
void InitDefault(const Int_t argc=0, char **argv=NULL)
void DumpEvent(void) const
Dump parameter index, name and value for the current event.
void Connect(const Int_t index, UShort_t **p) const
Connect a pointer to a data to the defined index in the Data Array.
Int_t GetRunNumber(void) const
Returns current run number.
void SetFileName(const TString filename)
Definition: GTGanilData.cpp:90
bool ReadNextEvent_EBYEDAT(void)
void PrintRunParameters(void) const
Print every class parameters, for now a simple dump.
virtual void SetUserTree(TTree *)
Not used.
void DumpParameterName(void) const
Dump parameter index and name.
Bool_t IsOpen(void) const
virtual void ReadParameters(void)
GTGanilData()
Default constructor.
Definition: GTGanilData.cpp:64
void SetScalerBuffersManagement(const ScalerWhat_t sc)
bool Next(void)
void MakeTree(const TString filename="", UInt_t nEvents=kMaxUInt)
virtual ~GTGanilData(void)
virtual bool EventUnravelling(CTRL_EVENT *)
void PrintDataParameters(void) const
void Open(void)
ScalerWhat_t
What to do with scaler buffer.
Definition: GTGanilData.h:66
Handle scaler buffers in GANIL DAQ data.
Definition: GTScalers.h:33
void ToUpper()
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
virtual Int_t Fill()
virtual Int_t Branch(const char *folder, Int_t bufsize=32000, Int_t splitlevel=99)
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
UNSINT32 Reserve[2]
Definition: GTGanilData.cpp:41
UNSINT32 Length
Definition: GTGanilData.cpp:38
UNSINT32 Acq_status
Definition: GTGanilData.cpp:40
union SCALE::JBUS_SCALE jbus_scale
UNSINT32 Nb_channel
Definition: GTGanilData.cpp:39
ROOT headers.
Definition: GTGanilData.h:42
UNSINT16 Info_jbus[NB_MAX_JBUS]
Definition: GTGanilData.cpp:44
scale_struct UnScale[NB_MAX_CHANNEL]
Definition: GTGanilData.cpp:43