Skip to content

Commit

Permalink
Prepping rtd
Browse files Browse the repository at this point in the history
  • Loading branch information
bmorris3 committed Jan 20, 2019
1 parent 1977d15 commit 2d5a80b
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 48 deletions.
28 changes: 0 additions & 28 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,35 +75,12 @@ matrix:
- os: osx
env: SETUP_CMD='test'

# Do a coverage test.
- os: linux
env: SETUP_CMD='test --coverage'

# Check for sphinx doc build warnings - we do this first because it
# may run for a long time
- os: linux
env: SETUP_CMD='build_docs -w'
CONDA_DEPENDENCIES=$CONDA_DEPENDENCIES_DOC

# Now try Astropy dev with the latest Python and LTS with Python 2.7 and 3.x.
- os: linux
env: ASTROPY_VERSION=development
EVENT_TYPE='pull_request push cron'
- os: linux
env: ASTROPY_VERSION=lts

# Try all python versions and Numpy versions. Since we can assume that
# the Numpy developers have taken care of testing Numpy with different
# versions of Python, we can vary Python and Numpy versions at the same
# time.

- os: linux
env: PYTHON_VERSION=3.5 NUMPY_VERSION=1.12
- os: linux
env: PYTHON_VERSION=3.6 NUMPY_VERSION=1.13
- os: linux
env: NUMPY_VERSION=1.14

# Try numpy pre-release
- os: linux
env: NUMPY_VERSION=prerelease
Expand All @@ -113,11 +90,6 @@ matrix:
- os: linux
env: MAIN_CMD='flake8 telescopy --count --show-source --statistics $FLAKE8_OPT' SETUP_CMD=''

allow_failures:
# Do a PEP8 test with flake8
# (allow to fail unless your code completely compliant)
- os: linux
env: MAIN_CMD='flake8 telescopy --count --show-source --statistics $FLAKE8_OPT' SETUP_CMD=''

install:

Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@


html_theme_options = {
'logotext1': 'telescopy', # white, semi-bold
'logotext2': '', # orange, light
'logotext1': 'telesco', # white, semi-bold
'logotext2': 'py', # orange, light
'logotext3': ':docs' # white, light
}

Expand Down
5 changes: 0 additions & 5 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,3 @@ This is the documentation for telescopy.
:maxdepth: 2

telescopy/index.rst

.. note:: The layout of this directory is simply a suggestion. To follow
traditional practice, do *not* edit this page, but instead place
all documentation for the package inside ``telescopy/``.
You can follow this practice or choose your own layout.
57 changes: 51 additions & 6 deletions telescopy/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,23 @@


class Filter(object):
"""
Transmissivity curve for a filter.
"""
def __init__(self, wavelength=None, transmissivity=None, path=None,
name=None):
"""
Parameters
----------
wavelength : `~astropy.units.Quantity`
Wavelength array for the transmissivity curve.
transmissivity : `~numpy.ndarray`
Transmissivity of the filter
path : str
Path to text transmissivity file
name : str
Name of the filter
"""
self.path = path
self.name = name

Expand All @@ -29,20 +44,50 @@ def __init__(self, wavelength=None, transmissivity=None, path=None,

@classmethod
def from_name(cls, name):
"""
Transmissivity of a built-in filter.
Parameters
----------
name : str
Must be one of the filters returned by
`~telescopy.Filter.available_filters()`.
"""
path = os.path.join(filter_path, '*' + name.replace('_', '.') + '.txt')
globbed_path = glob(path)
if len(globbed_path) < 1:
raise ValueError('No filter found matching name "{0}"'.format(name))
return cls(path=globbed_path[0], name=name)

@staticmethod
def available_filters():
"""
Available filters stored in telescopy.
Returns
-------
filters : list
List of available filter names
"""
return [i.split('_')[1].replace('.', '_')[:-4]
for i in glob(os.path.join(filter_path, '*'))]

def plot(self, ax=None):
"""
Plot the transmissivity curve of a filter
Parameters
----------
ax : `~matplotlib.pyplot.Axes` or None
Axis object.
Returns
-------
ax : `~matplotlib.pyplot.Axes`
Plot with transmissivity curve
"""
if ax is None:
fig, ax = plt.subplots()
ax.plot(self.wavelength, self.transmissivity)
ax.set(xlabel='Wavelength [Angstrom]', ylabel='Transmissivity')
return ax

@staticmethod
def available_filters():
return [i.split('_')[1].replace('.', '_')[:-4]
for i in glob(os.path.join(filter_path, '*'))]
return ax
69 changes: 63 additions & 6 deletions telescopy/imager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,27 @@ def gaussian_2d(x, y, x0, y0, std):


class Imager(object):
"""
Container for an imager.
"""
@u.quantity_input(plate_scale=u.arcsec, seeing=u.arcsec)
def __init__(self, plate_scale=None, seeing=None, binning=None,
quantum_efficiency=None, gain=None):
self.plate_scale = plate_scale
"""
Parameters
----------
plate_scale : `~astropy.units.Quantity`
Plate scale of detector in units of arcsec (per pixel)
seeing : `~astropy.units.Quantity`
Astronomical seeing at time of observation
binning : int
Pixel binning factor
quantum_efficiency : float
Quantum efficiency of the detector
gain : float
Gain of the detector (e-'s per ADU)
"""
self.plate_scale = plate_scale # arcsec / pixel
self.seeing = seeing

if quantum_efficiency is None:
Expand All @@ -22,18 +39,58 @@ def __init__(self, plate_scale=None, seeing=None, binning=None,

if binning is None:
binning = 1
self.binning = binning
self.binning = binning # assumes square?

if gain is None:
gain = 1.0
self.gain = gain
self.gain = gain # e- / ADU

@u.quantity_input(exposure_duration=u.s)
def image(self, telescope, target, exposure_duration, n=20):
total_electrons = (telescope.photons(target, exposure_duration) *
self.quantum_efficiency / self.gain)
"""
Generate an image of ``target`` observed by ``telescope``.
Parameters
----------
telescope : `~telescopy.Telescope`
Telescope object
target : `~telescopy.Target`
Target object
exposure_duration : `~astropy.units.Quantity`
Exposure duration (s, or compatible unit)
n : int
Pixel length of a side of the image returned
Returns
-------
image : `~numpy.ndarray`
Simulated image of ``target``.
"""
total_counts = self.counts(telescope, target, exposure_duration)
x, y = np.mgrid[:n, :n]
spread = float(self.seeing / self.plate_scale / self.binning)
img = gaussian_2d(x - n/2, y - n/2, 0, 0, spread) * total_electrons
img = gaussian_2d(x - n/2, y - n/2, 0, 0, spread) * total_counts
return np.array(img, dtype=int)

def counts(self, telescope, target, exposure_duration):
"""
Number of ADU detected by the detector.
Parameters
----------
telescope : `~telescopy.Telescope`
Telescope object
target : `~telescopy.Target`
Target object
exposure_duration : `~astropy.units.Quantity`
Exposure duration (s, or compatible unit)
Returns
-------
total_counts : float
Number of counts estimated in the exposure.
"""
total_electrons = (telescope.photons(target, exposure_duration) *
self.quantum_efficiency)
total_counts = total_electrons / self.gain
return total_counts
41 changes: 40 additions & 1 deletion telescopy/telescope.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,64 @@ def relative_flux(m1, m2):


class Telescope(object):
"""
Container for information about a telescope.
"""
@u.quantity_input(aperture_diameter=u.m)
def __init__(self, aperture_diameter=None, throughput=None):
"""
Parameters
----------
aperture_diameter : `~astropy.units.Quantity`
(Effective) Diameter of the primary mirror
throughput : float
Telescope throughput
"""
self.aperture_diameter = aperture_diameter
self.throughput = throughput

@u.quantity_input(exposure_duration=u.s)
def photons(self, target, exposure_duration):
"""
Compute the number of photons detected in an ``exposure_duration``
exposure of ``target``.
Parameters
----------
target : `~telescopy.Target`
Target object
exposure_duration : `~astropy.units.Quantity`
Length of the exposure
Returns
-------
n_photons : int
Number of photons observed.
"""
flux_scale = relative_flux(target.magnitude,
vega.mag(target.filter.name))

telescope_aperture = np.pi * (self.aperture_diameter / 2)**2
energy = (flux_scale * vega.integrate_filter(target.filter) *
telescope_aperture * self.throughput * exposure_duration)
nu = c / target.filter.lam0
n_photons = int((energy / (h * nu)).decompose())
n_photons = int(energy / (h * nu))
return n_photons


class Target(object):
"""
Container for target metadata.
"""
def __init__(self, magnitude=None, filter=None):
"""
Parameters
----------
magnitude : float
Target magnitude in ``filter``
filter : `~telescopy.Filter`
Filter object.
"""
self.magnitude = magnitude
self.filter = filter
43 changes: 43 additions & 0 deletions telescopy/vega.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@


class Vega(object):
"""
Container object for the spectrum of Vega.
"""
def __init__(self):
# TODO: lazy load
vega = fits.getdata(vega_path)
Expand All @@ -23,6 +26,19 @@ def __init__(self):
self._mags = None

def plot(self, ax=None):
"""
Plot Vega's flux-calibrated spectrum.
Parameters
----------
ax : `~matplotlib.pyplot.Axes` or None
Axis object.
Returns
-------
ax : `~matplotlib.pyplot.Axes`
Plot with spectrum of Vega
"""
if ax is None:
fig, ax = plt.subplots()
ax.semilogx(self.wavelength, self.flam)
Expand All @@ -31,13 +47,40 @@ def plot(self, ax=None):
return ax

def integrate_filter(self, filter):
"""
Integrate Vega's spectral flux density within ``filter``.
Parameters
----------
filter : `~telescopy.Filter`
Filter object
Returns
-------
flux : `~astropy.units.Quantity`
Flux within ``filter``
"""
interp_transmissivity = np.interp(self.wavelength, filter.wavelength,
filter.transmissivity,
left=0, right=0)
flux = self.flam * self.wavelength * interp_transmissivity
return np.sum(flux)

def mag(self, filter_name):
"""
Vega's magnitude in filter ``filter_name``
Parameters
----------
filter_name : str
Name of filter. Must be one of the filters returned by
`~telescopy.Filter.available_filters()`.
Returns
-------
mag : float
Magnitude of Vega in ``filter_name``
"""
if self._mags is None:
self._mags = load(open(mags_path))
return self._mags[filter_name]
Expand Down

0 comments on commit 2d5a80b

Please sign in to comment.