Skip to content

Commit

Permalink
new API for lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
bmorris3 committed Aug 19, 2024
1 parent 4e65b98 commit c5b0ad4
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 14 deletions.
47 changes: 47 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,53 @@ Contents
Simple example
^^^^^^^^^^^^^^

Find available filters like this:

.. code-block:: python
>>> from tynt.lookup import filters
>>> # filters.<TAB> # this works in a Jupyter environment, OR:
>>> dir(filters) # this works in any interactive environment
['CAHA',
'CHEOPS',
'CTIO',
'GAIA',
...
To see the filters available within a filter set:
.. code-block:: python
>>> from tynt.lookup import filters
>>> filters.Kepler
<FilterSet: "Kepler"
Available filters: ["Kepler_K"]>
Plot the filter transmittance curve:
.. plot::
:include-source:
from tynt.lookup import filters
filters.Kepler.Kepler_K.plot()
Compare several optical filters:
.. plot::
:include-source:
from tynt.lookup import filters
filters.Kepler.Kepler_K.plot(label='Kepler')
filters.CHEOPS.CHEOPS_band.plot(label='CHEOPS')
filters.TESS.TESS_Red.plot(label='TESS')
FilterGenerator
^^^^^^^^^^^^^^^
Let's plot the transmittance curve of the SDSS r' filter:
.. plot::
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ setup_requires = setuptools_scm
install_requires =
numpy
astropy
matplotlib
scipy

[options.extras_require]
all =
Expand Down
85 changes: 77 additions & 8 deletions tynt/core.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import os

import numpy as np
import matplotlib.pyplot as plt

import astropy.units as u
from astropy.io import fits
from astropy.table import Table
from astropy.utils.data import download_file
from astropy.modeling import models
from astropy.modeling.tabular import Tabular1D
from astropy.table import Table
from astropy.utils.data import download_file
from astropy.visualization import quantity_support

__all__ = ['FilterGenerator', 'Filter']

Expand All @@ -17,7 +20,7 @@ class FilterGenerator:
"""
Astronomical filter object generator.
"""
def __init__(self, path=None):
def __init__(self, path=None, name=None):
"""
Parameters
----------
Expand All @@ -28,6 +31,7 @@ def __init__(self, path=None):
path = data_path

self.path = path
self.name = name
self.table = Table(fits.getdata(path))
self.table.add_index('Filter name')

Expand Down Expand Up @@ -152,8 +156,11 @@ def fft_model(x):

astropy_model = fft_model()

filter_set, filter_name = identifier.split('/')
return Filter(
wavelength * u.Angstrom, transmittance, model=astropy_model
wavelength * u.Angstrom, transmittance,
filter_set=filter_set, filter_name=identifier,
model=astropy_model
)

def download_true_transmittance(self, identifier, **kwargs):
Expand All @@ -174,18 +181,28 @@ def download_true_transmittance(self, identifier, **kwargs):
f'theory/fps3/fps.php?ID={identifier}', **kwargs)

true_transmittance = Table.read(path, format='votable')

filter_set, filter_name = identifier.split('/')

return Filter(
true_transmittance['Wavelength'].data.data * u.Angstrom,
true_transmittance['Transmission'].data.data
true_transmittance['Transmission'].data.data,
filter_set=filter_set, filter_name=identifier
)


_filter_generator = FilterGenerator()


class Filter:
"""
Astronomical filter.
"""
@u.quantity_input(wavelength=u.m)
def __init__(self, wavelength, transmittance, model=None):
def __init__(
self, wavelength=None, transmittance=None,
model=None, filter_set=None, filter_name=None
):
"""
Parameters
----------
Expand All @@ -196,9 +213,39 @@ def __init__(self, wavelength, transmittance, model=None):
model : ~astropy.modeling.Model
Astropy model for the transmittance curve
"""
self.wavelength = wavelength
self.transmittance = transmittance
self._wavelength = wavelength
self._transmittance = transmittance
self.model = model
self.filter_set = filter_set
self.filter_name = filter_name

@property
def wavelength(self):
if self._wavelength is None:
self._get_filter_from_name()
return self._wavelength

@wavelength.setter
def wavelength(self, value):
if value is not None:
self._wavelength = value

@property
def transmittance(self):
if self._transmittance is None:
self._get_filter_from_name()
return self._transmittance

@transmittance.setter
def transmittance(self, value):
if value is not None:
self._transmittance = value

def _get_filter_from_name(self):
name = f"{self.filter_set}/{self.filter_name.replace('__', '.')}"
filt = _filter_generator.reconstruct(name)
self.wavelength = filt.wavelength
self.transmittance = filt.transmittance

@property
def table(self):
Expand All @@ -212,3 +259,25 @@ def table(self):
"""
return Tabular1D(points=self.wavelength,
lookup_table=self.transmittance)

def __repr__(self):
if None not in (self.filter_name, self.filter_set):
return f"<Filter: {self.filter_set}/{self.filter_name}>"
return "<Filter>"

def plot(self, ax=None, x_unit=u.um, y_label='Transmittance', **kwargs):

if ax is None:
ax = plt.gca()

label = kwargs.pop('label', self.filter_name)

with quantity_support():
ax.plot(
self.wavelength.to(x_unit), self.transmittance,
label=label, **kwargs
)
ax.legend()

if y_label is not None:
ax.set(ylabel=y_label)
73 changes: 73 additions & 0 deletions tynt/lookup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from collections import defaultdict
from tynt.core import Filter, _filter_generator

__all__ = ['filters']


class FilterSet:

def __init__(self, filter_set, filter_names):
self._filter_set = filter_set
self._filter_names = filter_names
self.filters = set()
for filter_name in filter_names:
fname = filter_name.replace('.', '_')
setattr(
self, fname,
Filter(filter_set=filter_set, filter_name=filter_name)
)
self.filters.add(f'"{fname}"')

def __repr__(self):
return (f"<FilterSet: \"{self._filter_set}\"\n "
f"Available filters: [{', '.join(sorted(self.filters))}]>")


def assemble_filter_sets():

filter_sets = defaultdict(list)

for name in _filter_generator.available_filters():
filter_set, filter_name = name.split('/')
filter_sets[filter_set].append(filter_name)

sets = dict()
for filter_set, filter_names in filter_sets.items():
sets[filter_set] = FilterSet(filter_set, filter_names)

return sets


class DefaultFacilities:
TWOMASS = None
SLOAN = None
Kepler = None
TESS = None
HST = None
JWST = None
LSST = None
Keck = None
WISE = None
WFIRST = None
Roman = None
Spitzer = None
GAIA = None
CHEOPS = None


class FilterLookup(DefaultFacilities):
_accessors = set()

def __init__(self):

filter_sets = assemble_filter_sets()

for name, filter_set in filter_sets.items():
if name[0].isnumeric():
name = name.replace('2', 'TWO')

setattr(self, name, filter_set)
self._accessors.add(name)


filters = FilterLookup()
14 changes: 8 additions & 6 deletions tynt/tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
import numpy as np
from astropy.tests.helper import assert_quantity_allclose

import astropy.units as u
from astropy.tests.helper import assert_quantity_allclose
from scipy.integrate import trapezoid

from ..core import FilterGenerator
from tynt.core import FilterGenerator

filter_generator = FilterGenerator()

Expand Down Expand Up @@ -68,11 +70,11 @@ def test_lambda_eff_w_eff(
for identifier in filters:
filt = filter_generator.reconstruct(identifier)

lambda_bar_approx = (np.trapz(filt.transmittance * filt.wavelength,
filt.wavelength) /
np.trapz(filt.transmittance, filt.wavelength))
lambda_bar_approx = (trapezoid(filt.transmittance * filt.wavelength,
filt.wavelength) /
trapezoid(filt.transmittance, filt.wavelength))

width_approx = (np.trapz(filt.transmittance, filt.wavelength) /
width_approx = (trapezoid(filt.transmittance, filt.wavelength) /
filt.transmittance.max())

w_eff_approx.append(width_approx)
Expand Down

0 comments on commit c5b0ad4

Please sign in to comment.