Exemple #1
0
def test_fixpixels_multiple_ext(niriprim2):
    regions = [
        '430:437, 513:533',  # vertical region
        '1 / 450,521',  # single pixel
        '2/429:439, 136:140',  # horizontal region
    ]
    ad = niriprim2.fixPixels(regions=';'.join(regions), debug=DEBUG)[0]

    # for all extensions
    sy, sx = cartesian_regions_to_slices(regions[0])
    assert_almost_equal(ad[0].data[sy, sx].min(), 18.555, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 42.888, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].min(), 18.555, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].max(), 42.888, decimal=2)

    # only ext 1
    sy, sx = cartesian_regions_to_slices(regions[1][3:])
    assert_almost_equal(ad[0].data[sy, sx].min(), 24.5, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 24.5, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].min(), 2733, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].max(), 2733, decimal=2)

    # only ext 2
    sy, sx = cartesian_regions_to_slices(regions[2][2:])
    assert_almost_equal(ad[0].data[sy, sx].min(), -125, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 21293, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].min(), 37.166, decimal=2)
    assert_almost_equal(ad[1].data[sy, sx].max(), 60.333, decimal=2)
Exemple #2
0
def test_fixpixels_median(niriprim):
    regions = [
        '450,521',  # single pixel
    ]
    ad = niriprim.fixPixels(regions=';'.join(regions),
                            use_local_median=True, debug=DEBUG)[0]

    sy, sx = cartesian_regions_to_slices(regions[0])
    assert_almost_equal(ad[0].data[sy, sx].min(), 28, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 28, decimal=2)
Exemple #3
0
def test_fixpixels(niriprim):
    regions = [
        '430:437,513:533',  # vertical region
        '450,521',  # single pixel
        '429:439,136:140',  # horizontal region
    ]
    ad = niriprim.fixPixels(regions=';'.join(regions), debug=DEBUG)[0]

    sy, sx = cartesian_regions_to_slices(regions[0])
    assert_almost_equal(ad[0].data[sy, sx].min(), 18.555, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 42.888, decimal=2)

    sy, sx = cartesian_regions_to_slices(regions[1])
    assert_almost_equal(ad[0].data[sy, sx].min(), 24.5, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 24.5, decimal=2)

    sy, sx = cartesian_regions_to_slices(regions[2])
    assert_almost_equal(ad[0].data[sy, sx].min(), 37.166, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 60.333, decimal=2)
Exemple #4
0
def test_fixpixels_with_file(niriprim, tmp_path):
    regions = [
        '450,521',  # single pixel
        '429:439,136:140',  # horizontal region
    ]
    regions_file = str(tmp_path / 'regions.txt')
    with open(regions_file, mode='w') as f:
        f.write('\n'.join(regions))

    ad = niriprim.fixPixels(regions='430:437,513:533',  # vertical region
                            regions_file=regions_file,
                            debug=DEBUG)[0]

    sy, sx = cartesian_regions_to_slices('430:437,513:533')
    assert_almost_equal(ad[0].data[sy, sx].min(), 18.555, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 42.888, decimal=2)

    sy, sx = cartesian_regions_to_slices(regions[0])
    assert_almost_equal(ad[0].data[sy, sx].min(), 24.5, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 24.5, decimal=2)

    sy, sx = cartesian_regions_to_slices(regions[1])
    assert_almost_equal(ad[0].data[sy, sx].min(), 37.166, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 60.333, decimal=2)
Exemple #5
0
def test_fixpixels_specify_axis(niriprim):
    regions = [
        '430:437,513:533',  # vertical region
    ]

    with pytest.raises(ValueError):
        ad = niriprim.fixPixels(regions=';'.join(regions), axis=0)[0]

    with pytest.raises(ValueError):
        ad = niriprim.fixPixels(regions=';'.join(regions), axis=3)[0]

    ad = niriprim.fixPixels(regions=';'.join(regions), axis=2, debug=DEBUG)[0]

    sy, sx = cartesian_regions_to_slices(regions[0])
    assert_almost_equal(ad[0].data[sy, sx].min(), 17.636, decimal=2)
    assert_almost_equal(ad[0].data[sy, sx].max(), 38.863, decimal=2)
Exemple #6
0
    def __init__(self,
                 visualizer,
                 fitting_parameters,
                 domain,
                 x,
                 y,
                 weights=None,
                 min_order=1,
                 max_order=10,
                 xlabel='x',
                 ylabel='y',
                 plot_width=600,
                 plot_height=400,
                 plot_residuals=True,
                 enable_user_masking=True):
        """
        Panel for visualizing a 1-D fit, perhaps in a tab

        Parameters
        ----------
        visualizer : :class:`~geminidr.interactive.fit.fit1d.Fit1DVisualizer`
            visualizer to associate with
        fitting_parameters : dict
            parameters for this fit
        domain : list of pixel coordinates
            Used for new fit_1D fitter
        x : :class:`~numpy.ndarray`
            X coordinate values
        y : :class:`~numpy.ndarray`
            Y coordinate values
        min_order : int
            minimum order in UI
        max_order : int
            maximum order in UI
        xlabel : str
            label for X axis
        ylabel : str
            label for Y axis
        plot_width : int
            width of plot area in pixels
        plot_height : int
            height of plot area in pixels
        plot_residuals : bool
            True if we want the lower plot showing the differential between the fit and the data
        grow_slider : bool
            True if we want the slider for modifying growth radius
        """
        # Just to get the doc later
        self.visualizer = visualizer

        self.info_div = Div()

        # Make a listener to update the info panel with the RMS on a fit
        def update_info(info_div, f):
            info_div.update(text='<b>RMS:</b> {rms:.4f}'.format(rms=f.rms))

        listeners = [
            lambda f: update_info(self.info_div, f),
        ]

        self.fitting_parameters = fitting_parameters
        self.fit = InteractiveModel1D(fitting_parameters,
                                      domain,
                                      x,
                                      y,
                                      weights,
                                      listeners=listeners)

        fit = self.fit
        order_slider = interactive.build_text_slider("Order",
                                                     fit.order,
                                                     1,
                                                     min_order,
                                                     max_order,
                                                     fit,
                                                     "order",
                                                     fit.perform_fit,
                                                     throttled=True)
        self.sigma_upper_slider = interactive.build_text_slider(
            "Sigma (Upper)",
            fitting_parameters["sigma_upper"],
            0.01,
            1,
            10,
            fitting_parameters,
            "sigma_upper",
            self.sigma_slider_handler,
            throttled=True)
        self.sigma_lower_slider = interactive.build_text_slider(
            "Sigma (Lower)",
            fitting_parameters["sigma_lower"],
            0.01,
            1,
            10,
            fitting_parameters,
            "sigma_lower",
            self.sigma_slider_handler,
            throttled=True)
        sigma_button = bm.CheckboxGroup(
            labels=['Sigma clip'], active=[0] if self.fit.sigma_clip else [])
        sigma_button.on_change('active', self.sigma_button_handler)
        controls_column = [
            order_slider,
            row(self.sigma_upper_slider, sigma_button)
        ]
        controls_column.append(self.sigma_lower_slider)
        controls_column.append(
            interactive.build_text_slider("Max iterations",
                                          fitting_parameters["niter"], 1, 0,
                                          10, fitting_parameters, "niter",
                                          fit.perform_fit))
        controls_column.append(
            interactive.build_text_slider("Grow", fitting_parameters["grow"],
                                          1, 0, 10, fitting_parameters, "grow",
                                          fit.perform_fit))

        mask_button = bm.Button(label="Mask",
                                align='center',
                                button_type='primary',
                                width_policy='min')
        mask_button.on_click(self.mask_button_handler)

        unmask_button = bm.Button(label="Unmask",
                                  align='center',
                                  button_type='primary',
                                  width_policy='min')
        unmask_button.on_click(self.unmask_button_handler)

        controller_div = Div()
        self.info_div = Div()

        if enable_user_masking:
            controls = column(*controls_column, row(mask_button,
                                                    unmask_button),
                              controller_div, self.info_div)
        else:
            controls = column(*controls_column, controller_div, self.info_div)

        # Now the figures
        x_range = None
        y_range = None
        try:
            if self.fit.data and 'x' in self.fit.data.data and len(
                    self.fit.data.data['x']) >= 2:
                x_min = min(self.fit.data.data['x'])
                x_max = max(self.fit.data.data['x'])
                x_pad = (x_max - x_min) * 0.1
                x_range = Range1d(x_min - x_pad, x_max + x_pad)
            if self.fit.data and 'y' in self.fit.data.data and len(
                    self.fit.data.data['y']) >= 2:
                y_min = min(self.fit.data.data['y'])
                y_max = max(self.fit.data.data['y'])
                y_pad = (y_max - y_min) * 0.1
                y_range = Range1d(y_min - y_pad, y_max + y_pad)
        except:
            pass  # ok, we don't *need* ranges...
        if enable_user_masking:
            tools = "pan,wheel_zoom,box_zoom,reset,lasso_select,box_select,tap"
        else:
            tools = "pan,wheel_zoom,box_zoom,reset"
        p_main = figure(plot_width=plot_width,
                        plot_height=plot_height,
                        title='Fit',
                        x_axis_label=xlabel,
                        y_axis_label=ylabel,
                        tools=tools,
                        output_backend="webgl",
                        x_range=x_range,
                        y_range=y_range)
        p_main.height_policy = 'fixed'
        p_main.width_policy = 'fit'

        class Fit1DRegionListener(GIRegionListener):
            """
            Wrapper class so we can just detect when a bands are finished.

            We don't want to do an expensive recalc as a user is dragging
            a band around.
            """
            def __init__(self, fn):
                """
                Create a band listener that just updates on `finished`
                Parameters
                ----------
                fn : function
                    function to call when band is finished.
                """
                self.fn = fn

            def adjust_region(self, region_id, start, stop):
                pass

            def delete_region(self, region_id):
                self.fn()

            def finish_regions(self):
                self.fn()

        self.band_model = GIRegionModel()

        def update_regions():
            self.fit.model.regions = self.band_model.build_regions()

        self.band_model.add_listener(Fit1DRegionListener(update_regions))
        self.band_model.add_listener(
            Fit1DRegionListener(self.band_model_handler))

        connect_figure_extras(p_main, None, self.band_model)

        Controller(p_main,
                   None,
                   self.band_model,
                   controller_div,
                   mask_handlers=(self.mask_button_handler,
                                  self.unmask_button_handler))
        fig_column = [p_main]

        if plot_residuals:
            x_range = None
            try:
                if self.fit.data and 'x' in self.fit.data.data and len(
                        self.fit.data.data['x']) >= 2:
                    x_min = min(self.fit.data.data['x'])
                    x_max = max(self.fit.data.data['x'])
                    x_pad = (x_max - x_min) * 0.1
                    x_range = Range1d(x_min - x_pad, x_max + x_pad)
            except:
                pass  # ok, we don't *need* ranges...
            p_resid = figure(plot_width=plot_width,
                             plot_height=plot_height // 2,
                             title='Fit Residuals',
                             x_axis_label=xlabel,
                             y_axis_label='delta' + ylabel,
                             tools="pan,box_zoom,reset",
                             output_backend="webgl",
                             x_range=x_range,
                             y_range=None)
            p_resid.height_policy = 'fixed'
            p_resid.width_policy = 'fit'
            connect_figure_extras(p_resid, None, self.band_model)
            fig_column.append(p_resid)
            # Initalizing this will cause the residuals to be calculated
            self.fit.data.data['residuals'] = np.zeros_like(self.fit.x)
            p_resid.scatter(x='x',
                            y='residuals',
                            source=self.fit.data,
                            size=5,
                            **self.fit.mask_rendering_kwargs())

        # Initializing regions here ensures the listeners are notified of the region(s)
        if "regions" in fitting_parameters and fitting_parameters[
                "regions"] is not None:
            region_tuples = cartesian_regions_to_slices(
                fitting_parameters["regions"])
            self.band_model.load_from_tuples(region_tuples)

        self.scatter = p_main.scatter(x='x',
                                      y='y',
                                      source=self.fit.data,
                                      size=5,
                                      **self.fit.mask_rendering_kwargs())
        self.fit.add_listener(self.model_change_handler)

        # TODO refactor? this is dupe from band_model_handler
        # hacking it in here so I can account for the initial
        # state of the band model (which used to be always empty)
        x_data = self.fit.data.data['x']
        for i in np.arange(len(x_data)):
            if self.band_model.contains(x_data[i]):
                self.fit.band_mask[i] = 0
            else:
                self.fit.band_mask[i] = 1

        self.fit.perform_fit()
        self.line = p_main.line(x='xlinspace',
                                y='model',
                                source=self.fit.evaluation,
                                line_width=3,
                                color='black')

        region_editor = RegionEditor(self.band_model)
        fig_column.append(region_editor.get_widget())
        col = column(*fig_column)
        col.sizing_mode = 'scale_width'
        self.component = row(controls, col)