Monarch  v3.8.2
Project 8 Data File Format Library
M3Header.cc
Go to the documentation of this file.
1 /*
2 
3  * M3Header.cc
4  *
5  * Created on: Dec 4, 2014
6  * Author: nsoblath
7  */
8 
9 #define M3_API_EXPORTS
10 #define hdf5_EXPORTS
11 
12 #include "M3Header.hh"
13 
14 #include "M3IToA.hh"
15 #include "logger.hh"
16 #include "M3Version.hh"
17 
18 #include <cstdlib> // for atol in parsing timestamp
19 #include <cstring> // for strcpy
20 
21 // for parsing timestamp
22 #include <sstream>
23 using std::stringstream;
24 using std::string;
25 
26 namespace monarch3
27 {
28  LOGGER( mlog, "M3Header" );
29 
30  //*********************
31  // M3StreamHeader
32  //*********************
33 
35  fLabel( NULL ),
36  fNumber( 0 ),
37  fSource(),
38  fNChannels( 0 ),
39  fChannels(),
40  fChannelFormat( sSeparate ),
41  fAcquisitionRate( 0 ),
42  fRecordSize( 0 ),
43  fSampleSize( 0 ),
44  fDataTypeSize( 0 ),
45  fDataFormat( sDigitizedUS ),
46  fBitDepth( 0 ),
47  fBitAlignment( sBitsAlignedLeft ),
48  fNAcquisitions( 0 ),
49  fNRecords( 0 )
50  {
51  }
52 
53  M3StreamHeader::M3StreamHeader( const std::string& aSource, uint32_t aNumber, uint32_t aNChannels, uint32_t aFirstChannel, uint32_t aFormat,
54  uint32_t anAcqRate, uint32_t aRecSize, uint32_t aSampleSize,
55  uint32_t aDataTypeSize, uint32_t aDataFormat,
56  uint32_t aBitDepth, uint32_t aBitAlignment ) :
57  fLabel( NULL ),
58  fNumber( 0 ),
59  fSource( aSource ),
60  fNChannels( aNChannels ),
61  fChannels( aNChannels ),
62  fChannelFormat( aFormat ),
63  fAcquisitionRate( anAcqRate ),
64  fRecordSize( aRecSize ),
65  fSampleSize( aSampleSize ),
66  fDataTypeSize( aDataTypeSize ),
67  fDataFormat( aDataFormat ),
68  fBitDepth( aBitDepth ),
69  fBitAlignment( aBitAlignment ),
70  fNAcquisitions( 0 ),
71  fNRecords( 0 )
72  {
73  SetNumber( aNumber );
74  for( unsigned iChannel = 0; iChannel < fNChannels; ++iChannel )
75  {
76  fChannels[ iChannel ] = aFirstChannel + iChannel;
77  }
78  }
79 
81  fLabel( NULL ),
82  fNumber( 0 ),
83  fSource( orig.fSource ),
84  fNChannels( orig.fNChannels ),
85  fChannels( orig.fChannels ),
86  fChannelFormat( orig.fChannelFormat ),
87  fAcquisitionRate( orig.fAcquisitionRate ),
88  fRecordSize( orig.fRecordSize ),
89  fSampleSize( orig.fSampleSize ),
90  fDataTypeSize( orig.fDataTypeSize ),
91  fDataFormat( orig.fDataFormat ),
92  fBitDepth( orig.fBitDepth ),
93  fBitAlignment( orig.fBitAlignment ),
94  fNAcquisitions( orig.fNAcquisitions ),
95  fNRecords( orig.fNRecords )
96  {
97  SetNumber( orig.fNumber );
98  }
99 
101  {
102  delete [] fLabel;
103  }
104 
105  void M3StreamHeader::SetNumber( uint32_t aNumber ) const
106  {
107  fNumber = aNumber;
108 
109  static const size_t prefixSize = 6; // # of characters in "stream"
110  delete [] fLabel;
111  fLabel = new char[ prefixSize + 10 ]; // 10 = max digits in 32-bit integer
112  strcpy( fLabel, "stream" );
113  u32toa( aNumber, fLabel + prefixSize );
114 
115  return;
116  }
117 
118  void M3StreamHeader::WriteToHDF5( HAS_GRP_IFC* aParent )
119  {
120  LDEBUG( mlog, "Writing stream <" << fLabel << ">" );
121  H5::Group tThisStreamGroup = aParent->createGroup( fLabel );
122 
123  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "number", fNumber );
124  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "source", fSource );
125  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "n_channels", fNChannels );
126  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "channel_format", fChannelFormat );
127  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "acquisition_rate", fAcquisitionRate );
128  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "record_size", fRecordSize );
129  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "sample_size", fSampleSize );
130  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "data_type_size", fDataTypeSize );
131  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "data_format", fDataFormat );
132  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "bit_depth", fBitDepth );
133  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "bit_alignment", fBitAlignment );
134  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "n_acquisitions", fNAcquisitions );
135  M3Header::WriteScalarToHDF5( &tThisStreamGroup, "n_records", fNRecords );
136 
137  WriteChannels( &tThisStreamGroup );
138 
139  return;
140  }
141 
142  void M3StreamHeader::ReadFromHDF5( const HAS_GRP_IFC* aParent, const std::string& aLabel ) const
143  {
144  LDEBUG( mlog, "Reading stream <" << aLabel << ">" );
145  H5::Group tThisStreamGroup = aParent->openGroup( aLabel.c_str() );
146 
147  SetNumber( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "number" ) );
148  Source() = M3Header::ReadScalarFromHDF5< string >( &tThisStreamGroup, "source" );
149  SetNChannels( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "n_channels" ) );
150  SetChannelFormat( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "channel_format" ) );
151  SetAcquisitionRate( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "acquisition_rate" ) );
152  SetRecordSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "record_size" ) );
153  SetSampleSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "sample_size" ) );
154  SetDataTypeSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "data_type_size" ) );
155  SetDataFormat( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "data_format" ) );
156  SetBitDepth( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "bit_depth" ) );
157  SetBitAlignment( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "bit_alignment", fBitAlignment ) );
158  SetNAcquisitions( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "n_acquisitions" ) );
159  SetNRecords( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisStreamGroup, "n_records" ) );
160 
161  ReadChannels( &tThisStreamGroup );
162 
163  return;
164  }
165 
166  void M3StreamHeader::WriteChannels( HAS_ATTR_IFC* aLoc )
167  {
168  const unsigned tNDims = 1;
169  hsize_t tDims[ tNDims ] = { fNChannels };
170 
171  H5::DataSpace tDataspace( tNDims, tDims );
172  //H5::DataSet tDataset = aLoc->createDataSet( "channels", MH5Type< uint32_t >::H5(), tDataspace );
173  H5::Attribute tAttr = aLoc->createAttribute( "channels", MH5Type< uint32_t >::H5(), tDataspace );
174 
175  uint32_t* tCSBuffer = new uint32_t[ fNChannels ];
176  for( unsigned i = 0; i < fNChannels; ++i )
177  {
178  tCSBuffer[ i ] = fChannels[ i ];
179  }
180 
181  //tDataset.write( tCSBuffer, MH5Type< uint32_t >::Native(), tDataspace );
182  tAttr.write( MH5Type< uint32_t >::Native(), tCSBuffer );
183 
184  delete [] tCSBuffer;
185 
186  return;
187  }
188 
189  void M3StreamHeader::ReadChannels( const HAS_ATTR_IFC* aLoc ) const
190  {
191  const unsigned tNDims = 1;
192  hsize_t tDims[ tNDims ];
193 
194  //H5::DataSet tDataset = aLoc->openDataSet( "channels" );
195  H5::Attribute tAttr = aLoc->openAttribute( "channels" );
196  //H5::DataSpace tDataspace( tDataset.getSpace() );
197  H5::DataSpace tDataspace( tAttr.getSpace() );
198  tDataspace.getSimpleExtentDims( tDims );
199 
200  if( tDims[ 0 ] != fNChannels )
201  {
202  LERROR( mlog, "Channels dataset dimensions (" << tDims[ 0 ] << ") do not match number of channels, " << fNChannels );
203  return;
204  }
205 
206  uint32_t* tCSBuffer = new uint32_t[ fNChannels ];
207  //tDataset.read( tCSBuffer, MH5Type< uint32_t >::Native(), tDataspace );
208  tAttr.read( MH5Type< uint32_t >::Native(), tCSBuffer );
209 
210  fChannels.clear();
211  fChannels.resize( fNChannels );
212  for( unsigned i = 0; i < fNChannels; ++i )
213  {
214  fChannels[ i ] = tCSBuffer[ i ];
215  }
216 
217  delete [] tCSBuffer;
218 
219  return;
220  }
221 
222  //*********************
223  // M3ChannelHeader
224  //*********************
225 
227  fLabel( NULL ),
228  fNumber( 0 ),
229  fSource(),
230  fAcquisitionRate( 0 ),
231  fRecordSize( 0 ),
232  fSampleSize( 0 ),
233  fDataTypeSize( 0 ),
234  fDataFormat( sDigitizedUS ),
235  fBitDepth( 0 ),
236  fBitAlignment( sBitsAlignedLeft ),
237  fVoltageOffset( 0. ),
238  fVoltageRange( 0. ),
239  fDACGain( 0. ),
240  fFrequencyMin( 0. ),
241  fFrequencyRange( 0. )
242  {
243  }
244 
245  M3ChannelHeader::M3ChannelHeader( const std::string& aSource, uint32_t aNumber,
246  uint32_t anAcqRate, uint32_t aRecSize, uint32_t aSampleSize,
247  uint32_t aDataTypeSize, uint32_t aDataFormat,
248  uint32_t aBitDepth, uint32_t aBitAlignment ) :
249  fLabel( NULL ),
250  fNumber( 0 ),
251  fSource( aSource ),
252  fAcquisitionRate( anAcqRate ),
253  fRecordSize( aRecSize ),
254  fSampleSize( aSampleSize ),
255  fDataTypeSize( aDataTypeSize ),
256  fDataFormat( aDataFormat ),
257  fBitDepth( aBitDepth ),
258  fBitAlignment( aBitAlignment ),
259  fVoltageOffset( 0. ),
260  fVoltageRange( 0. ),
261  fDACGain( 0. ),
262  fFrequencyMin( 0. ),
263  fFrequencyRange( 0. )
264  {
265  SetNumber( aNumber );
266  }
267 
269  fLabel( NULL ),
270  fNumber( 0 ),
271  fSource( orig.fSource ),
272  fAcquisitionRate( orig.fAcquisitionRate ),
273  fRecordSize( orig.fRecordSize ),
274  fSampleSize( orig.fSampleSize ),
275  fDataTypeSize( orig.fDataTypeSize ),
276  fDataFormat( orig.fDataFormat ),
277  fBitDepth( orig.fBitDepth ),
278  fBitAlignment( orig.fBitAlignment ),
279  fVoltageOffset( orig.fVoltageOffset ),
280  fVoltageRange( orig.fVoltageRange ),
281  fDACGain( orig.fDACGain ),
282  fFrequencyMin( orig.fFrequencyMin ),
283  fFrequencyRange( orig.fFrequencyRange )
284  {
285  SetNumber( orig.fNumber );
286  }
287 
289  {
290  delete [] fLabel;
291  }
292 
293  void M3ChannelHeader::SetNumber( uint32_t aNumber ) const
294  {
295  fNumber = aNumber;
296 
297  static const size_t prefixSize = 7; // # of characters in "channel"
298  delete [] fLabel;
299  fLabel = new char[ prefixSize + 10 ]; // 10 = max digits in 32-bit integer
300  strcpy( fLabel, "channel" );
301  u32toa( aNumber, fLabel + prefixSize );
302 
303  return;
304  }
305 
306  void M3ChannelHeader::WriteToHDF5( HAS_GRP_IFC* aParent )
307  {
308  LDEBUG( mlog, "Writing channel <" << fLabel << ">" );
309  H5::Group tThisChannelGroup = aParent->createGroup( fLabel );
310 
311  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "number", fNumber );
312  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "source", fSource );
313  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "acquisition_rate", fAcquisitionRate );
314  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "record_size", fRecordSize );
315  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "sample_size", fSampleSize );
316  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "data_type_size", fDataTypeSize );
317  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "data_format", fDataFormat );
318  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "bit_depth", fBitDepth );
319  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "bit_alignment", fBitAlignment );
320  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "voltage_offset", fVoltageOffset );
321  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "voltage_range", fVoltageRange );
322  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "dac_gain", fDACGain );
323  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "frequency_min", fFrequencyMin );
324  M3Header::WriteScalarToHDF5( &tThisChannelGroup, "frequency_range", fFrequencyRange );
325 
326  return;
327  }
328 
329  void M3ChannelHeader::ReadFromHDF5( const HAS_GRP_IFC* aParent, const std::string& aLabel ) const
330  {
331  LDEBUG( mlog, "Reading channel <" << aLabel << ">" );
332  H5::Group tThisChannelGroup = aParent->openGroup( aLabel.c_str() );
333 
334  SetNumber( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "number" ) );
335  Source() = M3Header::ReadScalarFromHDF5< string >( &tThisChannelGroup, "source" );
336  SetAcquisitionRate( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "acquisition_rate" ) );
337  SetRecordSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "record_size" ) );
338  SetSampleSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "sample_size" ) );
339  SetDataTypeSize( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "data_type_size" ) );
340  SetDataFormat( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "data_format" ) );
341  SetBitDepth( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "bit_depth" ) );
342  SetBitAlignment( M3Header::ReadScalarFromHDF5< uint32_t >( &tThisChannelGroup, "bit_alignment", fBitAlignment ) );
343  SetVoltageOffset( M3Header::ReadScalarFromHDF5< double >( &tThisChannelGroup, "voltage_offset" ) );
344  SetVoltageRange( M3Header::ReadScalarFromHDF5< double >( &tThisChannelGroup, "voltage_range" ) );
345  SetDACGain( M3Header::ReadScalarFromHDF5< double >( &tThisChannelGroup, "dac_gain" ) );
346  SetFrequencyMin( M3Header::ReadScalarFromHDF5< double >( &tThisChannelGroup, "frequency_min" ) );
347  SetFrequencyRange( M3Header::ReadScalarFromHDF5< double >( &tThisChannelGroup, "frequency_range" ) );
348 
349  return;
350  }
351 
352 
353  //*********************
354  // M3Header
355  //*********************
356 
358  fEggVersion( TOSTRING(Egg_VERSION) ),
359  fFilename(),
360  fRunDuration( 0 ),
361  fTimestamp(),
362  fDescription(),
363  fNChannels( 0 ),
364  fNStreams( 0 ),
365  fChannelStreams(),
366  fChannelCoherence(),
367  fFile( NULL ),
368  fStreamsGroup( NULL ),
369  fChannelsGroup( NULL )
370  {
371  }
372 
374  {
375  delete fStreamsGroup;
376  delete fChannelsGroup;
377  }
378 
379  void M3Header::CopyBasicInfo( const M3Header& aOrig )
380  {
381  fEggVersion = aOrig.fEggVersion;
382  fFilename = aOrig.fFilename;
383  fRunDuration = aOrig.fRunDuration;
384  fTimestamp = aOrig.fTimestamp;
385  fDescription = aOrig.fDescription;
386  return;
387  }
388 
389  void M3Header::SetCoherence( unsigned aChanA, unsigned aChanB, bool aCoherence )
390  {
391  if( aChanA >= fNChannels || aChanB >= fNChannels )
392  {
393  throw M3Exception() << "Channel out of bounds: " << aChanA << " or " << aChanB << " >= " << fNChannels;
394  }
395  fChannelCoherence[ aChanA ][ aChanB ] = aCoherence;
396  fChannelCoherence[ aChanB ][ aChanA ] = aCoherence;
397  return;
398  }
399 
400  uint32_t M3Header::AddStream( const std::string& aSource,
401  uint32_t anAcqRate, uint32_t aRecSize, uint32_t aSampleSize,
402  uint32_t aDataTypeSize, uint32_t aDataFormat,
403  uint32_t aBitDepth, uint32_t aBitAlignment,
404  std::vector< unsigned >* aChanVec )
405  {
406  LDEBUG( mlog, "Adding stream " << fNStreams << " for channel " << fNChannels << " with record size " << aRecSize );
407  if( aChanVec != NULL ) aChanVec->push_back( fNChannels );
408  fChannelStreams.push_back( fNStreams );
409  fChannelHeaders.push_back( M3ChannelHeader( aSource, fNChannels, anAcqRate, aRecSize, aSampleSize, aDataTypeSize, aDataFormat, aBitDepth, aBitAlignment ) );
410  fStreamHeaders.push_back( M3StreamHeader( aSource, fNStreams, 1, fNChannels, sSeparate, anAcqRate, aRecSize, aSampleSize, aDataTypeSize, aDataFormat, aBitDepth, aBitAlignment ) );
411  ++fNChannels;
412  //std::cout << "resizing to " << fNChannels << std::endl;
413  fChannelCoherence.resize( fNChannels ); // resize number of columns
414  for( unsigned i = 0; i < fNChannels; ++i ) // resize each row
415  {
416  fChannelCoherence[ i ].resize( fNChannels, false );
417  }
418  fChannelCoherence.back().back() = true; // each channel is coherent with itself
419  return fNStreams++;
420  }
421 
422  uint32_t M3Header::AddStream( const std::string& aSource, uint32_t aNChannels, uint32_t aFormat,
423  uint32_t anAcqRate, uint32_t aRecSize, uint32_t aSampleSize,
424  uint32_t aDataTypeSize, uint32_t aDataFormat,
425  uint32_t aBitDepth, uint32_t aBitAlignment,
426  std::vector< unsigned >* aChanVec )
427  {
428  LDEBUG( mlog, "Adding stream " << fNStreams << " for multiple channels with record size " << aRecSize );
429  unsigned tFirstNewChannel = fNChannels;
430  for( uint32_t iNewChannel = 0; iNewChannel < aNChannels; ++iNewChannel )
431  {
432  LDEBUG( mlog, "Adding channel " << fNChannels );
433  if( aChanVec != NULL ) aChanVec->push_back( fNChannels );
434  fChannelStreams.push_back( fNStreams );
435  fChannelHeaders.push_back( M3ChannelHeader( aSource, fNChannels, anAcqRate, aRecSize, aSampleSize, aDataTypeSize, aDataFormat, aBitDepth, aBitAlignment ) );
436  ++fNChannels;
437  fChannelCoherence.resize( fNChannels ); // resize number of columns
438  for( unsigned i = 0; i < fNChannels; ++i ) // resize all rows
439  {
440  fChannelCoherence[ i ].resize( fNChannels, false );
441  }
442  fChannelCoherence.back().back() = true; // each channel is coherent with itself
443  if( fNChannels > 0 ) // this condition is necessary because if it's not the case, fNChannels-1 will be some huge number, since we're dealing with unsigned ints, so the for-loop condition won't be sufficient
444  {
445  for( unsigned i = tFirstNewChannel; i < fNChannels - 1; ++i )
446  {
447  fChannelCoherence[ fNChannels - 1 ][ i ] = true;
448  fChannelCoherence[ i ][ fNChannels - 1 ] = true;
449  }
450  }
451  }
452  fStreamHeaders.push_back( M3StreamHeader( aSource, fNStreams, aNChannels, tFirstNewChannel, aFormat, anAcqRate, aRecSize, aSampleSize, aDataTypeSize, aDataFormat, aBitDepth, aBitAlignment ) );
453  return fNStreams++;
454  }
455 
456  void M3Header::WriteToHDF5( H5::H5File* aFile )
457  {
458  try
459  {
460  LDEBUG( mlog, "Writing run header" );
461  fFile = aFile;
462  WriteScalarToHDF5( fFile, "egg_version", fEggVersion );
463  WriteScalarToHDF5( fFile, "filename", fFilename );
464  WriteScalarToHDF5( fFile, "n_channels", fNChannels );
465  WriteScalarToHDF5( fFile, "n_streams", fNStreams );
466  WriteScalarToHDF5( fFile, "run_duration", fRunDuration );
467  WriteScalarToHDF5( fFile, "timestamp", fTimestamp );
468  WriteScalarToHDF5( fFile, "description", fDescription );
472 
473  LDEBUG( mlog, "Writing stream headers" );
474  fStreamsGroup = new H5::Group( fFile->createGroup( "streams" ) );
475  for( uint32_t iStream = 0; iStream < fNStreams; ++iStream )
476  {
477  fStreamHeaders[ iStream ].WriteToHDF5( fStreamsGroup );
478  }
479 
480  LDEBUG( mlog, "Writing channel headers" );
481  fChannelsGroup = new H5::Group( fFile->createGroup( "channels" ) );
482  for( uint32_t iChan = 0; iChan < fNChannels; ++iChan )
483  {
484  fChannelHeaders[ iChan ].WriteToHDF5( fChannelsGroup );
485  }
486  }
487  catch( H5::Exception& e )
488  {
489  throw M3Exception() << "HDF5 error while writing header: " << e.getCDetailMsg();
490  }
491  catch( M3Exception& e )
492  {
493  LDEBUG( mlog, "M3Exception: " << e.what() );
494  throw;
495  }
496 
497  return;
498  }
499 
500  void M3Header::ReadFromHDF5( const H5::H5File* aFile ) const
501  {
502  try
503  {
504  LDEBUG( mlog, "Reading run header" );
505  fFile = const_cast< H5::H5File* >( aFile );
506  EggVersion() = ReadScalarFromHDF5< string >( fFile, string("egg_version") );
507  Filename() = ReadScalarFromHDF5< string >( fFile, "filename" );
508  SetNChannels( ReadScalarFromHDF5< uint32_t >( fFile, "n_channels" ) );
509  SetNStreams( ReadScalarFromHDF5< uint32_t >( fFile, "n_streams" ) );
510  SetRunDuration( ReadScalarFromHDF5< uint32_t >( fFile, "run_duration" ) );
511  Timestamp() = ReadScalarFromHDF5< string >( fFile, "timestamp" );
512  Description() = ReadScalarFromHDF5< string >( fFile, "description" );
513 
514  //fChannelStreams.clear();
515  //Read1DFromHDF5< std::vector< uint32_t > >( fFile, "channel_streams", fChannelStreams );
516  ReadChannelStreams( aFile );
517  ReadChannelCoherence( aFile );
518  /*
519  for( unsigned i = 0; i < fNChannels; ++i )
520  {
521  std::cout << " ";
522  for( unsigned j = 0; j < fNChannels; ++j )
523  {
524  std::cout << fChannelCoherence[ i ][ j ] << " ";
525  }
526  std::cout << std::endl;
527  }
528  */
529 
530  // Windows' HDF5 really doesn't like using std::strings
531  const unsigned tBuffSize = 256;
532  char tBuffer[ tBuffSize ];
533 
534  LDEBUG( mlog, "Reading stream headers" );
535  fStreamHeaders.clear();
536  fStreamsGroup = new H5::Group( fFile->openGroup( "streams" ) );
537  hsize_t nStreams = fStreamsGroup->getNumObjs();
538  if( nStreams != fNStreams )
539  {
540  throw M3Exception() << "Number of streams <" << fNStreams << "> disagrees with the number of objects in the stream group <" << nStreams << ">";
541  }
542  for( hsize_t iStream = 0; iStream < nStreams; ++iStream )
543  {
544  //string tStreamLabel = fStreamsGroup->getObjnameByIdx( iStream );
545  unsigned tLabelSize = fStreamsGroup->getObjnameByIdx( iStream, tBuffer, tBuffSize );
546  std::string tStreamLabel( tBuffer, tLabelSize );
547  LDEBUG( mlog, "Attempting to read stream header #" << iStream << "; label <" << tStreamLabel << ">" );
548  fStreamHeaders.push_back( M3StreamHeader() );
549  LDEBUG( mlog, "Testing if we can access the last header: " << fStreamHeaders.back().GetLabel() );
550  fStreamHeaders.back().ReadFromHDF5( fStreamsGroup, tStreamLabel );
551  }
552 
553  LDEBUG( mlog, "Reading channel headers" );
554  fChannelHeaders.clear();
555  fChannelsGroup = new H5::Group( fFile->openGroup( "channels" ) );
556  hsize_t nChannels = fChannelsGroup->getNumObjs();
557  for( hsize_t iChan = 0; iChan < nChannels; ++iChan )
558  {
559  //string tChannelLabel = fChannelsGroup->getObjnameByIdx( iChan );
560  unsigned tLabelSize = fChannelsGroup->getObjnameByIdx( iChan, tBuffer, tBuffSize );
561  std::string tChannelLabel( tBuffer, tLabelSize );
562  fChannelHeaders.push_back( M3ChannelHeader() );
563  fChannelHeaders.back().ReadFromHDF5( fChannelsGroup, tChannelLabel );
564  }
565  }
566  catch( H5::Exception& e )
567  {
568  //H5::Exception::printErrorStack();
569  throw M3Exception() << "Unable to open header group or find header data\n";
570  }
571  return;
572  }
573 
574  void M3Header::WriteChannelStreams( HAS_ATTR_IFC* aLoc )
575  {
576  const unsigned tNDims = 1;
577  hsize_t tDims[ tNDims ] = { fNChannels };
578 
579  H5::DataSpace tDataspace( tNDims, tDims );
580  //H5::DataSet tDataset = aLoc->createDataSet( "channel_streams", MH5Type< uint32_t >::H5(), tDataspace );
581  H5::Attribute tAttr = aLoc->createAttribute( "channel_streams", MH5Type< uint32_t >::H5(), tDataspace );
582 
583  uint32_t* tCSBuffer = new uint32_t[ fNChannels ];
584  for( unsigned i = 0; i < fNChannels; ++i )
585  {
586  tCSBuffer[ i ] = fChannelStreams[ i ];
587  }
588 
589  //tDataset.write( tCSBuffer, MH5Type< uint32_t >::Native(), tDataspace );
590  tAttr.write( MH5Type< uint32_t >::Native(), tCSBuffer );
591 
592  delete [] tCSBuffer;
593 
594  return;
595  }
596 
597  void M3Header::ReadChannelStreams( const HAS_ATTR_IFC* aLoc ) const
598  {
599  const unsigned tNDims = 1;
600  hsize_t tDims[ tNDims ];
601 
602  //H5::DataSet tDataset = aLoc->openDataSet( "channel_streams" );
603  H5::Attribute tAttr = aLoc->openAttribute( "channel_streams" );
604  //H5::DataSpace tDataspace( tDataset.getSpace() );
605  H5::DataSpace tDataspace( tAttr.getSpace() );
606  tDataspace.getSimpleExtentDims( tDims );
607 
608  if( tDims[ 0 ] != fNChannels )
609  {
610  LERROR( mlog, "Channel-streams dataset dimensions (" << tDims[ 0 ] << ") do not match number of channels, " << fNChannels );
611  return;
612  }
613 
614  uint32_t* tCSBuffer = new uint32_t[ fNChannels ];
615  //tDataset.read( tCSBuffer, MH5Type< uint32_t >::Native(), tDataspace );
616  tAttr.read( MH5Type< uint32_t >::Native(), tCSBuffer );
617 
618  fChannelStreams.clear();
619  fChannelStreams.resize( fNChannels );
620  for( unsigned i = 0; i < fNChannels; ++i )
621  {
622  fChannelStreams[ i ] = tCSBuffer[ i ];
623  }
624 
625  delete [] tCSBuffer;
626 
627  return;
628  }
629 
630  void M3Header::WriteChannelCoherence( HAS_ATTR_IFC* aLoc )
631  {
632  const unsigned tNDims = 2;
633  hsize_t tDims[ tNDims ] = { fNChannels, fNChannels };
634 
635  H5::DataSpace tDataspace( tNDims, tDims );
636  //H5::DataSet tDataset = aLoc->createDataSet( "channel_coherence", MH5Type< bool >::H5(), tDataspace );
637  H5::Attribute tAttr = aLoc->createAttribute( "channel_coherence", MH5Type< bool >::H5(), tDataspace );
638 
639  uint8_t* tCCBuffer = new uint8_t[ fNChannels * fNChannels ];
640  for( unsigned i = 0; i < fNChannels; ++i )
641  {
642  for( unsigned j = 0; j < fNChannels; ++j )
643  {
644  tCCBuffer[ i * fNChannels + j ] = (uint8_t)fChannelCoherence[ i ][ j ];
645  }
646  }
647 
648  //tDataset.write( tCCBuffer, MH5Type< bool >::Native(), tDataspace );
649  tAttr.write( MH5Type< bool >::Native(), tCCBuffer );
650 
651  delete [] tCCBuffer;
652 
653  return;
654  }
655 
656  void M3Header::ReadChannelCoherence( const HAS_ATTR_IFC* aLoc ) const
657  {
658  const unsigned tNDims = 2;
659  hsize_t tDims[ tNDims ];
660 
661  //H5::DataSet tDataset = aLoc->openDataSet( "channel_coherence" );
662  H5::Attribute tAttr = aLoc->openAttribute( "channel_coherence" );
663  //H5::DataSpace tDataspace( tDataset.getSpace() );
664  H5::DataSpace tDataspace( tAttr.getSpace() );
665  tDataspace.getSimpleExtentDims( tDims );
666 
667  if( tDims[ 0 ] != fNChannels || tDims[ 1 ] != fNChannels )
668  {
669  LERROR( mlog, "Channel coherence dataset dimensions (" << tDims[ 0 ] << ", " << tDims[ 1 ] << ") do not match number of channels, " << fNChannels );
670  return;
671  }
672 
673  uint8_t* tCCBuffer = new uint8_t[ fNChannels * fNChannels ];
674  //tDataset.read( tCCBuffer, MH5Type< bool >::Native(), tDataspace );
675  tAttr.read( MH5Type< bool >::Native(), tCCBuffer );
676 
677  fChannelCoherence.clear();
678  fChannelCoherence.resize( fNChannels );
679  for( unsigned i = 0; i < fNChannels; ++i )
680  {
681  fChannelCoherence[ i ].resize( fNChannels );
682  for( unsigned j = 0; j < fNChannels; ++j )
683  {
684  fChannelCoherence[ i ][ j ] = (bool)tCCBuffer[ i * fNChannels + j ];
685  }
686  }
687 
688  delete [] tCCBuffer;
689 
690  return;
691  }
692 
693 }
694 
695 M3_API std::ostream& operator<<( std::ostream& out, const monarch3::M3StreamHeader& hdr )
696 {
697  out << "Stream Header Content:\n";
698  out << "\tStream Number: " << hdr.GetNumber() << '\n';
699  out << "\tSource: " << hdr.Source() << '\n';
700  out << "\tNumber of Channels: " << hdr.GetNChannels() << '\n';
701  out << "\tChannel Format: " << hdr.GetChannelFormat() << '\n';
702  out << "\tAcquisition Rate: " << hdr.GetAcquisitionRate() << " MHz\n";
703  out << "\tRecord Size: " << hdr.GetRecordSize() << " samples\n";
704  out << "\tSample Size: " << hdr.GetSampleSize() << " elements\n";
705  out << "\tData Type Size: " << hdr.GetDataTypeSize() << " bytes\n";
706  out << "\tData Format: " << hdr.GetDataFormat() << '\n';
707  out << "\tBit Depth: " << hdr.GetBitDepth() << " bits\n";
708  out << "\tBit Alignment: " << hdr.GetBitAlignment() << '\n';
709  out << "\tNumber of Acquisitions: " << hdr.GetNAcquisitions() << '\n';
710  out << "\tNumber of Records: " << hdr.GetNRecords() << '\n';
711  return out;
712 }
713 
714 M3_API std::ostream& operator<<( std::ostream& out, const monarch3::M3ChannelHeader& hdr )
715 {
716  out << "Channel Header Content:\n";
717  out << "\tChannel Number: " << hdr.GetNumber() << '\n';
718  out << "\tSource: " << hdr.Source() << '\n';
719  out << "\tAcquisition Rate: " << hdr.GetAcquisitionRate() << " MHz\n";
720  out << "\tRecord Size: " << hdr.GetRecordSize() << " samples\n";
721  out << "\tSample Size: " << hdr.GetSampleSize() << " elements\n";
722  out << "\tData Type Size: " << hdr.GetDataTypeSize() << " bytes\n";
723  out << "\tData Format: " << hdr.GetDataFormat() << '\n';
724  out << "\tBit Depth: " << hdr.GetBitDepth() << " bits\n";
725  out << "\tBit Alignment: " << hdr.GetBitAlignment() << '\n';
726  out << "\tVoltage Offset: " << hdr.GetVoltageOffset() << " V\n";
727  out << "\tVoltage Range: " << hdr.GetVoltageRange() << " V\n";
728  out << "\tFrequency Min: " << hdr.GetFrequencyMin() << " Hz\n";
729  out << "\tFrequency Range: " << hdr.GetFrequencyRange() << " Hz\n";
730  return out;
731 }
732 
733 M3_API std::ostream& operator<<( std::ostream& out, const monarch3::M3Header& hdr )
734 {
735  out << "Monarch Header Content:\n";
736  out << "\tEgg Version: " << hdr.EggVersion() << "\n";
737  out << "\tFilename: " << hdr.Filename() << "\n";
738  out << "\tRun Duration: " << hdr.GetRunDuration() << " ms\n";
739  out << "\tTimestamp: " << hdr.Timestamp() << "\n";
740  out << "\tDescription: " << hdr.Description() << "\n";
741  out << "\tNumber of Channels: " << hdr.GetNChannels() << "\n";
742  out << "\tNumber of Streams: " << hdr.GetNStreams() << "\n";
743  out << "\tChannel-to-stream mapping:\n";
744  for( uint32_t iChan = 0; iChan < hdr.ChannelStreams().size(); ++iChan )
745  {
746  out << "\t\tChannel " << iChan << " --> Stream " << hdr.ChannelStreams()[ iChan ] << "\n";
747  }
748  out << "\tStream headers:\n";
749  for( uint32_t iStream = 0; iStream < hdr.StreamHeaders().size(); ++iStream )
750  {
751  out << hdr.StreamHeaders()[ iStream ];
752  }
753  out << "\tChannel headers:\n";
754  for( uint32_t iChan = 0; iChan < hdr.ChannelHeaders().size(); ++iChan )
755  {
756  out << hdr.ChannelHeaders()[ iChan ];
757  }
758  return out;
759 }
void WriteChannelCoherence(HAS_ATTR_IFC *aLoc)
Definition: M3Header.cc:630
static const uint32_t sSeparate
Definition: M3Constants.hh:51
static const uint32_t sDigitizedUS
Definition: M3Constants.hh:38
std::ostream & operator<<(std::ostream &out, const monarch3::M3StreamHeader &hdr)
Definition: M3Header.cc:695
void WriteChannels(HAS_ATTR_IFC *aLoc)
Definition: M3Header.cc:166
static void WriteScalarToHDF5(HAS_ATTR_IFC *aLoc, const std::string &aName, const std::string &aValue)
Definition: M3Header.hh:276
virtual const char * what() const
Definition: M3Exception.cc:34
void ReadChannelCoherence(const HAS_ATTR_IFC *aLoc) const
Definition: M3Header.cc:656
void ReadFromHDF5(const H5::H5File *aFile) const
Definition: M3Header.cc:500
Egg file header information.
Definition: M3Header.hh:152
void SetCoherence(unsigned aChanA, unsigned aChanB, bool aCoherence)
Definition: M3Header.cc:389
Single-channel header information.
Definition: M3Header.hh:92
H5::Group * fStreamsGroup
Definition: M3Header.hh:223
void ReadFromHDF5(const HAS_GRP_IFC *aParent, const std::string &aLabel) const
Definition: M3Header.cc:142
void ReadChannels(const HAS_ATTR_IFC *aLoc) const
Definition: M3Header.cc:189
void ReadFromHDF5(const HAS_GRP_IFC *aParent, const std::string &aLabel) const
Definition: M3Header.cc:329
void SetNumber(uint32_t aNumber) const
Definition: M3Header.cc:293
void u32toa(uint32_t value, char *buffer)
Quickly convert a 32-bit unsigned integer to a char array (buffer should already be allocated) ...
Definition: M3IToA.cc:42
Specialized exception class for Monarch3.
Definition: M3Exception.hh:28
Single-stream header information.
Definition: M3Header.hh:33
static scarab::logger mlog("M3Header")
void CopyBasicInfo(const M3Header &aOrig)
Definition: M3Header.cc:379
H5::H5File * fFile
Definition: M3Header.hh:222
void WriteToHDF5(H5::H5File *aFile)
Definition: M3Header.cc:456
void WriteToHDF5(HAS_GRP_IFC *aParent)
Definition: M3Header.cc:306
void SetNumber(uint32_t aNumber) const
Definition: M3Header.cc:105
static const uint32_t sBitsAlignedLeft
Definition: M3Constants.hh:44
#define M3_API
Definition: M3Constants.hh:21
void WriteChannelStreams(HAS_ATTR_IFC *aLoc)
Definition: M3Header.cc:574
unsigned AddStream(const std::string &aSource, uint32_t anAcqRate, uint32_t aRecSize, uint32_t aSampleSize, uint32_t aDataTypeSize, uint32_t aDataFormat, uint32_t aBitDepth, uint32_t aBitAlignment, std::vector< unsigned > *aChanVec=NULL)
Definition: M3Header.cc:400
void ReadChannelStreams(const HAS_ATTR_IFC *aLoc) const
Definition: M3Header.cc:597
void WriteToHDF5(HAS_GRP_IFC *aParent)
Definition: M3Header.cc:118
H5::Group * fChannelsGroup
Definition: M3Header.hh:224