Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for subsets in time #12

Merged
merged 5 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions lcviz/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import numpy as np
import pytest
from astropy import units as u
from astropy.utils.masked import Masked
from lightkurve import LightCurve

from lcviz import __version__, LCviz
Expand All @@ -22,7 +21,6 @@ def light_curve_like_kepler_quarter(seed=42):
"""
np.random.seed(seed)
exp_per_day = (30 * u.min).to_value(u.day)
masked_fraction = 0.01

# approx start and stop JD for Kepler Quarter 10:
time = np.arange(2455739, 2455833, exp_per_day)
Expand All @@ -32,19 +30,10 @@ def light_curve_like_kepler_quarter(seed=42):
) * u.dimensionless_unscaled
flux_err = scale * np.ones_like(flux)

# randomly apply mask to fraction of the data:
mask_indices = np.random.randint(
low=0,
high=len(flux),
size=int(masked_fraction * len(flux))
)
mask = np.zeros(len(flux), dtype=bool)
mask[mask_indices] = True
quality = np.zeros(len(time), dtype=np.int32)

flux = Masked(flux, mask)
flux_err = Masked(flux_err, mask)
return LightCurve(
time=time, flux=flux, flux_err=flux_err
time=time, flux=flux, flux_err=flux_err, quality=quality
)


Expand Down
55 changes: 54 additions & 1 deletion lcviz/helper.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
import astropy.units as u

from lightkurve import LightCurve

from jdaviz.core.helpers import ConfigHelper

__all__ = ['LCviz']


def _get_range_subset_bounds(self, subset_state, *args, **kwargs):
# Instead of overriding the jdaviz version of this method on jdaviz.Application,
# we could put in jdaviz by (1) checking if helper has a
# _default_time_viewer_reference_name, (2) using the LCviz version if so, and (3)
# using the jdaviz version otherwise.
viewer = self.get_viewer(self._jdaviz_helper._default_time_viewer_reference_name)
reference_time = viewer.state.reference_data.meta['reference_time']
if viewer:
units = u.Unit(viewer.state.x_display_unit)
else:
raise ValueError("Unable to find time axis units")

region = reference_time + u.Quantity([subset_state.lo * units, subset_state.hi * units])

return [{"name": subset_state.__class__.__name__,
"glue_state": subset_state.__class__.__name__,
"region": region,
"subset_state": subset_state}]


class LCviz(ConfigHelper):
_default_configuration = {
'settings': {'configuration': 'lcviz',
Expand All @@ -13,7 +37,10 @@ class LCviz(ConfigHelper):
'dense_toolbar': False,
'context': {'notebook': {'max_height': '600px'}}},
'toolbar': ['g-data-tools', 'g-subset-tools'],
'tray': ['g-metadata-viewer', 'g-plot-options', 'HelloWorldPlugin', 'g-export-plot'],
'tray': [
'g-metadata-viewer', 'g-plot-options', 'g-subset-plugin',
'HelloWorldPlugin', 'g-export-plot'
],
'viewer_area': [{'container': 'col',
'children': [{'container': 'row',
'viewers': [{'name': 'time-viewer',
Expand All @@ -24,6 +51,11 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._default_time_viewer_reference_name = 'time-viewer'

# override jdaviz behavior to support temporal subsets
self.app._get_range_subset_bounds = (
lambda *args, **kwargs: _get_range_subset_bounds(self.app, *args, **kwargs)
)
kecnry marked this conversation as resolved.
Show resolved Hide resolved

def load_data(self, data, data_label=None):
"""
Load data into LCviz.
Expand All @@ -47,3 +79,24 @@ def load_data(self, data, data_label=None):
parser_reference='light_curve_parser',
data_label=data_label
)

def get_data(self, data_label=None, cls=LightCurve, subset_to_apply=None):
"""
Returns data with name equal to data_label of type cls with subsets applied from
subset_to_apply.

Parameters
----------
data_label : str, optional
Provide a label to retrieve a specific data set from data_collection.
cls : light curve class, optional
The type that data will be returned as.
subset_to_apply : str, optional
Subset that is to be applied to data before it is returned.

Returns
-------
data : cls
Data is returned as type cls with subsets applied.
"""
return super()._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply)
34 changes: 30 additions & 4 deletions lcviz/tests/test_parser.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# import pytest
import numpy as np
from glue.core.roi import XRangeROI
from astropy.time import Time
# from astropy.utils.data import download_file
from lightkurve import LightCurve
# from lightkurve.io import kepler
from gwcs.wcs import WCS
import astropy.units as u

from lcviz.utils import TimeCoordinates

# @pytest.mark.remote_data
# def test_kepler_via_mast_local_file(helper):
Expand All @@ -23,7 +24,7 @@
# flux_unit = u.Unit(data.get_component('flux').units)
# flux = flux_arr * flux_unit
#
# assert isinstance(data.coords, WCS)
# assert isinstance(data.coords, TimeCoordinates)
# assert isinstance(flux, u.Quantity)
# assert flux.unit.is_equivalent(u.electron / u.s)
#
Expand All @@ -43,7 +44,7 @@
# flux_unit = u.Unit(data.get_component('flux').units)
# flux = flux_arr * flux_unit
#
# assert isinstance(data.coords, WCS)
# assert isinstance(data.coords, TimeCoordinates)
# assert isinstance(flux, u.Quantity)
# assert flux.unit.is_equivalent(u.electron / u.s)

Expand All @@ -60,6 +61,31 @@ def test_synthetic_lc(helper):
flux_unit = u.Unit(data.get_component('flux').units)
flux = flux_arr * flux_unit

assert isinstance(data.coords, WCS)
assert isinstance(data.coords, TimeCoordinates)
assert isinstance(flux, u.Quantity)
assert flux.unit.is_equivalent(u.electron / u.s)


def test_apply_xrangerois(helper, light_curve_like_kepler_quarter):
lc = light_curve_like_kepler_quarter
helper.load_data(lc)
viewer = helper.app.get_viewer("time-viewer")
subset_plugin = helper.plugins['Subset Tools']

# the min/max of temporal regions can be defined in two ways:
time_ranges = [
[6, 8], # in same units as the x axis, OR
Time(['2011-07-19', '2011-07-23']) # directly with a Time object
]

for time_range in time_ranges:
subset_plugin._obj.subset_selected = "Create New"
viewer.apply_roi(XRangeROI(*time_range))

subsets = helper.app.get_subsets_from_viewer('time-viewer')

subset_1_bounds_jd = subsets['Subset 1'][0]['region'].jd
subset_2_bounds_jd = subsets['Subset 2'][0]['region'].jd

np.testing.assert_allclose(subset_1_bounds_jd, [2455745., 2455747.])
np.testing.assert_allclose(subset_2_bounds_jd, [2455761.50076602, 2455765.50076602])
Loading