GammaWare  Head Version for release 0.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GPSIConverter.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_GPSICONVERTER_H
24 #include "GPSIConverter.h"
25 #endif
26 
27 #ifndef ROOT_TRegexp
28 #include <TRegexp.h>
29 #endif
30 
31 #ifndef ROOT_TSystem
32 #include <TSystem.h>
33 #endif
34 
35 #include <iostream>
36 using namespace std;
37 
38 namespace { GPSIConverter gGPSIConverter; } // prototype ONLY use to create a new DB system
39 
40 //__________________________________________________________________
42 {
43  // default for gpsi
44  fType = "gpsi";
45 
46  CheckDirectory(name);
47  fLog.GetProcessName() = "GPSIConverter";
48 }
49 
50 //__________________________________________________________________
51 void GPSIConverter::CheckDirectory(const char *name)
52 {
53  // Default for the header of the file
54  fHeader.fNbSpectra = 0;
55  fHeader.fFileSize = 0;
56 
57  // defaults for the sp headers
58  for (int i = 0; i < MAX_SP; i++) {
59  fHeader.fWhere[i] = 0;
60 
61  fLabel[i].fNx = 0;
62  fLabel[i].fNy = 0;
63  for (int j = 0; j < 12; j++) fLabel[i].fSpName[j] = 0;
64  }
65 
66  // chech if the file extension, if not set to zombie !
67  TString tmp = name;
68  if ( tmp.EndsWith(fFileExt) == kFALSE ) {
69  SetError(HistoConverter::kZombie,"extension must be .s for gpsi files !");
70  }
71  else {
72  // check out if this file can be read by trying to open it in reading mode
73  fStreamIN.open(name,ios::in);
74 
75  if ( fStreamIN.is_open() ) { // it already exist, load the header part and close it
76  // check out that the file length is the same length
77  // that is written in the header part. The reading of the header
78  // part also determined if swapping is needed
79  if ( ReadHeaders() == false ) {
80  fLog.GetProcessMethod() = "CheckDirectory(const char* )";
81  SetError(HistoConverter::kZombie,
82  "Problems when reading the header part");
83  }
84  fStreamIN.close();
85  }
86  else { // try to open an new file and init the header part.
87  fLog.GetProcessMethod() = "CheckDirectory(const char* )";
88  SetError(HistoConverter::kZombie,
89  "Currently, only possible to read existing gpsi files");
90  }
91  }
92 }
93 
94 //__________________________________________________________________
96 {
97  // default for gpsi
98  fType = "gpsi";
99  fFileExt = ".s";
100  fOptions = "";
101 
102  // add this interface to the DB service
103  AddPrototype(GetType(),this);
104 }
105 
106 //__________________________________________________________________
108 {
109  if ( fStreamIN.is_open() ) { fStreamIN.close(); }
110 }
111 
112 
113 
114 //__________________________________________________________________
115 HistoConverter *GPSIConverter::NewDB(const char *name) const
116 {
117  return new GPSIConverter(name);
118 }
119 
120 //__________________________________________________________________
121 bool GPSIConverter::ReadHeaders()
122 {
123  if ( fStreamIN.is_open() == false ) return false; // the file must be opened to read
124 
125  char tmp[512]; for (int i = 0; i < 512; i++) tmp[i] = 0;
126 
127  // determine the file size using seek
128  long real_size;
129  fStreamIN.seekg(0,ios::end); real_size = fStreamIN.tellg();
130  if ( real_size < 512*512 ) {
131  //SetError(HistoConverter::kFail,
132  // Form("[GPSIConverter::ReadHeaders] file too small to be a gpsi file %d",real_size)) ;
133  if ( gDebug > 0 ) {
134  fLog.GetProcessMethod() = "ReadHeaders()";
135  fLog << debug << "File too small to be a gpsi file"
136  << real_size
137  << nline;
138  }
139  return false;
140  }
141  // read the number of expected spectra, the expected file size
142  // and compare it to what is obtained before
143  // the coded value concerning the file size is in 512 units
144  // so the read size is obtained with: 512*(filesize-1)
145  short nbspectra1 = 0, nbspectra2 = 0; int filesize1 = 0, filesize2 = 0;
146 
147  fIsSwapping = false;
148  fStreamIN.seekg(0,ios::beg);
149  fStreamIN.read(tmp,2); nbspectra1 = Short(tmp);
150  fStreamIN.read(tmp,2); filesize1 = Short(tmp); filesize1 = 512*(filesize1-1);
151  fIsSwapping = true;
152  fStreamIN.seekg(0,ios::beg);
153  fStreamIN.read(tmp,2); nbspectra2 = Short(tmp);
154  fStreamIN.read(tmp,2); filesize2 = Short(tmp); filesize2 = 512*(filesize2-1);
155 
156  // check first if it is a good # of spectra
157  short which_swap = 0;
158  if ( 0 < nbspectra1 && nbspectra1 < 254 ) which_swap = 1;
159  if ( 0 < nbspectra2 && nbspectra2 < 254 ) which_swap = 2;
160 
161  if ( which_swap == 0 ) { // cannot be a gpsi file
162  //SetError(HistoConverter::kFail,
163  // "[GPSIConverter::ReadHeaders] # of spectra not in the range [1,253]");
164  if ( gDebug > 0 ) {
165  fLog.GetProcessMethod() = "ReadHeaders()";
166  fLog << error << "# of spectra not in the range [1,253]" << nline ;
167  }
168  return false;
169  }
170 
171  // check if the file size coded inside is the likely one.
172  // it doesn't check exactly because I have gpsi file that differ of 2 units
173  // from the real size ... maybe a PB with gpsi in Lyon. I've check that other
174  // gpsi files work properly
175  fIsSwapping = false;
176  if ( real_size == 512*512 ) { // not enough spectra to check filesize
177  if ( which_swap == 2 ) fIsSwapping = true;
178  }
179  else {
180  if ( (real_size-5) < filesize1 && filesize1 < (real_size+5) ) which_swap += 10;
181  if ( (real_size-5) < filesize2 && filesize2 < (real_size+5) ) which_swap += 20;
182 
183  if ( which_swap == 11 || which_swap == 22 ) {
184  if ( which_swap == 22 ) fIsSwapping = true;
185  }
186  else {
187  //SetError(HistoConverter::kFail,
188  // Form("[GPSIConverter::ReadHeaders] cannot determine endian type swap %d",which_swap));
189  if ( gDebug > 0 ) {
190  fLog.GetProcessMethod() = "ReadHeaders()";
191  fLog << error << "Cannot determine endian type swap " << which_swap << nline ;
192  }
193  return false;
194  }
195  } // else
196 
197  // now re-start reading from the beginning
198  fStreamIN.seekg(0,ios::beg);
199  fStreamIN.read(tmp,2); fHeader.fNbSpectra = Short(tmp);
200 
201  // read all sp headers
202  for (int i = 0; i < fHeader.fNbSpectra; i++ ) {
203 
204  // determine where is the header for spectrum #i
205  fStreamIN.seekg(2*i+4,ios::beg); fStreamIN.read(tmp,2); fHeader.fWhere[i] = Short(tmp);
206 
207  // read the header for spectrum #i
208  fStreamIN.seekg((fHeader.fWhere[i]-1)*512,ios::beg);
209  fStreamIN.read(tmp,512);
210 
211  unsigned short test_label1 = UShort(tmp);
212  unsigned short test_label2 = UShort(tmp+2);
213  if ( test_label1 != 0xFFFF || test_label2 != 0xFFFF ) {
214  //SetError(HistoConverter::kFail,
215  // Form("[GPSIConverter::ReadHeaders] SP #%d has an incorrect header .. probably not a gpsi file",i));
216  if ( gDebug > 0 ) {
217  fLog.GetProcessMethod() = "ReadHeaders()";
218  fLog << error << "SP #"
219  << i << " has an incorrect header .. probably not a gpsi file" << nline;
220  }
221  return false;
222  }
223  int len = Short(tmp+16) - 12;
224  strncpy(fLabel[i].fSpName, (tmp + 31), len);
225  fLabel[i].fNx = Short(tmp+70);
226  fLabel[i].fNy = Short(tmp+66);
227  }
228  return true;
229 }
230 
231 //__________________________________________________________________
232 void GPSIConverter::ls(Option_t *o) const
233 {
234  HistoConverter::ls(o);
235  cout << fHeader.fNbSpectra << " spectra found in the file " << endl;
236  for (int i = 0; i < fHeader.fNbSpectra; i++){
237  cout << " [" << i << "] " << fLabel[i].fSpName;
238 
239  /*
240  if ( fLabel[i].fNy == 1 )
241  cout << " - " << fLabel[i].fNx << " bins" ;
242  else
243  cout << " - " << fLabel[i].fNx << " bins_x " << fLabel[i].fNy << "bins_y"; */
244 
245  if ( (i+1) % 5 == 0 ) cout << endl;
246  else cout << "\t";
247  }
248  cout << endl;
249 }
250 
251 //__________________________________________________________________
252 TH1 *GPSIConverter::Get(int which)
253 {
254  if ( which < 0 || which >= fHeader.fNbSpectra ) return NULL;
255  else return Get(fLabel[which].fSpName);
256 }
257 
258 //__________________________________________________________________
259 TH1 *GPSIConverter::Get(const char *name)
260 {
261  TH1F *h = new TH1F();
262 
263  h->SetName(name);
264  if ( !Read((*h)) ) { delete h; h = NULL; }
265 
266  return h;
267 }
268 
269 //__________________________________________________________________
271 {
272  bool ok = false; TString hname = h.GetName();
273 
274  // look for a spectrum with a similar name in the list of labels
275  int which = -1 ;
276  for (int i = 0; i < fHeader.fNbSpectra; i++ ) {
277  if ( hname.CompareTo(fLabel[i].fSpName) == 0 ) {
278  h.SetBins(fLabel[i].fNx*fLabel[i].fNy,0,fLabel[i].fNx*fLabel[i].fNy); which = i; break;
279  }
280  }
281  if ( which == -1 ) {
282  fLog.GetProcessMethod() = "Read(TH1&)";
283  SetError(HistoConverter::kFail,
284  Form("SP %s not found",h.GetName()));
285  return false;
286  } // not in this file
287 
288  // now read the spectrum from the file
289  fStreamIN.clear(); fStreamIN.open(fName.Data(),ios::in);
290  if ( fStreamIN.is_open() ) {
291  // move to the good postion and read
292  char *tmp = new char[4*fLabel[which].fNx*fLabel[which].fNy];
293  if (tmp == NULL) return false;
294 
295  fStreamIN.seekg(fHeader.fWhere[which]*512,ios::beg);
296  fStreamIN.read(tmp,4*fLabel[which].fNx*fLabel[which].fNy);
297 
298  if ( fStreamIN.good() ) {
299  for ( int i = 0; i < fLabel[which].fNx*fLabel[which].fNy; i++ )
300  h.Fill(i,Float(tmp+4*i)) ;
301  ok = true;
302  }
303  fStreamIN.close(); delete [] tmp;
304  }
305  else { ok = false; }
306 
307  return ok;
308 }
309 
310 //__________________________________________________________________
311 bool GPSIConverter::Write(const TH1 &/*h*/)
312 {
313  fLog.GetProcessMethod() = "Write(const TH1&)";
314  SetError(HistoConverter::kFail,
315  "CANNOT WRITE - gpsi is a deprecated DB system"); return false;
316 }
317 
318 //__________________________________________________________________
319 bool GPSIConverter::Read(TH2 &/*h*/)
320 {
321  fLog.GetProcessMethod() = "Read(TH2&)";
322  SetError(HistoConverter::kFail,
323  "NO IMPLEMENTATION !!") ; return false;
324 }
325 
326 //__________________________________________________________________
327 bool GPSIConverter::Write(const TH2 &/*h*/)
328 {
329  fLog.GetProcessMethod() = "Write(const TH2&)";
330  SetError(HistoConverter::kFail,
331  "CANNOT WRITE - gpsi is a deprecated DB system"); return false;
332 }
333 
334 //__________________________________________________________________
335 bool GPSIConverter::Read(THStack &hs)
336 {
337  TString tmphs = hs.GetName();
338  // pattern expression
339  Bool_t wildcard = false;
340  if ( tmphs.Contains("*") )
341  wildcard = true;
342  TRegexp all("*",kTRUE), pattern(hs.GetName(),wildcard);
343 
344  if ( pattern.Status() != TRegexp::kOK ) {
345  if ( gDebug > 0 ) cerr << "pattern * " << hs.GetName() << endl ;
346  pattern = all;
347  }
348  else { if ( gDebug > 0 ) cerr << "pattern " << hs.GetName() << endl ; }
349 
350  TH1 *h;
351  for (int i = 0; i < fHeader.fNbSpectra; i++ ) {
352 
353  h = NULL;
354 
355  if ( gDebug > 0 ) {
356  fLog.GetProcessMethod() = "Read(THStack&)";
357  fLog << debug << "Comparing " << fLabel[i].fSpName << " ..";
358  }
359  TString tmp;
360  tmp = fLabel[i].fSpName;
361  if ( tmp.Contains(pattern) ) h = Get(fLabel[i].fSpName);
362 
363  // if a new spectrum, add it to the stack
364  if ( h ) { hs.Add(h); if ( gDebug > 0 ) cerr << " IN STACK " << endl; }
365  else { if ( gDebug > 0 ) cerr << " NOT IN STACK " << endl; }
366  }
367  return true;
368 }
369 
370 //__________________________________________________________________
371 bool GPSIConverter::Write(const THStack &/*hs*/)
372 {
373  fLog.GetProcessMethod() = "Write(const TH1&)";
374  SetError(HistoConverter::kFail,
375  "CANNOT WRITE - gpsi is a deprecated DB system"); return false;
376 }
377 
void SetError(HistoConverter::EStatus status=kGood, const char *msgerror="")
to set/reset the status of this converter
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 &)
virtual bool Write(const TH1 &)
to write an histogram
virtual const char * GetType() const
to know what type of HistoConverter system it is
Definition: GPSIConverter.h:77
virtual void ls(Option_t *) const
to show the spectra in this DB system on the standard output
unsigned short UShort(char *buf)
virtual bool Read(TH1 &)
to read an histogram
virtual HistoConverter * NewDB(const char *) const
to creat a new DB system
virtual ~GPSIConverter()
LogMessage & debug(LogMessage &)
virtual std::string & GetProcessName()
To get the Process name.
Definition: GwLogMessage.h:224
ADF::LogMessage & endl(ADF::LogMessage &log)
#define MAX_SP
Definition: GPSIConverter.h:9
virtual TH1 * Get(int)
to get histo number i in the list
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