From 36097dbeb89c68e21af74edee9db85a08eaac1c6 Mon Sep 17 00:00:00 2001 From: LukasK13 Date: Thu, 9 Apr 2020 17:51:55 +0200 Subject: [PATCH] calculate signal and noise --- .../optical_component/AOpticalComponent.py | 34 ++++++++++++++---- tests/test_AOpticalComponent.py | 35 +++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 tests/test_AOpticalComponent.py diff --git a/esbo_etc/classes/optical_component/AOpticalComponent.py b/esbo_etc/classes/optical_component/AOpticalComponent.py index ae4f7df..f3da6c8 100644 --- a/esbo_etc/classes/optical_component/AOpticalComponent.py +++ b/esbo_etc/classes/optical_component/AOpticalComponent.py @@ -1,7 +1,9 @@ from ..ITransmissive import ITransmissive from abc import abstractmethod from ..SpectralQty import SpectralQty -import copy +from esbo_etc.lib.helpers import error +import astropy.units as u +from astropy.modeling.models import BlackBody class AOpticalComponent(ITransmissive): @@ -10,8 +12,10 @@ class AOpticalComponent(ITransmissive): """ @abstractmethod + @u.quantity_input(obstructor_temp=[u.K, u.Celsius]) def __init__(self, parent: ITransmissive, transreflectivity: SpectralQty = None, - noise: SpectralQty = None, obstruction: float = 0): + noise: SpectralQty = None, obstruction: float = 0, obstructor_temp: u.Quantity = 0 * u.K, + obstructor_emissivity: float = 0): """ Initialize a new optical component @@ -31,6 +35,10 @@ class AOpticalComponent(ITransmissive): denotes a completely obstructed component with therefore no incoming flux. It is important to note, that the obstruction factor reflects the obstruction of the optical component additionally to the obstruction factors of the prior elements in the beam. + obstructor_temp : Quantity in Kelvin / Celsius + Temperature of the obstructing component. + obstructor_emissivity : float + Emissivity of the obstructing component. """ self._parent = parent if transreflectivity: @@ -38,6 +46,8 @@ class AOpticalComponent(ITransmissive): if noise: self._noise = noise self._obstruction = obstruction + self._obstructor_temp = obstructor_temp + self._obstructor_emissivity = obstructor_emissivity def calcSignal(self) -> SpectralQty: """ @@ -48,7 +58,7 @@ class AOpticalComponent(ITransmissive): signal : SpectralQty The spectral flux density of the target's signal """ - return self.propagate(copy.deepcopy(self._parent.calcSignal())).multiply(1 - self._obstruction) + return self.propagate(self._parent.calcSignal()) * (1 - self._obstruction) def calcNoise(self) -> SpectralQty: """ @@ -59,7 +69,13 @@ class AOpticalComponent(ITransmissive): noise : SpectralQty The spectral radiance of the target's noise """ - return self.propagate(copy.deepcopy(self._parent.calcNoise())).add(self.ownNoise()) + parent = self.propagate(self._parent.calcNoise()) + if self._obstructor_temp > 0 * u.K: + bb = BlackBody(temperature=self._obstructor_temp, scale=1. * u.W / (u.m ** 2 * u.nm * u.sr)) + obstructor = bb(parent.wl) * self._obstructor_emissivity + return parent * (1. - self._obstruction) + obstructor * self._obstruction + self.ownNoise() + else: + return parent * (1. - self._obstruction) + self.ownNoise() def propagate(self, sqty: SpectralQty) -> SpectralQty: """ @@ -75,7 +91,10 @@ class AOpticalComponent(ITransmissive): sqty : SpectralQty Manipulated incoming radiation """ - return sqty.multiply(self._transreflectivity) + if hasattr(self, "_transreflectivity"): + return sqty * self._transreflectivity + else: + error("Transreflectivity not given. Method propagate() needs to be implemented.") def ownNoise(self) -> SpectralQty: """ @@ -86,4 +105,7 @@ class AOpticalComponent(ITransmissive): sqty : SpectralQty The noise created by the optical component """ - return self._noise + if hasattr(self, "_noise"): + return self._noise + else: + error("noise not given. Method ownNoise() needs to be implemented.") diff --git a/tests/test_AOpticalComponent.py b/tests/test_AOpticalComponent.py new file mode 100644 index 0000000..0e074ce --- /dev/null +++ b/tests/test_AOpticalComponent.py @@ -0,0 +1,35 @@ +from unittest import TestCase +from esbo_etc.classes import * +import astropy.units as u +import numpy as np + + +class OpticalComponent(AOpticalComponent): + def __init__(self, parent: ITransmissive, transreflectivity: SpectralQty = None, + noise: SpectralQty = None, obstruction: float = 0, obstructor_temp: u.Quantity = 0 * u.K, + obstructor_emissivity: float = 0): + super().__init__(parent, transreflectivity, noise, obstruction, obstructor_temp, obstructor_emissivity) + + +class TestAOpticalComponent(TestCase): + wl = np.arange(4, 8, 1) << u.um + + def setUp(self): + self.target = BlackBodyTarget(self.wl, temp=5778 * u.K, mag=10 * u.mag, band="U") + self.comp = OpticalComponent(self.target, SpectralQty(self.wl, [0.5] * 4), + SpectralQty(self.wl, [1e-5] * 4 << u.W / (u.m ** 2 * u.nm * u.sr)), + obstruction=0.1, obstructor_temp=300 * u.K, obstructor_emissivity=1) + + def test_calcSignal(self): + self.assertEqual(self.comp.calcSignal(), SpectralQty(self.wl, [1.25575776e-17, 5.50570557e-18, 2.77637739e-18, + 1.54664415e-18] << u.W / (u.m ** 2 * u.nm))) + + def test_calcNoise(self): + self.assertEqual(self.comp.calcNoise(), + SpectralQty(self.wl, [8.21976423e-05, 2.70268340e-04, 5.27503292e-04, + 7.60597616e-04] << u.W / (u.m ** 2 * u.nm * u.sr))) + comp = OpticalComponent(self.comp, SpectralQty(self.wl, [0.5] * 4), + SpectralQty(self.wl, [0] * 4 << u.W / (u.m ** 2 * u.nm * u.sr)), + obstruction=0.1, obstructor_temp=300 * u.K, obstructor_emissivity=1) + self.assertEqual(comp.calcNoise(), SpectralQty(self.wl, [1.09186581e-04, 3.81889092e-04, 7.54879773e-04, + 10.92866544e-04] << u.W / (u.m ** 2 * u.nm * u.sr)))