Skip to content

Commit

Permalink
pytests re-written (and Camera fixed to require units, which we also …
Browse files Browse the repository at this point in the history
…test for now).
  • Loading branch information
Juan Cabanela committed Jul 18, 2023
1 parent 1fae7ae commit 6ed2bdc
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 25 deletions.
39 changes: 26 additions & 13 deletions stellarphot/core.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
from astropy import units as u
from astropy.table import QTable, Table, Column

from astropy import units as u
from astropy.coordinates import EarthLocation, SkyCoord
from astropy.timeseries.core import BaseTimeSeries, autocheck_required_columns
from astropy.time import Time

import numpy as np
Expand All @@ -23,7 +20,7 @@ class Camera:
times the image data matches the unit of the `read_noise`.
read_noise : `astropy.quantity.Quantity`
The read noise of the camera in units of electrons.
The read noise of the camera with units
dark_current : `astropy.quantity.Quantity`
The dark current of the camera in units such that, when multiplied by
Expand Down Expand Up @@ -67,12 +64,27 @@ def __init__(self, gain=1.0 * u.electron / u.adu,
read_noise=1.0 * u.electron,
dark_current=0.01 * u.electron / u.second):
super().__init__()
self.gain = gain
self.read_noise = read_noise
self.dark_current = dark_current

# Check that input has units and if not crap out.
if isinstance(gain, u.Quantity):
self.gain = gain
else:
raise TypeError("gain must have units.")

if isinstance(read_noise, u.Quantity):
self.read_noise = read_noise
else:
raise TypeError("read_noise must have units.")

if isinstance(dark_current, u.Quantity):
self.dark_current = dark_current
else:
raise TypeError("dark_current must have units.")

def copy(self):
return Camera(gain=self.gain, read_noise=self.read_noise, dark_current=self.dark_current)
return Camera(gain=self.gain,
read_noise=self.read_noise,
dark_current=self.dark_current)

def __copy__(self):
return self.copy()
Expand Down Expand Up @@ -107,14 +119,15 @@ class BaseEnhancedTable(QTable):
"""

def __init__(self, table_description, data):
# Confirm a proper table description is passed (that is dict-like with keys and values)
# Confirm a proper table description is passed (that is dict-like with keys and
# values)
try:
self._table_description = {k: v for k, v in table_description.items()}
except AttributeError:
raise TypeError(f"You must provide a dict as table_description (it is type {type(self._table_description)}).")

# Build the data table
if not isinstance(data, QTable):
if not isinstance(data, Table):
raise TypeError(f"You must provide an astropy QTable as data (it is type {type(data)}).")
else:
# Check the format of the data table matches the table_description by checking
Expand Down Expand Up @@ -263,7 +276,7 @@ def __init__(self, observatory, camera, data, passband_map=None, retain_user_co
raise ValueError(f"data['date-obs'] astropy.time.Time must have scale='utc', not \'{data['date-obs'][0].scale}\'.")
except AttributeError:
# Happens if first item dosn't have a "scale"
raise ValueError(f"data['date-obs'] is not column of astropy.time.Time objects.")
raise ValueError("data['date-obs'] is not column of astropy.time.Time objects.")

# Check for consistency of counts-related columns
counts_columns = ['aperture_sum', 'annulus_sum', 'sky_per_pix_avg', 'sky_per_pix_med',
Expand Down Expand Up @@ -296,7 +309,7 @@ def __init__(self, observatory, camera, data, passband_map=None, retain_user_co

case 'snr':
# Since noise in counts, the proper way to compute SNR is sqrt(gain)*counts/noise
self['snr'] = np.sqrt(self.camera.gain) * self['aperture_net_cnts'].value / self['noise'].value
self['snr'] = np.sqrt(self.camera.gain.value) * self['aperture_net_cnts'].value / self['noise'].value

case 'bjd':
self['bjd'] = self.add_bjd_col()
Expand All @@ -317,7 +330,7 @@ def __init__(self, observatory, camera, data, passband_map=None, retain_user_co
self['night'] = Column(data=np.array((Time(self['date-obs']) + shift).to_value('mjd'), dtype=int), name='night')

case 'mag_inst':
self['mag_inst'] = -2.5 * np.log10(self.camera.gain * self['aperture_net_cnts'].value /
self['mag_inst'] = -2.5 * np.log10(self.camera.gain.value * self['aperture_net_cnts'].value /
self['exposure'].value)

case 'mag_error':
Expand Down
38 changes: 26 additions & 12 deletions stellarphot/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@


def test_camera_attributes():
gain = 2.0
read_noise = 10
dark_current = 0.01
gain = 2.0 * u.electron / u.adu
read_noise = 10 * u.electron
dark_current = 0.01 * u.electron / u.second
c = Camera(gain=gain, read_noise=read_noise, dark_current=dark_current)
assert c.gain == gain
assert c.dark_current == dark_current
assert c.read_noise == read_noise


def test_camera_unitscheck():
gain = 2.0
read_noise = 10
dark_current = 0.01
with pytest.raises(TypeError):
c = Camera(gain=gain, read_noise=read_noise, dark_current=dark_current)


# Create several test descriptions for use in base_enhanced_table tests.
test_descript = {'id': None,
'ra': u.deg,
Expand All @@ -40,7 +48,9 @@ def test_camera_attributes():
testdata = Table(data, names=colnames, dtype=coltypes, units=colunits)

# Define some configuration information assuming Feder telescope
feder_cg_16m = Camera(gain=1.5, read_noise=10.0, dark_current=0.01)
feder_cg_16m = Camera(gain = 1.5 * u.electron / u.adu,
read_noise = 10.0 * u.electron,
dark_current=0.01 * u.electron / u.second)
feder_passbands = {'up':'SU', 'gp':'SG', 'rp':'SR', 'zp':'SZ', 'ip':'SI'}
feder_obs = EarthLocation(lat = 46.86678,lon=-96.45328, height=311)

Expand Down Expand Up @@ -123,8 +133,8 @@ def test_base_enhanced_table_blank():
def test_base_enhanced_table_from_existing_table():
# Should create a populated dataset properly and display the astropy data
test_base2 = BaseEnhancedTable(test_descript, testdata)
assert len(test_base2.data['ra']) == 1
assert len(test_base2.data['dec']) == 1
assert len(test_base2['ra']) == 1
assert len(test_base2['dec']) == 1


def test_base_enhanced_table_no_inputs():
Expand All @@ -137,7 +147,7 @@ def test_base_enhanced_table_missing_column():
# Should raise exception because the RA data is missing from input data
testdata_nora = testdata.copy()
testdata_nora.remove_column('ra')
with pytest.raises(KeyError):
with pytest.raises(ValueError):
test_base = BaseEnhancedTable(test_descript, testdata_nora)


Expand All @@ -155,9 +165,9 @@ def test_photometry_data():
phot_data = PhotometryData(observatory=feder_obs, camera=feder_cg_16m, passband_map=feder_passbands, data=testphot_clean)

# Check some aspects of that data are sound
assert phot_data.camera.gain == 1.5
assert phot_data.camera.read_noise == 10.0
assert phot_data.camera.dark_current == 0.01
assert phot_data.camera.gain == 1.5 * u.electron / u.adu
assert phot_data.camera.read_noise == 10.0 * u.electron
assert phot_data.camera.dark_current == 0.01 * u.electron / u.second
assert phot_data.observatory.lat.value == 46.86678
assert phot_data.observatory.lat.unit == u.deg
assert phot_data.observatory.lon.value == -96.45328
Expand All @@ -175,7 +185,7 @@ def test_photometry_data():
# Dec 22 30 20.77733059
# which had a result of 2459910.775405664 (Uses IDL routine, astropy is SOFA checked).
# Demand a difference of less than 1/20 of a second.
assert (phot_data.data['bjd'][0].value - 2459910.775405664)*86400 < 0.05
assert (phot_data['bjd'][0].value - 2459910.775405664)*86400 < 0.05

def test_photometry_badtime():
with pytest.raises(ValueError):
Expand All @@ -194,5 +204,9 @@ def test_photometry_inconsistent_computed_col_exists():
phot_data = PhotometryData(observatory=feder_obs, camera=feder_cg_16m, passband_map=feder_passbands, data=testphot_goodUnits)

phot_data = PhotometryData(observatory=feder_obs, camera=feder_cg_16m, passband_map=feder_passbands, data=testphot_goodUnits, retain_user_computed=True)
assert np.abs(phot_data['snr'][0] - 46.795229859903905) < 1e-6
# This keeps a bad user column for 'snr' which has bogus units, so check the units
# cause a crash in the math.
with pytest.raises(u.core.UnitConversionError):
assert np.abs(phot_data['snr'][0] - 46.795229859903905) < 1e-6
assert np.abs(phot_data['snr'][0].value - 46.795229859903905) < 1e-6

0 comments on commit 6ed2bdc

Please sign in to comment.