예제 #1
0
def value_slider(source, plots):
    val_min = source.data["xmin"].min()
    val_max = source.data["xmax"].max()
    if "ci_lower" in source.column_names:
        val_min = min(val_min, source.data["ci_lower"].min())
    if "ci_upper" in source.column_names:
        val_max = max(val_max, source.data["ci_upper"].max())
    x_range = val_max - val_min
    value_column_slider = RangeSlider(
        start=val_min - 0.02 * x_range,
        end=val_max + 0.02 * x_range,
        value=(val_min, val_max),
        step=x_range / 500,
        title="Value",
        name="value_slider",
    )

    code = """
        var lower_end = cb_obj.value[0]
        var upper_end = cb_obj.value[1]

        for (var i = 0; i < plots.length; ++ i){
            plots[i].x_range.start = lower_end;
            plots[i].x_range.end = upper_end;
        }
    """

    callback = CustomJS(args={"plots": plots}, code=code)
    value_column_slider.js_on_change("value", callback)
    return value_column_slider
예제 #2
0
def make_plot1(df):
    data = ColumnDataSource(
        data={
            "x": df["Saniye"],
            "y": df["ECG"],
            "z": df["AFIB_STATUS"],
            "r": df[df["Peaks"] == "R"],
            "q": df[df["Peaks"] == "Q"],
            "s": df[df["Peaks"] == "S"],
            "p": df[df["Peaks"] == "QRS_complex_on"],
            "t": df[df["Peaks"] == "QRS_complex_off"]
        })
    hover_tool1 = HoverTool(tooltips=[("ECG Value",
                                       "@y"), ("AFIB Status",
                                               "@z"), ("Second", "@x")])
    plot1 = figure(tools=[hover_tool1],
                   x_axis_label="Second",
                   y_axis_label="ECG Value",
                   title="Basic ECG Analysis",
                   plot_width=1500,
                   plot_height=500)
    plot1.xaxis.ticker = SingleIntervalTicker(interval=0.04)
    plot1.xgrid.grid_line_color = "LightPink"
    plot1.yaxis.ticker = SingleIntervalTicker(interval=0.04)
    plot1.ygrid.grid_line_color = "LightPink"

    plot1.line(x="x", y="y", source=data)
    for data, name, color in zip([
            data.data["r"], data.data["q"], data.data["s"], data.data["p"],
            data.data["t"]
    ], ["R", "Q", "S", "QRS_complex_on", "QRS_complex_off"],
                                 ["red", "green", "gray", "cyan", "black"]):
        #df = pd.DataFrame(data)
        plot1.circle(data["Saniye"],
                     data["ECG"],
                     color=color,
                     alpha=0.8,
                     muted_color=color,
                     muted_alpha=0.1,
                     legend_label=name,
                     size=8)
    plot1.legend.location = "top_right"
    plot1.legend.click_policy = "mute"
    callback2 = CustomJS(args=dict(plot1=plot1),
                         code="""
                    var a = cb_obj.value;
                    plot1.x_range.start = a[0];
                    plot1.x_range.end = a[1];
                    plot1.change.emit();
                    cb_obj.title = "Interval is " + a[0] + " Second to " + a[1] + " Second" 
                    """)
    slider_widget = RangeSlider(start=df["Saniye"].min(),
                                end=df["Saniye"].max(),
                                step=1,
                                value=(df["Saniye"].min(), df["Saniye"].max()),
                                title="Select Second Interval")
    slider_widget.js_on_change("value_throttled", callback2)
    return plot1, slider_widget
예제 #3
0
def _subgroup_slider(source, subgroup_col):
    sorted_uniques = np.array(sorted(set(source.data[subgroup_col])))
    min_val, max_val = sorted_uniques[0], sorted_uniques[-1]
    min_dist_btw_vals = (sorted_uniques[1:] - sorted_uniques[:-1]).min()
    slider = RangeSlider(
        start=min_val - 0.05 * min_val,
        end=max_val + 0.05 * max_val,
        value=(min_val, max_val),
        step=min_dist_btw_vals,
        title=subgroup_col.title(),
        name="subgroup_widget",
    )
    slider.js_on_change(
        "value", CustomJS(code="source.change.emit();",
                          args={"source": source}))
    return slider
예제 #4
0
    def _get_xaxis_slider(self, plot_obj):
        """
        Creates an "x-axis slider" that allows the user to interactively change the boundaries of the axes
        :param plot_obj: Bokeh plot object
        :return: x-axis slider
        """
        callback = CustomJS(args={'plot': plot_obj}, code="""
            var a = cb_obj.value;
            plot.x_range.start = a[0];
            plot.x_range.end = a[1];
        """)
        slider = RangeSlider(start=0, end=50, value=(self.df['x'].min(), self.df['x'].max()),
                             step=1, title="x-axis range slider", width=200)
        slider.js_on_change('value', callback)

        return slider
예제 #5
0
def make_plot2(df):
    TOOLS = "tap"

    hover_tool = HoverTool(tooltips=[("Distance", "@dist")])
    plot1 = figure(x_axis_label="Second",
                   y_axis_label="ECG Value",
                   title="Basic AFIB Analysis",
                   plot_width=1500,
                   plot_height=500,
                   tools=[TOOLS, hover_tool])
    plot1.xaxis.ticker = SingleIntervalTicker(interval=0.04)
    plot1.xgrid.grid_line_color = "LightPink"
    plot1.yaxis.ticker = SingleIntervalTicker(interval=0.04)
    plot1.ygrid.grid_line_color = "LightPink"
    data3 = ColumnDataSource(data={
        "true": df[df["AFIB_STATUS"] == 1],
        "false": df[df["AFIB_STATUS"] == 0]
    })
    for data, name, color in zip([data3.data["true"], data3.data["false"]],
                                 ["Yes", "No"], ["red", "blue"]):
        plot1.line(data["Saniye"],
                   data["ECG"],
                   color=color,
                   alpha=1,
                   muted_color=color,
                   muted_alpha=0.1,
                   legend_label=name)
    plot1.legend.location = "top_left"
    plot1.legend.click_policy = "mute"
    data = ColumnDataSource(
        data={
            "r": df[df["Peaks"] == "R"],
            "q": df[df["Peaks"] == "Q"],
            "s": df[df["Peaks"] == "S"],
            "p": df[df["Peaks"] == "QRS_complex_on"],
            "t": df[df["Peaks"] == "QRS_complex_off"],
        })
    for data, name, color in zip([
            data.data["r"], data.data["q"], data.data["s"], data.data["p"],
            data.data["t"]
    ], ["R", "Q", "S", "QRS_complex_on", "QRS_complex_off"],
                                 ["red", "green", "gray", "cyan", "black"]):
        #df = pd.DataFrame(data)
        plot1.circle(data["Saniye"],
                     data["ECG"],
                     color=color,
                     alpha=0.8,
                     muted_color=color,
                     muted_alpha=0.1,
                     legend_label=name,
                     size=4)
    plot1.legend.location = "top_right"
    plot1.legend.click_policy = "mute"
    source = ColumnDataSource(data=dict(x=[], y=[], dist=[]))
    plot1.line(x="x", y="y", source=source)
    plot1.circle(source=source, x='x', y='y', size=8)
    callback2 = CustomJS(args=dict(plot1=plot1),
                         code="""
                    var a = cb_obj.value;
                    plot1.x_range.start = a[0];
                    plot1.x_range.end = a[1];
                    plot1.change.emit();
                    cb_obj.title = "Interval is " + a[0] + " Second to " + a[1] + " Second" 
                    """)
    slider_widget = RangeSlider(start=df["Saniye"].min(),
                                end=df["Saniye"].max(),
                                step=1,
                                value=(df["Saniye"].min(), df["Saniye"].max()),
                                title="Select Second Interval")
    slider_widget.js_on_change("value", callback2)
    callback = CustomJS(args=dict(source=source,
                                  plot1=plot1,
                                  slider_widget=slider_widget),
                        code="""
    // the event that triggered the callback is cb_obj:
    // The event type determines the relevant attributes
    
        var data = source.data;
        var x = data['x']
        var y = data['y']
        var dist = data['dist']
        if(x.length < 1) {
                x.push(cb_obj.x)
                y.push(cb_obj.y)
                dist.push(cb_obj.x - 0)
                
                }
        else if(x.length == 1) {
                x.push(cb_obj.x)
                y.push(cb_obj.y)
                dist.push(cb_obj.x - x[0])

                
            } 
        else  {
                source.data["x"] = []
                source.data["y"] = []
                }
        
        
        source.change.emit();
    
    """)
    plot1.js_on_event('tap', callback)
    callback3 = CustomJS(args=dict(plot1=plot1, slider_widget=slider_widget),
                         code="""
                    var a = slider_widget.value;
                    plot1.x_range.start = a[0];
                    plot1.x_range.end = a[1];
                    plot1.change.emit(); 
                    """)

    plot1.js_on_event(MouseMove, callback3)
    return plot1, slider_widget
예제 #6
0
yaxis.axis_line_width = 1
yaxis.axis_label_text_font_style = "italic"
p.add_layout(yaxis, 'left')

x_slider = RangeSlider(start=500, end=1800, value=(500,1800), step=.1, title="Wavelength(nm)",width=250 )
y_slider = RangeSlider(start=-5000, end=5000, value=(-5000,5000), step=.1, title="polarizability (a.u.)",width=250 )

callback = CustomJS(args=dict(p=p, x_slide=x_slider, y_slide=y_slider),
                    code="""
    p.x_range.start = x_slide.value[0];
    p.x_range.end = x_slide.value[1];
    p.y_range.start = y_slide.value[0];
    p.y_range.end = y_slide.value[1];
""")

x_slider.js_on_change('value', callback)
y_slider.js_on_change('value', callback)

# p.scatter(source = source, x= 'wavelength', y= 'polarizability' , marker="circle", legend='Cs6s',size=2,alpha=0.9,color="green" )
# p.scatter(source = source2, x= 'wavelength', y= 'polarizability' , marker="circle", legend='7p1',size=2,alpha=0.9,color= "navy", line_join='bevel', line_cap='round' )
x_data,y_data = data_function(df)
for x,y in zip(x_data,y_data):
    p.line(x= x, y=y ,color="#ff005b", legend_label='CS6s')

x_data,y_data = data_function(df2)
for x,y in zip(x_data,y_data):
    p.line( x =x, y=y ,color="navy", legend_label='7p1' )

source = ColumnDataSource(data=dict(x=[1194.3, 1758.7],
                                    y=[0.115,  0.67],
                                    names=['x=1194.3, y=0.115','x=1758.7, y=0.67']))
예제 #7
0
파일: navia.py 프로젝트: d-que/navia
mass_finder_exact_mass_text = Div(text= "Enter exact Mass (Da)", width= 150, height=30 )
mass_finder_exact_mass_sele = TextInput(value=str(mass_finder_mass.value*1000), disabled=False, width=100, height=30)

mass_finder_line_text = Div(text= "Show mz prediction", width= 150, height=30 )
mass_finder_line_sele = Toggle(label='off', active=False, width=100, height=30, callback=toggle_cb)

mass_finder_cb =CustomJS(args=dict(mass_finder_line_sele=mass_finder_line_sele, raw_mz=raw_mz, mass_finder_data=mass_finder_data, mass_finder_exact_mass_sele=mass_finder_exact_mass_sele, mass_finder_mass=mass_finder_mass, mass_finder_range_slider=mass_finder_range_slider, mfl=mfl), code=open(os.path.join(os.getcwd(), 'JS_Functions', "mass_finder_cb.js")).read())
mass_finder_exact_cb =CustomJS(args=dict(mass_finder_line_sele=mass_finder_line_sele, mass_finder_exact_mass_sele=mass_finder_exact_mass_sele, mass_finder_mass=mass_finder_mass), code=open(os.path.join(os.getcwd(), 'JS_Functions', "mass_finder_exact_cb.js")).read())
mass_finder_exact_mass_sele.js_on_change('value', mass_finder_exact_cb)

mass_finder_column=Column(mass_finder_header,mass_finder_mass, mass_finder_range_slider, Row(mass_finder_exact_mass_text,mass_finder_exact_mass_sele), Row(mass_finder_line_text, mass_finder_line_sele), visible=False)
mass_finder.js_link('active', mass_finder_column, 'visible')
mass_finder_line_sele.js_link('active', mfl, 'visible')
mass_finder_mass.js_on_change('value', mass_finder_cb)
mass_finder_line_sele.js_on_change('active', mass_finder_cb)
mass_finder_range_slider.js_on_change('value',mass_finder_cb)
### DATA PROCESSING ###

cropping = Div(text= " Range mz:", width= 150, height=30 )
# crop_max = Div(text= " ", width= 150, height=30 )
gau_name = Div(text= " Gaussian Smoothing:", width= 150, height=30 )
n_smooth_name = Div(text= " Repeats of Smoothing:", width= 150, height=30 )
# bin_name = Div(text= " Bin Every:", width= 150, height=30 )
int_name = Div(text= " Intensity Threshold (%)", width= 150, height=30 )
sub_name = Select(options=['Substract Minimum', 'Substract Line', 'Substract Curved'], name='sub_mode', value='Substract Minimum', width= 150, height=30 )
# add_name = Div(text= " Adduct Mass (Da)", width= 150, height=30 )
# dat_name = Div(text= " Data Reduction (%)", width= 150, height=30 )
#pro_name = Div(text= " bla", width= 150, height=30 )
dt_name  = Div(text= " <h2>Data Processing</h2>", height=45 )
dtp_update=CustomJS(args=dict(DataProcessingParameters=DataProcessingParameters), code=open(os.path.join(os.getcwd(), 'JS_Functions', "DataProcessingParameters_update_cb.js")).read())
예제 #8
0
class QCWorkTool:
    """The almighty QC-tool.

    Used for quality control of high resolution CTD-data (oceanography).
    """

    # TODO: Well, this is great.. However, we need to simplify and
    #  divide this class into widgets instead.. to be continued..
    #  - delete color fields? use flag fields instead?

    def __init__(
        self,
        dataframe,
        datasets=None,
        settings=None,
        tabs=None,
        ctdpy_session=None,
        export_folder=False,
        output_filename="CTD_QC_VIZ.html",
        output_as_notebook=False,
        output_as_standalone=False,
    ):
        """Initiate."""
        self.seconds = ColumnDataSource(
            data=dict(tap_time=[None], reset_time=[None]))
        self.ctd_session = ctdpy_session
        self.multi_sensors = settings.multi_sensors
        self.combo_plots = settings.combo_plots

        self.map = None
        self.plot_keys = settings.plot_keys
        self.datasets = datasets
        self.key_ds_mapper = self.get_mapper_key_to_ds(
            settings.file_name_elements)
        self.parameters = settings.data_parameters_with_units
        self.plot_parameters_mapping = settings.plot_parameters_mapping
        self.color_fields = settings.q_colors
        self.size_fields = settings.scatter_size
        self.qflag_fields = settings.q_parameters
        self.auto_qflag_fields = settings.q0_plot_keys
        self.tabs = tabs
        self.output_as_notebook = output_as_notebook
        self.as_standalone = output_as_standalone
        if self.output_as_notebook:
            raise NotImplementedError(
                'Not yet applicable to work with notebooks!')
        elif self.as_standalone:
            output_file(output_filename)

        self.tile_provider = get_provider(Vendors.CARTODBPOSITRON_RETINA)

        self.figures = {}
        xrange_callbacks = {}
        y_range_setting = None
        for p in self.plot_parameters_mapping:
            if p == 'y' or 'q' in p or p[0].isupper() or \
                    p.startswith('color') or p.startswith('size'):
                continue
            param = self.plot_parameters_mapping.get(p)
            self.figures[p] = figure(
                tools="pan,reset,wheel_zoom,lasso_select,save",
                active_drag="lasso_select",
                title="",
                height=400,
                width=400,
                y_range=y_range_setting,
                tooltips=[(param, "@{}".format(p)), ("Pressure [dbar]", "@y"),
                          ("Auto-QC", "@{}_q0".format(p))])
            self.figures[p].title.align = 'center'
            self.figures[p].xaxis.axis_label = param
            self.figures[p].xaxis.axis_label_text_font_style = 'bold'
            self.figures[p].ygrid.band_fill_alpha = 0.05
            self.figures[p].ygrid.band_fill_color = "black"
            self.figures[p].toolbar.active_scroll = self.figures[p].select_one(
                WheelZoomTool)

            if not y_range_setting or (self.multi_sensors and p == 'x4'):
                self.figures[p].yaxis.axis_label = 'Pressure (dbar)'
                self.figures[p].yaxis.axis_label_text_font_style = 'bold'

            y_range_setting = y_range_setting or self.figures[p].y_range

            xrange_callbacks[p] = cbs.x_range_callback(
                x_range_obj=self.figures[p].x_range, seconds=self.seconds)
            self.figures[p].x_range.js_on_change('start', xrange_callbacks[p])

        if self.combo_plots and self.multi_sensors:
            # TODO check the p2 (_) variable.. Should it not be used?
            for name, p1, _ in zip(('COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY'),
                                   ('x1', 'x2', 'x3'), ('x4', 'x5', 'x6')):
                param = self.plot_parameters_mapping.get(p1)
                self.figures[name] = figure(
                    tools="pan,reset,wheel_zoom,lasso_select,save",
                    active_drag="lasso_select",
                    title="",
                    height=400,
                    width=400,
                    y_range=y_range_setting,
                )
                self.figures[name].title.align = 'center'
                self.figures[name].xaxis.axis_label = param
                self.figures[name].xaxis.axis_label_text_font_style = 'bold'
                self.figures[name].ygrid.band_fill_alpha = 0.05
                self.figures[name].ygrid.band_fill_color = "black"
                self.figures[name].toolbar.active_scroll = \
                    self.figures[name].select_one(WheelZoomTool)

                if p1 == 'x1':
                    self.figures[name].yaxis.axis_label = 'Pressure (dbar)'
                    self.figures[
                        name].yaxis.axis_label_text_font_style = 'bold'

        cbs.add_hlinked_crosshairs(*(fig_obj
                                     for i, fig_obj in self.figures.items()))

        self.ts = figure(
            title="CTD TS Diagram",
            tools=[PanTool(),
                   WheelZoomTool(),
                   ResetTool(),
                   SaveTool()],
            tooltips=[("Serie", "@key")],
            height=400,
            width=400,
            x_range=(2, 36),
            y_range=(-2, 20))
        self.ts.title.align = 'center'

        self._setup_position_source(dataframe)
        self.data_source = setup_data_source(
            dataframe,
            pmap=self.plot_parameters_mapping,
            key_list=np.unique(self.position_source.data['KEY']),
            parameter_list=self.color_fields + self.size_fields +
            self.plot_keys + self.auto_qflag_fields +
            ['COMNT_SAMP']  # noqa: E501
        )
        self.ts_source = TS_Source()
        self.ts_source.setup_source(dataframe, self.plot_parameters_mapping)
        self.ts_plot_source = ColumnDataSource(
            data=dict(x=[], y=[], color=[], key=[]))

        self._setup_month_selector()
        self._setup_comnt_inputs()
        self._setup_selection_widgets()
        self._setup_multiflag_widget()
        self._setup_flag_widgets()
        self._setup_reset_callback(**xrange_callbacks)
        self._setup_datasource_callbacks()
        self._setup_download_button(settings.user_download_directory,
                                    export_folder=export_folder,
                                    icons=settings.icons)
        self._setup_get_file_button()
        self._setup_serie_table()
        self._setup_info_block(export_folder)
        self._setup_map()

        self.ts_axis_ranges = {
            't_min': 0,
            't_max': 25,
            's_min': 2,
            's_max': 36
        }

    def get_mapper_key_to_ds(self, file_name_elements):
        """Return mapper between dataset filename and key.

        Key = serie key (eg. '20191009_77SE_0005')
        """
        selected_keys = ('SDATE', 'SHIPC', 'SERNO')
        mapper = {}
        for ds_name in self.datasets:
            name_map = {
                k: v
                for k, v in zip(file_name_elements,
                                ds_name.replace('.txt', '').split('_'))
            }
            mapper['_'.join(
                (name_map.get(k) for k in selected_keys))] = ds_name
        return mapper

    @staticmethod
    def _get_monthly_keys(position_df):
        """Return mapper of monthly keys."""
        # FIXME Is this really necessary ?
        dictionary = {'All': position_df['KEY'].to_list()}
        for month in [str(m).zfill(2) for m in range(1, 13)]:
            boolean = position_df['MONTH'] == month
            dictionary[month] = position_df.loc[boolean, 'KEY'].to_list()
        return dictionary

    def _setup_position_source(self, df):
        """Set position data sources.

        self.position_source: Contains all position information.
        self.position_plot_source: Contains only the selected information.
        """
        position_df = df[[
            'STATION', 'LATITUDE_DD', 'LONGITUDE_DD', 'KEY', 'MONTH'
        ]].drop_duplicates(keep='first').reset_index(drop=True)

        for pos_row in position_df.itertuples():
            try:
                float(pos_row.LATITUDE_DD)
            except Exception:
                print('not valid', pos_row.KEY)

        xs, ys = convert_projection(
            position_df['LATITUDE_DD'].astype(float).values,
            position_df['LONGITUDE_DD'].astype(float).values)
        position_df['LONGI'] = xs
        position_df['LATIT'] = ys

        comnts = []
        for key in position_df['KEY']:
            ds_meta = self.datasets[self.key_ds_mapper.get(key)]['metadata']
            cv_boolean = ds_meta.str.startswith('//METADATA;COMNT_VISIT;')
            value = ds_meta[cv_boolean].values[0].replace(
                '//METADATA;COMNT_VISIT;', '')
            comnts.append(value)
        position_df['COMNT_VISIT'] = comnts

        self.monthly_keys = self._get_monthly_keys(position_df)
        self.position_source = ColumnDataSource(data=position_df)
        self.position_plot_source = ColumnDataSource(data=position_df)

    def _setup_month_selector(self):
        """Set month selection widget."""
        callback = cbs.month_selection_callback(
            position_source=self.position_source,
            position_plot_source=self.position_plot_source)
        self.month_selector = Select(
            title="Select month",
            value='All',
            options=['All'] + pd.date_range(
                start='2020-01', freq='M', periods=12).month_name().to_list())
        self.month_selector.js_on_change('value', callback)
        # self.month_selector.title.text_align = 'center'
        callback.args["month"] = self.month_selector

    def _setup_download_button(self, savepath, export_folder=None, icons=None):
        """Set download widget."""
        self.download_button = cbs.get_download_widget(
            self.datasets,
            self.position_plot_source,
            self.ctd_session,
            self.key_ds_mapper,
            savepath,
            export_folder=export_folder,
            icons=icons)

    def _setup_get_file_button(self):
        """Set file button widget."""
        self.file_button = cbs.get_file_widget()

    def _setup_serie_table(self):
        """Create data table associated to the position_plot_source object."""
        columns = [
            TableColumn(field="STATION", title="Station"),
            TableColumn(field="KEY", title="Key"),
        ]
        self.selected_series = DataTable(source=self.position_plot_source,
                                         columns=columns,
                                         width=300,
                                         height=322)

    def _setup_flag_widgets(self):
        """Set flag widgets."""
        self.flag_widgets = {}
        for fig_key in self.figures.keys():
            if fig_key.startswith('COMBO'):
                continue
            parameter = self.plot_parameters_mapping.get(fig_key).split()[0]
            self.flag_widgets[fig_key] = cbs.get_flag_buttons_widget(
                self.position_plot_source,
                self.data_source['main_source'],
                self.datasets,
                key_mapper=self.key_ds_mapper,
                figure_objs=self.figures,
                flag_keys=self.plot_parameters_mapping[parameter].get(
                    'q_flags'),
                color_keys=self.plot_parameters_mapping[parameter].get(
                    'color_keys'),
                size_keys=self.plot_parameters_mapping[parameter].get(
                    'size_keys'),
                select_button=self.select_all_button)

    def _setup_comnt_inputs(self):
        """Set comment input widgets."""
        self.comnt_visit = TextInput(value="", title="COMNT_VISIT:")
        self.comnt_visit_button = cbs.comnt_visit_change_button(
            datasets=self.datasets,
            position_source=self.position_plot_source,
            key_mapper=self.key_ds_mapper,
            comnt_obj=self.comnt_visit,
        )

        self.comnt_samp = TextInput(value="", title="COMNT_SAMP:")
        self.comnt_samp_button = cbs.comnt_samp_change_button(
            datasets=self.datasets,
            position_source=self.position_plot_source,
            key_mapper=self.key_ds_mapper,
            data_source=self.data_source['main_source'],
            comnt_obj=self.comnt_samp,
        )

        self.comnt_samp_selector = cbs.comnt_samp_selection(
            data_source=self.data_source['main_source'],
            comnt_obj=self.comnt_samp,
        )

    def _setup_info_block(self, export_folder):
        """Set text block objects."""
        self.info_block = get_info_block()
        self.text_export = get_export_info_block(export_folder)
        self.text_index_selection = standard_block_header(
            text='Profile index selection', height=30)
        self.text_multi_serie_flagging = standard_block_header(
            text='Multi serie parameter flagging', height=30)
        self.text_meta = standard_block_header(text='Change comments',
                                               height=30)
        self.text_import = standard_block_header(text='Not yet applicable',
                                                 height=30)

    def _setup_selection_widgets(self):
        """Set selection widgets."""
        self.select_all_button = cbs.select_button(
            data_source=self.data_source['main_source'])
        self.deselect_all_button = cbs.deselect_button(
            data_source=self.data_source['main_source'])

        self.pressure_slider = RangeSlider(start=0,
                                           end=100,
                                           value=(0, 100),
                                           step=0.5,
                                           title="Select with pressure range",
                                           width=300)
        callback = cbs.range_selection_callback(
            data_source=self.data_source['main_source'])
        self.pressure_slider.js_on_change('value', callback)

    def _setup_multiflag_widget(self):
        """Set multiflag widgets."""
        def sorted_params(plist):
            para_list = []
            i = 0
            while i < len(plist):
                if '2' in plist[i]:
                    para_list.extend([plist[i + 1], plist[i]])
                    i += 2
                else:
                    para_list.append(plist[i])
                    i += 1
            return para_list

        parameter_list = []
        for p in self.figures.keys():
            if not p.startswith('COMBO'):
                parameter_list.append(
                    self.plot_parameters_mapping.get(p).split()[0])

        parameter_list = sorted_params(sorted(parameter_list))

        self.parameter_selector = Select(title="Select parameter",
                                         value=parameter_list[0],
                                         options=parameter_list)

        self.multi_flag_widget = cbs.get_multi_serie_flag_widget(
            self.position_plot_source,
            self.data_source,
            self.datasets,
            key_mapper=self.key_ds_mapper,
            parameter_selector=self.parameter_selector,
            parameter_mapping=self.plot_parameters_mapping,
            figure_objs=None)

    def _setup_reset_callback(self, **kwargs):
        """Set linked figure reset functionality.

        Autoreset all figures.
        """
        for p in self.figures.keys():
            xr_cbs = (xr_cb for xr_cb in kwargs.values())
            self.figures[p].js_on_event('reset',
                                        cbs.reset_callback(self.seconds),
                                        *xr_cbs)

    def _setup_datasource_callbacks(self):
        """Set multiflag widgets."""
        set_button_type_callback = cbs.change_button_type_callback(
            button=self.select_all_button, btype='default')
        self.data_source['main_source'].selected.js_on_change(
            'indices', set_button_type_callback)

    def _setup_map(self):
        """Initiate the map object including all the connected interactivity."""
        pan = PanTool()
        save = SaveTool()
        tap = TapTool()
        lasso = LassoSelectTool()
        reset = ResetTool()
        wheel = WheelZoomTool()

        tooltips = HoverTool(tooltips=[("Station",
                                        "@STATION"), ("Serie", "@KEY")])

        # range bounds supplied in web mercator coordinates
        self.map = figure(
            x_range=(0, 4000000),
            y_range=(7100000, 9850000),
            x_axis_type="mercator",
            y_axis_type="mercator",
            plot_height=420,
            plot_width=1000,
            tools=[pan, wheel, tap, lasso, tooltips, reset, save])

        self.map.yaxis.axis_label = ' '  # in order to aline y-axis with figure window below
        self.map.xgrid.grid_line_color = None
        self.map.ygrid.grid_line_color = None
        self.map.toolbar.active_scroll = self.map.select_one(WheelZoomTool)
        self.map.add_tile(self.tile_provider)

        station_data_callback = cbs.station_callback(
            position_source=self.position_plot_source,
            data_source=self.data_source,
            figures=self.figures,
            seconds=self.seconds,
            pmap=self.plot_parameters_mapping)
        tap.callback = station_data_callback

        # When we mark stations on the map using lasso selection, we activate the TS-diagram.
        lasso_callback = cbs.lasso_callback(monthly_keys=self.monthly_keys,
                                            in_data=self.ts_source,
                                            plot_data=self.ts_plot_source,
                                            x_range=self.ts.x_range,
                                            y_range=self.ts.y_range)

        station_data_callback_2 = cbs.station_callback(
            position_source=self.position_plot_source,
            data_source=self.data_source,
            figures=self.figures,
            seconds=self.seconds,
            pmap=self.plot_parameters_mapping)

        comnt_callback = cbs.comnt_callback(
            position_source=self.position_plot_source,
            comnt_obj=self.comnt_visit,
            single_select=1)

        comnt_samp_callback = cbs.comnt_samp_callback(
            position_source=self.position_plot_source,
            data_source=self.data_source['main_source'],
            comnt_obj=self.comnt_samp,
            comnt_selector=self.comnt_samp_selector,
            single_select=1,
        )

        update_slider_callback = cbs.range_slider_update_callback(
            slider=self.pressure_slider,
            data_source=self.data_source['main_source'],
        )

        select_button_type_callback = cbs.change_button_type_callback(
            button=self.select_all_button, btype='default')

        lasso_callback.args["month"] = self.month_selector
        self.position_plot_source.selected.js_on_change(
            'indices',
            lasso_callback,
            station_data_callback_2,
            comnt_callback,
            update_slider_callback,
            select_button_type_callback,
            comnt_samp_callback,
        )

    def plot_stations(self):
        """Plot loaded stations on the map."""
        renderer = self.map.circle('LONGI',
                                   'LATIT',
                                   source=self.position_plot_source,
                                   color="#5BC798",
                                   line_color="aquamarine",
                                   size=10,
                                   alpha=0.7)
        selected_circle = Circle(fill_alpha=0.5,
                                 fill_color="#FF0202",
                                 line_color="aquamarine")
        nonselected_circle = Circle(fill_alpha=0.3,
                                    fill_color="#5BC798",
                                    line_color="aquamarine")
        renderer.selection_glyph = selected_circle
        renderer.nonselection_glyph = nonselected_circle

    def plot_data(self):
        """Plot default data in figures.

        Default data: x=[1] and y=[1].
        """
        combo_mapping = {
            'COMBO_TEMP': ('x1', 'x4'),
            'COMBO_SALT': ('x2', 'x5'),
            'COMBO_DOXY': ('x3', 'x6')
        }

        nonselected_circle = Circle(fill_alpha=0.1,
                                    fill_color="#898989",
                                    line_color="lightgrey")

        for p, item in self.figures.items():
            if p.startswith('COMBO'):
                p1, p2 = combo_mapping.get(p)
                item.line(p1,
                          'y',
                          color=f"color_{p1}",
                          line_color="navy",
                          line_width=1,
                          alpha=0.3,
                          source=self.data_source['main_source'])
                item.circle(p1,
                            'y',
                            color=f"color_{p1}",
                            line_color="white",
                            size=f"size_{p1}",
                            alpha=0.5,
                            source=self.data_source['main_source'])

                item.line(p2,
                          'y',
                          color=f"color_{p2}",
                          line_color="navy",
                          line_width=1,
                          alpha=0.3,
                          source=self.data_source['main_source'])
                item.cross(p2,
                           'y',
                           color=f"color_{p2}",
                           size=f"size_{p2}",
                           alpha=0.5,
                           source=self.data_source['main_source'])

                item.y_range.flipped = True
            else:
                item.line(p,
                          'y',
                          color=f"color_{p}",
                          line_color="navy",
                          line_width=1,
                          alpha=0.3,
                          source=self.data_source['main_source'])
                renderer = item.circle(p,
                                       'y',
                                       color=f"color_{p}",
                                       line_color="white",
                                       size=f"size_{p}",
                                       alpha=0.5,
                                       source=self.data_source['main_source'])
                renderer.nonselection_glyph = nonselected_circle
                item.y_range.flipped = True

        # T/S - diagram
        self.ts.circle('x',
                       'y',
                       color='color',
                       size=3,
                       alpha=0.8,
                       source=self.ts_plot_source,
                       legend_label='Sensor 1')
        self.ts.toolbar.active_scroll = self.ts.select_one(WheelZoomTool)
        self.ts.legend.location = "top_left"

        number_of_colors = int(self.ts_source.data[
            self.plot_parameters_mapping.get('y')].max()) * 2
        number_of_colors += 1
        cm_map = cm.get_cmap('cool', number_of_colors)
        color_array = [
            colors.to_hex(cm_map(c)) for c in range(number_of_colors)
        ]
        color_bar = ColorBar(
            color_mapper=LinearColorMapper(
                palette=color_array,
                low=0,
                high=self.ts_source.data[self.plot_parameters_mapping.get(
                    'y')].max()),
            location=(0, 0),
        )

        self.ts.add_layout(color_bar, 'right')

        x_min, x_max, y_min, y_max = 0, 40, -10, 30
        contour_data = get_contour_data(x_min, x_max, y_min, y_max)
        for key in contour_data.keys():
            self.ts.line(contour_data[key]['salt'],
                         contour_data[key]['temp'],
                         line_color="grey",
                         line_alpha=0.8,
                         line_width=1.5)

    def append_qc_comment(self, meta_series):
        """Append commnet at the end of the metadata serie.

        Will be placed on the row just above the data table in each data file.
        """
        time_stamp = get_time_as_format(now=True, fmt='%Y%m%d%H%M')
        meta_series[len(meta_series) + 1] = '//QC_COMNT; MANUAL QC PERFORMED BY {}; TIMESTAMP {}' \
                                            ''.format(self.ctd_session.settings.user, time_stamp)

    def get_tab_layout(self):
        """Return bokeh tab widget."""
        fig_tabs = [
            Panel(child=column([Spacer(height=30, width=20), self.ts]),
                  title="TS")
        ]
        for p, item in self.figures.items():
            if (self.multi_sensors and p not in ['x1', 'x2', 'x3', 'x4', 'x5', 'x6',
                                                 'COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY']) \
                    or (not self.multi_sensors and p not in ['x1', 'x2', 'x3']):
                tab_layout = column([self.flag_widgets[p], item])
                tab_name = self.plot_parameters_mapping.get(
                    p).split()[0].replace('_CTD', '')
                pan = Panel(child=tab_layout, title=tab_name)
                fig_tabs.append(pan)

        return Tabs(tabs=fig_tabs)

    def get_tabs(self, **kwargs):
        """Return bokeh tab widget."""
        tabs = []
        for name, item in kwargs.items():
            tab = self.get_column(item)
            pan = Panel(child=tab, title=name)
            tabs.append(pan)

        return Tabs(tabs=tabs)

    def get_column(self, item):
        """Return bokeh column layout."""
        c_list = []
        for attr in item:
            if type(attr) == str:
                c_list.append(self.__getattribute__(attr))
            elif type(attr) == tuple:
                r = row([self.__getattribute__(a) for a in attr],
                        sizing_mode="stretch_width")
                c_list.append(r)
        return column(c_list)

    def get_std_parameter_tab_layout(self):
        """Return list of bokeh column layouts."""
        def pan_title(string):
            return string.split()[0].replace('_CTD', '')

        columns = []

        if self.multi_sensors:
            for params in zip(('x1', 'x2', 'x3'), ('x4', 'x5', 'x6'),
                              ('COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY')):
                pans = []
                for p in params:
                    if p in self.figures:
                        tab_cols = []
                        if p in self.flag_widgets:
                            tab_cols.append(self.flag_widgets[p])
                        else:
                            tab_cols.append(Spacer(width=20, height=41))
                        tab_cols.append(self.figures[p])
                        tab = column(tab_cols)
                        pan = Panel(child=tab,
                                    title=pan_title(
                                        self.plot_parameters_mapping.get(p)
                                        or p))
                        pans.append(pan)
                columns.append(column([Tabs(tabs=pans)]))
        else:
            for p1 in ('x1', 'x2', 'x3'):
                columns.append(
                    column([self.flag_widgets[p1], self.figures[p1]]))

        return columns

    def get_layout(self):
        """Return the complete bokeh layout."""
        tabs = self.get_tab_layout()
        tab_kwargs = {
            'Data': [
                'text_index_selection',
                ('select_all_button', 'deselect_all_button'),
                'pressure_slider', 'text_multi_serie_flagging',
                'parameter_selector', 'multi_flag_widget'
            ],
            'Metadata': [
                'text_meta', 'comnt_visit', 'comnt_visit_button', 'comnt_samp',
                'comnt_samp_selector', 'comnt_samp_button'
            ],
            'Info': ['info_block']
        }
        if not self.as_standalone:
            tab_kwargs['Import'] = ['text_import', 'file_button']
            tab_kwargs['Export'] = ['text_export', 'download_button']

        meta_tabs = self.get_tabs(**tab_kwargs)
        std_parameter_tabs = self.get_std_parameter_tab_layout()
        widgets_1 = column(
            [self.month_selector, self.spacer, self.selected_series],
            sizing_mode="fixed",
            height=400,
            width=200)
        widgets_2 = column([Spacer(height=10, width=125)],
                           sizing_mode="fixed",
                           height=10,
                           width=125)
        widgets_3 = column([meta_tabs],
                           sizing_mode="stretch_both",
                           height=100,
                           width=100)
        return grid([
            row([self.map, widgets_1, widgets_2, widgets_3]),
            row([*std_parameter_tabs, column([tabs])])
        ])

    @property
    def spacer(self):
        """Return bokeh spacer."""
        return Spacer(height=10, width=20)

    def return_layout(self):
        """Return the layout.

        Can be displayed in an embedded bokeh server.
        """
        return self.get_layout()

    def show_plot(self):
        """Show layout in a html-file or in jupyter notebook."""
        show(self.get_layout())
예제 #9
0
p.line('y', 'x', source=source, line_width=2)

range_slider = RangeSlider(title="Data Range Slider: ",
                           start=0,
                           end=len(lon),
                           value=(0, len(lon)),
                           step=1)

callback = CustomJS(args=dict(source=source,
                              slider=range_slider,
                              long=lon,
                              lati=lat),
                    code="""
    var data = source.data;
    const start = slider.value[0];
    const end = slider.value[1];
    
    data['x'] = long.slice(start, end)
    data['y'] = lati.slice(start, end)

    source.change.emit();
    """)

range_slider.js_on_change('value', callback)

layout = row(p, range_slider)

output_file("diag_plot_bike_data.html")

show(layout)
예제 #10
0
def plotIt(xName, yName, widgetList, generator, sourceMeta):
    '''
    generate the initial plots and populate them with data
    '''
    LINE_ARGS = dict(color="#3A8785", line_color=None)
    TOOLS = "reset,save,pan,wheel_zoom,box_zoom,box_select,lasso_select,hover"
    TS_TOOLS = "reset,save,pan,xwheel_zoom,hover"

    firstCycle = sourceMeta["timeRange"][0]["first"]
    lastCycle = sourceMeta["timeRange"][0]["last"]
    startCycle, x, y = generator.adapter.get_points(
        firstCycle, lastCycle, sourceMeta["timeRange"][0]["units"],
        [xName, yName], -1)

    source = ColumnDataSource(data=dict(x=x, y=y, index=startCycle))

    scatterView = CDSView(source=source,
                          filters=[IndexFilter(np.arange(len(x)))])

    # create the scatter plot
    p = figure(tools=TOOLS,
               plot_width=700,
               plot_height=700,
               min_border=10,
               min_border_left=30,
               toolbar_location="above",
               title="Comparison",
               output_backend="webgl",
               x_axis_label=xName,
               y_axis_label=yName)

    xAxis = p.xaxis[0]
    yAxis = p.yaxis[0]
    p.background_fill_color = "#fafafa"
    p.select(BoxSelectTool).select_every_mousemove = False
    p.select(LassoSelectTool).select_every_mousemove = False

    scatter = p.scatter('x',
                        'y',
                        source=source,
                        size=3,
                        marker='diamond',
                        color="navy",
                        alpha=0.85,
                        view=scatterView)

    # create the horizontal histogram
    hedges, hhist = generator.generate_histogram(
        firstCycle, lastCycle, sourceMeta["timeRange"][0]["units"], xName, -1)
    hh = figure(toolbar_location=None,
                plot_width=p.plot_width,
                plot_height=200,
                x_range=p.x_range,
                min_border=10,
                min_border_left=50,
                y_axis_location="right",
                y_axis_label="count",
                output_backend="webgl")
    hh.xgrid.grid_line_color = None
    hh.yaxis.major_label_orientation = np.pi / 4
    hh.background_fill_color = "#fafafa"

    horzPanelSource = ColumnDataSource(
        data=dict(bottom=np.zeros(len(hedges) - 1),
                  left=hedges[:-1],
                  right=hedges[1:],
                  top=hhist))
    hh.quad(left='left',
            bottom='bottom',
            top='top',
            right='right',
            source=horzPanelSource,
            color="rgb(170,186,215)",
            line_color="rgb(144,159,186)")
    horzHistSource = ColumnDataSource(
        data=dict(bottom=np.zeros(len(hedges) - 1),
                  left=hedges[:-1],
                  right=hedges[1:],
                  top=np.zeros(len(hedges) - 1)))

    hh.quad(left='left',
            bottom='bottom',
            top='top',
            right='right',
            source=horzHistSource,
            alpha=0.5,
            **LINE_ARGS)

    # create the vertical histogram
    vedges, vhist = generator.generate_histogram(
        firstCycle, lastCycle, sourceMeta["timeRange"][0]["units"], yName, -1)

    pv = figure(toolbar_location=None,
                plot_width=200,
                plot_height=p.plot_height,
                y_range=p.y_range,
                min_border=10,
                y_axis_location="right",
                x_axis_label="count",
                output_backend="webgl")
    pv.ygrid.grid_line_color = None
    pv.xaxis.major_label_orientation = np.pi / 4
    pv.background_fill_color = "#fafafa"

    vertPanelSource = ColumnDataSource(data=dict(top=vedges[1:],
                                                 bottom=vedges[:-1],
                                                 right=vhist,
                                                 left=np.zeros(len(vedges))))
    pv.quad(left='left',
            bottom='bottom',
            top='top',
            right='right',
            source=vertPanelSource,
            color="rgb(170,186,215)",
            line_color="rgb(144,159,186)")

    vertHistSource1 = ColumnDataSource(
        data=dict(top=vedges[1:],
                  bottom=vedges[:-1],
                  right=np.zeros(len(vedges) - 1),
                  left=np.zeros(len(vedges) - 1)))
    # vh1 =
    pv.quad(left='left',
            bottom='bottom',
            top='top',
            right='right',
            source=vertHistSource1,
            alpha=0.5,
            **LINE_ARGS)

    rs = RangeSlider(start=firstCycle,
                     end=lastCycle,
                     value=(firstCycle, lastCycle),
                     step=10,
                     title="Visible Range",
                     width=535,
                     align="center",
                     show_value=True)

    # compute the trend line

    try:
        xValues, yValues = generator.generate_regression_line(
            firstCycle, lastCycle, sourceMeta["timeRange"][0]["units"],
            [xName, yName], -1)
        regLineSource = ColumnDataSource("x",
                                         "y",
                                         data=dict(x=xValues, y=yValues))
        regLine = p.line('x',
                         'y',
                         source=regLineSource,
                         color="#f44242",
                         line_width=2.5)
    except LinAlgError:
        regLine.visible = False

    box = BoxAnnotation(fill_alpha=0.5,
                        line_alpha=0.5,
                        level='underlay',
                        left=rs.start,
                        right=rs.end)

    # time series 1
    ts1 = figure(plot_width=600,
                 plot_height=225,
                 title=xName,
                 tools=TS_TOOLS,
                 active_scroll="xwheel_zoom",
                 x_range=Range1d(firstCycle, lastCycle, bounds="auto"))
    ts1.line(
        x='index',
        y='x',
        source=source,
    )
    ts1.add_layout(box)

    xTsLabel = ts1.title

    ts2 = figure(
        plot_width=600,
        plot_height=225,
        title=yName,
        tools=TS_TOOLS,
        active_scroll="xwheel_zoom",
        # y_range = Range1d(-1.1 * max(y), 1.1 * max(y), bounds = (-1.1 * max(y), 1.1 * max(y))),
        x_range=ts1.x_range)
    ts2.line(
        x='index',
        y='y',
        source=source,
    )
    ts2.add_layout(box)
    yTsLabel = ts2.title

    # setup JS callbacks for widgets
    w1, w2 = widgetList

    rs.js_on_change(
        'value',
        CustomJS(args=dict(rs=rs,
                           box=box,
                           scatter=scatter,
                           scatterView=scatterView,
                           ts1=ts1,
                           ts2=ts2,
                           source=source,
                           p=p,
                           w1=w1,
                           w2=w2,
                           xAxis=xAxis,
                           yAxis=yAxis,
                           horzPanelSource=horzPanelSource,
                           horzHistSource=horzHistSource,
                           vertPanelSource=vertPanelSource,
                           vertHistSource1=vertHistSource1,
                           regLineSource=regLineSource,
                           xName=xTsLabel,
                           yName=yTsLabel),
                 code='''
        rangeUpdateDebounceCB(rs, box, scatter, scatterView, ts1, ts2, source, p,
                  w1, w2, xAxis,yAxis, horzPanelSource, horzHistSource,
                  vertPanelSource, vertHistSource1, regLineSource, xName, yName);
                  '''))

    timeSeriesPanJS = CustomJS(args=dict(rs=rs,
                                         box=box,
                                         scatter=scatter,
                                         scatterView=scatterView,
                                         ts1=ts1,
                                         ts2=ts2,
                                         source=source,
                                         p=p,
                                         w1=w1,
                                         w2=w2,
                                         xAxis=xAxis,
                                         yAxis=yAxis,
                                         horzPanelSource=horzPanelSource,
                                         horzHistSource=horzHistSource,
                                         vertPanelSource=vertPanelSource,
                                         vertHistSource1=vertHistSource1,
                                         regLineSource=regLineSource,
                                         xName=xTsLabel,
                                         yName=yTsLabel),
                               code='''
        timeSeriesPanDebounceCB(rs, box, scatter, scatterView, ts1, ts2, source, p, w1, w2, xAxis,
                                yAxis, horzPanelSource, horzHistSource, vertPanelSource, vertHistSource1,
                                regLineSource, xName, yName);''')

    ts1.js_on_event(PanEnd, timeSeriesPanJS)
    ts1.js_on_event(Pinch, timeSeriesPanJS)
    ts1.js_on_event(Reset, timeSeriesPanJS)
    ts1.js_on_event(MouseWheel, timeSeriesPanJS)

    ts2.js_on_event(PanEnd, timeSeriesPanJS)
    ts2.js_on_event(Pinch, timeSeriesPanJS)
    ts2.js_on_event(Reset, timeSeriesPanJS)
    ts2.js_on_event(MouseWheel, timeSeriesPanJS)

    dropdownCallback = CustomJS(args=dict(
        source=source,
        p=p,
        w1=w1,
        w2=w2,
        xAxis=xAxis,
        yAxis=yAxis,
        horzPanelSource=horzPanelSource,
        horzHistSource=horzHistSource,
        vertPanelSource=vertPanelSource,
        vertHistSource1=vertHistSource1,
        regLineSource=regLineSource,
        xName=xTsLabel,
        yName=yTsLabel,
        rs=rs,
        scatterView=scatterView,
    ),
                                code='''
        updateAll(cb_obj, source, w1.value, w2.value, xAxis, yAxis,
                  vertPanelSource, vertHistSource1,
                  horzPanelSource, horzHistSource,
                  regLineSource, xName, yName, rs, scatterView);
                  ''')

    w1.js_on_change("value", dropdownCallback)

    w2.js_on_change("value", dropdownCallback)

    # w2.js_on_change("select", CustomJS(code='''console.log("asdf");'''))

    # global layout
    newLayout = layout([
        row([p, pv,
             column([widgetList[0], widgetList[1], rs, ts1, ts2])]), [hh]
    ])

    return newLayout
예제 #11
0
    def getPlot(score,allscore,classification,counts,rest,tabledict,title,maxval):

	classification=sorted(classification)
	legendlist=[]
	for l in classification:
	    legendlist.append(bokutils.makeLegendKey(l))
	
	labellist=[]
	for l in counts:
	    labellist.append(str(l))
	

        hover = HoverTool(tooltips="""
        <div style=" opacity: .8; padding: 5px; background-color: @type_color;color: @font_color;>
                          <h1 style="margin: 0; font-size: 12px;"> @legendlist</h1>
                          <h1 style="margin: 0; font-size: 24px;"><strong> @counts </strong></h1>
                          <table>
                          @subgroups{safe}
                          </table>
                          </div>
                          """
                          )

                          

        subdict={}
        for i, val in enumerate(classification):
            subdict[i]=tabledict[val]

                          
        
        ## Left diagram
        classlen=len(classification)
        my_palette=bokutils.getColors(classlen,True,False)
        
        colordict={}
        for i, val in enumerate(my_palette):
            colordict[i]=val
        
        source = ColumnDataSource(data=dict(classification=classification, counts=counts,
					    legendlist=legendlist,
					    labellist=labellist,
                                            type_color=[colordict[x] for x in colordict],
                                            font_color=[bokutils.contrasting_text_color(colordict[x]) for x in colordict],
                                            subgroups=[subdict[x] for x in subdict]))
        

        p = figure(x_range=classification, plot_height=bokutils.PLOT_HEIGHT,plot_width=bokutils.PLOT_WIDTH, tools=[hover],toolbar_location=None, title=title)
        p.vbar(x='classification', top='counts', width=0.9, source=source, legend="legendlist",
               line_color='white', fill_color=factor_cmap('classification', palette=my_palette, factors=classification))
        
        p.xgrid.grid_line_color = None
        p.y_range.start = 0
        p.y_range.end = maxval
        p.legend.orientation = "vertical"
        #p.legend.location = "top_right"
        text_source = ColumnDataSource({'year': ['%s' % 1968]})
        text= Text(x=1, y=35, text='year',
                   text_font_size='80pt',
                   text_color='#EEEEEE'
                   )
        p.add_glyph(text_source, text)
        p.xaxis.major_label_orientation = 1.2

	blabel = LabelSet(x='classification', y='counts', text='labellist', level='glyph',
			  x_offset=5, y_offset=5, source=source, render_mode='canvas')

	p.add_layout(blabel)

	new_legend = p.legend[0]
	p.legend[0].plot = None
	p.add_layout(new_legend, 'right')

	blabel = LabelSet(x='classification', y='counts', text='labellist', level='glyph',
			  x_offset=5, y_offset=5, source=source, render_mode='canvas')

	p.add_layout(blabel)
		      
        slider = RangeSlider(
                              start=bokutils.FIRST_YEAR,
                              end=bokutils.LAST_YEAR,
                              value=[bokutils.LAST_YEAR, bokutils.LAST_YEAR],
                              step=1,
                              title='Year',
			      bar_color="#b3cccc")



        def slider_update(source=source, slider=slider, plot=p,window=None):
            year0 = slider.value[0]
            year1 = slider.value[1]
            return

        
        slider.js_on_change('value', bokutils.translatepy2js(slider_update))

        wb=widgetbox(children=[slider], sizing_mode='scale_width')
        thisrow=Column(children=[p, wb],
                       sizing_mode='scale_both')
        return thisrow
예제 #12
0
def home():

    #Access the SQL database
    engine = create_engine('sqlite:///../tapestation.db', echo=False)

    #Make a plot of strongest peaks, sizes and peak molarity

    #Get the data
    peak_df = pd.read_sql('SELECT * FROM peaks', engine)

    #Get region data
    region_df = pd.read_sql('SELECT * from regions', engine)
    region_cols = ['ts_data_id', 'well_id', 'avg_size']
    region_size_df = region_df[region_cols]

        
    #Choose only the first peak as well as from samples only
    first_peak_mask = (peak_df['samp_desc'] != 'Electronic Ladder') & (peak_df['peak_id'] == 1)
    first_peak_df = peak_df[first_peak_mask].copy()
    first_peak_cols = ['ts_data_id', 'well_id', 'peak_mol', 'int_area', 'size', 'cal_conc']
    first_peak_df = first_peak_df[first_peak_cols]

    #Merging the data
    combined_df = pd.merge(first_peak_df, region_size_df, on=['ts_data_id', 'well_id'], how='outer')
    #print(combined_df)
    source_data = ColumnDataSource(combined_df)

    #Have two instances of the data so for callback purposes
    #Because we are essentially filtering the data
    #We don't want to lose the data when altering widgets, keep an 'unchanged' copy
    unchanged_data = ColumnDataSource(combined_df)

    first_peak_plot = figure()
    first_peak_plot.circle(x='size', y='peak_mol', source=source_data)

    first_peak_plot.title.text = 'Size vs Peak Molarity of Strongest Peaks'
    first_peak_plot.xaxis.axis_label = 'Size [bp]'
    first_peak_plot.yaxis.axis_label = 'Peak Molarity [pmol/l]'

    #Add a hover tool for the relevant information from peaks table
    hover_first_peak = HoverTool()
    hover_first_peak.tooltips=[
            ('TS Data ID', '@ts_data_id'),
            ('Well', '@well_id'),
            ('Size [bp]','@size'),
            ('Peak Molarity [pmol/l]', '@peak_mol'),
            ('Calibrated Concentration [pg/mul]', '@cal_conc'),
            ('% Integrated Area', '@int_area')
            ]
    first_peak_plot.add_tools(hover_first_peak)


    #Make a plot comparing well size to average size
    size_plot = figure(match_aspect=True) #match_aspect keep aspect ratio the same
    size_plot.circle(x='size', y='avg_size', source=source_data)

    size_plot.title.text = 'Size of Strongest Peak vs Avg Size of Region [bp]'
    size_plot.xaxis.axis_label = 'Size of Strongest Peak [bp]'
    size_plot.yaxis.axis_label = 'Avg Size of Region [bp]'

    size_plot.ray(x=[0,2,3], y=[0,2,3], length=0, angle=[45], angle_units='deg', color="#FB8072")
    #Add a hover tool for the relevant information
    hover_size = HoverTool()
    hover_size.tooltips = [
            ('TS Data ID', '@ts_data_id'),
            ('Well', '@well_id'),
            ('Size [bp]', '@size'),
            ('Avg size [bp]', '@avg_size')
            ]

    size_plot.add_tools(hover_size)


    #Slider callbacks with CustomJS
    callback_JS="""
    //Get the value from out int area slider
    var int_area_cutoff = int_area_slider.value;

    //Get the range of our calibrated concentration slider
    var conc_min = conc_slider.value[0];
    var conc_max = conc_slider.value[1];

    //Get the values from ts data multi_select
    var ts_data_list = ts_data_multi_select.value;
    //console.log(ts_data_list);

    //Call the unchanged data
    var uc_data = unchanged_data.data;
    var uc_ts_data_id_data = uc_data['ts_data_id'];
    var uc_well_id_data = uc_data['well_id'];
    var uc_cal_conc_data = uc_data['cal_conc'];
    var uc_int_area_data = uc_data['int_area'];
    var uc_size_data = uc_data['size'];
    var uc_peak_mol_data = uc_data['peak_mol'];
    var uc_avg_size = uc_data['avg_size'];

    //Call the data that we'll change
    var data = source_data.data;

    //The four columns we will change are cal_conc, int_area, size, and peak_mol
    var cal_conc=[];
    var int_area=[];
    var size=[];
    var peak_mol=[];
    var ts_data_id = [];
    var well_id = [];
    var avg_size = [];

    //Filter the data
    for(var i=0; i<uc_cal_conc_data.length;i++){
        if(uc_int_area_data[i] >= int_area_cutoff){
            if(uc_cal_conc_data[i] >= conc_min && uc_cal_conc_data[i] <= conc_max){
                if(ts_data_list.includes(uc_ts_data_id_data[i])){
                cal_conc.push(uc_cal_conc_data[i]);
                int_area.push(uc_int_area_data[i]);
                size.push(uc_size_data[i]);
                peak_mol.push(uc_peak_mol_data[i]);
                ts_data_id.push(uc_ts_data_id_data[i]);
                well_id.push(uc_well_id_data[i]);
                avg_size.push(uc_avg_size[i]);
                }
            }
        }
    }

    //Change the index too, since lengths are not the same any longer
    var index=[];
    for(var j=0; j<cal_conc.length;j++){
        index.push(j);
    }

    //Replace the data and emit it to source
    data['ts_data_id'] = ts_data_id;
    data['well_id'] = well_id;
    data['cal_conc'] = cal_conc;
    data['int_area'] = int_area;
    data['size'] = size;
    data['peak_mol'] = peak_mol;
    data['index'] = index;
    data['avg_size'] = avg_size;
    //console.log(data)

    source_data.change.emit();
    """
    callback = CustomJS(args=dict(source_data=source_data, unchanged_data=unchanged_data), code=callback_JS)

    # Want to make a slider for integrate_area cutoff
    int_area_N = 0
    int_area_slider = Slider(start=0, end=100, step=1, value = int_area_N, title="% Integrated Area Cutoff")
    int_area_slider.js_on_change('value', callback)
    #Want to make a rangeslider for calibrated concentration
    cal_conc_min = first_peak_df['cal_conc'].min()
    cal_conc_max = first_peak_df['cal_conc'].max()
    conc_slider = RangeSlider(start=cal_conc_min, end=cal_conc_max, value=(cal_conc_min, cal_conc_max),step=(cal_conc_max - cal_conc_min) / 100, title='Range of Calibrated Concentration [pg/mul]')
    conc_slider.js_on_change('value',callback)


    #Make a Multiselect tool
    ts_data_list = first_peak_df['ts_data_id'].unique().tolist()
    ts_data_multi_select = MultiSelect(title='Select Data: ', value=ts_data_list, options=ts_data_list, height=130)
    ts_data_multi_select.js_on_change('value',callback)


    #Callback arguments
    callback.args['int_area_slider'] = int_area_slider
    callback.args['conc_slider'] = conc_slider
    callback.args['ts_data_multi_select'] = ts_data_multi_select


    #Create a paragraph to discuss first two plots
    readme = Paragraph(text = """
    These first two plots correspond to the strongest peaks of the datasets.  The first plot showing the size vs peak molarity, where the second plot shows the size vs the average size of the region. 

    The user can use the following tools to filter the data being plotted.  
    'Select Data' is a MultiSelect Table,from which users can select which data to plot. 
    'Range of Calibrated Concentration allows users to choose the range of calibrated concentration.
    '% Integrated Area Cutoff allows user to choose the minimum required % Integrated Area for the strongest peak.
    """, width=1000)

    #Make another plot of the lower markers and the upper markers
    #marker_df = pd.read_sql('SELECT * FROM markers', engine)
    #marker_cols = ['ts_data_id', 'well_id', 'peak_mol', 'int_area', 'size', 'cal_conc', 'marker_id']
    #marker_df = marker_df[marker_cols]

    #Separate the two
    #lower_mask = marker_df['marker_id'] == 'Lower Marker'
    #upper_mask = marker_df['marker_id'] == 'Upper Marker'

    #lower_df = marker_df[lower_mask].copy()
    #upper_df = marker_df[upper_mask].copy()

    #sc_data_lower = ColumnDataSource(lower_df)
    #uc_data_lower = ColumnDataSource(lower_df)
    #sc_data_upper = ColumnDataSource(upper_df)

    #Plot the two's sizes vs 





    l = layout(
            [WidgetBox(readme)],
            [ts_data_multi_select],
            [conc_slider],
            [int_area_slider],
            [first_peak_plot, size_plot]
            )

    script, div_dict = components(l)
    return render_template('homepage.html', script=script, div=div_dict, bokeh_version=BOKEH_VERSION)
예제 #13
0
def image_review_helperf(args):
    converthu = args["converthu"]
    invert = args["invert"]
    calculate_histogram = args["calculate_histogram"]
    colormap = args["colormap"]
    w = args["w"]
    general_functions.set_configuration(args["config"])
    
    temp_folder, file_path = RestToolbox.GetSingleDcm(config.ORTHANC_URL, w)
    try:
        img = pylinac_image.DicomImage(file_path)
        if invert:
            img.invert()
        if converthu:  # Convert back to pixel values if needed.
            img.array = (img.array - int(img.metadata.RescaleIntercept)) / int(img.metadata.RescaleSlope)
        img_array = np.flipud(img.array)
    except:
        return template("error_template", {"error_message": "Cannot read image."})
    size_x = img_array.shape[1]
    size_y = img_array.shape[0]
    img_min = np.min(img_array)
    img_max = np.max(img_array)

    x1 = np.arange(0, size_x, 1).tolist()
    y1 = img_array[int(size_y//2), :].tolist()
    y2 = np.arange(0, size_y, 1).tolist()
    x2 = img_array[:, int(size_x//2)].tolist()
    
    source = ColumnDataSource(data=dict(x1=x1, y1=y1))  # Bottom plot
    source2 = ColumnDataSource(data=dict(x2=x2, y2=y2))  # Right plot
    sourcebp = ColumnDataSource(data=dict(xbp=[], ybp=[]))
    sourcerp = ColumnDataSource(data=dict(xrp=[], yrp=[]))

    # Add table for pixel position and pixel value
    hfmt = NumberFormatter(format="0.00")
    source6 = ColumnDataSource(dict(
                                x=[],
                                y=[],
                                value=[]
                                ))
    columns2 = [TableColumn(field="x", title="x", formatter=hfmt),
               TableColumn(field="y", title="y", formatter=hfmt),
               TableColumn(field="value", title="value", formatter=hfmt)]
    table2 = DataTable(source=source6, columns=columns2, editable=False, height=50, width = 220)


    # Plotting profiles
    callback = CustomJS(args=dict(source=source, source2=source2, sourcebp=sourcebp,
                                  sourcerp=sourcerp, source6=source6), code="""
        var geometry = cb_data['geometry'];
        var x_data = parseInt(geometry.x); // current mouse x position in plot coordinates
        var y_data = parseInt(geometry.y); // current mouse y position in plot coordinates
        var data = source.data;
        var data2 = source2.data;
        var array = """+json.dumps(img_array.tolist())+""";
        data['y1'] = array[y_data];
        var column = [];
        for(var i=0; i < array.length; i++){
          column.push(array[i][x_data]);
        }
        data2['x2'] = column;
        
        source.change.emit();
        source2.change.emit();
        
        var length_x = array[0].length;
        var length_y = array.length;

        if ((x_data<=length_x && x_data>=0)  && (y_data<=length_y && y_data>=0)){
            
            // Add points to plot:
            sourcebp.data['xbp'] = [x_data];
            sourcebp.data['ybp'] = [array[y_data][x_data]];
            sourcerp.data['xrp'] = [array[y_data][x_data]];
            sourcerp.data['yrp'] = [y_data];
            
            // Get position and pixel value for table
            source6.data["x"] = [geometry.x];
            source6.data["y"] = [geometry.y];
            source6.data["value"] = [array[y_data][x_data]];

            sourcebp.change.emit();
            sourcerp.change.emit();
            source6.change.emit();
            }
    """)

    # Add callback for calculating average value inside Rectangular ROI
    x3 = np.arange(0, size_x, 1).tolist()
    y3 = np.arange(0, size_y, 1).tolist()
    source3 = ColumnDataSource(data=dict(x3=x3, y3=y3))
    source4 = ColumnDataSource(data=dict(x4=[], y4=[], width4=[], height4=[]))
    # Add table for mean and std
    source5 = ColumnDataSource(dict(
                                mean=[],
                                median=[],
                                std=[],
                                minn=[],
                                maxx=[]
                                ))

    columns = [TableColumn(field="mean", title="mean", formatter=hfmt),
               TableColumn(field="median", title="median", formatter=hfmt),
               TableColumn(field="std", title="std", formatter=hfmt),
               TableColumn(field="minn", title="min", formatter=hfmt),
               TableColumn(field="maxx", title="max", formatter=hfmt)]
    table = DataTable(source=source5, columns=columns, editable=False, height=50, width = 480)

    # Calculate things within ROI
    callback2 = CustomJS(args=dict(source3=source3, source4=source4, source5=source5), code="""
        var geometry = cb_obj['geometry'];
        var data3 = source3.data;
        var data4 = source4.data;
        var data5 = source5.data;

        // Get data
        var x0 = parseInt(geometry['x0']);
        var x1 = parseInt(geometry['x1']);
        var y0 = parseInt(geometry['y0']);
        var y1 = parseInt(geometry['y1']);

        // calculate Rect attributes
        var width = x1 - x0;
        var height = y1 - y0;
        var x = x0 + width/2;
        var y = y0 + height/2;

        // update data source with new Rect attributes
        data4['x4'] = [x];
        data4['y4'] = [y];
        data4['width4'] = [width];
        data4['height4'] = [height];

        // Get average value inside ROI
        var array = """+json.dumps(img_array.tolist())+""";

        var length_x = array[0].length;
        var length_y = array.length;

        if ((x0<=length_x && x0>=0) && (x1<=length_x && x1>=0) && (y0<=length_y && y0>=0) && (y1<=length_y && y1>=0)){
            var avg_ROI = [];

            for (var i=y0; i< y1; i++){
                for (var j=x0; j<x1; j++){
                    avg_ROI.push(array[i][j]);
                }
            }
    
            if (avg_ROI == undefined || avg_ROI.length==0){
                data5["mean"] = [0];
                data5["median"] = [0];
                data5["std"] = [0];
                }
            else{
                data5["mean"] = [math.mean(avg_ROI)];
                data5["median"] = [math.median(avg_ROI)];
                data5["std"] = [math.std(avg_ROI, 'uncorrected')];
                data5["maxx"] = [math.max(avg_ROI)];
                data5["minn"] = [math.min(avg_ROI)];
                }
            
            source4.change.emit();
            source5.change.emit();
            }
    """)

    plot_width = 500
    plot_height = int((plot_width-20)*size_y/size_x)
    
    fig = figure(x_range=[0, size_x], y_range=[0, size_y],
                 plot_width=plot_width, plot_height=plot_height, title="",
                 toolbar_location="right",
                 tools=["crosshair, wheel_zoom, pan, reset"])
    fig_r = figure(x_range=[img_min, img_max], y_range=fig.y_range,
                 plot_width=250, plot_height=plot_height, title="",
                 toolbar_location="right",
                 tools=[])
    fig_b = figure(x_range=fig.x_range, y_range=[img_min, img_max],
                 plot_width=plot_width, plot_height=200, title="",
                 toolbar_location="right",
                 tools=[])

    # Define matplotlib palette and make it possible to be used dynamically.
    cmap = matplotlib.cm.get_cmap(colormap) #chose any matplotlib colormap here
    bokehpalette = [matplotlib.colors.rgb2hex(m) for m in cmap(np.arange(cmap.N)[::-1])]  # Reversed direction of colormap
    mapper = LinearColorMapper(palette=bokehpalette, low=np.min(img_array), high=np.max(img_array))

    callback3 = CustomJS(args=dict(mapper=mapper, x_range=fig_r.x_range, y_range=fig_b.y_range), code="""
           mapper.palette = """+json.dumps(bokehpalette)+""";
           var start = cb_obj.value[0];
           var end = cb_obj.value[1];
           mapper.low = start;
           mapper.high = end;
           x_range.setv({"start": start, "end": end});
           y_range.setv({"start": start, "end": end});
           //mapper.change.emit();
    """)

    range_slider = RangeSlider(start=np.min(img_array), end=np.max(img_array), value=(np.min(img_array), np.max(img_array)), step=10, title="Level")
    range_slider.js_on_change('value', callback3)

    fig.image([img_array], x=0, y=0, dw=size_x, dh=size_y, color_mapper=mapper)

    fig_b.line(x='x1', y='y1', source=source)
    fig_r.line(x='x2', y='y2', source=source2)
    fig_b.circle(x='xbp', y='ybp', source=sourcebp, size=7, fill_color="red", fill_alpha=0.5, line_color=None) # For point connected to crosshair
    fig_r.circle(x='xrp', y='yrp', source=sourcerp, size=7, fill_color="red", fill_alpha=0.5, line_color=None) # For point connected to crosshair
    fig.rect(x='x4', y='y4', width='width4', height='height4', source=source4, fill_alpha=0.3, fill_color='#009933')
    
    fig.add_tools(HoverTool(tooltips=None, callback=callback))
    fig.add_tools(BoxSelectTool())
    fig.js_on_event(SelectionGeometry, callback2)  # Add event_callback to Boxselecttool

    grid = gridplot([[table, range_slider],  [fig, fig_r], [fig_b, table2]])
    script, div = components(grid)
    
    # Calculate pixel value histogram
    if calculate_histogram:
        try:
            bitsstored = int(img.metadata.BitsStored)
        except:
            bitsstored = 16
        max_pixelvalue = 2**bitsstored-1
        counts, bins = np.histogram(img_array.flatten(), density=False, range=(0, max_pixelvalue), bins=max_pixelvalue+1)
    
        fig_hist = figure(x_range = [-100, max_pixelvalue*1.05], y_range=[0.5, np.max(counts)],
                         plot_width=750, plot_height=400, title="Pixel value histogram", y_axis_type="log",
                         toolbar_location="right", tools=["box_zoom, pan, reset"])
    
        fig_hist.quad(top=counts, bottom=0.5, left=bins[:-1], right=bins[1:], alpha=0.5)
        fig_hist.grid.visible = False
        fig_hist.yaxis.axis_label = "Pixel Count"
        fig_hist.xaxis.axis_label = "Pixel Value"
        script_hist, div_hist = components(fig_hist)
    else:
        script_hist, div_hist = ["", ""]
    
    variables = {"script": script,
                 "div": div,
                 "bokeh_file_css": BOKEH_FILE_CSS,
                 "bokeh_file_js": BOKEH_FILE_JS,
                 "bokeh_widgets_js": BOKEH_WIDGETS_JS,
                 "bokeh_tables_js": BOKEH_TABLES_JS,
                 "script_hist": script_hist,
                 "div_hist": div_hist
                 }
    #gc.collect()

    general_functions.delete_files_in_subfolders([temp_folder]) # Delete image
    return template("image_review_results", variables)