GammaWare  Head Version for release 0.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RADConverter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2004-2006 by Olivier Stezowski & Christophe Theisen *
3  * stezow(AT)ipnl.in2p3.fr, christophe.theisen(AT)cea.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
23 #ifndef GW_RADCONVERTER_H
24 #include "RADConverter.h"
25 #endif
26 
27 
28 #ifndef ROOT_TRegexp
29 #include <TRegexp.h>
30 #endif
31 
32 #ifndef ROOT_TSystem
33 #include <TSystem.h>
34 #endif
35 
36 #ifndef ROOT_TSystemDirectory
37 #include <TSystemDirectory.h>
38 #endif
39 
40 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
41 #include "TList.h"
42 #endif
43 
44 #include <iostream>
45 using namespace std;
46 
47 namespace { RADConverter gRADConverter; } // prototype ONLY use to create a new DB system
48 
49 //___________________________________________________________________
50 RADConverter::RADConverter(const char *name) : HistoConverter(name)
51 {
52  fType = "rad";
53  CheckDirectory(name);
54  fCycle = '_'; // because ; is not supported by all file systems
55  fLog.GetProcessName() = "RADConverter";
56 }
57 
58 //___________________________________________________________________
60 {
61  fType = "rad";
62  fFileExt = ".spe";
63  fOptions = "";
64  // add this interface to the DB service
65  AddPrototype(GetType(),this);
66 }
67 
68 //___________________________________________________________________
70 {
71 
72 }
73 
74 //___________________________________________________________________
75 void RADConverter::ls(Option_t *o) const
76 {
77  HistoConverter::ls(o);
78  TSystemDirectory dir; dir.SetDirectory(fName.Data()); TList *list = dir.GetListOfFiles();
79 
80  TIter iter(list); TObject *entry; int count = 0;
81  while ( (entry = iter()) ) {
82  TString tmp = entry->GetName();
83  //cout << " file name " << entry->GetName() << endl;
84  if ( tmp.EndsWith(fFileExt) ) {
85  cout << " [" << count++ << "] " << entry->GetName() ;
86 
87  if ( (count+1) % 5 == 0 ) cout << endl;
88  else cout << "\t";
89  }
90  }
91  cout << endl; if ( list ) delete list;
92 }
93 
94 //___________________________________________________________________
95 HistoConverter *RADConverter::NewDB(const char *name) const
96 {
97  return new RADConverter(name);
98 }
99 
100 //___________________________________________________________________
101 TH1 *RADConverter::Get(int which)
102 {
103  // list all the file to find the entry name correponding to which
104  TSystemDirectory dir; dir.SetDirectory(fName.Data()); TList *list = dir.GetListOfFiles();
105 
106  TIter iter(list); TObject *entry; int count = 0; TString result = "_EMPTY_";
107  while ( (entry = iter()) ) {
108  TString tmp = entry->GetName();
109  if ( tmp.EndsWith(fFileExt) ) {
110  if ( which == count ) result = entry->GetName(); count++;
111  }
112  }
113  if ( list ) delete list;
114 
115  if ( result != "_EMPTY_" ) return Get(result.Data()); // an entry has been found
116  fLog.GetProcessMethod() = "Get(Int_t )";
117  SetError(HistoConverter::kFail,
118  Form("Cannot find entry # %d",which));
119 
120  return NULL;
121 }
122 
123 //___________________________________________________________________
124 TH1 *RADConverter::Get(const char *name)
125 {
126  TH1F *h = new TH1F();
127 
128  h->SetName(name);
129  if ( !Read((*h)) ) { delete h; h = NULL; }
130 
131  return h;
132 }
133 
134 //___________________________________________________________________
135 bool RADConverter::Read(TH1 &h)
136 {
137  TString filename = fName.Data(); // set file name as a full path name
138  if ( filename.IsNull() ) filename = "."; // for mine types
139 
140  if ( ! filename.EndsWith("/") ) filename+= "/"; // set file name as a full path name
141 
142  filename += h.GetName();
143  if ( filename.EndsWith(fFileExt) == false ) filename += fFileExt;
144 
145  if (fVerboseLevel)
146  fLog << info << "Reading spectrum " << filename << nline;
147 
148  ifstream file;
149 
150  file.open(filename.Data());
151  if ( ! file.is_open() ){
152  fLog.GetProcessMethod() = "Read(TH1& )";
153  SetError(HistoConverter::kFail,
154  Form("Cannot open file %s",filename.Data()));
155  return false;
156  }
157 
158  // now read the spectrum
159  char nom[24], nam[8]; int ndim[4], dum[2], i;
160  float buffer[32768];
161 
162  file.read(nom,4);
163  file.read(nam,8);
164  if ( gDebug > 0 ) fLog << debug << "Spectrum name : " << nam << nline;
165 // sprintf(name,nam);
166  file.read((char*)ndim, 16);
167  if (ndim[0] >= 65536) {// swapping is needeed
168  fIsSwapping = true;
169  for(i=0; i<4; i++) ndim[i] = Int(((char*)&(ndim[i])));
170  }
171 
172  if ( gDebug > 0 ) fLog << debug << "Spectrum size : " << ndim[0] << nline;
173 // printf("%d \n",ndim[1]);
174 // printf("%d \n",ndim[2]);
175 // printf("%d \n",ndim[3]);
176 
177  file.read((char*)dum, 8);
178  file.read((char*)buffer, 4*ndim[0]);
179 // printf("%d \n",n);
180 // printf("Spectrum size : %d \n",ndim[0]);
181 
182 
183  if ( file.good() ) { // change h only if everything was read correctly
184  h.SetName(nam);
185  h.SetBins(ndim[0],0,ndim[0]);
186  for (i=0; i<ndim[0]; i++)
187  h.Fill(i,Float((char*)&(buffer[i])));
188  }
189 
190  return file.good();
191 }
192 
193 //___________________________________________________________________
194 bool RADConverter::Write(const TH1 &h)
195 {
196  TString hname, filename; // set file name as a full path name
197  hname = h.GetName();
198  filename = CheckFileVersion(hname);
199 
200  fLog.GetProcessMethod() = "Write(const TH1& )";
201 
202  filename.Prepend(fName.Data());
203  if ( gDebug > 0 ) {
204  fLog << error << "File to store the spectrum "
205  << filename << nline ;
206  }
207 
208  if (fVerboseLevel)
209  fLog << info << "Writing spectrum " << filename << nline ;
210 
211 
212  FILE *fprad;
213  int /*dum,*/ i, j = 24, toto, tab[4] = {0,1,1,1}, size; char spname[8];
214 
215  ::strncpy(spname,h.GetName(),8);
216  tab[0] = size = h.GetNbinsX(); toto = size * sizeof(float);
217 
218  fprad = fopen(filename.Data(),"w");
219  if (fprad == NULL){
220  SetError(HistoConverter::kFail,
221  Form("[RADConverter::Write] Cannot open %s in writing mode",filename.Data()));
222  return false;
223  }
224  float *spectre = new float[h.GetNbinsX()];
225  for ( i = 0; i < tab[0]; i++ )
226  spectre[i] = h.GetBinContent(i+1);
227 
228 // dum = fwrite(&j, sizeof(int), 1, fprad);
229 // dum = fwrite(spname, 8, 1, fprad);
230 // dum = fwrite(tab, sizeof(int), 4, fprad);
231 // dum = fwrite(&j, sizeof(int), 1, fprad);
232 // dum = fwrite(&toto, sizeof(int), 1, fprad);
233 // dum = fwrite(spectre, sizeof(float), size, fprad);
234 // dum = fwrite(&toto,sizeof(int),1,fprad);
235 
236  fwrite(&j, sizeof(int), 1, fprad);
237  fwrite(spname, 8, 1, fprad);
238  fwrite(tab, sizeof(int), 4, fprad);
239  fwrite(&j, sizeof(int), 1, fprad);
240  fwrite(&toto, sizeof(int), 1, fprad);
241  fwrite(spectre, sizeof(float), size, fprad);
242  fwrite(&toto,sizeof(int),1,fprad);
243 
244  fclose(fprad); delete spectre; return true;
245 }
246 
247 //___________________________________________________________________
248 bool RADConverter::Read(TH2 &h)
249 {
250  // set file name as a full path name
251  TString filename = fName.Data(); filename += h.GetName();
252 
253  fLog.GetProcessMethod() = "Read(TH2& )";
254 
255  // CHECK OUT THE EXTENSION
256  int whichext = 0;
257  if ( filename.EndsWith(".mat") ) whichext = 1;
258  if ( filename.EndsWith(".m4b") ) whichext = 2;
259  if ( filename.EndsWith(".spn") ) whichext = 3;
260 
261  if ( whichext == 0 ) filename += ".mat"; //assumes mat as a standard
262 
263  if (fVerboseLevel)
264  fLog << info << "Reading matrix " << filename << nline;
265 
266  // now open the file for reading
267  ifstream file;
268 
269  file.open(filename.Data());
270  if ( ! file.is_open() ){
271  SetError(HistoConverter::kFail,
272  Form("Cannot open file %s",filename.Data()));
273  return false;
274  }
275  // check out the file size (should be divided by 4096*4096) and set the item size
276  int itemsize;
277  file.seekg(0,ios::end); long filesize = file.tellg() ;
278  //cout << filesize << endl;
279  if ( (filesize != 2*4096*4096) && (filesize != 4*4096*4096) ) {
280  fLog.GetProcessMethod() = "Read(TH2& )";
281  SetError(HistoConverter::kFail,
282  Form("File %s cannot be a Radware matrix",filename.Data()));
283  file.close(); return false;
284  }
285  else { itemsize = file.tellg() / (4096*4096) ; }
286  file.seekg(0,ios::beg);
287  bool ok = false;
288  if ( itemsize == 2 ) { ok = DecodeMAT(h,file); }
289  if ( itemsize == 4 ) { ok = DecodeSPN(h,file); }
290 
291  file.close(); return ok;
292 }
293 
294 //___________________________________________________________________
295 bool RADConverter::DecodeMAT(TH2 &h, ifstream & file)
296 {
297  // Read the matrix for the file. First scan to determine if the file can be read
298  // without any problem and if swapping is needed.
299  // swapping will be determined by computing the value: Sum ( ABS(mat(i,j) )
300  // The swapping that minimize this value will be considered as the good swapping
301 
302  int i,j; char buffer[2*4096];
303 
304  double swap = 0.0, noswap = 0.0;
305  for(i=0; i<4096 ; i++){
306  //printf("Reading row #%d \r",i);
307  file.read(buffer,2*4096);
308  if ( file.fail() ) {
309  fLog.GetProcessMethod() = "DecodeMAT(TH2&, ifstream& )";
310  SetError(HistoConverter::kFail,
311  "Cannot read correctly the file");
312  return false;
313  }
314  else {
315  for (j=0; j<4096; j++) {
316  fIsSwapping = true; swap += TMath::Abs(Short(buffer+2*j));
317  fIsSwapping = false; noswap += TMath::Abs(Short(buffer+2*j));
318  }
319  }
320  }
321  if ( swap > noswap ) fIsSwapping = false;
322  else fIsSwapping = true;
323 
324  // rewing and re-start and fills the histograms
325  file.seekg(0,ios::beg);
326 
327  h.SetBins(4096,0,4096,4096,0,4096);
328  for(i=0; i<4096 ; i++){
329  printf("Reading row #%d \r",i);
330  file.read(buffer,2*4096);
331  for (j=0; j<4096; j++) h.Fill(i,j,Short(buffer+2*j));
332  }
333 
334  return true;
335 }
336 
337 //___________________________________________________________________
338 bool RADConverter::DecodeSPN(TH2 &h, ifstream & file)
339 {
340  // Read the matrix for the file. First scan to determine if the file can be read
341  // without any problem and if swapping is needed.
342  // swapping will be determined by computing the value: Sum ( ABS(mat(i,j) )
343  // The swapping that minimize this value will be considered as the good swapping
344 
345  int i,j; char buffer[4*4096];
346 
347  double swap = 0.0, noswap = 0.0;
348  for(i=0; i<4096 ; i++){
349  // printf("Reading row #%d \r",i);
350  file.read(buffer,4*4096);
351  if ( file.fail() ) {
352  fLog.GetProcessMethod() = "DecodeSPN(TH2&, ifstream& )";
353  SetError(HistoConverter::kFail,
354  "Cannot read correctly the file");
355  return false;
356  }
357  else {
358  for (j=0; j<4096; j++) {
359  fIsSwapping = true; swap += TMath::Abs(Int(buffer+4*j));
360  fIsSwapping = false; noswap += TMath::Abs(Int(buffer+4*j));
361  }
362  }
363  }
364  if ( swap > noswap ) fIsSwapping = false;
365  else fIsSwapping = true;
366 
367  // rewing and re-start and fills the histograms
368  file.seekg(0,ios::beg);
369 
370  h.SetBins(4096,0,4096,4096,0,4096);
371  for(i=0; i<4096 ; i++){
372  printf("Reading row #%d \r",i);
373  file.read(buffer,4*4096);
374  for (j=0; j<4096; j++){
375  h.Fill(i,j,Int(buffer+4*j));
376  }
377  }
378 
379  return true;
380 }
381 
382 //___________________________________________________________________
383 bool RADConverter::Write(const TH2 &h)
384 {
385  // only TH2S and TH2I can be exported
386  fLog.GetProcessMethod() = "Write(TH2& )";
387 
388  if ( !h.InheritsFrom("TH2S") && !h.InheritsFrom("TH2I") ) {
389  fLog.GetProcessMethod() = "Write(const TH2& )";
390  SetError(HistoConverter::kFail,
391  "Only TH2S or TH2I can be exported as Radware matrix");
392  return false;
393  }
394 
395  TString hname, filename, ext; // set file name as a full path name
396 
397  // check out the histogram name to avoid blank in a filename
398  hname = h.GetName(); hname.ReplaceAll(" ","");
399 
400  // CHECK OUT THE EXTENSION
401  if ( hname.EndsWith(".mat") ) { hname.Remove(hname.Last('.'));}
402  if ( hname.EndsWith(".m4b") ) { hname.Remove(hname.Last('.'));}
403  if ( hname.EndsWith(".spn") ) { hname.Remove(hname.Last('.'));}
404 
405  filename = hname;
406  if ( h.InheritsFrom("TH2S") )
407  { filename += ".mat"; ext = "mat"; }
408  else
409  { filename += ".m4b"; ext = "m4b"; }
410 
411 
412 
413  // determine the name of the file taking into account the versionning system
414  TSystemDirectory dir;
415  dir.SetDirectory(fName.Data()); TList *list = dir.GetListOfFiles();
416 
417  if ( list ) {
418  // look for the next cycle
419  int cycle;
420  for ( int i = 0; i <= MAXCYCLE; i++ ) { // up to MAXCYCLE files
421 
422  TString tmp;
423  if ( i == 0 ) tmp.Form("%s.%s",hname.Data(),ext.Data());
424  else tmp.Form("%s%c%d.%s",hname.Data(),fCycle,i,ext.Data());
425 
426  cycle = i;
427  if ( !list->FindObject(tmp.Data()) ) { break; }
428  }
429  if ( cycle == 0) { // the file doesn't exist yet
430  filename.Form("%s.%s",hname.Data(),ext.Data());
431  }
432  if ( cycle == MAXCYCLE ) { // force overwriting even if in versionning mode
433  filename.Form("%s%c%d.%s",hname.Data(),fCycle,MAXCYCLE,ext.Data());
434  }
435  if ( 0 < cycle && cycle < MAXCYCLE ) {
436  if ( fMode == HistoConverter::kVersion ) // ready for a new file
437  filename.Form("%s%c%d.%s",hname.Data(),fCycle,cycle,ext.Data());
438  else { // comes back to the previous one
439  cycle--;
440  if ( cycle == 0 )
441  filename.Form("%s.%s",hname.Data(),ext.Data());
442  else
443  filename.Form("%s%c%d.%s",hname.Data(),fCycle,cycle,ext.Data());
444  }
445  }
446  if ( gDebug > 0 )
447  fLog << debug << "cycle is " << cycle << nline;
448 
449  delete list;
450  }
451  filename.Prepend(fName.Data());
452  if ( gDebug > 0 ) {
453  fLog << error << "File to store the matrix "
454  << filename << nline;
455  }
456 
457  if (fVerboseLevel)
458  fLog << info << "Writing matrix " << filename << nline;
459 
460  // now the matrix could be store
461  ofstream file;
462 
463  file.open(filename.Data());
464  if ( ! file.is_open() ) {
465  SetError(HistoConverter::kFail,
466  Form("Cannot open file %s",filename.Data()));
467  return false;
468  }
469 
470  bool ok;
471  for(int i=0; i<4096 ; i++) {
472  for (int j=0; j<4096; j++) {
473  if ( h.InheritsFrom("TH2S") ) {
474  short value = 0;
475  if ( i < h.GetNbinsX() && j < h.GetNbinsY() )
476  value = (short)h.GetBinContent(i+1,j+1);
477  file.write((char *)&value,2);
478  }
479  else {
480  int value;
481  if ( i < h.GetNbinsX() && j < h.GetNbinsY() )
482  value = (int)h.GetBinContent(i+1,j+1);
483  file.write((char *)&value,4);
484  }
485  }
486  }
487  ok = !file.fail(); file.close(); return ok;
488 }
489 
490 //___________________________________________________________________
491 bool RADConverter::Read(THStack &hs)
492 {
493  TString hsname = hs.GetName();
494 
495  // to avoid blanck in name and to get the correct extention .spe in pattern
496  hsname.ReplaceAll(" ","");
497  if ( !hsname.EndsWith(fFileExt) )
498  hsname.Append(fFileExt);
499 
500  // pattern expression
501  TString reg = "*" + fFileExt; Bool_t wildcard = false;
502  if ( hsname.Contains("*") )
503  wildcard = true;
504  TRegexp all(reg,kTRUE), pattern(hsname.Data(),wildcard);
505 
506  if ( pattern.Status() != TRegexp::kOK ) {
507  if ( gDebug > 0 ) cerr << "pattern [*] intead of " << hsname << endl ;
508  pattern = all;
509  }
510  else { if ( gDebug > 0 ) cerr << "pattern " << hsname << endl ; }
511 
512  // loop on files to load the good ones.
513  TSystemDirectory dir; dir.SetDirectory(fName.Data()); TList *list = dir.GetListOfFiles();
514 
515  TIter iter(list); TObject *entry;
516  while ( (entry = iter()) ) {
517 
518  TString tmp = entry->GetName();
519 
520  if ( tmp.Contains(pattern) ) { // should be added to the collection
521  if (fVerboseLevel) {
522  fLog.GetProcessMethod() = "Read(THStack& )";
523  fLog << info << "Reading spectrum " << entry->GetName() << nline;
524  }
525  TH1 *h = Get(entry->GetName()); if ( h ) { hs.Add(h); }
526  }
527  }
528  if ( list ) delete list;
529 
530  return true;
531 }
532 
533 //___________________________________________________________________
534 bool RADConverter::Write(const THStack &/*hs*/)
535 {
536  fLog.GetProcessMethod() = "Write(const THStack& )";
537  SetError(HistoConverter::kFail,"NO IMPLEMENTATION !!");
538  return false;
539 }
540 
void SetError(HistoConverter::EStatus status=kGood, const char *msgerror="")
to set/reset the status of this converter
printf("******************************************************************** \n")
virtual ~RADConverter()
virtual TH1 * Get(int)
to get histo number i in the list
LogMessage & error(LogMessage &)
static void AddPrototype(const char *, HistoConverter *)
to add a new type of database service
float Float(char *buf)
short Short(char *buf)
LogMessage & nline(LogMessage &)
UInt_t value[MaxValue]
Definition: ReadDaqAlone.C:29
virtual void ls(Option_t *) const
to show the spectra in this DB system on the standard output
LogMessage & info(LogMessage &)
manipulator to modify the LogMessage
virtual bool Write(const TH1 &)
to write an histogram
#define MAXCYCLE
Base class that interfaces all other histograms DB systems.
virtual bool Read(TH1 &)
to read an histogram
LogMessage & debug(LogMessage &)
virtual std::string & GetProcessName()
To get the Process name.
Definition: GwLogMessage.h:224
ADF::LogMessage & endl(ADF::LogMessage &log)
virtual HistoConverter * NewDB(const char *) const
to creat a new DB system
static int fVerboseLevel
const Int_t size
Definition: BenchIO.C:24
virtual void CheckDirectory(const char *name)
check if the given directory can be read/written
virtual std::string & GetProcessMethod()
To get the current method.
Definition: GwLogMessage.h:227
int Int(char *buf)
TString CheckFileVersion(TString filename)
virtual const char * GetType() const
to know what type of HistoConverter system it is
Definition: RADConverter.h:63