@@ -390,6 +390,13 @@ def sample_dataset_with_background_intermediates():
390390 bg_rate_stat_uncert_exposure_factor2 ,
391391 )
392392
393+ # Background systematic error times exposure time
394+ bg_rate_sys_err_exposure_factor = np .ones ((1 , n_energy )) * 0.05
395+ dataset ["bg_rate_sys_err_exposure_factor" ] = (
396+ ("epoch" , "energy" ),
397+ bg_rate_sys_err_exposure_factor ,
398+ )
399+
393400 # Add exposure time (using current naming convention)
394401 exposure = np .ones ((1 , n_energy )) * 1.0 # 1 second
395402 dataset ["exposure_factor" ] = (("epoch" , "energy" ), exposure )
@@ -848,6 +855,10 @@ def test_normalize_coordinates_basic(self, species):
848855 PSET_DIMS ,
849856 np .ones (PSET_SHAPE ) * 0.01 ,
850857 ),
858+ f"{ species } _background_rates_sys_err" : (
859+ PSET_DIMS ,
860+ np .ones (PSET_SHAPE ) * 0.02 ,
861+ ),
851862 },
852863 coords = {
853864 "epoch" : [8.1794907049e17 ],
@@ -880,6 +891,7 @@ def test_normalize_coordinates_basic(self, species):
880891 assert "exposure_factor" in result .data_vars
881892 assert "bg_rate" in result .data_vars
882893 assert "bg_rate_stat_uncert" in result .data_vars
894+ assert "bg_rate_sys_err" in result .data_vars
883895
884896 # Check that old variable names are gone
885897 assert f"{ species } _counts" not in result .data_vars
@@ -919,6 +931,10 @@ def test_normalize_coordinates_removes_old_coordinate(self):
919931 PSET_DIMS ,
920932 np .ones (PSET_SHAPE ) * 0.01 ,
921933 ),
934+ f"{ species } _background_rates_sys_err" : (
935+ PSET_DIMS ,
936+ np .ones (PSET_SHAPE ) * 0.02 ,
937+ ),
922938 "esa_energy_step_var" : xr .DataArray ([1 , 2 , 3 , 4 , 5 , 6 , 7 ]), # Variable
923939 },
924940 coords = {
@@ -1010,6 +1026,7 @@ def test_calculate_efficiency_corrected_quantities(self):
10101026 "exposure_factor" : (("energy" ,), np .ones (7 ) * 1.0 ), # 1 second
10111027 "bg_rate" : (("energy" ,), np .ones (7 ) * 0.1 ), # 0.1 counts/s
10121028 "bg_rate_stat_uncert" : (("energy" ,), np .ones (7 ) * 0.01 ), # uncertainty
1029+ "bg_rate_sys_err" : (("energy" ,), np .ones (7 ) * 0.02 ), # systematic
10131030 "efficiency" : (
10141031 ("energy" ,),
10151032 np .array ([0.8 , 0.85 , 0.9 , 0.95 , 0.88 , 0.92 , 0.87 ]),
@@ -1025,6 +1042,7 @@ def test_calculate_efficiency_corrected_quantities(self):
10251042 assert "counts_over_eff_squared" in result .data_vars
10261043 assert "bg_rate_exposure_factor" in result .data_vars
10271044 assert "bg_rate_stat_uncert_exposure_factor2" in result .data_vars
1045+ assert "bg_rate_sys_err_exposure_factor" in result .data_vars
10281046
10291047 # Check dimensions
10301048 assert result ["counts_over_eff" ].dims == pset ["counts" ].dims
@@ -1052,6 +1070,11 @@ def test_calculate_efficiency_corrected_quantities(self):
10521070 result ["bg_rate_stat_uncert_exposure_factor2" ], expected_bg_uncert_exposure
10531071 )
10541072
1073+ expected_bg_sys_err_exposure = pset ["bg_rate_sys_err" ] * pset ["exposure_factor" ]
1074+ xr .testing .assert_allclose (
1075+ result ["bg_rate_sys_err_exposure_factor" ], expected_bg_sys_err_exposure
1076+ )
1077+
10551078
10561079class TestCalculateRates :
10571080 """Tests for the calculate_rates function."""
@@ -1134,17 +1157,17 @@ def test_calculate_intensities_basic(self, sample_dataset_with_geometric_factors
11341157 result ["ena_intensity_stat_uncert" ], expected_stat_uncert
11351158 )
11361159
1137- # Check systematic uncertainty calculation. The single `_sys_err` is the
1138- # mean of the asymmetric minus/plus bounds.
1139- mean_gf_stat_uncert = 0.5 * (
1140- sample_dataset_with_geometric_factors [ "geometric_factor_stat_uncert_minus" ]
1141- + sample_dataset_with_geometric_factors [ "geometric_factor_stat_uncert_plus" ]
1142- )
1143- expected_sys_err = (
1144- result [ "ena_intensity" ]
1145- * mean_gf_stat_uncert
1146- / sample_dataset_with_geometric_factors [ "geometric_factor" ]
1147- )
1160+ # Check systematic uncertainty calculation
1161+ gf = sample_dataset_with_geometric_factors [ "geometric_factor" ]
1162+ dg_minus = sample_dataset_with_geometric_factors [
1163+ "geometric_factor_stat_uncert_minus"
1164+ ]
1165+ dg_plus = sample_dataset_with_geometric_factors [
1166+ "geometric_factor_stat_uncert_plus"
1167+ ]
1168+ expected_sys_err_plus = result [ "ena_intensity" ] * dg_minus / ( gf - dg_minus )
1169+ expected_sys_err_minus = result [ "ena_intensity" ] * dg_plus / ( gf + dg_plus )
1170+ expected_sys_err = np . sqrt ( expected_sys_err_minus * expected_sys_err_plus )
11481171 xr .testing .assert_allclose (result ["ena_intensity_sys_err" ], expected_sys_err )
11491172
11501173 def test_calculate_intensities_missing_variables (self ):
@@ -1196,14 +1219,9 @@ def test_calculate_backgrounds_basic(
11961219 )
11971220 xr .testing .assert_allclose (result ["bg_rate_stat_uncert" ], expected_stat_uncert )
11981221
1199- # Check systematic uncertainty calculation
1200- # (mean(geometric_factor_stat_uncert bounds) / geometric_factor) * bg_rate
1201- mean_gf_stat_uncert = 0.5 * (
1202- dataset ["geometric_factor_stat_uncert_minus" ]
1203- + dataset ["geometric_factor_stat_uncert_plus" ]
1204- )
1222+ # Check systematic error calculation
12051223 expected_sys_err = (
1206- result [ "bg_rate " ] * mean_gf_stat_uncert / dataset ["geometric_factor " ]
1224+ dataset [ "bg_rate_sys_err_exposure_factor " ] / dataset ["exposure_factor " ]
12071225 )
12081226 xr .testing .assert_allclose (result ["bg_rate_sys_err" ], expected_sys_err )
12091227
@@ -1219,6 +1237,10 @@ def test_calculate_backgrounds_zero_exposure(self):
12191237 ("epoch" , "energy" ),
12201238 np .ones ((1 , 7 )) * 0.004 ,
12211239 ),
1240+ "bg_rate_sys_err_exposure_factor" : (
1241+ ("epoch" , "energy" ),
1242+ np .ones ((1 , 7 )) * 0.05 ,
1243+ ),
12221244 "exposure_factor" : (("epoch" , "energy" ), np .zeros ((1 , 7 ))),
12231245 "geometric_factor" : (("energy" ,), np .ones (7 ) * 1e-4 ),
12241246 "geometric_factor_stat_uncert_minus" : (("energy" ,), np .ones (7 ) * 1e-5 ),
@@ -1839,6 +1861,7 @@ def test_cleanup_intermediate_variables(self):
18391861 "counts_over_eff_squared" : (("energy" ,), np .ones (7 )),
18401862 "bg_rate_exposure_factor" : (("energy" ,), np .ones (7 )),
18411863 "bg_rate_stat_uncert_exposure_factor2" : (("energy" ,), np .ones (7 )),
1864+ "bg_rate_sys_err_exposure_factor" : (("energy" ,), np .ones (7 )),
18421865 "ena_intensity" : (("energy" ,), np .ones (7 )), # Should be kept
18431866 "exposure_factor" : (("energy" ,), np .ones (7 )), # Should be kept
18441867 }
@@ -1856,6 +1879,7 @@ def test_cleanup_intermediate_variables(self):
18561879 assert "counts_over_eff_squared" not in result .data_vars
18571880 assert "bg_rate_exposure_factor" not in result .data_vars
18581881 assert "bg_rate_stat_uncert_exposure_factor2" not in result .data_vars
1882+ assert "bg_rate_sys_err_exposure_factor" not in result .data_vars
18591883
18601884 def test_cleanup_partial_variables (self ):
18611885 """Test cleanup when only some intermediate variables exist."""
@@ -2327,6 +2351,10 @@ def test_calculate_all_rates_and_intensities_complete(self):
23272351 ("energy" ,),
23282352 np .ones (7 ) * 0.009 ,
23292353 ),
2354+ "bg_rate_sys_err_exposure_factor" : (
2355+ ("energy" ,),
2356+ np .ones (7 ) * 0.06 ,
2357+ ),
23302358 }
23312359 )
23322360
@@ -2373,6 +2401,10 @@ def test_calculate_all_rates_with_cg_correction(
23732401 ("epoch" , "energy" ),
23742402 np .ones ((1 , 7 )) * 0.009 ,
23752403 )
2404+ dataset ["bg_rate_sys_err_exposure_factor" ] = (
2405+ ("epoch" , "energy" ),
2406+ np .ones ((1 , 7 )) * 0.06 ,
2407+ )
23762408 dataset ["energy_sc_exposure_factor" ] = xr .ones_like (dataset ["ena_intensity" ])
23772409
23782410 # Mock the interpolation function
@@ -2425,6 +2457,10 @@ def test_calculate_all_rates_cg_with_other_corrections(
24252457 ("epoch" , "energy" ),
24262458 np .ones ((1 , 7 )) * 0.009 ,
24272459 )
2460+ dataset ["bg_rate_sys_err_exposure_factor" ] = (
2461+ ("epoch" , "energy" ),
2462+ np .ones ((1 , 7 )) * 0.06 ,
2463+ )
24282464 dataset ["energy_sc_exposure_factor" ] = xr .ones_like (dataset ["ena_intensity" ])
24292465
24302466 with patch (
@@ -2869,8 +2905,10 @@ def test_project_pset_to_map_value_keys(self, minimal_pset_for_species):
28692905 "counts_over_eff_squared" ,
28702906 "bg_rate" ,
28712907 "bg_rate_stat_uncert" ,
2908+ "bg_rate_sys_err" ,
28722909 "bg_rate_exposure_factor" ,
28732910 "bg_rate_stat_uncert_exposure_factor2" ,
2911+ "bg_rate_sys_err_exposure_factor" ,
28742912 ]
28752913
28762914 for key in expected_keys :
0 commit comments