@@ -551,6 +551,7 @@ int run_command_util( const int argc, char *argv[] )
551551  bool  no_background_spec, no_foreground_spec, no_intrinsic_spec;
552552  bool  no_calibration_spec, no_unknown_spec;
553553  bool  background_only, foreground_only, calibration_only, intrinsic_only;
554+   bool  sum_det_per_sample, sum_samples_per_det;
554555  // bool spectra_of_likely_interest_only;
555556  vector<string> detector_renaimings, detectors_to_include, detectors_to_exclude;
556557
@@ -775,6 +776,14 @@ int run_command_util( const int argc, char *argv[] )
775776   " Ex., ./cambio --det-to-include=Aa1 input.n42 output.pcf\n\t " 
776777   "      ./cambio --det-to-include 'Aa 1' input.n42 output.pcf\n\t " 
777778  )
779+   (" sum-det-per-sample" bool >(&sum_det_per_sample)->default_value (false )->implicit_value (true ),
780+    " For each sample number, sum all detectors for that sample number together.\n\t " 
781+    " i.e. Output one spectrum for each sample, no matter how many detectors there are." 
782+   )
783+   (" sum-samples-per-det" bool >(&sum_samples_per_det)->default_value (false )->implicit_value (true ),
784+    " For each detector, sum all sample numbers together.\n\t " 
785+    " i.e. Output one spectrum for each detector, no matter how many sample is in input." 
786+   )
778787  (" combine-input-files" bool >(&combine_all_files)->default_value (false )->implicit_value (true ),
779788   " Combines all input files, and writes a single output file." 
780789   "   An output file name must be specified." 
@@ -1465,12 +1474,21 @@ int run_command_util( const int argc, char *argv[] )
14651474    }
14661475  }// if( combine_all_files ) / else
14671476
1477+   if ( sum_det_per_sample && sum_samples_per_det )
1478+   {
1479+     cerr << " You can not specify both 'sum-det-per-sample' and 'sum-samples-per-det'." 
1480+     return  36 ;
1481+   }// if( sum_det_per_sample && sum_samples_per_det )
1482+   
14681483
1484+  
14691485
14701486  //  We'll define a lambda to actually write the output file
14711487  auto  write_output_file = [
14721488    // First we'll capture variables we wont change, by value
1473-     force_writing, summ_meas_for_single_out
1489+     force_writing, summ_meas_for_single_out,
1490+     sum_det_per_sample, 
1491+     sum_samples_per_det
14741492#if ( SpecUtils_ENABLE_D3_CHART )
14751493    , html_to_include
14761494#endif 
@@ -1485,6 +1503,122 @@ int run_command_util( const int argc, char *argv[] )
14851503    bool  file_existed = false ;
14861504    bool  opened_all_output_files = true , encoded_all_files = true ;
14871505
1506+     
1507+     if ( sum_det_per_sample )
1508+     {
1509+       const  set<int > orig_samples = info.sample_numbers ();
1510+       const  vector<string> orig_dets = info.detector_names ();
1511+       
1512+       vector<shared_ptr<SpecUtils::Measurement>> keepers;
1513+       for ( const  int  sample : orig_samples )
1514+       {
1515+         vector<shared_ptr<const  SpecUtils::Measurement>> sample_meass = info.sample_measurements (sample);
1516+         if ( sample_meass.size () == 1  )
1517+         {
1518+           auto  m = make_shared<SpecUtils::Measurement>( *(sample_meass[0 ]) );
1519+           m->set_detector_name ( " summed" 
1520+           keepers.push_back ( m );
1521+         }else  if ( sample_meass.size () > 1  )
1522+         {
1523+           //  TODO: summing will fail if we dont have any Measurements with gamma spectra that have valid energy calibrations (e.g., all Measurements are neutrons) - we should handle this case
1524+           try 
1525+           {
1526+             shared_ptr<SpecUtils::Measurement> m = info.sum_measurements ( {sample}, orig_dets, 0  );
1527+             
1528+             set<string> titles;
1529+             bool  all_background = true ;
1530+             for ( auto  orig : sample_meass )
1531+             {
1532+               const  bool  empty_title = orig->title ().empty ();
1533+               if ( !empty_title )
1534+                 titles.insert ( orig->title () );
1535+               
1536+               all_background &= (SpecUtils::icontains ( orig->title (), " Background" 
1537+                                  || (orig->source_type () == SpecUtils::SourceType::Background)
1538+                                  || (info.passthrough () && (orig->occupied () == SpecUtils::OccupancyStatus::NotOccupied)));
1539+             }// for( auto orig : sample_meass )
1540+             
1541+             assert ( m );
1542+             if ( m )
1543+             {
1544+               m->set_detector_name ( " summed" 
1545+               m->set_sample_number ( sample );
1546+               
1547+               if ( titles.size () == 1  )
1548+                 m->set_title ( *begin (titles) );
1549+               else  if ( all_background )
1550+                 m->set_title ( " Background" 
1551+               else 
1552+                 m->set_title ( " " 
1553+               
1554+               keepers.push_back ( m );
1555+             }// if( m )
1556+           }catch ( std::exception & )
1557+           {
1558+             cerr << " Error summing records for sample " "  - omitting the " 
1559+                  << sample_meass.size () << "  records for this sample number." 
1560+           }// try / catch - to sum the measurements for this sample
1561+         }// for( const int sample : orig_samples )
1562+       }// for( const int sample : orig_samples )
1563+       
1564+       info.remove_measurements ( info.measurements () );
1565+       for ( auto  m : keepers )
1566+         info.add_measurement ( m, false  );
1567+       
1568+       info.set_uuid ( " " 
1569+       info.cleanup_after_load ( SpecUtils::SpecFile::CleanupAfterLoadFlags::DontChangeOrReorderSamples );
1570+     }// if( sum_det_per_sample )
1571+     
1572+     
1573+     if ( sum_samples_per_det )
1574+     {
1575+       const  set<int > orig_samples = info.sample_numbers ();
1576+       const  vector<string> orig_dets = info.detector_names ();
1577+       
1578+       vector<shared_ptr<SpecUtils::Measurement>> keepers;
1579+       map<string,vector<shared_ptr<const  SpecUtils::Measurement>>> detector_to_meas;
1580+       map<string,shared_ptr<SpecUtils::Measurement>> detector_to_sum;
1581+       
1582+       for ( const  string &det : orig_dets )
1583+       {
1584+         vector<shared_ptr<const  SpecUtils::Measurement>> &det_meas = detector_to_meas[det];
1585+         for ( const  int  sample : orig_samples )
1586+         {
1587+           auto  m = info.measurement ( sample, det );
1588+           if ( m )
1589+             det_meas.push_back ( m );
1590+         }// for( const int sample : orig_samples )
1591+         
1592+         if ( det_meas.size () == 1  )
1593+         {
1594+           auto  m = make_shared<SpecUtils::Measurement>( *det_meas.front () );
1595+           m->set_sample_number ( 1  );
1596+           keepers.push_back ( m );
1597+         }else  if ( det_meas.size () > 1  )
1598+         {
1599+           //  TODO: summing will fail if we dont have any Measurements with gamma spectra that have valid energy calibrations (e.g., this is a neutron detector) - we should handle this case
1600+           try 
1601+           {
1602+             shared_ptr<SpecUtils::Measurement> m = info.sum_measurements ( orig_samples, {det}, 0  );
1603+             m->set_detector_name ( det );
1604+             m->set_sample_number ( 1  );
1605+             keepers.push_back ( m );
1606+           }catch ( std::exception & )
1607+           {
1608+             cerr << " Error summing records for detector '" " ' - omitting the " 
1609+                  << orig_samples.size () << "  records for this detector." 
1610+           }// try / catch - to sum the measurements for this sample
1611+         }// if( det_meas.size() == 1 ) / else 2 or more detectors
1612+       }// for( const string &det : orig_dets )
1613+       
1614+       info.remove_measurements ( info.measurements () );
1615+       for ( auto  m : keepers )
1616+         info.add_measurement ( m, false  );
1617+       
1618+       info.set_uuid ( " " 
1619+       info.cleanup_after_load ( SpecUtils::SpecFile::CleanupAfterLoadFlags::DontChangeOrReorderSamples );
1620+     }// if( sum_samples_per_det )
1621+     
14881622    if ( format == SpecUtils::SaveSpectrumAsType::Chn
14891623       || format == SpecUtils::SaveSpectrumAsType::SpcBinaryInt
14901624       || format == SpecUtils::SaveSpectrumAsType::SpcBinaryFloat
0 commit comments