Calculate sensitivity

This commit is contained in:
Lukas Klass 2020-05-16 15:52:27 +02:00
parent ccad053e78
commit 14a7abca74
4 changed files with 65 additions and 8 deletions

View File

@ -142,10 +142,10 @@ class Configuration(object):
if hasattr(self.conf.common, "exposure_time"): if hasattr(self.conf.common, "exposure_time"):
mes = self.conf.common.exposure_time.check_quantity("val", u.s) mes = self.conf.common.exposure_time.check_quantity("val", u.s)
mes is not None and error("Configuration check: common -> exposure_time: " + mes) mes is not None and error("Configuration check: common -> exposure_time: " + mes)
elif hasattr(self.conf.common, "snr"): if hasattr(self.conf.common, "snr"):
mes = self.conf.common.snr.check_quantity("val", u.dimensionless_unscaled) mes = self.conf.common.snr.check_quantity("val", u.dimensionless_unscaled)
mes is not None and error("Configuration check: common -> snr: " + mes) mes is not None and error("Configuration check: common -> snr: " + mes)
else: if not (hasattr(self.conf.common, "exposure_time") or hasattr(self.conf.common, "snr")):
error("Configuration check: common: Expected one of the containers 'exposure_time' or 'snr' but got none.") error("Configuration check: common: Expected one of the containers 'exposure_time' or 'snr' but got none.")
# Check astroscene # Check astroscene
@ -162,7 +162,10 @@ class Configuration(object):
dir(tg), 1)[0] + "'?") dir(tg), 1)[0] + "'?")
mes = getattr(tg, self.conf.astroscene.target.type).check_config(self.conf.astroscene.target) mes = getattr(tg, self.conf.astroscene.target.type).check_config(self.conf.astroscene.target)
mes is not None and error("Configuration check: astroscene -> target: " + mes) mes is not None and error("Configuration check: astroscene -> target: " + mes)
if hasattr(self.conf.common, "exposure_time") and hasattr(self.conf.common, "snr"):
if self.conf.astroscene.target.type.lower() != "blackbodytarget":
error("Configuration check: astroscene -> target: Sensitivity calculation only possible for " +
"a target of the type 'BlackBodyTarget'.")
mes = self.__check_optical_components(self.conf.astroscene) mes = self.__check_optical_components(self.conf.astroscene)
mes is not None and error("Configuration check: astroscene -> " + mes) mes is not None and error("Configuration check: astroscene -> " + mes)

View File

@ -39,13 +39,14 @@ class ASensor:
pass pass
@abstractmethod @abstractmethod
def getExpTime(self, snr: float): @u.quantity_input(snr=u.dimensionless_unscaled)
def getExpTime(self, snr: u.Quantity):
""" """
Calculate the necessary exposure time in order to achieve the given SNR. Calculate the necessary exposure time in order to achieve the given SNR.
Parameters Parameters
---------- ----------
snr : float snr : Quantity
The SNR for which the necessary exposure time shall be calculated. The SNR for which the necessary exposure time shall be calculated.
Returns Returns
@ -55,6 +56,28 @@ class ASensor:
""" """
pass pass
@abstractmethod
@u.quantity_input(exp_time="time", snr=u.dimensionless_unscaled, target_brightness=u.mag)
def getSensitivity(self, exp_time: u.Quantity, snr: u.Quantity, target_brightness: u.Quantity):
"""
Calculate the sensitivity of the telescope detector combination.
Parameters
----------
exp_time : Quantity
The exposure time in seconds.
snr : Quantity
The SNR for which the sensitivity time shall be calculated.
target_brightness : Quantity
The target brightness in magnitudes.
Returns
-------
sensitivity: Quantity
The sensitivity as limiting apparent star magnitude in mag.
"""
pass
@staticmethod @staticmethod
def check_config(sensor: Entry, conf: Entry) -> Union[None, str]: def check_config(sensor: Entry, conf: Entry) -> Union[None, str]:
""" """

View File

@ -149,6 +149,34 @@ class Imager(ASensor):
self.__calcSNR(signal_current * exp_time, background_current * exp_time, read_noise, dark_current * exp_time) self.__calcSNR(signal_current * exp_time, background_current * exp_time, read_noise, dark_current * exp_time)
return exp_time return exp_time
@u.quantity_input(exp_time="time", snr=u.dimensionless_unscaled, target_brightness=u.mag)
def getSensitivity(self, exp_time: u.Quantity, snr: u.Quantity, target_brightness: u.Quantity):
"""
Calculate the sensitivity of the telescope detector combination.
Parameters
----------
exp_time : Quantity
The exposure time in seconds.
snr : Quantity
The SNR for which the sensitivity time shall be calculated.
target_brightness : Quantity
The target brightness in magnitudes.
Returns
-------
sensitivity: Quantity
The sensitivity as limiting apparent star magnitude in mag.
"""
# Calculate the electron currents
signal_current, background_current, read_noise, dark_current = self.__exposePixels()
# Fix the physical units of the SNR
snr = snr * u.electron ** 0.5
signal_current_lim = snr * (snr + np.sqrt(
snr ** 2 + 4 * (exp_time * (background_current.sum() + dark_current.sum()) + (read_noise ** 2).sum()))) / (
2 * exp_time)
return target_brightness - 2.5 * np.log10(signal_current_lim / signal_current.sum()) * u.mag
@u.quantity_input(signal=u.electron, background=u.electron, read_noise=u.electron ** 0.5, dark=u.electron) @u.quantity_input(signal=u.electron, background=u.electron, read_noise=u.electron ** 0.5, dark=u.electron)
def __calcSNR(self, signal: u.Quantity, background: u.Quantity, read_noise: u.Quantity, def __calcSNR(self, signal: u.Quantity, background: u.Quantity, read_noise: u.Quantity,
dark: u.Quantity) -> u.dimensionless_unscaled: dark: u.Quantity) -> u.dimensionless_unscaled:

View File

@ -23,9 +23,12 @@ if __name__ == "__main__":
parent = oc_factory.fromConfigBatch(conf) parent = oc_factory.fromConfigBatch(conf)
sensor_factory = etc.SensorFactory(parent, conf.common) sensor_factory = etc.SensorFactory(parent, conf.common)
imager = sensor_factory.create(conf.instrument.sensor) imager = sensor_factory.create(conf.instrument.sensor)
if hasattr(conf.common, "exposure_time"): if hasattr(conf.common, "exposure_time") and hasattr(conf.common, "snr"):
sensitivity = imager.getSensitivity(conf.common.exposure_time(), conf.common.snr(), conf.astroscene.target.mag)
print("The limiting apparent magnitude is: %.2f mag." % sensitivity.value)
elif hasattr(conf.common, "exposure_time"):
snr = imager.getSNR(conf.common.exposure_time()) snr = imager.getSNR(conf.common.exposure_time())
print("The SNR is: %.2f" % snr) print("The SNR is: %.2f." % snr.value)
elif hasattr(conf.common, "snr"): elif hasattr(conf.common, "snr"):
exp_time = imager.getExpTime(conf.common.snr()) exp_time = imager.getExpTime(conf.common.snr())
print("The necessary exposure time is: %.2f s" % exp_time.value) print("The necessary exposure time is: %.2f s." % exp_time.value)