Dropdown(label="Primary Dropdown 2", button_type="primary", menu=menu),
 Dropdown(label="Success Dropdown 3", button_type="success", menu=menu),
 CheckboxButtonGroup(
     labels=["Checkbox Option 1", "Checkbox Option 2", "Checkbox Option 3"],
     button_type="default",
     active=[0, 1]),
 CheckboxButtonGroup(
     labels=["Checkbox Option 4", "Checkbox Option 5", "Checkbox Option 6"],
     button_type="primary",
     active=[1, 2]),
 CheckboxButtonGroup(
     labels=["Checkbox Option 7", "Checkbox Option 8", "Checkbox Option 9"],
     button_type="success",
     active=[0, 2]),
 RadioButtonGroup(
     labels=["Radio Option 1", "Radio Option 2", "Radio Option 3"],
     button_type="default",
     active=0),
 RadioButtonGroup(
     labels=["Radio Option 4", "Radio Option 5", "Radio Option 6"],
     button_type="primary",
     active=1),
 RadioButtonGroup(
     labels=["Radio Option 7", "Radio Option 8", "Radio Option 9"],
     button_type="success",
     active=2),
 TextInput(placeholder="TextInput 1"),
 TextInput(placeholder="TextInput 2"),
 TextInput(placeholder="TextInput 3"),
 AutocompleteInput(placeholder="AutocompleteInput 1 ...",
                   completions=["aaa", "aab", "aac", "baa", "caa"]),
 AutocompleteInput(placeholder="AutocompleteInput 2 ...",
예제 #2
0
               "F", "D-", "D", "D+", "C-", "C", "C+", "B-", "B", "B+", "A-",
               "A", "A+"
           ])

#add labels for glyphs
labels = LabelSet(x="average_grades",
                  y="exam_grades",
                  text="student_names",
                  x_offset=5,
                  y_offset=5,
                  source=source)
f.add_layout(labels)

#create glyphs
f.circle(x="average_grades", y="exam_grades", source=source, size=8)


def update_labels(attr, old, new):
    labels.text = options[radio_button_group.active]


#create radio buttons widget
options = ["average_grades", "exam_grades", "student_names"]
radio_button_group = RadioButtonGroup(labels=options)
radio_button_group.on_change("active", update_labels)

#create layout and add to curdoc
lay_out = layout([[radio_button_group]])
curdoc().add_root(f)
curdoc().add_root(lay_out)
예제 #3
0
def app(doc, hist_storage_, data_storage_, freq_storage_, depolarizer, names):

    # вспомогательные глобальные

    data_source = ColumnDataSource({key: [] for key in names})
    fit_handler = {
        "fit_line": None,
        "input_fields": {},
        "fit_indices": tuple()
    }
    utc_plus_7h = 7 * 3600
    time_coef = 10**3  # Пересчёт времени в мс для формата datetime Bokeh
    fit_line_points_amount = 300  # Количество точек для отрисовки подгоночной кривой
    depol_list = []

    datetime_formatter = DatetimeTickFormatter(
        milliseconds=['%M:%S:%3Nms'],
        seconds=['%H:%M:%S'],
        minsec=['%H:%M:%S'],
        minutes=['%H:%M:%S'],
        hourmin=['%H:%M:%S'],
        hours=['%H:%M:%S'],
        days=["%d.%m"],
        months=["%Y-%m-%d"],
    )

    # Гистограмма пятна
    img, img_x_std, img_y_std = hist_storage_.get_hist_with_std()
    hist_source = ColumnDataSource(data=dict(image=[img]))
    width_ = config.GEM_X * 5
    hist_height_ = config.GEM_Y * 5
    hist_fig = figure(plot_width=width_,
                      plot_height=hist_height_,
                      x_range=(0, config.GEM_X),
                      y_range=(0, config.GEM_Y))

    hist_fig.image(image='image',
                   x=0,
                   y=0,
                   dw=config.GEM_X,
                   dh=config.GEM_Y,
                   palette="Spectral11",
                   source=hist_source)

    hist_label = Label(
        x=0,
        y=0,
        x_units='screen',
        y_units='screen',
        text=f"x_std={'%.2f' % img_x_std},y_std={'%.2f' % img_y_std}",
        render_mode='css',
        border_line_color='black',
        border_line_alpha=1.0,
        background_fill_color='white',
        background_fill_alpha=1.0)

    hist_fig.add_layout(hist_label)

    hist_buffer_len = config.hist_buffer_len - 1
    hist_slider = RangeSlider(start=0,
                              end=hist_buffer_len,
                              value=(0, hist_buffer_len),
                              step=1,
                              title="Срез пятна (от..до) сек назад")

    def hist_update():
        img, img_x_std, img_y_std = hist_storage_.get_hist_with_std(
            hist_buffer_len - hist_slider.value[1],
            hist_buffer_len - hist_slider.value[0])
        hist_label.text = f"x_std={'%.2f' % img_x_std},y_std={'%.2f' % img_y_std}"
        hist_source.data = {'image': [img]}

    # График асимметрии

    asym_fig = figure(
        plot_width=width_,
        plot_height=400,
        tools="box_zoom, xbox_select, wheel_zoom, pan, save, reset",
        active_scroll="wheel_zoom",
        active_drag="pan",
        toolbar_location="below",
        lod_threshold=100,
        x_axis_location=None,
        x_range=DataRange1d())

    asym_fig.yaxis.axis_label = "мм"
    asym_fig.extra_x_ranges = {
        "time_range": asym_fig.x_range,
        "depolarizer": asym_fig.x_range,
        "sec": asym_fig.x_range
    }

    depol_axis = LinearAxis(x_range_name="depolarizer",
                            axis_label='Деполяризатор',
                            major_label_overrides={},
                            major_label_orientation=pi / 2)

    asym_fig.add_layout(
        LinearAxis(x_range_name="time_range",
                   axis_label='Время',
                   formatter=datetime_formatter), 'below')

    # Прямая, с которой идёт отсчёт времени для подгонки
    zone_of_interest = Span(location=0,
                            dimension='height',
                            line_color='green',
                            line_dash='dashed',
                            line_width=3)

    sec_axis = LinearAxis(
        x_range_name='sec',
        axis_label='Секунды')  # Секундная ось сверху (настр. диапазон)
    sec_axis.formatter = FuncTickFormatter(
        code=
        f"return ((tick - {zone_of_interest.location}) / {time_coef}).toFixed(1);"
    )

    def double_tap(event):
        """Двойной клик для перемещения отсчёта времени для подгонки"""
        zone_of_interest.location = event.x
        sec_axis.formatter = FuncTickFormatter(
            code=f"return ((tick - {event.x}) / {time_coef}).toFixed(1);")

    asym_fig.add_layout(depol_axis, 'below')
    asym_fig.add_layout(sec_axis, 'above')
    asym_fig.add_layout(zone_of_interest)
    asym_fig.on_event(DoubleTap, double_tap)

    def draw_selected_area(attr, old, new):
        """Подсветка выделенной для подгонки области"""

        # Удаляет предыдущую выделенную область
        asym_fig.renderers = [
            r for r in asym_fig.renderers if r.name != 'fit_zone'
        ]

        if not new.indices:
            fit_handler["fit_indices"] = tuple()
            return

        l_time_ = data_source.data['time'][min(new.indices)]
        r_time_ = data_source.data['time'][max(new.indices)]

        if l_time_ != r_time_:
            fit_handler["fit_indices"] = (l_time_, r_time_)
            box_select = BoxAnnotation(left=l_time_,
                                       right=r_time_,
                                       name="fit_zone",
                                       fill_alpha=0.1,
                                       fill_color='red')
            asym_fig.add_layout(box_select)

    asym_box_select_overlay = asym_fig.select_one(BoxSelectTool).overlay
    asym_box_select_overlay.line_color = "firebrick"

    data_source.on_change('selected', draw_selected_area)

    def create_whisker(data_name: str):
        """ Создает усы для data_name от time

        :param data_name: имя поля данных из data_storage
                (у данных должны быть поля '_up_error', '_down_error')
        :return: Bokeh Whisker
        """
        return Whisker(source=data_source,
                       base="time",
                       upper=data_name + "_up_error",
                       lower=data_name + "_down_error")

    def create_render(data_name: str, glyph: str, color: str):
        """ Рисует data_name от time

        :param data_name: имя поля данных из data_storage
        :param glyph: ['circle', 'square']
        :param color: цвет
        :return: Bokeh fig
        """
        if glyph == 'circle':
            func = asym_fig.circle
        elif glyph == 'square':
            func = asym_fig.square
        else:
            raise ValueError('Неверное значение glyph')
        return func('time',
                    data_name,
                    source=data_source,
                    name=data_name,
                    color=color,
                    nonselection_alpha=1,
                    nonselection_color=color)

    # Список линий на графике асимметрии: data_name, name, glyph, color
    asym_renders_name = [('y_one_asym', 'ΔY ONE', 'circle', 'black'),
                         ('y_cog_asym', 'ΔY COG', 'circle', 'green'),
                         ('x_one_asym', 'ΔX ONE', 'square', 'black'),
                         ('x_cog_asym', 'ΔX COG', 'square', 'green')]

    pretty_names = dict([(data_name, name)
                         for data_name, name, *_ in asym_renders_name])
    asym_renders = [
        create_render(data_name, glyph, color)
        for data_name, _, glyph, color in asym_renders_name
    ]
    asym_error_renders = [
        create_whisker(data_name) for data_name, *_ in asym_renders_name
    ]

    for render, render_error in zip(asym_renders, asym_error_renders):
        asym_fig.add_layout(render_error)
        render.js_on_change(
            'visible',
            CustomJS(args=dict(x=render_error),
                     code="x.visible = cb_obj.visible"))

    asym_fig.add_layout(
        Legend(items=[(pretty_names[r.name], [r]) for r in asym_renders],
               click_policy="hide",
               location="top_left",
               background_fill_alpha=0.2,
               orientation="horizontal"))

    # Вывод информации о точке при наведении мыши
    asym_fig.add_tools(
        HoverTool(
            renderers=asym_renders,
            formatters={"time": "datetime"},
            mode='vline',
            tooltips=[
                ("Время", "@time{%F %T}"),
                *[(pretty_names[r.name],
                   f"@{r.name}{'{0.000}'} ± @{r.name + '_error'}{'{0.000}'}")
                  for r in asym_renders],
                ("Деполяризатор", f"@depol_energy{'{0.000}'}")
            ]))

    # Окно ввода периода усреднения
    period_input = TextInput(value='300', title="Время усреднения (с):")

    # Глобальный список параметров, для сохранения результатов запросов к data_storage
    params = {'last_time': 0, 'period': int(period_input.value)}

    def update_data():
        """
        Обновляет данные для пользовательского интерфейса, собирая их у data_storage
        """
        if params['period'] != int(period_input.value):
            data_source.data = {name: [] for name in names}
            params['period'] = int(period_input.value)
            params['last_time'] = 0
            depol_axis.ticker = []
            depol_axis.major_label_overrides.clear()
            depol_list.clear()

        points, params['last_time'] = data_storage_.get_mean_from(
            params['last_time'], params['period'])

        if not points['time']:
            return

        points['time'] = [(i + utc_plus_7h) * time_coef for i in points['time']
                          ]  # Учёт сдвижки UTC+7 для отрисовки

        for time, energy in zip(points['time'], points['depol_energy']):
            if energy == 0:
                continue
            depol_axis.major_label_overrides[time] = str(energy)
            depol_list.append(time)

        depol_axis.ticker = depol_list  # TODO: оптимизировать
        data_source.stream({key: np.array(val)
                            for key, val in points.items()},
                           rollover=250)

    def period_correction_func(attr, old, new):
        """Проверка введенного значения на целое число больше нуля"""
        if not new.isdigit() or int(new) <= 0:
            period_input.value = old

    period_input.on_change('value', period_correction_func)

    # Создание панели графиков (вкладок)

    def create_fig(data_names: list,
                   colors: list,
                   y_axis_name: str,
                   ers: str = None):
        """Создаёт график data_names : time. Если в data_names несколько имён,
        то они будут на одном графике. Возвращает fig.

        :param data_names: список с именами полей данных из data_storage
        :param colors: список цветов, соотв. элементам из fig_names
        :param y_axis_name: имя оси Y
        :param ers: 'err', 'pretty' --- вид усов (у данных должны быть поля '_up_error', '_down_error'),
                       'err' --- усы обыкновенные
                       'pretty' --- усы без шляпки и цветом совпадающим с цветом точки
        :return fig --- Bokeh figure
        """

        if len(data_names) != len(colors):
            raise IndexError('Кол-во цветов и графиков не совпадает')

        fig = figure(plot_width=width_,
                     plot_height=300,
                     tools="box_zoom, wheel_zoom, pan, save, reset",
                     active_scroll="wheel_zoom",
                     lod_threshold=100,
                     x_axis_type="datetime")

        for fig_name, color in zip(data_names, colors):

            if ers == 'err':
                fig.add_layout(
                    Whisker(source=data_source,
                            base="time",
                            upper=fig_name + '_up_error',
                            lower=fig_name + '_down_error'))
            elif ers == 'pretty':
                fig.add_layout(
                    Whisker(source=data_source,
                            base="time",
                            upper=fig_name + '_up_error',
                            lower=fig_name + '_down_error',
                            line_color=color,
                            lower_head=None,
                            upper_head=None))

            fig.circle('time',
                       fig_name,
                       source=data_source,
                       size=5,
                       color=color,
                       nonselection_alpha=1,
                       nonselection_color=color)

        fig.yaxis.axis_label = y_axis_name
        fig.xaxis.axis_label = 'Время'
        fig.xaxis.formatter = datetime_formatter
        fig.x_range = asym_fig.x_range

        return fig

    figs = [(create_fig(['y_one_l'], ['black'], 'Y [мм]', 'err'), 'Y ONE L'),
            (create_fig(['y_one_r'], ['black'], 'Y [мм]', 'err'), 'Y ONE R'),
            (create_fig(['y_cog_l'], ['black'], 'Y [мм]', 'err'), 'Y COG L'),
            (create_fig(['y_cog_r'], ['black'], 'Y [мм]', 'err'), 'Y COG R'),
            (create_fig(['rate' + i for i in ['_l', '_r']], ['red', 'blue'],
                        'Усл. ед.', 'pretty'), 'Rate'),
            (create_fig(['corrected_rate' + i for i in ['_l', '_r']],
                        ['red', 'blue'], 'Усл. ед.', 'pretty'), 'Corr. rate'),
            (create_fig(['delta_rate'], ['black'], 'Корр. лев. - корр. пр.',
                        'err'), 'Delta corr. rate'),
            (create_fig(['charge'], ['blue'], 'Ед.'), 'Charge')]

    tab_handler = Tabs(
        tabs=[Panel(child=fig, title=fig_name) for fig, fig_name in figs],
        width=width_)

    # Окно статуса деполяризатора

    depol_status_window = Div(text="Инициализация...", width=500, height=500)

    depol_start_stop_buttons = RadioButtonGroup(
        labels=["Старт", "Стоп"], active=(0 if depolarizer.is_scan else 1))

    fake_depol_button = Button(label="Деполяризовать", width=200)
    fake_depol_button.on_click(GEM.depolarize)

    depol_input_harmonic_number = TextInput(value=str(
        '%.1f' % depolarizer.harmonic_number),
                                            title=f"Номер гармоники",
                                            width=150)

    depol_input_attenuation = TextInput(value=str('%.1f' %
                                                  depolarizer.attenuation),
                                        title=f"Аттенюатор (дБ)",
                                        width=150)

    depol_input_speed = TextInput(
        value=str(depolarizer.frequency_to_energy(depolarizer.speed, n=0)),
        title=f"Скорость ({'%.1f' % depolarizer.speed} Гц):",
        width=150)

    depol_input_step = TextInput(
        value=str(depolarizer.frequency_to_energy(depolarizer.step, n=0)),
        title=f"Шаг ({'%.1f' % depolarizer.step} Гц):",
        width=150)

    depol_input_initial = TextInput(
        value=str(depolarizer.frequency_to_energy(depolarizer.initial)),
        title=f"Начало ({'%.1f' % depolarizer.initial} Гц):",
        width=150)

    depol_input_final = TextInput(
        value=str(depolarizer.frequency_to_energy(depolarizer.final)),
        title=f"Конец ({'%.1f' % depolarizer.final} Гц):",
        width=150)

    depol_dict = {
        "speed": (depol_input_speed, depolarizer.set_speed),
        "step": (depol_input_step, depolarizer.set_step),
        "initial": (depol_input_initial, depolarizer.set_initial),
        "final": (depol_input_final, depolarizer.set_final),
        "harmonic_number":
        (depol_input_harmonic_number, depolarizer.set_harmonic_number),
        "attenuation": (depol_input_attenuation, depolarizer.set_attenuation)
    }

    def change_value_generator(value_name):
        """Возвращает callback функцию для параметра value_name деполяризатора"""
        def change_value(attr, old, new):
            if float(old) == float(new):
                return

            depol_input, depol_set = depol_dict[value_name]
            depol_current = depolarizer.get_by_name(value_name)
            try:
                if value_name in ['harmonic_number', 'attenuation']:
                    new_val = float(new)
                elif value_name in ['speed', 'step']:
                    new_val = depolarizer.energy_to_frequency(float(new), n=0)
                else:
                    new_val = depolarizer.energy_to_frequency(float(new))

                if depol_current == new_val:
                    return

                depol_set(new_val)
                if value_name not in ['harmonic_number', 'attenuation']:
                    name = depol_input.title.split(' ')[0]
                    depol_input.title = name + f" ({'%.1f' % new_val} Гц):"

            except ValueError as e:
                if value_name in ['harmonic_number', 'attenuation']:
                    depol_input.value = str(depol_current)
                elif value_name in ['speed', 'step']:
                    depol_input.value = str(
                        depolarizer.frequency_to_energy(depol_current, n=0))
                else:
                    depol_input.value = str(
                        depolarizer.frequency_to_energy(depol_current))
                print(e)

        return change_value

    depol_input_harmonic_number.on_change(
        'value', change_value_generator('harmonic_number'))
    depol_input_attenuation.on_change('value',
                                      change_value_generator("attenuation"))
    depol_input_speed.on_change('value', change_value_generator("speed"))
    depol_input_step.on_change('value', change_value_generator("step"))
    depol_input_initial.on_change('value', change_value_generator("initial"))
    depol_input_final.on_change('value', change_value_generator("final"))

    def update_depol_status(
    ):  # TODO: самому пересчитывать начало и конец сканирования по частотам
        """Обновляет статус деполяризатора,
        если какое-то значение поменялось другим пользователем"""
        depol_start_stop_buttons.active = 0 if depolarizer.is_scan else 1

        depol_status_window.text = f"""
<p>Сканирование: 
<font color={'"green">включено' if depolarizer.is_scan else '"red">выключено'}</font></p>
<p/>Частота {"%.1f" % depolarizer.current_frequency} (Гц)</p>
<p/>Энергия {"%.3f" % depolarizer.current_energy} МэВ</p>"""

        for value_name in ['speed', 'step']:
            depol_input, _ = depol_dict[value_name]
            depol_value = depolarizer.frequency_to_energy(
                depolarizer.get_by_name(value_name), n=0)
            if float(depol_input.value) != depol_value:
                depol_input.value = str(depol_value)

        for value_name in ['initial', 'final']:
            depol_input, _ = depol_dict[value_name]
            freq = depolarizer.get_by_name(value_name)
            energy = depolarizer.frequency_to_energy(freq)
            if float(depol_input.value) != energy:
                depol_input.value = str(energy)
            else:
                name = depol_input.title.split(' ')[0]
                depol_input.title = name + f" ({'%.1f' % freq} Гц):"

        for value_name in ['attenuation', 'harmonic_number']:
            depol_input, _ = depol_dict[value_name]
            depol_value = depolarizer.get_by_name(value_name)
            if float(depol_input.value) != depol_value:
                depol_input.value = str(int(depol_value))

    depol_start_stop_buttons.on_change(
        "active", lambda attr, old, new:
        (depolarizer.start_scan() if new == 0 else depolarizer.stop_scan()))

    # Подгонка

    fit_line_selection_widget = Select(title="Fitting line:",
                                       width=200,
                                       value=asym_renders[0].name,
                                       options=[(render.name,
                                                 pretty_names[render.name])
                                                for render in asym_renders])

    options = [name for name in fit.function_handler.keys()]
    if not options:
        raise IndexError("Пустой function_handler в fit.py")

    fit_function_selection_widget = Select(title="Fitting function:",
                                           value=options[0],
                                           options=options,
                                           width=200)

    fit_button = Button(label="FIT", width=200)

    def make_parameters_table():
        """Создание поля ввода данных для подгонки: начальное значение, fix и т.д."""
        name = fit_function_selection_widget.value

        t_width = 10
        t_height = 12

        rows = [
            row(Paragraph(text="name", width=t_width, height=t_height),
                Paragraph(text="Fix", width=t_width, height=t_height),
                Paragraph(text="Init value", width=t_width, height=t_height),
                Paragraph(text="step (error)", width=t_width, height=t_height),
                Paragraph(text="limits", width=t_width, height=t_height),
                Paragraph(text="lower_limit", width=t_width, height=t_height),
                Paragraph(text="upper_limit", width=t_width, height=t_height))
        ]

        fit_handler["input_fields"] = {}

        for param, value in fit.get_function_params(name):
            fit_handler["input_fields"][param] = {}
            fit_handler["input_fields"][param]["fix"] = CheckboxGroup(
                labels=[""], width=t_width, height=t_height)
            fit_handler["input_fields"][param]["Init value"] = TextInput(
                width=t_width, height=t_height, value=str(value))
            fit_handler["input_fields"][param]["step (error)"] = TextInput(
                width=t_width, height=t_height, value='1')
            fit_handler["input_fields"][param]["limits"] = CheckboxGroup(
                labels=[""], width=t_width, height=t_height)
            fit_handler["input_fields"][param]["lower_limit"] = TextInput(
                width=t_width, height=t_height)
            fit_handler["input_fields"][param]["upper_limit"] = TextInput(
                width=t_width, height=t_height)

            rows.append(
                row(Paragraph(text=param, width=t_width, height=t_height),
                    fit_handler["input_fields"][param]["fix"],
                    fit_handler["input_fields"][param]["Init value"],
                    fit_handler["input_fields"][param]["step (error)"],
                    fit_handler["input_fields"][param]["limits"],
                    fit_handler["input_fields"][param]["lower_limit"],
                    fit_handler["input_fields"][param]["upper_limit"]))

        return column(rows)

    def clear_fit():
        """Удаление подогнанной кривой"""
        if fit_handler["fit_line"] in asym_fig.renderers:
            asym_fig.renderers.remove(fit_handler["fit_line"])

    energy_window = Div(text="Частота: , энергия: ")
    clear_fit_button = Button(label="Clear", width=200)
    clear_fit_button.on_click(clear_fit)

    def fit_callback():
        if not fit_handler["fit_indices"]:
            return

        name = fit_function_selection_widget.value
        line_name = fit_line_selection_widget.value

        left_time_, right_time_ = fit_handler["fit_indices"]

        left_ind_ = bisect.bisect_left(data_source.data['time'], left_time_)
        right_ind_ = bisect.bisect_right(data_source.data['time'],
                                         right_time_,
                                         lo=left_ind_)

        if left_ind_ == right_ind_:
            return

        clear_fit()

        x_axis = data_source.data['time'][left_ind_:right_ind_]
        y_axis = data_source.data[line_name][left_ind_:right_ind_]
        y_errors = data_source.data[line_name +
                                    '_up_error'][left_ind_:right_ind_] - y_axis

        init_vals = {
            name: float(val["Init value"].value)
            for name, val in fit_handler["input_fields"].items()
        }

        steps = {
            "error_" + name: float(val["step (error)"].value)
            for name, val in fit_handler["input_fields"].items()
        }

        fix_vals = {
            "fix_" + name: True
            for name, val in fit_handler["input_fields"].items()
            if val["fix"].active
        }

        limit_vals = {
            "limit_" + name:
            (float(val["lower_limit"].value), float(val["upper_limit"].value))
            for name, val in fit_handler["input_fields"].items()
            if val["limits"].active
        }

        kwargs = {}
        kwargs.update(init_vals)
        kwargs.update(steps)
        kwargs.update(fix_vals)
        kwargs.update(limit_vals)

        # Предобработка времени, перевод в секунды, вычитание сдвига (для лучшей подгонки)
        left_ = zone_of_interest.location
        x_time = x_axis - left_  # Привёл время в интервал от 0
        x_time /= time_coef  # Перевёл в секунды

        # Создание точек, которые передадутся в подогнанную функцию с параметрами,
        # и точек, которые соответсвуют реальным временам на графике (т.е. без смещения к 0)

        fit_line_real_x_axis = np.linspace(left_time_, right_time_,
                                           fit_line_points_amount)
        fit_line_x_axis = fit_line_real_x_axis - left_
        fit_line_x_axis /= time_coef

        m = fit.create_fit_func(name, x_time, y_axis, y_errors, kwargs)

        fit.fit(m)
        params_ = m.get_param_states()
        for param in params_:
            fit_handler["input_fields"][
                param['name']]["Init value"].value = "%.3f" % param['value']
            fit_handler["input_fields"][
                param['name']]["step (error)"].value = "%.3f" % param['error']
            if param['name'] == "depol_time":
                freq = freq_storage_.find_closest_freq(param['value'] +
                                                       left_ / time_coef -
                                                       utc_plus_7h)
                freq_error = abs(depolarizer.speed * param['error'])
                energy = depolarizer.frequency_to_energy(
                    freq) if freq != 0 else 0
                energy_error = depolarizer.frequency_to_energy(
                    freq_error, depolarizer._F0, 0)
                energy_window.text = "<p>Частота: %8.1f +- %.1f Hz,</p> <p>Энергия: %7.3f +- %.1f МэВ</p>" % (
                    freq, freq_error, energy, energy_error)

        fit_handler["fit_line"] = asym_fig.line(
            fit_line_real_x_axis,
            fit.get_line(name, fit_line_x_axis, [x['value'] for x in params_]),
            color="red",
            line_width=2)

    fit_button.on_click(fit_callback)

    # Инициализация bokeh app, расположение виджетов
    column_1 = column(gridplot([tab_handler], [asym_fig], merge_tools=False),
                      period_input,
                      width=width_ + 50)
    widgets_ = WidgetBox(depol_start_stop_buttons, depol_input_harmonic_number,
                         depol_input_attenuation, depol_input_speed,
                         depol_input_step, depol_input_initial,
                         depol_input_final, depol_status_window)

    row_21 = column(hist_fig, hist_slider)
    column_21 = column(widgets_)
    if config.GEM_idle:
        column_22 = column(fit_button, clear_fit_button, fake_depol_button,
                           fit_line_selection_widget,
                           fit_function_selection_widget, energy_window,
                           make_parameters_table())
        make_parameters_table_id = 6
    else:
        column_22 = column(fit_button, clear_fit_button,
                           fit_line_selection_widget,
                           fit_function_selection_widget, energy_window,
                           make_parameters_table())
        make_parameters_table_id = 5

    def rebuild_table(attr, old, new):
        column_22.children[make_parameters_table_id] = make_parameters_table()

    fit_function_selection_widget.on_change("value", rebuild_table)

    row_22 = row(column_21, column_22)
    column_2 = column(row_21, row_22, width=width_ + 50)
    layout_ = layout([[column_1, column_2]])

    # Настройка документа Bokeh

    update_data()
    doc.add_periodic_callback(hist_update,
                              1000)  # TODO запихнуть в один callback
    doc.add_periodic_callback(update_data, 1000)  # TODO: подобрать периоды
    doc.add_periodic_callback(update_depol_status, 1000)
    doc.title = "Laser polarimeter"
    doc.add_root(layout_)
예제 #4
0
                  end=99.0,
                  step=0.1)

# for labels (filters):
lbl_ops = ['None', '-', '+', '*', '/']
filters_optional = ['None']
filters = []
for afilter in isocmds[0.00][0.0][0.0].hdr_list[9:-1]:
    filters.append(afilter)
    filters_optional.append(afilter)

# axis value and operator selection
# x-axis:
x_lbl1 = Select(title="x-axis value 1", value=v_label, options=filters)
x_op_title = Div(text="""x-axis operator (optional)""", height=10, width=200)
x_op = RadioButtonGroup(active=1, labels=lbl_ops)
x_lbl2 = Select(title="x-axis value 2 (optional)",
                value=i_label,
                options=filters_optional)
#y-axis:
y_lbl1 = Select(title="y-axis value 1", value=i_label, options=filters)
y_op_title = Div(text="""y-axis operator (optional)""", height=10, width=200)
y_op = RadioButtonGroup(active=0, labels=lbl_ops)
y_lbl2 = Select(title="y-axis value 2 (optional)",
                value='None',
                options=filters_optional)

# initial mass slider:
mi_slider = RangeSlider(start=mi_range[0],
                        end=mi_range[-1],
                        value=(0.1, 8.0),
def source_comparison_tab(old_to_new_sources, new_to_old_sources,
                          old_to_new_regions, n_folds_list, agg_all_nfolds):

    ## Get region names and list of sources
    region_names_new = list(old_to_new_regions.values())
    region_names_new.sort()
    # sourceset_display = ['Best'] + list(old_to_new_sources.keys())[1:]
    # sourceset_display = list(old_to_new_sources.keys())[1:]
    sourceset_display = sorted(list(new_to_old_sources.keys())[1:])
    # Put Climate at the end
    if 'Climate' in sourceset_display:
        c_idx = sourceset_display.index('Climate')
        sourceset_display.pop(c_idx)
        sourceset_display.append('Climate')

    n_folds_display = [np.str(x) for x in n_folds_list]

    # Replace long names to shorter ones for display
    shorter_source_names = {
        'Colombia & GT by State': 'CO & GT by State',
        'Colombia & GT by Symptom': 'CO & GT by Symptom',
        'Colombia Border & GT': 'CO Border & GT',
        'GT by State - Ven & Col': 'GT by State - VE & CO'
    }
    sourceset_display_short = [
        x if x not in shorter_source_names.keys() else shorter_source_names[x]
        for x in sourceset_display
    ]

    # All regions and sources
    # all_regions = np.unique(agg_all_nfolds.Region).tolist()
    # all_sources = np.unique(agg_all_nfolds.SourcesSet).tolist()

    # Score types considered
    score_types = ['In Sample', 'OOS']

    # Data to display: select one region and one value of n_folds
    gs_name_bar = 'Amazonas'
    n_folds_bar = n_folds_list[0]
    agg_gs = agg_all_nfolds.loc[agg_all_nfolds.Region == gs_name_bar]
    agg_n_gs = agg_gs.loc[agg_gs.NbFolds == n_folds_bar,:].\
        sort_values(by='SourcesSet',ascending=True)
    # agg_n_gs.sort_values(by='SourcesSet',ascending=True,inplace=True)
    in_sample_vals = agg_n_gs.loc[agg_n_gs.ScoreType == 'InSample',\
                                  'Value'].values.tolist()
    OOS_vals = agg_n_gs.loc[agg_n_gs.ScoreType == 'OOS',\
                            'Value'].values.tolist()
    data_dict = {
        'Source Set': sourceset_display_short,
        'In Sample': in_sample_vals,
        'OOS': OOS_vals
    }
    x = [(s, score) for s in sourceset_display_short for score in score_types]

    counts = sum(zip(data_dict['In Sample'], data_dict['OOS']),
                 ())  # like an hstack
    colors = (Category10[3])[1:] * len(sourceset_display_short)
    source_bar = ColumnDataSource(data=dict(x=x, counts=counts, color=colors))
    p_bar = figure(x_range=FactorRange(*x),
                   plot_height=350,
                   plot_width=1050,
                   title='R squared for a given Region',
                   toolbar_location=None,
                   tools="")

    p_bar.vbar(x='x',
               top='counts',
               width=0.9,
               source=source_bar,
               color='color')

    p_bar.y_range.start = -1
    p_bar.y_range.end = 1
    p_bar.x_range.range_padding = 0.1
    p_bar.xaxis.major_label_orientation = 1
    p_bar.xgrid.grid_line_color = None

    #show(p_bar,browser="chrome")

    ## Radio buttons for bar graph
    # Define buttons
    regions_button_bar = RadioButtonGroup(labels=region_names_new, active=0)
    n_folds_button_bar = RadioButtonGroup(labels=n_folds_display, active=0)

    # Text above graph
    # div_text_bar = 'Gold Standard: ' + gs_name_bar + \
    #                '<br>Predictor Set: ' + np.str(n_folds_bar)
    div_text_bar = ''
    div_bar = Div(text=div_text_bar, width=700, height=50)

    # Update function
    ###########################################################################
    def bar_callback(attr, old, new):
        # Get new selected value
        #new_score = score_types[new.active]
        gs_name_bar = region_names_new[regions_button_bar.active]
        n_folds_bar = np.int(n_folds_display[n_folds_button_bar.active])

        # Update data to display
        agg_gs = agg_all_nfolds.loc[agg_all_nfolds.Region == gs_name_bar]
        agg_n_gs = agg_gs.loc[agg_gs.NbFolds == n_folds_bar,:].\
            sort_values(by='SourcesSet',ascending=True)
        # agg_n_gs.sort_values(by='SourcesSet',ascending=True,inplace=True)
        in_sample_vals = agg_n_gs.loc[agg_n_gs.ScoreType == 'InSample',\
                                             'Value'].values.tolist()
        OOS_vals = agg_n_gs.loc[agg_n_gs.ScoreType == 'OOS',\
                                             'Value'].values.tolist()
        data_dict = {
            'Source Set': sourceset_display_short,
            'In Sample': in_sample_vals,
            'OOS': OOS_vals
        }
        # x = [ (s, score) for s in sourceset_display for score in score_types ]

        counts = sum(zip(data_dict['In Sample'], data_dict['OOS']),
                     ())  # like an hstack
        # new_source = ColumnDataSource(data=dict(x=x, counts=counts, color=colors))
        new_source_data = dict(x=x, counts=counts, color=colors)
        source_bar.data = new_source_data

        # new_text_bar = 'Gold Standard: ' + gs_name_bar + \
        #                '<br>Predictor Set: ' + np.str(n_folds_bar)
        # div_bar.text = new_text_bar
        return

    ###########################################################################
    regions_button_bar.on_change('active', bar_callback)
    n_folds_button_bar.on_change('active', bar_callback)

    # Put controls in a single element
    controls = WidgetBox(n_folds_button_bar, regions_button_bar)

    # Create a row layout
    layout = column(controls, div_bar, p_bar)

    # Make a tab with the layout
    tab = Panel(child=layout, title='Comparison of Source Sets')

    return tab


###############################################################################
예제 #6
0
def bokeh_plot(histo, jup_url="http://127.0.0.1:8889"):
    if not isnotebook():
        raise NotImplementedError("Only usable in jupyter notebook")
    import bokeh.plotting.figure as bk_figure
    from bokeh.io import show
    from bokeh import palettes
    from bokeh.layouts import row, column
    from bokeh.models import ColumnDataSource
    from bokeh.models.widgets import RadioButtonGroup, CheckboxButtonGroup
    from bokeh.models.widgets import RangeSlider, Div
    from bokeh.io import output_notebook  # enables plot interface in J notebook

    # init bokeh

    from bokeh.application import Application
    from bokeh.application.handlers import FunctionHandler

    from bokeh.core.validation import silence
    from bokeh.core.validation.warnings import EMPTY_LAYOUT

    silence(EMPTY_LAYOUT, True)

    output_notebook()

    # Set up widgets
    cfg_labels = ["Ghost"]
    wi_config = CheckboxButtonGroup(labels=cfg_labels, active=[0])
    wi_dense_select = RadioButtonGroup(
        labels=[ax.name for ax in histo.dense_axes()], active=0)
    wi_sparse_select = RadioButtonGroup(
        labels=[ax.name for ax in histo.sparse_axes()], active=0)

    # Dense widgets
    sliders = {}
    for ax in histo.dense_axes():
        edge_vals = (histo.axis(ax.name).edges()[0],
                     histo.axis(ax.name).edges()[-1])
        _smallest_bin = numpy.min(numpy.diff(histo.axis(ax.name).edges()))
        sliders[ax.name] = RangeSlider(
            title=ax.name,
            value=edge_vals,
            start=edge_vals[0],
            end=edge_vals[1],
            step=_smallest_bin,
            name=ax.name,
        )

    # Cat widgets
    togglers = {}
    for ax in histo.sparse_axes():
        togglers[ax.name] = CheckboxButtonGroup(
            labels=[i.name for i in ax.identifiers()],
            active=[0],
            name=ax.name)

    # Toggles for all widgets
    configers = {}
    for ax in histo.sparse_axes():
        configers[ax.name] = CheckboxButtonGroup(labels=["Display", "Ghost"],
                                                 active=[0, 1],
                                                 name=ax.name)
    for ax in histo.dense_axes():
        configers[ax.name] = CheckboxButtonGroup(labels=["Display"],
                                                 active=[0],
                                                 name=ax.name)

    # Figure
    fig = bk_figure(
        title="1D Projection",
        plot_width=500,
        plot_height=500,
        min_border=20,
        toolbar_location=None,
    )
    fig.yaxis.axis_label = "N"
    fig.xaxis.axis_label = "Quantity"

    # Iterate over possible overlays
    _max_idents = 0  # Max number of simultaneou histograms
    for ax in histo.sparse_axes():
        _max_idents = max(_max_idents, len([i.name for i in ax.identifiers()]))

    # Data source list
    sources = []
    sources_ghost = []
    for i in range(_max_idents):
        sources.append(
            ColumnDataSource(dict(left=[], top=[], right=[], bottom=[])))
        sources_ghost.append(
            ColumnDataSource(dict(left=[], top=[], right=[], bottom=[])))

    # Hist list
    hists = []
    hists_ghost = []
    for i in range(_max_idents):
        if _max_idents < 10:
            _color = palettes.Category10[min(max(3, _max_idents), 10)][i]
        else:
            _color = palettes.magma(_max_idents)[i]
        hists.append(
            fig.quad(
                left="left",
                right="right",
                top="top",
                bottom="bottom",
                source=sources[i],
                alpha=0.9,
                color=_color,
            ))
        hists_ghost.append(
            fig.quad(
                left="left",
                right="right",
                top="top",
                bottom="bottom",
                source=sources_ghost[i],
                alpha=0.05,
                color=_color,
            ))

    def update_data(attrname, old, new):
        sparse_active = wi_sparse_select.active
        sparse_name = [ax.name for ax in histo.sparse_axes()][sparse_active]
        sparse_other = [
            ax.name for ax in histo.sparse_axes() if ax.name != sparse_name
        ]

        dense_active = wi_dense_select.active
        dense_name = [ax.name for ax in histo.dense_axes()][dense_active]
        dense_other = [
            ax.name for ax in histo.dense_axes() if ax.name != dense_name
        ]

        # Apply cuts in projections
        _h = histo.copy()
        for proj_ax in sparse_other:
            _idents = histo.axis(proj_ax).identifiers()
            _labels = [ident.name for ident in _idents]
            if 0 in configers[proj_ax].active:
                _h = _h.integrate(
                    proj_ax, [_labels[i] for i in togglers[proj_ax].active])
            else:
                _h = _h.integrate(proj_ax)

        for proj_ax in dense_other:
            _h = _h.integrate(
                proj_ax,
                slice(sliders[proj_ax].value[0], sliders[proj_ax].value[1]))

        for cat_ix in range(_max_idents):
            # Update histo for each toggled overlay
            if cat_ix in togglers[sparse_name].active:
                cat_value = histo.axis(sparse_name).identifiers()[cat_ix]
                h1d = _h.integrate(sparse_name, cat_value)

                # Get shown histogram
                values = h1d.project(dense_name).values()
                if values != {}:
                    h = values[()]
                    bins = h1d.axis(dense_name).edges()

                    # Apply cuts on shown axis
                    bin_los = bins[:-1][
                        bins[:-1] > sliders[dense_name].value[0]]
                    bin_his = bins[1:][bins[1:] < sliders[dense_name].value[1]]
                    new_bins = numpy.intersect1d(bin_los, bin_his)
                    bin_ixs = numpy.searchsorted(bins, new_bins)[:-1]
                    h = h[bin_ixs]

                    sources[cat_ix].data = dict(
                        left=new_bins[:-1],
                        right=new_bins[1:],
                        top=h,
                        bottom=numpy.zeros_like(h),
                    )
                else:
                    sources[cat_ix].data = dict(left=[],
                                                right=[],
                                                top=[],
                                                bottom=[])

                # Add ghosts
                if 0 in wi_config.active:
                    h1d = histo.integrate(sparse_name, cat_value)
                    for proj_ax in sparse_other:
                        _idents = histo.axis(proj_ax).identifiers()
                        _labels = [ident.name for ident in _idents]
                        if 1 not in configers[proj_ax].active:
                            h1d = h1d.integrate(
                                proj_ax,
                                [_labels[i] for i in togglers[proj_ax].active])
                        else:
                            h1d = h1d.integrate(proj_ax)
                    values = h1d.project(dense_name).values()
                    if values != {}:
                        h = h1d.project(dense_name).values()[()]
                        bins = h1d.axis(dense_name).edges()
                        sources_ghost[cat_ix].data = dict(
                            left=bins[:-1],
                            right=bins[1:],
                            top=h,
                            bottom=numpy.zeros_like(h),
                        )
                    else:
                        sources_ghost[cat_ix].data = dict(left=[],
                                                          right=[],
                                                          top=[],
                                                          bottom=[])
            else:
                sources[cat_ix].data = dict(left=[],
                                            right=[],
                                            top=[],
                                            bottom=[])
                sources_ghost[cat_ix].data = dict(left=[],
                                                  right=[],
                                                  top=[],
                                                  bottom=[])

        # Cosmetics
        fig.xaxis.axis_label = dense_name

    for name, slider in sliders.items():
        slider.on_change("value", update_data)
    for name, toggler in togglers.items():
        toggler.on_change("active", update_data)
    for name, configer in configers.items():
        configer.on_change("active", update_data)
    # Button
    for w in [wi_dense_select, wi_sparse_select, wi_config]:
        w.on_change("active", update_data)

    from bokeh.models.widgets import Panel, Tabs

    layout = row(
        fig,
        column(
            Div(
                text="<b>Overlay Axis:</b>",
                style={
                    "font-size": "100%",
                    "color": "black"
                },
            ), wi_sparse_select,
            Div(text="<b>Plot Axis:</b>",
                style={
                    "font-size": "100%",
                    "color": "black"
                }), wi_dense_select,
            Div(
                text="<b>Categorical Cuts:</b>",
                style={
                    "font-size": "100%",
                    "color": "black"
                },
            ), *[toggler for name, toggler in togglers.items()],
            Div(text="<b>Dense Cuts:</b>",
                style={
                    "font-size": "100%",
                    "color": "black"
                }), *[slider for name, slider in sliders.items()]),
    )

    # Config prep
    incl_lists = [[], [], []]
    for i, key in enumerate(list(configers.keys())):
        incl_lists[i // max(5,
                            len(list(configers.keys())) / 3)].append(
                                Div(
                                    text="<b>{}:</b>".format(key),
                                    style={
                                        "font-size": "70%",
                                        "color": "black"
                                    },
                                ))
        incl_lists[i // max(5,
                            len(list(configers.keys())) / 3)].append(
                                configers[key])

    layout_cfgs = column(
        row(
            column(
                Div(
                    text="<b>Configs:</b>",
                    style={
                        "font-size": "100%",
                        "color": "black"
                    },
                ),
                wi_config,
            )),
        Div(text="<b>Axis togglers:</b>",
            style={
                "font-size": "100%",
                "color": "black"
            }),
        row(
            column(incl_lists[0]),
            column(incl_lists[1]),
            column(incl_lists[2]),
        ),
    )

    # Update active buttons
    def update_layout(attrname, old, new):
        active_axes = [None]
        for name, wi in configers.items():
            if 0 in wi.active:
                active_axes.append(name)
        for child in layout.children[1].children:
            if child.name not in active_axes:
                child.visible = False
            else:
                child.visible = True

    for name, configer in configers.items():
        configer.on_change("active", update_layout)

    tab1 = Panel(child=layout, title="Projection")
    tab2 = Panel(child=layout_cfgs, title="Configs")
    tabs = Tabs(tabs=[tab1, tab2])

    def modify_doc(doc):
        doc.add_root(row(tabs, width=800))
        doc.title = "Sliders"

    handler = FunctionHandler(modify_doc)
    app = Application(handler)

    show(app, notebook_url=jup_url)
    update_data("", "", "")
예제 #7
0
        msg = "No csv files chosen"
        MessageBox.text = msg
        return
    fpath = os.path.join(fdir, csvfiles[0])


cfg = bu.config()
Config = Paragraph(text=bu.config())
Above = Paragraph(text="You are Here")
Here = Paragraph()
Here.text = CurDir
MessageBox = Paragraph(text="Go")
Timer = Paragraph()
spacer = Paragraph(width=10)
blabels = bu.list_from_path(CurDir)
button_group = RadioButtonGroup(labels=blabels)
button_group.on_click(dir_select)


def dirs_source_callback(attr, old, new):
    global dirs_source
    oldind = old.get('1d', None)
    newind = (new['1d']['indices'][0]
              if len(new['1d']['indices']) > 0 else None)
    if newind is None:
        return
    if dirs_source.data['Name'][newind] == '.':
        return
    newpath = (dirs_source.data['Name'][newind]
               if newind is not None else None)
                 menu=menu,
                 default_action="baz")
split.on_click(split_handler)

checkbox_group = CheckboxGroup(labels=["Option 1", "Option 2", "Option 3"],
                               active=[0, 1])
checkbox_group.on_click(checkbox_group_handler)

radio_group = RadioGroup(labels=["Option 1", "Option 2", "Option 3"], active=0)
radio_group.on_click(radio_group_handler)

checkbox_button_group = CheckboxButtonGroup(
    labels=["Option 1", "Option 2", "Option 3"], active=[0, 1])
checkbox_button_group.on_click(checkbox_button_group_handler)

radio_button_group = RadioButtonGroup(
    labels=["Option 1", "Option 2", "Option 3"], active=0)
radio_button_group.on_click(radio_button_group_handler)

vbox = VBox(children=[
    button, toggle, dropdown, split, checkbox_group, radio_group,
    checkbox_button_group, radio_button_group
])

document.add(vbox)
session.store_document(document)

if __name__ == "__main__":
    link = session.object_link(document.context)
    print("Please visit %s to see the plots" % link)
    view(link)
    print("\npress ctrl-C to exit")
예제 #9
0
파일: edit.py 프로젝트: j-brady/peakipy
    def setup_plot(self):
        """" code to setup the bokeh plots """
        #  make bokeh figure
        tools = [
            "tap",
            "box_zoom",
            "lasso_select",
            "box_select",
            "wheel_zoom",
            "pan",
            "reset",
        ]
        self.p = figure(
            x_range=(self.peakipy_data.f2_ppm_0, self.peakipy_data.f2_ppm_1),
            y_range=(self.peakipy_data.f1_ppm_0, self.peakipy_data.f1_ppm_1),
            x_axis_label=f"{self.peakipy_data.f2_label} - ppm",
            y_axis_label=f"{self.peakipy_data.f1_label} - ppm",
            tools=tools,
            active_drag="pan",
            active_scroll="wheel_zoom",
            active_tap=None,
        )
        if not self.thres:
            self.thres = threshold_otsu(self.peakipy_data.data[0])
        self.contour_start = self.thres  # contour level start value
        self.contour_num = 20  # number of contour levels
        self.contour_factor = 1.20  # scaling factor between contour levels
        cl = self.contour_start * self.contour_factor ** np.arange(self.contour_num)
        if len(cl) > 1 and np.min(np.diff(cl)) <= 0.0:
            print(f"Setting contour levels to np.abs({cl})")
            cl = np.abs(cl)
        self.extent = (
            self.peakipy_data.f2_ppm_0,
            self.peakipy_data.f2_ppm_1,
            self.peakipy_data.f1_ppm_0,
            self.peakipy_data.f1_ppm_1,
        )
        self.spec_source = get_contour_data(
            self.peakipy_data.data[0], cl, extent=self.extent, cmap=viridis
        )
        #  negative contours
        self.spec_source_neg = get_contour_data(
            self.peakipy_data.data[0] * -1.0, cl, extent=self.extent, cmap=autumn
        )
        self.p.multi_line(
            xs="xs", ys="ys", line_color="line_color", source=self.spec_source
        )
        self.p.multi_line(
            xs="xs", ys="ys", line_color="line_color", source=self.spec_source_neg
        )
        # contour_num = Slider(title="contour number", value=20, start=1, end=50,step=1)
        # contour_start = Slider(title="contour start", value=100000, start=1000, end=10000000,step=1000)
        self.contour_start = TextInput(
            value="%.2e" % self.thres, title="Contour level:", width=100
        )
        # contour_factor = Slider(title="contour factor", value=1.20, start=1., end=2.,step=0.05)
        self.contour_start.on_change("value", self.update_contour)
        # for w in [contour_num,contour_start,contour_factor]:
        #    w.on_change("value",update_contour)

        #  plot mask outlines
        el = self.p.ellipse(
            x="X_PPM",
            y="Y_PPM",
            width="X_DIAMETER_PPM",
            height="Y_DIAMETER_PPM",
            source=self.source,
            fill_color="color",
            fill_alpha=0.1,
            line_dash="dotted",
            line_color="red",
        )

        self.p.add_tools(
            HoverTool(
                tooltips=[
                    ("Index", "$index"),
                    ("Assignment", "@ASS"),
                    ("CLUSTID", "@CLUSTID"),
                    ("RADII", "@X_RADIUS_PPM{0.000}, @Y_RADIUS_PPM{0.000}"),
                    (
                        f"{self.peakipy_data.f2_label},{self.peakipy_data.f1_label}",
                        "$x{0.000} ppm, $y{0.000} ppm",
                    ),
                ],
                mode="mouse",
                # add renderers
                renderers=[el],
            )
        )
        # p.toolbar.active_scroll = "auto"
        # draw border around spectrum area
        spec_border_x = [
            self.peakipy_data.f2_ppm_min,
            self.peakipy_data.f2_ppm_min,
            self.peakipy_data.f2_ppm_max,
            self.peakipy_data.f2_ppm_max,
            self.peakipy_data.f2_ppm_min,
        ]

        spec_border_y = [
            self.peakipy_data.f1_ppm_min,
            self.peakipy_data.f1_ppm_max,
            self.peakipy_data.f1_ppm_max,
            self.peakipy_data.f1_ppm_min,
            self.peakipy_data.f1_ppm_min,
        ]

        self.p.line(
            spec_border_x,
            spec_border_y,
            line_width=1,
            line_color="black",
            line_dash="dotted",
            line_alpha=0.5,
        )
        self.p.circle(x="X_PPM", y="Y_PPM", source=self.source, color="color")
        # plot cluster numbers
        self.p.text(
            x="X_PPM",
            y="Y_PPM",
            text="CLUSTID",
            text_color="color",
            source=self.source,
            text_font_size="8pt",
            text_font_style="bold",
        )

        self.p.on_event(DoubleTap, self.peak_pick_callback)

        self.pos_neg_contour_dic = {0: "pos/neg", 1: "pos", 2: "neg"}
        self.pos_neg_contour_radiobutton = RadioButtonGroup(
            labels=[
                self.pos_neg_contour_dic[i] for i in self.pos_neg_contour_dic.keys()
            ],
            active=0,
        )
        self.pos_neg_contour_radiobutton.on_change("active", self.update_contour)
        # call fit_peaks
        self.fit_button = Button(label="Fit selected cluster", button_type="primary")
        # lineshape selection
        self.lineshapes = {
            0: "PV",
            1: "V",
            2: "G",
            3: "L",
            4: "PV_PV",
            # 5: "PV_L",
            # 6: "PV_G",
            # 7: "G_L",
        }
        self.radio_button_group = RadioButtonGroup(
            labels=[self.lineshapes[i] for i in self.lineshapes.keys()], active=0
        )
        self.ls_div = Div(
            text="""Choose lineshape you wish to fit. This can be Voigt (V), pseudo-Voigt (PV), Gaussian (G), Lorentzian (L).
            PV_PV fits a PV lineshape with independent "fraction" parameters for the direct and indirect dimensions"""
        )
        self.clust_div = Div(
            text="""If you want to adjust how the peaks are automatically clustered then try changing the
                width/diameter/height (integer values) of the structuring element used during the binary dilation step
                (you can also remove it by selecting 'None'). Increasing the size of the structuring element will cause
                peaks to be more readily incorporated into clusters. Be sure to save your peak list before doing this as
                any manual edits will be lost."""
        )
        self.intro_div = Div(
            text="""<h2>peakipy - interactive fit adjustment </h2> 
            """
        )

        self.doc_link = Div(
            text="<h3><a href='https://j-brady.github.io/peakipy/build/usage/instructions.html', target='_blank'> ℹ️ click here for documentation</a></h3>"
        )
        self.fit_reports = ""
        self.fit_reports_div = Div(text="", height=400, style={"overflow": "scroll"})
        # Plane selection
        self.select_planes_list = [
            f"{i}"
            for i in range(self.peakipy_data.data.shape[self.peakipy_data.planes])
        ]
        self.select_plane = Select(
            title="Select plane:",
            value=self.select_planes_list[0],
            options=self.select_planes_list,
        )
        self.select_planes_dic = {
            f"{i}": i
            for i in range(self.peakipy_data.data.shape[self.peakipy_data.planes])
        }
        self.select_plane.on_change("value", self.update_contour)

        self.checkbox_group = CheckboxGroup(
            labels=["fit current plane only"], active=[]
        )

        #  not sure this is needed
        selected_df = self.peakipy_data.df.copy()

        self.fit_button.on_event(ButtonClick, self.fit_selected)

        columns = [
            TableColumn(field="ASS", title="Assignment"),
            TableColumn(field="CLUSTID", title="Cluster", editor=IntEditor()),
            TableColumn(
                field="X_PPM",
                title=f"{self.peakipy_data.f2_label}",
                editor=NumberEditor(step=0.0001),
                formatter=NumberFormatter(format="0.0000"),
            ),
            TableColumn(
                field="Y_PPM",
                title=f"{self.peakipy_data.f1_label}",
                editor=NumberEditor(step=0.0001),
                formatter=NumberFormatter(format="0.0000"),
            ),
            TableColumn(
                field="X_RADIUS_PPM",
                title=f"{self.peakipy_data.f2_label} radius (ppm)",
                editor=NumberEditor(step=0.0001),
                formatter=NumberFormatter(format="0.0000"),
            ),
            TableColumn(
                field="Y_RADIUS_PPM",
                title=f"{self.peakipy_data.f1_label} radius (ppm)",
                editor=NumberEditor(step=0.0001),
                formatter=NumberFormatter(format="0.0000"),
            ),
            TableColumn(
                field="XW_HZ",
                title=f"{self.peakipy_data.f2_label} LW (Hz)",
                editor=NumberEditor(step=0.01),
                formatter=NumberFormatter(format="0.00"),
            ),
            TableColumn(
                field="YW_HZ",
                title=f"{self.peakipy_data.f1_label} LW (Hz)",
                editor=NumberEditor(step=0.01),
                formatter=NumberFormatter(format="0.00"),
            ),
            TableColumn(
                field="VOL", title="Volume", formatter=NumberFormatter(format="0.0")
            ),
            TableColumn(
                field="include",
                title="Include",
                editor=SelectEditor(options=["yes", "no"]),
            ),
            TableColumn(field="MEMCNT", title="MEMCNT", editor=IntEditor()),
        ]

        self.data_table = DataTable(
            source=self.source, columns=columns, editable=True, fit_columns=True
        )

        # callback for adding
        # source.selected.on_change('indices', callback)
        self.source.selected.on_change("indices", self.select_callback)

        # Document layout
        fitting_controls = column(
            row(
                column(self.slider_X_RADIUS, self.slider_Y_RADIUS),
                column(
                    row(
                        widgetbox(self.contour_start, self.pos_neg_contour_radiobutton)
                    ),
                    widgetbox(self.fit_button),
                ),
            ),
            row(
                column(widgetbox(self.ls_div), widgetbox(self.radio_button_group)),
                column(widgetbox(self.select_plane), widgetbox(self.checkbox_group)),
            ),
        )

        # reclustering tab
        self.struct_el = Select(
            title="Structuring element:",
            value="disk",
            options=["square", "disk", "rectangle", "None", "mask_method"],
            width=100,
        )
        self.struct_el_size = TextInput(
            value="3",
            title="Size(width/radius or width,height for rectangle):",
            width=100,
        )

        self.recluster = Button(label="Re-cluster", button_type="warning")
        self.recluster.on_event(ButtonClick, self.recluster_peaks)

        # edit_fits tabs
        fitting_layout = fitting_controls
        log_layout = self.fit_reports_div
        recluster_layout = row(
            self.clust_div,
            column(
                self.contour_start, self.struct_el, self.struct_el_size, self.recluster
            ),
        )
        save_layout = column(self.savefilename, self.button, self.exit_button)

        fitting_tab = Panel(child=fitting_layout, title="Peak fitting")
        log_tab = Panel(child=log_layout, title="Log")
        recluster_tab = Panel(child=recluster_layout, title="Re-cluster peaks")
        save_tab = Panel(child=save_layout, title="Save edited peaklist")
        self.tabs = Tabs(
            tabs=[fitting_tab, log_tab, recluster_tab, save_tab],
            sizing_mode="scale_both",
        )
예제 #10
0
zoom.on_change('value', update1)
lat = Slider(start=36,
             end=36.24,
             value=36.1200,
             step=.02,
             title="Lat Position")
lat.on_change('value', update1)
lon = Slider(start=-115.30,
             end=-115.06,
             value=-115.18,
             step=.02,
             title="Lon Position")
lon.on_change('value', update1)

# Time Control
days_options = RadioButtonGroup(labels=["M", "T", "W", "T", "F", "S", "S"],
                                active=5)
days_options.on_change('active', update1)

slider = Slider(start=0, end=23, value=0, step=1, title="Hour of Day")
slider.on_change('value', update1)

# Select Options
neighborhood_options = list(set(df['neighborhood']))[1:]
alcohol_options = ['beer_and_wine', 'full_bar', 'none']
ambience = df['Ambience'][0]
ambience_options = [*ambience]
category_options = ['Casinos', 'Buffets', 'Nightlife', 'Cafes']

# Select Widgets
neighborhood = Select(title='Neighborhood',
                      value='All',
예제 #11
0
    # Corresponds to unscaled
    if scaling.active == 0:
        region_selection1.active = worst_d["worst9inds1"]
        region_selection2.active = worst_d["worst9inds2"]
    # Corresponds to per capita
    else:
        region_selection1.active = worst_d["worst9inds1_capita"]
        region_selection2.active = worst_d["worst9inds2_capita"]

    worst9.button_type = "primary"

#-----------------------------------------------------------------------------#

# Radio button group for selecting cases vs deaths
data_type = RadioButtonGroup(labels=["Cases", "Deaths"], active=0, 
                                 css_classes=["custom_button"])
data_type.on_change("active", update_plot)

# Radio button group for selecting unscaled vs per capita
scaling = RadioButtonGroup(labels=["Unscaled", "Per 100,000"], active=0, 
                                 css_classes=["custom_button"])
scaling.on_change("active", update_plot)

# Select and unselect all
select_all = Button(label="Select All", css_classes=["custom_button"])
select_all.on_click(select_all_update)
unselect_all = Button(label="Unselect All", css_classes=["custom_button"])
unselect_all.on_click(unselect_all_update)

# Button for displaying worst 9 regions
worst9 = Button(label="Show Worst 9 States", css_classes=["custom_button"])#, button_type="success")
예제 #12
0
                 depreciation.active.toString(),
                 deductibility.active.toString()];
    var reform_sources = %s;
    ref_source.data = reform_sources[parts.join('_')].data;

    // set baseline data source
    var bs_source = individual.active === 1 ? base_metr : base_mettr;
    base_source.data = bs_source.data;
    """ % js_source_array

callback = CustomJS(args=reform_sources, code=reform_source_change_code)

# Create buttons
rate_buttons = RadioButtonGroup(
    labels=["39.6%", "35%", "30%", "25%", "20%", "15%", "0%"],
    active=1,
    callback=callback,
    width=500)
depreciation_buttons = RadioButtonGroup(labels=[
    "Economic", "Current Law, No Bonus", "Current Law", "Full Expensing"
],
                                        active=2,
                                        callback=callback,
                                        width=500)
deductibility_buttons = RadioButtonGroup(
    labels=["Fully Deductible", "Non-Deductible"],
    active=0,
    callback=callback,
    width=500)
individual_buttons = RadioButtonGroup(labels=["Yes", "No"],
                                      active=0,
예제 #13
0
    def __init__(self, model):
        """
        Construct storage dashboard
        """
        # Save reference to model
        self.model = model

        ################################
        # Process button
        ################################

        self.process = Button(label="Generate",
                              button_type="primary",
                              name='process',
                              sizing_mode='scale_width')
        self.process.js_on_click(CustomJS(code="toggleLoading()"))

        ################################
        # Widgets
        ################################

        # Data type selection
        self.data_type = RadioButtonGroup(
            labels=["All Data", "Experimental", "Simulated"],
            active=0,
            css_classes=['dtypes'])

        # Adsorbate drop-down selections
        self.g1_sel = Select(title="Adsorbate 1",
                             options=self.model.ads_list,
                             value=self.model.g1,
                             css_classes=['g-selectors'])

        # Temperature selection
        self.t_absolute = Spinner(value=303,
                                  title='Temperature:',
                                  css_classes=['t_abs'])
        self.t_tolerance = Spinner(value=10,
                                   title='Tolerance:',
                                   css_classes=['t_tol'])

        # Combined in a layout
        self.dsel_widgets = layout([
            [self.data_type],
            [self.g1_sel, self.g2_sel, self.t_absolute, self.t_tolerance],
        ],
                                   sizing_mode='scale_width',
                                   name="widgets")

        ################################
        # KPI Plots
        ################################

        # Top graph generation
        tooltip = load_tooltip()
        self.p_henry, rend1 = self.top_graph("K", "Henry coefficient (log)",
                                             self.model.data,
                                             self.model.errors, tooltip)
        self.p_loading, rend2 = self.top_graph("L",
                                               "Uptake at selected pressure",
                                               self.model.data,
                                               self.model.errors, tooltip)
        self.p_wc, rend3 = self.top_graph(
            "W", "Working capacity in selected range", self.model.data,
            self.model.errors, tooltip)

        # Give graphs the same hover and select effect
        sel = Circle(fill_alpha=1, fill_color="red", line_color='black')
        for rend in [rend1, rend2, rend3]:
            rend.selection_glyph = sel
            rend.hover_glyph = sel

        # Pressure slider
        self.p_slider = Slider(
            title="Pressure (bar)",
            value=0.5,
            start=0,
            end=20,
            step=0.5,
            callback_policy='throttle',
            callback_throttle=500,
        )

        # Working capacity slider
        self.wc_slider = RangeSlider(
            title="Working capacity (bar)",
            value=(0.5, 5),
            start=0,
            end=20,
            step=0.5,
            callback_policy='throttle',
            callback_throttle=500,
        )

        # Material datatable
        self.mat_list = DataTable(
            columns=[
                TableColumn(field="labels", title="Material", width=300),
                TableColumn(field="sel",
                            title="KH2/KH1",
                            width=25,
                            formatter=NumberFormatter(format='‘0.0a’')),
                TableColumn(field="psa_W",
                            title="PSA-API",
                            width=30,
                            formatter=NumberFormatter(format='‘0.0a’')),
            ],
            source=self.model.data,
            index_position=None,
            selectable='checkbox',
            scroll_to_selection=True,
            width=400,
            fit_columns=True,
        )

        # Custom css classes for interactors
        self.p_henry.css_classes = ['g-henry']
        self.p_loading.css_classes = ['g-load']
        self.p_wc.css_classes = ['g-wcap']
        self.mat_list.css_classes = ['t-details']

        # Generate the axis labels
        self.top_graph_labels()

        self.kpi_plots = layout([
            [
                gridplot([[self.mat_list, self.p_henry],
                          [self.p_loading, self.p_wc]],
                         sizing_mode='scale_width')
            ],
            [self.p_slider, self.wc_slider],
        ],
                                sizing_mode='scale_width',
                                name="kpiplots")
        self.kpi_plots.children[0].css_classes = ['kpi']
        self.kpi_plots.children[1].css_classes = ['p-selectors']

        ################################
        # Isotherm details explorer
        ################################

        # Isotherm display graphs
        self.p_g1iso = self.bottom_graph(self.model.g1_iso_sel, self.model.g1)
        self.p_g2iso = self.bottom_graph(self.model.g2_iso_sel, self.model.g2)

        # Isotherm display palette
        self.c_cyc = cycle(gen_palette(20))

        self.detail_plots = layout([
            [self.p_g1iso, self.p_g2iso],
        ],
                                   sizing_mode='scale_width',
                                   name="detailplots")
        self.detail_plots.children[0].css_classes = ['isotherms']