@@ -88,6 +88,28 @@ string rsp_name( const string &name )
88
88
return name;
89
89
}// string rsp_name(...)
90
90
91
+
92
+ bool is_candidate_gxml (std::istream& input)
93
+ {
94
+ if (!input)
95
+ return false ;
96
+
97
+ char buffer[257 ] = { ' \0 ' };
98
+ const istream::pos_type start_pos = input.tellg ();
99
+ const bool successful_read = !!input.read (buffer, 256 );
100
+
101
+ input.clear ();
102
+ input.seekg (start_pos, ios::beg);
103
+
104
+ if (!successful_read)
105
+ return false ;
106
+
107
+ if (strstr (buffer, " <BGAMMA>" ) || strstr (buffer, " <bgamma>" ))
108
+ return true ;
109
+
110
+ return false ;
111
+ }// bool is_candidate_gxml(...)
112
+
91
113
}// namespace
92
114
93
115
@@ -134,14 +156,14 @@ bool SpecFile::load_from_xml_scan_data( std::istream &input )
134
156
135
157
rapidxml::file<char > input_file ( input );
136
158
137
- rapidxml::xml_document<char > doc;
159
+ std::unique_ptr< rapidxml::xml_document<char >> doc ( new rapidxml::xml_document< char >() ) ;
138
160
139
161
char *data = input_file.data ();
140
162
char *data_end = data + input_file.size ();
141
163
142
- doc. parse <rapidxml::parse_trim_whitespace | rapidxml::allow_sloppy_parse>( data, data_end );
164
+ doc-> parse <rapidxml::parse_trim_whitespace | rapidxml::allow_sloppy_parse>( data, data_end );
143
165
144
- const rapidxml::xml_node<char > *scanData = XML_FIRST_NODE ((& doc), " scanData" );
166
+ const rapidxml::xml_node<char > *scanData = XML_FIRST_NODE (doc. get (), " scanData" );
145
167
if ( !scanData )
146
168
throw runtime_error ( " No scanData element" );
147
169
@@ -464,4 +486,162 @@ bool SpecFile::load_from_xml_scan_data( std::istream &input )
464
486
return true ;
465
487
}// bool SpecFile::load_from_xml_scan_data(...)
466
488
489
+
490
+
491
+ bool SpecFile::load_caen_gxml_file (const std::string& filename)
492
+ {
493
+ #ifdef _WIN32
494
+ ifstream input (convert_from_utf8_to_utf16 (filename).c_str (), ios_base::binary | ios_base::in);
495
+ #else
496
+ ifstream input (filename.c_str (), ios_base::binary | ios_base::in);
497
+ #endif
498
+
499
+ if (!input.is_open ())
500
+ return false ;
501
+
502
+ const bool success = load_from_caen_gxml (input);
503
+
504
+ if (success)
505
+ filename_ = filename;
506
+
507
+ return success;
508
+ }// bool load_caen_gxml_file(const std::string& filename)
509
+
510
+
511
+ bool SpecFile::load_from_caen_gxml (std::istream& input)
512
+ {
513
+ reset ();
514
+
515
+ if (!input.good ())
516
+ return false ;
517
+
518
+ std::unique_lock<std::recursive_mutex> scoped_lock (mutex_);
519
+
520
+ const istream::pos_type start_pos = input.tellg ();
521
+
522
+ try
523
+ {
524
+ input.unsetf (ios::skipws);
525
+
526
+ if (!is_candidate_gxml (input))
527
+ throw runtime_error (" Not GXML file candidate." );
528
+
529
+ rapidxml::file<char > input_file (input);
530
+
531
+ std::unique_ptr<rapidxml::xml_document<char >> doc ( new rapidxml::xml_document<char >() );
532
+
533
+ char * data = input_file.data ();
534
+ char * data_end = data + input_file.size ();
535
+
536
+ doc->parse <rapidxml::parse_trim_whitespace | rapidxml::allow_sloppy_parse>(data, data_end);
537
+
538
+ const rapidxml::xml_node<char >* const bgamma_node = XML_FIRST_INODE (doc.get (), " BGAMMA" );
539
+ if (!bgamma_node)
540
+ throw runtime_error (" No BGAMMA element" );
541
+
542
+ const rapidxml::xml_node<char >* const spectrum_node = XML_FIRST_INODE (bgamma_node, " SPECTRUM" );
543
+ if (!spectrum_node)
544
+ throw runtime_error (" No SPECTRUM element" );
545
+
546
+ const rapidxml::xml_node<char >* const data_node = XML_FIRST_INODE (spectrum_node, " DATA" );
547
+ if (!data_node || (data_node->value_size () < 16 ))
548
+ throw runtime_error (" No spectrum DATA element" );
549
+
550
+ vector<string> warnings, remarks;
551
+ auto counts = make_shared<vector<float >>();
552
+ if (!SpecUtils::split_to_floats (data_node->value (), data_node->value_size (), *counts))
553
+ warnings.push_back (" May not have read in all channel counts." );
554
+
555
+ if (counts->size () < 16 )
556
+ throw runtime_error (" No channel counts" );
557
+
558
+ float live_time = 0 .0f , real_time = 0 .0f ;
559
+ const rapidxml::xml_node<char >* const lt_node = XML_FIRST_INODE (spectrum_node, " ELT" );
560
+ if (!lt_node
561
+ || !lt_node->value_size ()
562
+ || !SpecUtils::parse_float (lt_node->value (), lt_node->value_size (), live_time) )
563
+ {
564
+ warnings.push_back (" Unable to parse live time." );
565
+ }
566
+
567
+ const rapidxml::xml_node<char >* const rt_node = XML_FIRST_INODE (spectrum_node, " ERT" );
568
+ if (!rt_node
569
+ || !rt_node->value_size ()
570
+ || !SpecUtils::parse_float (rt_node->value (), rt_node->value_size (), real_time))
571
+ {
572
+ warnings.push_back (" Unable to parse real time." );
573
+ }
574
+
575
+ // From the one example I have, the <DATETIME> node is before START/STOP time, so we'll ignore for now
576
+ // const rapidxml::xml_node<char>* const datetime_node = XML_FIRST_INODE(bgamma_node, "DATETIME");
577
+
578
+ const rapidxml::xml_node<char >* const meas_node = XML_FIRST_INODE (bgamma_node, " MEASUREMENT" );
579
+
580
+ SpecUtils::time_point_t start_time{};
581
+ if (meas_node)
582
+ {
583
+ const rapidxml::xml_node<char >* const operator_node = XML_FIRST_INODE (meas_node, " OPERATOR" );
584
+ const rapidxml::xml_node<char >* const start_node = XML_FIRST_INODE (meas_node, " START" );
585
+ const rapidxml::xml_node<char >* const stop_node = XML_FIRST_INODE (meas_node, " STOP" );
586
+ const rapidxml::xml_node<char >* const comments_node = XML_FIRST_INODE (meas_node, " COMMENTS" );
587
+ const rapidxml::xml_node<char >* const tags_node = XML_FIRST_INODE (meas_node, " TAGS" );
588
+ if (start_node && start_node->value_size ())
589
+ start_time = SpecUtils::time_from_string (xml_value_str (start_node));
590
+ if (comments_node && comments_node->value_size ())
591
+ remarks.push_back (xml_value_str (comments_node));
592
+ if (tags_node && tags_node->value_size ())
593
+ remarks.push_back (" TAGS: " + xml_value_str (tags_node));
594
+ if (operator_node && operator_node->value_size ())
595
+ remarks.push_back (" Operator: " + xml_value_str (operator_node));
596
+ }// if (meas_node)
597
+
598
+
599
+ const rapidxml::xml_node<char >* const ch_start_node = XML_FIRST_INODE (spectrum_node, " CHNNLSTART" );
600
+ if (ch_start_node && ch_start_node->value () && !xml_value_compare (ch_start_node, " 0" ))
601
+ warnings.push_back (" File defined a channel start of '"
602
+ + xml_value_str (ch_start_node) + " ' - which is not handled." );
603
+
604
+ const rapidxml::xml_node<char >* const ch_end_node = XML_FIRST_INODE (spectrum_node, " CHNNLEND" );
605
+ if (ch_end_node && ch_end_node->value ())
606
+ {
607
+ int val = 0 ;
608
+ parse_int (ch_end_node->value (), ch_end_node->value_size (), val);
609
+ if ( val != static_cast <int >(counts->size () - 1 ) )
610
+ warnings.push_back (" File defined a channel end of '"
611
+ + xml_value_str (ch_end_node) + " ' - which is not handled." );
612
+ }// if (ch_end_node && ch_end_node->value())
613
+
614
+
615
+ auto meas = make_shared<Measurement>();
616
+ meas->gamma_counts_ = counts;
617
+ meas->start_time_ = start_time;
618
+ meas->real_time_ = real_time;
619
+ meas->live_time_ = live_time;
620
+ meas->gamma_count_sum_ = 0.0 ;
621
+ for (const float & v : *counts)
622
+ meas->gamma_count_sum_ += v;
623
+
624
+ measurements_.push_back (meas);
625
+ parse_warnings_ = warnings;
626
+ remarks_ = remarks;
627
+ manufacturer_ = " CAEN" ;
628
+ instrument_model_ = " Hexagon" ;
629
+ instrument_type_ = " Other" ;
630
+ detector_type_ = DetectorType::Unknown;
631
+
632
+ cleanup_after_load ();
633
+
634
+ return true ;
635
+ }catch (std::exception & e)
636
+ {
637
+ input.clear ();
638
+ input.seekg (start_pos, ios::beg);
639
+ reset ();
640
+ return false ;
641
+ }// try/catch
642
+
643
+ return true ;
644
+ }// bool load_from_caen_gxml(std::istream& input)
645
+
646
+
467
647
}// namespace SpecUtils
0 commit comments