Filter added

This commit is contained in:
Lukas Klass 2020-04-15 16:35:35 +02:00
parent afd3a0bf6d
commit 24de24aa6a
3 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,199 @@
from .AHotOpticalComponent import AHotOpticalComponent
from ..SpectralQty import SpectralQty
from ..ITransmissive import ITransmissive
from ...lib.helpers import error
from astropy import units as u
from typing import Union, Callable
class Filter(AHotOpticalComponent):
"""
A class to model a filter component and its thermal emission. The model can be created from a file, the name of
a band or a custom spectral range.
"""
_band_central_wl = dict(U=366 * u.nm, B=438 * u.nm, V=545 * u.nm, R=641 * u.nm, I=798 * u.nm, J=1220 * u.nm,
H=1630 * u.nm, K=2190 * u.nm)
_band_bandwidth = dict(U=68 * u.nm, B=98 * u.nm, V=89 * u.nm, R=220 * u.nm, I=240 * u.nm, J=300 * u.nm, H=400 * u.nm,
K=600 * u.nm)
@u.quantity_input(temp=[u.Kelvin, u.Celsius], obstructor_temp=[u.Kelvin, u.Celsius])
def __init__(self, parent: ITransmissive, transmittance: Union[SpectralQty, Callable],
emissivity: Union[SpectralQty, int, float] = 1, temp: u.Quantity = 0 * u.K, obstruction: float = 0,
obstructor_temp: u.Quantity = 0 * u.K, obstructor_emissivity: float = 1):
"""
Instantiate a new filter model
Parameters
----------
parent : ITransmissive
The parent element of the optical component from which the electromagnetic radiation is received.
transmittance : Union[SpectralQty, Callable]
The spectral transmittance coefficients of the filter.
emissivity : SpectralQty
The spectral emissivity coefficient for the optical surface.
temp: Quantity in Kelvin / Celsius
Temperature of the optical component
obstruction : float
The additional obstruction factor of the optical component. 0 means the component is not obstructed, 1
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.
"""
super().__init__(parent, emissivity, temp, obstruction, obstructor_temp, obstructor_emissivity)
self._transmittance = transmittance
@classmethod
# @u.quantity_input(temp=[u.Kelvin, u.Celsius], obstructor_temp=[u.Kelvin, u.Celsius])
def fromBand(cls, parent: ITransmissive, band: str, emissivity: Union[str, int, float] = 1,
temp: u.Quantity = 0 * u.K, obstruction: float = 0, obstructor_temp: u.Quantity = 0 * u.K,
obstructor_emissivity: float = 1) -> "Filter":
"""
Instantiate a new filter model from a spectral band. The filter will be modelled as bandpass filter of
infinite order and therefore similar to a hat-function.
Parameters
----------
parent : ITransmissive
The parent element of the optical component from which the electromagnetic radiation is received.
band : str
The spectral band of the filter. Can be one of [U, B, V, R, I, J, H, K].
emissivity : SpectralQty
The spectral emissivity coefficient for the optical surface.
temp: Quantity in Kelvin / Celsius
Temperature of the optical component
obstruction : float
The additional obstruction factor of the optical component. 0 means the component is not obstructed, 1
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.
Returns
-------
filter : Filter
The instantiated filter object.
"""
if band not in cls._band_central_wl.keys():
error("Band has to be one of '[" + ", ".join(list(cls._band_central_wl.keys())) + "]'")
return cls.fromRange(parent, cls._band_central_wl[band] - cls._band_bandwidth[band] / 2,
cls._band_central_wl[band] + cls._band_bandwidth[band] / 2, emissivity, temp, obstruction,
obstructor_temp, obstructor_emissivity)
@classmethod
# @u.quantity_input(temp=[u.Kelvin, u.Celsius], obstructor_temp=[u.Kelvin, u.Celsius])
def fromFile(cls, parent: ITransmissive, transmittance: str, emissivity: Union[str, int, float] = 1,
temp: u.Quantity = 0 * u.K, obstruction: float = 0, obstructor_temp: u.Quantity = 0 * u.K,
obstructor_emissivity: float = 1) -> "Filter":
"""
Instantiate a new filter model from a file containing the spectral transmittance coefficients.
Parameters
----------
parent : ITransmissive
The parent element of the optical component from which the electromagnetic radiation is received.
transmittance : str
Path to the file containing the spectral transmittance-coefficients of the filter element.
The format of the file will be guessed by `astropy.io.ascii.read()`.
emissivity : SpectralQty
The spectral emissivity coefficient for the optical surface.
temp: Quantity in Kelvin / Celsius
Temperature of the optical component
obstruction : float
The additional obstruction factor of the optical component. 0 means the component is not obstructed, 1
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.
Returns
-------
filter : Filter
The instantiated filter object.
"""
return cls(parent, SpectralQty.fromFile(transmittance, u.nm, u.dimensionless_unscaled), emissivity, temp,
obstruction, obstructor_temp, obstructor_emissivity)
@classmethod
# @u.quantity_input(start="length", end="length", temp=[u.Kelvin, u.Celsius], obstructor_temp=[u.Kelvin, u.Celsius])
def fromRange(cls, parent: ITransmissive, start: u.Quantity, end: u.Quantity,
emissivity: Union[str, int, float] = 1, temp: u.Quantity = 0 * u.K, obstruction: float = 0,
obstructor_temp: u.Quantity = 0 * u.K, obstructor_emissivity: float = 1) -> "Filter":
"""
Instantiate a new filter model from a spectral range. The filter will be modelled as bandpass filter of
infinite order and therefore similar to a hat-function.
Parameters
----------
parent : ITransmissive
The parent element of the optical component from which the electromagnetic radiation is received.
start : length-quantity
Start wavelength of the pass-band
end : length-quantity
End wavelength of the pass-band
emissivity : SpectralQty
The spectral emissivity coefficient for the optical surface.
temp: Quantity in Kelvin / Celsius
Temperature of the optical component
obstruction : float
The additional obstruction factor of the optical component. 0 means the component is not obstructed, 1
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.
Returns
-------
filter : Filter
The instantiated filter object.
"""
return cls(parent, cls._filter_factory(start, end), emissivity, temp,
obstruction, obstructor_temp, obstructor_emissivity)
def propagate(self, sqty: SpectralQty) -> SpectralQty:
"""
Propagate incoming radiation through the optical component
Parameters
----------
sqty : SpectralQty
The incoming radiation
Returns
-------
sqty : SpectralQty
Manipulated incoming radiation
"""
return sqty * self._transmittance
@staticmethod
# @u.quantity_input(start="length", end="length")
def _filter_factory(start: u.Quantity, end: u.Quantity):
"""
Create a infinite order bandpass filter
Parameters
----------
start : length-quantity
Start wavelength of the pass-band
end : length-quantity
End wavelength of the pass-band
Returns
-------
lambda : Callable
The filter function
"""
return lambda wl: 1 * u.dimensionless_unscaled if start <= wl <= end else 0 * u.dimensionless_unscaled

View File

@ -2,3 +2,4 @@ from esbo_etc.classes.optical_component.AOpticalComponent import *
from esbo_etc.classes.optical_component.Atmosphere import *
from esbo_etc.classes.optical_component.StrayLight import *
from esbo_etc.classes.optical_component.AHotOpticalComponent import *
from esbo_etc.classes.optical_component.Filter import *

21
tests/test_Filter.py Normal file
View File

@ -0,0 +1,21 @@
from unittest import TestCase
from esbo_etc import Filter, BlackBodyTarget, FileTarget, SpectralQty
import numpy as np
import astropy.units as u
class TestFilter(TestCase):
def test_fromBand(self):
wl = [400, 500, 501, 545, 589, 590, 600] << u.nm
target = BlackBodyTarget(wl, temp=5778 * u.K, mag=10 * u.mag, band="U")
filt = Filter.fromBand(target, "V")
self.assertEqual(filt.calcSignal(), SpectralQty(wl, [0.0, 0.0, 5.46516556e-15, 5.37748512e-15, 5.15313966e-15,
0.0, 0.0] << u.W / (u.m ** 2 * u.nm)))
def test_fromFile(self):
target = FileTarget("data/target/target_demo_1.csv")
filt = Filter.fromFile(target, "data/filter/filter_transmittance.csv")
self.assertEqual(filt.calcSignal(), SpectralQty(np.arange(200, 210, 1) << u.nm,
[1.10e-15, 1.20e-15, 1.30e-15, 1.40e-15, 1.35e-15, 1.44e-15,
1.53e-15, 1.44e-15, 1.52e-15, 1.40e-15] << u.W / (
u.m ** 2 * u.nm)))