bokeh.models.widgets.Paragraph

Here are the examples of the python api bokeh.models.widgets.Paragraph taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

1 Examples 7

0 View Source File : interact_bls.py
License : MIT License
Project Creator : nasa

def show_interact_widget(lc, notebook_url='localhost:8888', minimum_period=None,
                         maximum_period=None, resolution=2000):
    """Show the BLS interact widget.

    Parameters
    ----------
    notebook_url: str
        Location of the Jupyter notebook page (default: "localhost:8888")
        When showing Bokeh applications, the Bokeh server must be
        explicitly configured to allow connections originating from
        different URLs. This parameter defaults to the standard notebook
        host and port. If you are running on a different location, you
        will need to supply this value for the application to display
        properly. If no protocol is supplied in the URL, e.g. if it is
        of the form "localhost:8888", then "http" will be used.
    minimum_period : float or None
        Minimum period to assess the BLS to. If None, default value of 0.3 days
        will be used.
    maximum_period : float or None
        Maximum period to evaluate the BLS to. If None, the time coverage of the
        lightcurve / 4 will be used.
    resolution : int
        Number of points to use in the BLS panel. Lower this value to have a faster
        but less accurate compute time. You can also vary this value using the
        Resolution Slider.
    """
    try:
        import bokeh
        if bokeh.__version__[0] == '0':
            warnings.warn("interact_bls() requires Bokeh version 1.0 or later", LightkurveWarning)
    except ImportError:
        log.error("The interact_bls() tool requires the `bokeh` package; "
                  "you can install bokeh using e.g. `conda install bokeh`.")
        return None

    try:
        from astropy.timeseries import BoxLeastSquares
    except ImportError:
        try:
            from astropy.stats import BoxLeastSquares
        except ImportError:
            log.error("The `interact_bls()` tool requires AstroPy v3.1 or later.")

    def _create_interact_ui(doc, minp=minimum_period, maxp=maximum_period, resolution=resolution):
        """Create BLS interact user interface."""
        if minp is None:
            minp = 0.3
        if maxp is None:
            maxp = (lc.time[-1] - lc.time[0])/2

        time_format = ''
        if lc.time_format == 'bkjd':
            time_format = ' - 2454833 days'
        if lc.time_format == 'btjd':
            time_format = ' - 2457000 days'

        # Some sliders
        duration_slider = Slider(start=0.01,
                                 end=0.5,
                                 value=0.05,
                                 step=0.01,
                                 title="Duration [Days]",
                                 width=400)

        npoints_slider = Slider(start=500,
                                end=10000,
                                value=resolution,
                                step=100,
                                title="BLS Resolution",
                                width=400)

        # Set up the period values, BLS model and best period
        period_values = np.logspace(np.log10(minp), np.log10(maxp), npoints_slider.value)
        period_values = period_values[(period_values > duration_slider.value) &
                                        (period_values   <   maxp)]
        model = BoxLeastSquares(lc.time, lc.flux)
        result = model.power(period_values, duration_slider.value)
        loc = np.argmax(result.power)
        best_period = result.period[loc]
        best_t0 = result.transit_time[loc]

        # Some Buttons
        double_button = Button(label="Double Period", button_type="danger", width=100)
        half_button = Button(label="Half Period", button_type="danger", width=100)
        text_output = Paragraph(text="Period: {} days, T0: {}{}".format(
                                                    np.round(best_period, 7),
                                                    np.round(best_t0, 7), time_format),
                                width=350, height=40)

        # Set up BLS source
        bls_source = prepare_bls_datasource(result, loc)
        bls_help_source = prepare_bls_help_source(bls_source, npoints_slider.value)

        # Set up the model LC
        mf = model.model(lc.time, best_period, duration_slider.value, best_t0)
        mf /= np.median(mf)
        mask = ~(convolve(np.asarray(mf == np.median(mf)), Box1DKernel(2)) > 0.9)
        model_lc = LightCurve(lc.time[mask], mf[mask])
        model_lc = model_lc.append(LightCurve([(lc.time[0] - best_t0) + best_period/2], [1]))
        model_lc = model_lc.append(LightCurve([(lc.time[0] - best_t0) + 3*best_period/2], [1]))

        model_lc_source = ColumnDataSource(data=dict(
                                     time=np.sort(model_lc.time),
                                     flux=model_lc.flux[np.argsort(model_lc.time)]))

        # Set up the LC
        nb = int(np.ceil(len(lc.flux)/5000))
        lc_source = prepare_lightcurve_datasource(lc[::nb])
        lc_help_source = prepare_lc_help_source(lc)

        # Set up folded LC
        nb = int(np.ceil(len(lc.flux)/10000))
        f = lc.fold(best_period, best_t0)
        f_source = prepare_folded_datasource(f[::nb])
        f_help_source = prepare_f_help_source(f)

        f_model_lc = model_lc.fold(best_period, best_t0)
        f_model_lc = LightCurve([-0.5], [1]).append(f_model_lc)
        f_model_lc = f_model_lc.append(LightCurve([0.5], [1]))

        f_model_lc_source = ColumnDataSource(data=dict(
                                 phase=f_model_lc.time,
                                 flux=f_model_lc.flux))

        def _update_light_curve_plot(event):
            """If we zoom in on LC plot, update the binning."""
            mint, maxt = fig_lc.x_range.start, fig_lc.x_range.end
            inwindow = (lc.time > mint) & (lc.time  <  maxt)
            nb = int(np.ceil(inwindow.sum()/5000))
            temp_lc = lc[inwindow]
            lc_source.data = {'time': temp_lc.time[::nb],
                              'flux': temp_lc.flux[::nb]}

        def _update_folded_plot(event):
            loc = np.argmax(bls_source.data['power'])
            best_period = bls_source.data['period'][loc]
            best_t0 = bls_source.data['transit_time'][loc]
            # Otherwise, we can just update the best_period index
            minphase, maxphase = fig_folded.x_range.start, fig_folded.x_range.end
            f = lc.fold(best_period, best_t0)
            inwindow = (f.time > minphase) & (f.time  <  maxphase)
            nb = int(np.ceil(inwindow.sum()/10000))
            f_source.data = {'phase': f[inwindow].time[::nb],
                             'flux': f[inwindow].flux[::nb]}

        # Function to update the widget
        def _update_params(all=False, best_period=None, best_t0=None):
            if all:
                # If we're updating everything, recalculate the BLS model
                minp, maxp = fig_bls.x_range.start, fig_bls.x_range.end
                period_values = np.logspace(np.log10(minp), np.log10(maxp), npoints_slider.value)
                ok = (period_values > duration_slider.value) & (period_values  <  maxp)
                if ok.sum() == 0:
                    return
                period_values = period_values[ok]
                result = model.power(period_values, duration_slider.value)
                ok = np.isfinite(result['power']) & np.isfinite(result['duration']) &\
                         np.isfinite(result['transit_time']) & np.isfinite(result['period'])
                bls_source.data = dict(
                                     period=result['period'][ok],
                                     power=result['power'][ok],
                                     duration=result['duration'][ok],
                                     transit_time=result['transit_time'][ok])
                loc = np.nanargmax(bls_source.data['power'])
                best_period = bls_source.data['period'][loc]
                best_t0 = bls_source.data['transit_time'][loc]

                minpow, maxpow = bls_source.data['power'].min()*0.95,  bls_source.data['power'].max()*1.05
                fig_bls.y_range.start = minpow
                fig_bls.y_range.end = maxpow

            # Otherwise, we can just update the best_period index
            minphase, maxphase = fig_folded.x_range.start, fig_folded.x_range.end
            f = lc.fold(best_period, best_t0)
            inwindow = (f.time > minphase) & (f.time  <  maxphase)
            nb = int(np.ceil(inwindow.sum()/10000))
            f_source.data = {'phase': f[inwindow].time[::nb],
                             'flux': f[inwindow].flux[::nb]}

            mf = model.model(lc.time, best_period, duration_slider.value, best_t0)
            mf /= np.median(mf)
            mask = ~(convolve(np.asarray(mf == np.median(mf)), Box1DKernel(2)) > 0.9)
            model_lc = LightCurve(lc.time[mask], mf[mask])

            model_lc_source.data = {'time': np.sort(model_lc.time),
                                    'flux': model_lc.flux[np.argsort(model_lc.time)]}

            f_model_lc = model_lc.fold(best_period, best_t0)
            f_model_lc = LightCurve([-0.5], [1]).append(f_model_lc)
            f_model_lc = f_model_lc.append(LightCurve([0.5], [1]))

            f_model_lc_source.data = {'phase': f_model_lc.time,
                                      'flux': f_model_lc.flux}

            vertical_line.update(location=best_period)
            fig_folded.title.text = 'Period: {} days \t T0: {}{}'.format(
                                        np.round(best_period, 7),
                                        np.round(best_t0, 7), time_format)
            text_output.text = "Period: {} days, \t T0: {}{}".format(
                                        np.round(best_period, 7),
                                        np.round(best_t0, 7), time_format)

        # Callbacks
        def _update_upon_period_selection(attr, old, new):
            """When we select a period we should just update a few things, but we should not recalculate model
            """
            if len(new) > 0:
                new = new[0]
                best_period = bls_source.data['period'][new]
                best_t0 = bls_source.data['transit_time'][new]
                _update_params(best_period=best_period, best_t0=best_t0)

        def _update_model_slider(attr, old, new):
            """If the duration slider is updated, then update the whole model set."""
            _update_params(all=True)

        def _update_model_slider_EVENT(event):
            """If we update the duration slider, we should update the whole model set.
            This is the same as the _update_model_slider but it has a different call signature...
            """
            _update_params(all=True)

        def _double_period_event():
            fig_bls.x_range.start *= 2
            fig_bls.x_range.end *= 2
            _update_params(all=True)

        def _half_period_event():
            fig_bls.x_range.start /= 2
            fig_bls.x_range.end /= 2
            _update_params(all=True)

        # Help Hover Call Backs
        def _update_folded_plot_help_reset(event):
            f_help_source.data['phase'] = [(np.max(f.time) - np.min(f.time)) * 0.98 + np.min(f.time)]
            f_help_source.data['flux'] = [(np.max(f.flux) - np.min(f.flux)) * 0.98 + np.min(f.flux)]

        def _update_folded_plot_help(event):
            f_help_source.data['phase'] = [(fig_folded.x_range.end - fig_folded.x_range.start) * 0.95 + fig_folded.x_range.start]
            f_help_source.data['flux'] = [(fig_folded.y_range.end - fig_folded.y_range.start) * 0.95 + fig_folded.y_range.start]

        def _update_lc_plot_help_reset(event):
            lc_help_source.data['time'] = [(np.max(lc.time) - np.min(lc.time)) * 0.98 + np.min(lc.time)]
            lc_help_source.data['flux'] = [(np.max(lc.flux) - np.min(lc.flux)) * 0.9 + np.min(lc.flux)]

        def _update_lc_plot_help(event):
            lc_help_source.data['time'] = [(fig_lc.x_range.end - fig_lc.x_range.start) * 0.95 + fig_lc.x_range.start]
            lc_help_source.data['flux'] = [(fig_lc.y_range.end - fig_lc.y_range.start) * 0.9 + fig_lc.y_range.start]

        def _update_bls_plot_help_event(event):
            bls_help_source.data['period'] = [bls_source.data['period'][int(npoints_slider.value*0.95)]]
            bls_help_source.data['power'] = [(np.max(bls_source.data['power']) - np.min(bls_source.data['power'])) * 0.98
                                             + np.min(bls_source.data['power'])]

        def _update_bls_plot_help(attr, old, new):
            bls_help_source.data['period'] = [bls_source.data['period'][int(npoints_slider.value*0.95)]]
            bls_help_source.data['power'] = [(np.max(bls_source.data['power']) - np.min(bls_source.data['power'])) * 0.98
                                             + np.min(bls_source.data['power'])]

        # Create all the figures.
        fig_folded = make_folded_figure_elements(f, f_model_lc, f_source, f_model_lc_source, f_help_source)
        fig_folded.title.text = 'Period: {} days \t T0: {}{}'.format(np.round(best_period, 7), np.round(best_t0, 5), time_format)
        fig_bls, vertical_line = make_bls_figure_elements(result, bls_source, bls_help_source)
        fig_lc = make_lightcurve_figure_elements(lc, model_lc, lc_source, model_lc_source, lc_help_source)

        # Map changes

        # If we click a new period, update
        bls_source.selected.on_change('indices', _update_upon_period_selection)

        # If we change the duration, update everything, including help button for BLS
        duration_slider.on_change('value', _update_model_slider)
        duration_slider.on_change('value', _update_bls_plot_help)

        # If we increase resolution, update everything
        npoints_slider.on_change('value', _update_model_slider)

        # Make sure the vertical line always goes to the best period.
        vertical_line.update(location=best_period)

        # If we pan in the BLS panel, update everything
        fig_bls.on_event(PanEnd, _update_model_slider_EVENT)
        fig_bls.on_event(Reset, _update_model_slider_EVENT)

        # If we pan in the LC panel, rebin the points
        fig_lc.on_event(PanEnd, _update_light_curve_plot)
        fig_lc.on_event(Reset, _update_light_curve_plot)

        # If we pan in the Folded panel, rebin the points
        fig_folded.on_event(PanEnd, _update_folded_plot)
        fig_folded.on_event(Reset, _update_folded_plot)

        # Deal with help button
        fig_bls.on_event(PanEnd, _update_bls_plot_help_event)
        fig_bls.on_event(Reset, _update_bls_plot_help_event)
        fig_folded.on_event(PanEnd, _update_folded_plot_help)
        fig_folded.on_event(Reset, _update_folded_plot_help_reset)
        fig_lc.on_event(PanEnd, _update_lc_plot_help)
        fig_lc.on_event(Reset, _update_lc_plot_help_reset)

        # Buttons
        double_button.on_click(_double_period_event)
        half_button.on_click(_half_period_event)

        # Layout the widget
        doc.add_root(layout([
                            [fig_bls, fig_folded],
                            fig_lc,
                            [Spacer(width=70), duration_slider, Spacer(width=50), npoints_slider],
                            [Spacer(width=70), double_button, Spacer(width=70), half_button, Spacer(width=300), text_output]
                                ]))

    output_notebook(verbose=False, hide_banner=True)
    return show(_create_interact_ui, notebook_url=notebook_url)