From 59c5cd800066ba993b48d331406e820ebe8837b7 Mon Sep 17 00:00:00 2001 From: LukasK13 Date: Wed, 30 Sep 2020 21:53:09 +0200 Subject: [PATCH] Parse ATRAN files --- .../classes/optical_component/Atmosphere.py | 87 ++++++++++++++++--- tests/optical_component/test_Atmosphere.py | 7 +- tests/sensor/test_Heterodyne.py | 6 +- tests/test_RadiantFactory.py | 4 +- 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/esbo_etc/classes/optical_component/Atmosphere.py b/esbo_etc/classes/optical_component/Atmosphere.py index a2113a4..bbe4b48 100644 --- a/esbo_etc/classes/optical_component/Atmosphere.py +++ b/esbo_etc/classes/optical_component/Atmosphere.py @@ -2,7 +2,10 @@ from .AOpticalComponent import AOpticalComponent from ..IRadiant import IRadiant from ..SpectralQty import SpectralQty from ..Entry import Entry +from ...lib.logger import logger import astropy.units as u +from astropy.io import ascii +from astropy.modeling.models import BlackBody from typing import Union @@ -11,7 +14,7 @@ class Atmosphere(AOpticalComponent): A class to model the atmosphere including the atmosphere's spectral transmittance and emission. """ - def __init__(self, parent: IRadiant, transmittance: str, emission: str = None): + def __init__(self, **kwargs): """ Initialize a new atmosphere model @@ -27,18 +30,57 @@ class Atmosphere(AOpticalComponent): Path to the file containing the spectral radiance of the atmosphere. The format of the file will be guessed by `astropy.io.ascii.read()`. """ - # Read the transmittance - transmittance_sqty = SpectralQty.fromFile(transmittance, wl_unit_default=u.nm, - qty_unit_default=u.dimensionless_unscaled) - if emission is None: - # No emission is given, initialize the super class - super().__init__(parent, transmittance_sqty, 0) + + args = dict() + if "temp" in kwargs: + args = self._fromATRAN(**kwargs) + elif "transmittance" in kwargs: + args = self._fromFiles(**kwargs) else: - # Read the emission - emission_sqty = SpectralQty.fromFile(emission, wl_unit_default=u.nm, - qty_unit_default=u.W / (u.m ** 2 * u.nm * u.sr)) - # Initialize the super class - super().__init__(parent, transmittance_sqty, emission_sqty) + logger.error("Wrong parameters for class Atmosphere.") + super().__init__(parent=args["parent"], transreflectivity=args["transmittance"], noise=args["emission"]) + + def _fromFiles(self, parent: IRadiant, transmittance: str, emission: str = None): + """ + Initialize a new atmosphere model from two files + + Parameters + ---------- + parent : IRadiant + The parent element of the atmosphere from which the electromagnetic radiation is received. + This element is usually of type Target or StrayLight. + transmittance : str + Path to the file containing the spectral transmittance-coefficients of the atmosphere. + The format of the file will be guessed by `astropy.io.ascii.read()`. + emission : str + Path to the file containing the spectral radiance of the atmosphere. + The format of the file will be guessed by `astropy.io.ascii.read()`. + """ + # Read the transmittance + transmittance = SpectralQty.fromFile(transmittance, wl_unit_default=u.nm, + qty_unit_default=u.dimensionless_unscaled) + if emission is None: + emission = 0 + else: + emission = SpectralQty.fromFile(emission, wl_unit_default=u.nm, + qty_unit_default=u.W / (u.m ** 2 * u.nm * u.sr)) + return {"parent": parent, "transmittance": transmittance, "emission": emission} + + def _fromATRAN(self, parent: IRadiant, transmittance: str, temp: u.Quantity): + transmittance = "data_sofia/atmospheric_transmittance.dat" + # Read the file + data = ascii.read(transmittance, format=None) + # Set units + data["col2"].unit = u.um + data["col3"].unit = u.dimensionless_unscaled + # Create spectral quantity + transmittance = SpectralQty(data["col2"].quantity, data["col3"].quantity) + + # Create black body + bb = self.__gb_factory(temp) + # Calculate emission + emission = SpectralQty(transmittance.wl, bb(transmittance.wl)) * transmittance + return {"parent": parent, "transmittance": transmittance, "emission": emission} @staticmethod def check_config(conf: Entry) -> Union[None, str]: @@ -62,3 +104,24 @@ class Atmosphere(AOpticalComponent): mes = conf.check_file("emission") if mes is not None: return mes + + @staticmethod + @u.quantity_input(temp=[u.Kelvin, u.Celsius]) + def __gb_factory(temp: u.Quantity, em: Union[int, float] = 1): + """ + Factory for a grey body lambda-function. + + Parameters + ---------- + temp : Quantity in Kelvin / Celsius + The temperature fo the grey body. + em : Union[int, float] + Emissivity of the the grey body + + Returns + ------- + bb : Callable + The lambda function for the grey body. + """ + bb = BlackBody(temperature=temp, scale=em * u.W / (u.m ** 2 * u.nm * u.sr)) + return lambda wl: bb(wl) diff --git a/tests/optical_component/test_Atmosphere.py b/tests/optical_component/test_Atmosphere.py index 428c4d5..bcb5387 100644 --- a/tests/optical_component/test_Atmosphere.py +++ b/tests/optical_component/test_Atmosphere.py @@ -7,8 +7,9 @@ import astropy.units as u class TestAtmosphere(TestCase): def setUp(self): self.target = FileTarget("tests/data/target/target_demo_1.csv", np.arange(200, 208) << u.nm) - self.atmosphere = Atmosphere(self.target, "tests/data/atmosphere/atmosphere_transmittance_1.csv", - "tests/data/atmosphere/atmosphere_emission_1.csv") + self.atmosphere = Atmosphere(parent=self.target, + transmittance="tests/data/atmosphere/atmosphere_transmittance_1.csv", + emission="tests/data/atmosphere/atmosphere_emission_1.csv") def test_calcSignal(self): self.assertEqual(self.atmosphere.calcSignal()[0], @@ -16,7 +17,7 @@ class TestAtmosphere(TestCase): np.array([1.10e-15, 1.20e-15, 1.30e-15, 1.26e-15, 1.20e-15, 1.12e-15, 1.02e-15, 0.9e-15]) << u.W / (u.m ** 2 * u.nm))) - def test_calcBackgrounde(self): + def test_calcBackground(self): self.assertEqual(self.atmosphere.calcBackground(), SpectralQty(np.arange(200, 208) << u.nm, np.array([1.1e-16, 1.2e-16, 1.3e-16, 1.4e-16, 1.5e-16, 1.6e-16, 1.7e-16, diff --git a/tests/sensor/test_Heterodyne.py b/tests/sensor/test_Heterodyne.py index e6b75fb..92e0282 100644 --- a/tests/sensor/test_Heterodyne.py +++ b/tests/sensor/test_Heterodyne.py @@ -17,7 +17,7 @@ class TestHeterodyne(TestCase): receiver_temp=1050 * u.K, eta_fss=0.97, lambda_line=157.774 * u.um, kappa=1.0, common_conf=self.config.common) self.target = FileTarget("tests/data/target/line.csv", self.config.common.wl_bins()) - self.atmosphere = Atmosphere(self.target, "tests/data/atmosphere/transmittance_great.csv") + self.atmosphere = Atmosphere(parent=self.target, transmittance="tests/data/atmosphere/transmittance_great.csv") self.cosmic = CosmicBackground(self.atmosphere, temp=220 * u.K, emissivity=0.14) self.mirror = Mirror(self.cosmic, reflectance="tests/data/mirror/reflectance_great.csv", emissivity=0.08, temp=230 * u.K) @@ -36,13 +36,13 @@ class TestHeterodyne(TestCase): def test_getSensitivity(self): exp_time = 1900 * u.s target = BlackBodyTarget(self.config.common.wl_bins(), mag=20 * u.mag) - atmosphere = Atmosphere(target, "tests/data/atmosphere/transmittance_great.csv") + atmosphere = Atmosphere(parent=target, transmittance="tests/data/atmosphere/transmittance_great.csv") cosmic = CosmicBackground(atmosphere, temp=220 * u.K, emissivity=0.14) mirror = Mirror(cosmic, reflectance="tests/data/mirror/reflectance_great.csv", emissivity=0.08, temp=230 * u.K) heterodyne = Heterodyne(mirror, **self.heterodyne_args) snr = heterodyne.getSNR(exp_time) target = BlackBodyTarget(self.config.common.wl_bins(), mag=10 * u.mag) - atmosphere = Atmosphere(target, "tests/data/atmosphere/transmittance_great.csv") + atmosphere = Atmosphere(parent=target, transmittance="tests/data/atmosphere/transmittance_great.csv") cosmic = CosmicBackground(atmosphere, temp=220 * u.K, emissivity=0.14) mirror = Mirror(cosmic, reflectance="tests/data/mirror/reflectance_great.csv", emissivity=0.08, temp=230 * u.K) heterodyne = Heterodyne(mirror, **self.heterodyne_args) diff --git a/tests/test_RadiantFactory.py b/tests/test_RadiantFactory.py index d8a2bad..41f2e78 100644 --- a/tests/test_RadiantFactory.py +++ b/tests/test_RadiantFactory.py @@ -16,8 +16,8 @@ class TestRadiantFactory(TestCase): parent = oc_factory.fromConfigBatch(conf, parent) parent_2 = BlackBodyTarget(conf.common.wl_bins(), 5778 * u.K, 10 * u.mag, "V") - parent_2 = oc.Atmosphere(parent_2, "tests/data/atmosphere/transmittance.csv", - "tests/data/atmosphere/emission.csv") + parent_2 = oc.Atmosphere(parent=parent_2, transmittance="tests/data/atmosphere/transmittance.csv", + emission="tests/data/atmosphere/emission.csv") parent_2 = oc.StrayLight(parent_2, "tests/data/straylight/emission.csv") parent_2 = oc.Mirror(parent_2, "tests/data/mirror/reflectance.csv", "tests/data/mirror/emissivity.csv", 70 * u.K, obstruction=0.1, obstructor_temp=70 * u.K)