-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for external custom data #4
base: main
Are you sure you want to change the base?
Changes from 10 commits
6c7fb20
749452e
08aa9e3
92710ee
38647d0
078d2f8
dd0b034
d07a55d
0f4c117
27fb6cc
0666b16
bb1ea75
9f69958
3c2b3e2
ba3e00e
77e6d25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Added support for custom external performance data. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ | |
import importlib | ||
|
||
import astropy.units as u | ||
from gammapy.stats import WStatCountsStatistic | ||
import numpy as np | ||
from scipy import interpolate | ||
from scipy.integrate import quad | ||
|
@@ -15,14 +14,14 @@ | |
) | ||
from .io import load_ebl | ||
from .spectral import crab_nebula_spectrum | ||
from .statistics import probability_to_sigma, sigma_to_probability, significance_li_ma | ||
|
||
__all__ = [ | ||
"setup_logging", | ||
"check_input_configuration", | ||
"initialize_model", | ||
"observed_flux", | ||
"get_sed", | ||
"significance_li_ma", | ||
"prepare_data", | ||
"source_detection", | ||
"calculate", | ||
|
@@ -133,7 +132,7 @@ def get_horizon_stereo_profile(M1_data, M2_data): | |
return az * u.deg, zd * u.deg | ||
|
||
|
||
def check_input_configuration(config): | ||
def check_input_configuration(config, performance_data): | ||
""" | ||
Import and initialize a spectral model. | ||
|
||
|
@@ -151,6 +150,9 @@ def check_input_configuration(config): | |
# Assume a valid configuration | ||
is_valid = True | ||
|
||
if performance_data: | ||
performance_metadata = performance_data.meta | ||
|
||
extension = u.Quantity(config["extension"]).to_value("deg") | ||
|
||
if extension > 1: | ||
|
@@ -167,9 +169,13 @@ def check_input_configuration(config): | |
" region (n_off_regions) should be used." | ||
) | ||
is_valid = False | ||
if config["sum_trigger"] and (config["zenith_performance"] == "mid"): | ||
logger.warning("This functionality has not been yet implemented.") | ||
# raise NotImplementedError("This functionality has not been yet implemented.") | ||
if config["sum_trigger"] and (config["zenith_range"] == "mid"): | ||
is_valid = False | ||
raise NotImplementedError( | ||
"MAGIC SUM trigger at mid zenith range has not been yet implemented." | ||
) | ||
if ("LST" in performance_metadata) and config["sum_trigger"]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct, this is related to the thread above |
||
logger.warning("LST mode is not compatible with SUMT") | ||
is_valid = False | ||
if config["offset_degradation_factor"] > 1.00001: | ||
logger.warning( | ||
|
@@ -231,7 +237,7 @@ def initialize_model(config): | |
|
||
|
||
@u.quantity_input(energy=u.TeV) | ||
def observed_flux(energy, redshift, flux_int): | ||
def observed_flux(energy, redshift, flux_int, ebl_file_path): | ||
""" | ||
Get the attenuated flux of the source. | ||
|
||
|
@@ -249,7 +255,7 @@ def observed_flux(energy, redshift, flux_int): | |
valid : `bool` | ||
Initialized instance of a spectral model. | ||
""" | ||
ebl_redshift, ebl_energy, ebl_taus = load_ebl() | ||
ebl_redshift, ebl_energy, ebl_taus = load_ebl(ebl_file_path) | ||
ftau = interpolate.interp2d( | ||
ebl_redshift, ebl_energy.to_value(energy.unit), ebl_taus, kind="cubic" | ||
) | ||
|
@@ -280,43 +286,7 @@ def get_sed(energy, flux): | |
return sed | ||
|
||
|
||
def significance_li_ma(n_on, n_off, alpha, mu_sig=None): | ||
""" | ||
Get the Li & Ma significance. | ||
|
||
This is equivalent to eq.17 of [1]_. | ||
|
||
Parameters | ||
---------- | ||
n_on : `int` | ||
Measured counts in ON region. | ||
n_off : `int` | ||
Measured counts in OFF region. | ||
alpha : `float` | ||
Acceptance ratio of ON and OFF measurements. | ||
mu_sig : `float` | ||
Expected signal counts in ON region. | ||
|
||
Returns | ||
------- | ||
sqrt_ts : `float`` | ||
Significance as the square root of the Test Statistic. | ||
|
||
Notes | ||
----- | ||
The implementation uses `gammapy.stats.WStatCountsStatistic` | ||
and takes the square root of the Test Statistic. | ||
|
||
References | ||
---------- | ||
.. [1] Li, T.-P. & Ma, Y.-Q., ApJ, 1983, 272, 317, 10.1086/161295. | ||
""" | ||
statistics = WStatCountsStatistic(n_on, n_off, alpha, mu_sig) | ||
sqrt_ts = statistics.sqrt_ts | ||
return sqrt_ts | ||
|
||
|
||
def prepare_data(config): | ||
def prepare_data(config, performance_data=None): | ||
""" | ||
Extract the performance data. | ||
|
||
|
@@ -335,22 +305,28 @@ def prepare_data(config): | |
Rate of background events from performance data. | ||
""" | ||
|
||
performance_data = { | ||
"low": LOW_ZENITH_PERFORMANCE, | ||
"mid": MID_ZENITH_PERFORMANCE, | ||
} | ||
if not performance_data: | ||
if config["sum_trigger"] and config["zenith_range"] == "mid": | ||
message = "MAGIC Mid zenith performance with the SUM trigger is not currently available." | ||
logger.critical(message) | ||
raise NotImplementedError(message) | ||
|
||
if config["sum_trigger"] and config["zenith_performance"] == "low": | ||
message = "Low zenith performance with the SUM trigger" | ||
" is not currently available." | ||
logger.critical(message) | ||
raise NotImplementedError(message) | ||
# use packaged (public) datasets | ||
available_datasets = { | ||
"low": LOW_ZENITH_PERFORMANCE, | ||
"mid": MID_ZENITH_PERFORMANCE, | ||
} | ||
|
||
min_energy = performance_data[config["zenith_performance"]]["min_energy"] | ||
max_energy = performance_data[config["zenith_performance"]]["max_energy"] | ||
performance_data = available_datasets[config["zenith_range"]] | ||
|
||
min_energy = performance_data["min_energy"] | ||
max_energy = performance_data["max_energy"] | ||
energy_bins = np.append(min_energy.value, max_energy[-1].value) * min_energy.unit | ||
gamma_rate = performance_data[config["zenith_performance"]]["gamma_rate"] | ||
background_rate = performance_data[config["zenith_performance"]]["background_rate"] | ||
gamma_rate = performance_data["gamma_rate"] | ||
background_rate = performance_data["background_rate"] | ||
|
||
gamma_rate *= config["offset_degradation_factor"] | ||
background_rate *= config["offset_degradation_factor"] | ||
|
||
return energy_bins, gamma_rate, background_rate | ||
|
||
|
@@ -375,12 +351,21 @@ def source_detection(sigmas, observation_time): | |
|
||
time = observation_time.to("h") | ||
|
||
combined_probability = 1 | ||
combined_significance_text = "" | ||
if len(sigmas) > 0: | ||
combined_significance = sum(sigmas) / np.sqrt(len(sigmas)) | ||
combined_probability = np.prod(sigma_to_probability(sigmas)) | ||
combined_significance = probability_to_sigma(combined_probability) | ||
combined_significance_text = "{0:.2f}".format(combined_significance) | ||
if ( | ||
combined_probability < 1.0e-307 | ||
): # numerical accuracy problem, but significance will be either way large | ||
combined_significance = 38 # or more ... | ||
combined_significance_text = ">38" | ||
|
||
print( | ||
f"Combined significance (using the {len(sigmas):d} data points" | ||
f" shown in the SED) = {combined_significance:.1f}" | ||
f" shown in the SED) = {combined_significance_text}" | ||
) | ||
else: | ||
print(f"The source will not be detected in {time}.") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
from astropy.visualization import quantity_support | ||
import matplotlib.pyplot as plt | ||
|
||
from ..io import read_yaml | ||
from ..io import read_yaml, load_performance_ecsv | ||
from ..core import ( | ||
setup_logging, | ||
initialize_model, | ||
|
@@ -32,6 +32,12 @@ | |
type=str, | ||
help="Name of the source to estimate.", | ||
) | ||
parser.add_argument( | ||
"--performance", | ||
default="", | ||
type=str, | ||
help="Custom performance data.", | ||
) | ||
parser.add_argument( | ||
"--output-path", | ||
default=None, | ||
|
@@ -67,8 +73,14 @@ def main(): | |
logger.info("Loading configuration file") | ||
config = read_yaml(args.config) | ||
|
||
performance_data = None | ||
if args.performance: | ||
performance_data_file = Path(args.performance).resolve() | ||
logger.info("Loading performance data from %s", performance_data_file) | ||
performance_data = load_performance_ecsv(performance_data_file) | ||
|
||
logging.info("Validating input configuration") | ||
if not check_input_configuration(config): | ||
if not check_input_configuration(config, performance_data): | ||
logging.critical("One or more invalid configuration settings have been found.") | ||
parser.exit(status=1, message="iact-estimator terminated abnormally.") | ||
|
||
|
@@ -101,7 +113,10 @@ def main(): | |
label=source_name, | ||
) | ||
|
||
energy_bins, gamma_rate, background_rate = prepare_data(config) | ||
if not performance_data: | ||
energy_bins, gamma_rate, background_rate = prepare_data(config) | ||
else: | ||
energy_bins, gamma_rate, background_rate = prepare_data(performance_data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we need to put both of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
||
en, sed, dsed, sigmas, detected = calculate( | ||
energy_bins, gamma_rate, background_rate, config, assumed_spectrum | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nice to add unit for gamma_rate and background_rate as examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, when I produced this example table I forgot the units for this columns!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be better now, I basically copied the header from the MAGIC low energy data file