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

Feature/make slit illum interactive #330

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9d51871
The first iteration of adding interactivity to the makeSlitIllum prim…
Jan 4, 2022
5a305c8
The first attempt of separating regions from fitting. Created a custo…
Jan 13, 2022
a319f1b
bin editing works
Jan 14, 2022
65a4542
bin editing works
Jan 14, 2022
8e0b19c
Bin editor correctly accepts parsed user bins
Jan 24, 2022
8663ff3
Both interactive bin editor and bin fitter work with data correctly
Jan 24, 2022
855f6d2
Enable masking in bin fitting
Jan 25, 2022
592ffd4
Added interactive interface for last step 1d fitting, section param a…
Feb 7, 2022
dbd126a
Merge branch 'master' into feature/makeSlitIllum_interactive
Feb 7, 2022
9779ab3
Cleaned up the makeSlitIllum code
Feb 23, 2022
b6c4b0d
Removed some comments and optimized some code
Feb 24, 2022
21f9c0a
Merge branch 'master' into feature/makeSlitIllum_interactive
Feb 24, 2022
20a3588
Fix PrimitiveVisualizer to accept ui_params=None
Feb 24, 2022
9d49249
Fix BinResettingUI due to loss of dependency
Feb 24, 2022
cc063fb
remove cyclip.c from git
chris-simpson Feb 24, 2022
b501e3c
fixed lingering tic marks when reducing number of bins, added padding…
Feb 24, 2022
8d71ab9
made path to set y_range so that it will respect updates, using for m…
Feb 25, 2022
9ac50ff
Interpolation etc
Mar 8, 2022
1e7506d
Removed interactive interface for the interpolation step; added bound…
Mar 23, 2022
02915f4
Modified tests for makeSlitIllum and updated ref file
Mar 23, 2022
8a27aaf
Merge branch 'master' into feature/makeSlitIllum_interactive
Mar 24, 2022
f1f43ec
Added Jinja2==3.0.3 to conda_deps in tox.ini
Mar 24, 2022
3bfce0d
Removed an accidental comment
Mar 28, 2022
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
Prev Previous commit
Next Next commit
Removed some comments and optimized some code
Olesja Smirnova committed Feb 24, 2022
commit b6c4b0de8da6005a8460cdeca4e484f4cef38ca6
11 changes: 3 additions & 8 deletions geminidr/gmos/parameters_gmos_longslit.py
Original file line number Diff line number Diff line change
@@ -37,14 +37,11 @@ class makeSlitIllumConfig(config.Config):
(int, str), None, optional=True)
debug_plot = config.Field("Create diagnosis plots?",
bool, False, optional=True)

suffix = config.Field("Filename suffix",
str, "_slitIllum", optional=True)
interactive = config.Field("Set to activate an interactive preview to fine tune the input parameters",
bool, True, optional=True)
bool, False, optional=True)
regions = config.Field("Sample regions along the slit", str, None, optional=True)

# Fitting parameters
spat_function = config.ChoiceField("Fitting function to use for bin fitting (spatial direction)", str,
allowed={"spline3": "Cubic spline",
"chebyshev": "Chebyshev polynomial",
@@ -56,12 +53,11 @@ class makeSlitIllumConfig(config.Config):
disp_function = config.ChoiceField("Fitting function to use for row fitting (dispersion direction)", str,
allowed={"spline3": "Cubic spline",
"chebyshev": "Chebyshev polynomial",
"polynomial": "Least squares polynomial",
"legendre": "Legendre polynomial",
"spline1": "Linear spline"},
default="spline1", optional=False)
default="spline3", optional=False)
disp_order = config.Field("Order of the row fitting function",
int, 7, optional=True)
int, 6, optional=True)
hsigma = config.RangeField("High rejection threshold (sigma) of the bin fit",
float, 3., min=0)
lsigma = config.RangeField("Low rejection threshold (sigma) of the bin fit",
@@ -70,7 +66,6 @@ class makeSlitIllumConfig(config.Config):
int, 3, min = 0, optional=True)
grow = config.RangeField("Growth radius for rejected pixels of the bin fit",
float, 0, min=0, optional=True)

border = config.Field("Size of the border added to the reconstructed slit illumination image",
int, 2, optional=True)

34 changes: 17 additions & 17 deletions geminidr/gmos/primitives_gmos_longslit.py
Original file line number Diff line number Diff line change
@@ -90,7 +90,6 @@ def __init__(self, *args, reconstruct_overlay_points=None, **kw):
if 'function' in self.visualizer.ui_params.fields:
def fn_select_change(attr, old, new):
self._update_segment_data()

self.fitting_parameters_ui.function.on_change('value', fn_select_change)

def _update_overlay_data(self):
@@ -180,10 +179,12 @@ def reset_view(self, clip_y_range=True):
clipped_data = overlay_ydata
y_min, y_max = min(min(ydata), clipped_data.min()), max(max(ydata), clipped_data.max())

if y_min != y_max:
y_pad = (y_max - y_min) * 0.1
self.p_main.y_range.update(start=y_min - y_pad, end=y_max + y_pad)
#ToDo: fix this

# if y_min != y_max:
# y_pad = (y_max - y_min) * 0.1
# self.p_main.y_range.update(start=y_min - y_pad, end=y_max + y_pad)
self.p_main.y_range.update(start=0.6, end=1.4)
@parameter_override
@capture_provenance
class GMOSClassicLongslit(GMOSSpect):
@@ -557,15 +558,16 @@ def generate_ui_parameters(config, prefix, extras=None, reinit_params=None):
filename_info=filename_info)
geminidr.interactive.server.interactive_fitter(visualizer)
bin_list = _parse_user_bins(''.join(visualizer.results().split()))
bin_limits = np.array(sum(bin_list, ()))
nbins = len(bin_list)

cols_val = np.arange(-border, height+border)
rows_val = np.arange(-border, width+border)
binned_shape = (nbins, len(rows_val))
bin_data_avg = np.empty((nbins, data.shape[1]))
bin_std_avg = np.empty((nbins, data.shape[1]))
bin_data_fits = np.zeros(binned_shape)
bin_std_fits = np.zeros(binned_shape)
bin_data_avg = np.ma.empty((nbins, data.shape[1]))
bin_std_avg = np.ma.empty((nbins, data.shape[1]))
bin_data_fits = np.ma.zeros(binned_shape)
bin_std_fits = np.ma.zeros(binned_shape)
for i, bin in enumerate(bin_list):
bin_data_avg[i] = np.ma.mean(data[bin[0]:bin[1]], axis=0)
bin_std_avg[i] = np.ma.mean(std[bin[0]:bin[1]], axis=0)
@@ -596,7 +598,7 @@ def generate_ui_parameters(config, prefix, extras=None, reinit_params=None):
uiparams = generate_ui_parameters(config, prefix="spat_")
x_label = "Rows" if dispaxis == 1 else "Columns"
first_label = 'cols' if dispaxis == 1 else 'rows'
tab_names = [f'{start}:{end}' for (start, end) in bin_list]
tab_names = [f'[{start+1}:{end}]' for (start, end) in bin_list]
tab_names[0] = f"Mean of {first_label} {tab_names[0]}"

visualizer = fit1d.Fit1DVisualizer(data_with_weights, spat_fitting_pars,
@@ -651,15 +653,13 @@ def generate_ui_parameters(config, prefix, extras=None, reinit_params=None):

disp_fitting_pars = {"order": disp_order, "function": disp_function,
"regions": None, "niter": 0, "sigma_upper": 0, "sigma_lower": 0}
# TODO: If there is only one slit profile copy the profile to each column and skip the last
# interactive step

# Interactive interface for fitting image rows at bin center locations. Image data, normalized
# to the center of the slit, gets displayed along with fitting points and fitting curve
if interactive_reduce and nbins > 1:
reinit_params = ["row", ]

extras = {"row": RangeField("Row of data to operate on", int, int(len(rows_val)/2), min=1, max=len(rows_val))}
extras = {"row": RangeField("Row of data to operate on", int, int(len(rows_val)/3), min=1, max=len(rows_val))}
uiparams = generate_ui_parameters(config, prefix="disp_", reinit_params=reinit_params, extras=extras)

def reconstruct_points(ui_params):
@@ -1180,11 +1180,11 @@ def slitIllumCorrect(self, adinputs=None, slit_illum=None,
ad_outputs = []
for ad, slit_illum_ad in zip(*gt.make_lists(adinputs, slit_illum_list, force_ad=True)):

# if ad.phu.get(timestamp_key):
# log.warning(
# "No changes will be made to {}, since it has "
# "already been processed by flatCorrect".format(ad.filename))
# continue
if ad.phu.get(timestamp_key):
log.warning(
"No changes will be made to {}, since it has "
"already been processed by flatCorrect".format(ad.filename))
continue

if slit_illum_ad is None:
if self.mode in ['sq'] or do_cal == 'force':
6 changes: 2 additions & 4 deletions geminidr/gmos/tests/longslit/test_make_slit_illum.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env python
"""
Tests for the `makeSlitIllum` primitive. The primitive itself is
defined in :mod:`~geminidr.core.primitives_spect` but these tests use GMOS Spect
data.
Tests for the `makeSlitIllum` primitive.
"""
import os
import pytest
@@ -49,7 +47,7 @@ def test_create_slit_illumination_with_mosaicked_data(ad, change_working_dir, re
constant.

There are several ways of doing this but, given the noise levels, we bin
the data, fit a polynomium, and check that the fitted polynomium has its 1st
the data, fit a polynomial, and check that the fitted polynomial has its 1st
and 2nd coefficients almost zero.
"""
plot = request.config.getoption("--do-plots")
12 changes: 6 additions & 6 deletions geminidr/interactive/fit/bineditor.py
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@ class BinModel1D(InteractiveModel1D):
def perform_fit(self, *args):
"""
Dummy function. Needs to be here to be compliant with the InteractiveModel1D
interface, but we don't want to perform any calculation.
interface, but no calculation will be performed.
"""
...

@@ -199,7 +199,7 @@ def reset_dialog_handler(self, result):
Parameters
----------
result : bool
This is the user response to an ok/cancel confirmation dialog. If False, we do not reset.
This is the user response to an ok/cancel confirmation dialog. If False, do not reset.
"""
if result:
self.reset_model_regions()
@@ -327,7 +327,7 @@ def reset_view(self):
"""
This calculates the x and y ranges for the figure with some custom padding.

This is used when we initially build the figure, but also as a listener for
This is used when initially building the figure, but also as a listener for
whenever the data changes.
"""
if not hasattr(self, 'p_main') or self.p_main is None:
@@ -423,8 +423,8 @@ def __init__(self, data_source, xlabel='Column', ylabel='Signal',
self.layout = None
self.pad_buttons = pad_buttons

# Make the widgets accessible from external code so we can update
# their properties if the default setup isn't great
# Make the widgets accessible from external code so that their properties can be updated
# if the default setup isn't great
self.widgets = {}

# Keep a list of panels for access later
@@ -469,7 +469,7 @@ def submit_button_handler(self):
Submit button handler.

The parent version checks for bad/poor fits, but that's not an issue
here, so we just exit by disabling the submit button, which triggers
here, so we exit by disabling the submit button, which triggers
some callbacks.
"""
self.submit_button.disabled = True
6 changes: 3 additions & 3 deletions gempy/library/transform.py
Original file line number Diff line number Diff line change
@@ -1306,9 +1306,9 @@ def add_mosaic_wcs(ad, geotable):
-------
AstroData: the modified input AD, with WCS attributes
"""
# if any('mosaic' in getattr(ext.wcs, 'available_frames', '') for ext in ad):
# raise ValueError("A 'mosaic' frame is already present in one or "
# f"more extensions of {ad.filename}")
if any('mosaic' in getattr(ext.wcs, 'available_frames', '') for ext in ad):
raise ValueError("A 'mosaic' frame is already present in one or "
f"more extensions of {ad.filename}")

array_info = gt.array_information(ad)
offsets = [ad[exts[0]].array_section()