Ejemplo n.º 1
0
    y_desc = [y_axis.value] * len(x_data)
    color_desc = [color_axis.value] * len(x_data)

    source.data = dict(x=x_data,
                       y=y_data,
                       color=color,
                       color_data=color_data,
                       x_desc=x_desc,
                       y_desc=y_desc,
                       color_desc=color_desc,
                       SMILES=smiles,
                       IMGS=imgs)


def update_table(attr, old, new):
    idxs = new['1d']['indices']
    data = {key: [item[i] for i in idxs] for key, item in table_data.items()}
    table_source.data = data


x_axis.on_change("value", lambda attr, old, new: update())
y_axis.on_change("value", lambda attr, old, new: update())
color_axis.on_change("value", lambda attr, old, new: update())
source.on_change("selected", update_table)

widgetbox = widgetbox([x_axis, y_axis, color_axis], width=200)
layout = layout([[p, widgetbox], [table], [button]])

update()
curdoc().add_root(layout)
Ejemplo n.º 2
0
def modify_doc(doc):
    """ Contains the application, including all callbacks
        TODO: could the callbacks be outsourced?
    :param doc:
    :type doc:
    """
    logger.debug('modify_doc has been called')
    def get_data_frames(ie,):
        """ Called one time initially, and then every time the experiment number is changed by the slider
        :param ie: experiment number
        :type ie: int
        :returns: dataframe from stella datafile and dataframe with tau and phi and fitted values
        :rtype: list of 2 pandas dataframes
        """
        logger.debug('get_dataframe with ie={}'.format(ie))
        fid = polymer.getfid(ie) #read FID or series of FIDs for selected experiment
        try:
            tau = polymer.get_tau_axis(ie) #numpy array containing the taus for experiment ie
            try:
                startpoint=fid_slider.range[0] #lower integration bound
                endpoint = fid_slider.range[1] #upper integration bound
            except NameError:
                # fid_slider not initialized for first plot. Use default values:
                startpoint=int(0.05*polymer.getparvalue(ie,'BS'))
                endpoint = int(0.1*polymer.getparvalue(ie,'BS'))
                logger.debug('fid_slider not initialized for first plot. Use default values {} and {}.'.format(startpoint, endpoint))
                
            polymer.addparameter(ie,'fid_range',(startpoint,endpoint)) #add integration range to parameters to make it accesible
            phi = get_mag_amplitude(fid, startpoint, endpoint,
                                    polymer.getparvalue(ie,'NBLK'),
                                    polymer.getparvalue(ie,'BS')) # list containing averaged fid amplitudes (which is proportional to a magnetization phi)
            df = pd.DataFrame(data=np.c_[tau, phi], columns=['tau', 'phi']) # DataFrames are nice
            df['phi_normalized'] = (df['phi'] - df['phi'].iloc[0] ) / (df['phi'].iloc[-1] - df['phi'].iloc[1] ) #Normalize magnetization,
            #Note: in the normalized magnetization the magnetization build-up curves and magnetization decay curves look alike
            #Note: this makes it easier for fitting as everything looks like 1 * exp(-R/time) in first order
            polymer.addparameter(ie,'df_magnetization',df) # make the magnetization dataframe accesible as parameter
            fit_option = 2 #mono exponential, 3 parameter fit
            p0=[1.0, polymer.getparvalue(ie,'T1MX')**-1*2, 0] #choose startparameters for fitting an exponential decay
            df, popt = magnetization_fit(df, p0, fit_option) # use leastsq to find optimal parameters
            polymer.addparameter(ie,'popt(mono_exp)',popt) # add fitting parameters for later access
            logger.info('fitfunction(t) = {} * exp(- {} * t) + {}'.format(*popt)) # print the fitting parameters to console (for convenience)
        except KeyError:
            logger.warning('no relaxation experiment found')
            tau=np.zeros(1)
            phi=np.zeros(1)
            df = pd.DataFrame(data=np.c_[tau, phi], columns=['tau', 'phi'])
            df['phi_normalized'] = np.zeros(1)
            df['fit_phi'] = np.zeros(1)
        return fid, df

    def calculate_mag_dec(attr, old, new, start_ie=None):
        ''' Is being call from the callback for the experiment chooser
            loads selected experiment visualize in plot p1 and p2 
            gets experiment number from the slider
            writes source_fid.data from the fid from the polymer object
            writes source_mag_dec.data from the dataframe
            '''
        ie = experiment_slider.value   #get expermient number from the slider
        logger.debug('calculate mag_dec for ie={}'.format(ie))
        fid, df = get_data_frames(ie)
        source_fid.data=ColumnDataSource.from_df(fid) #convert fid to bokeh format
        source_mag_dec.data = ColumnDataSource.from_df(df)

    def plot_par():
        ''' Creates plot for the parameters 
            Called with every update from the callback'''
        logger.debug('creating plot for the parameters')

        # read data due to selection of select_x/y
        xs = par_df[select_xaxis.value ].values
        ys = par_df[select_yaxis.value].values
        # read titles due to name of select_x/y
        x_title = select_xaxis.value.title()
        y_title = select_yaxis.value.title()

        # remark: many attributes in a bokeh plot cannot be modified after initialization
        #         for example p4.x_axis_type='datetime' does not work. keywords are a
        #         workaround to pass all optional arguments initially
        # set optional keyword arguments, kw, for figure()
        kw = dict() #initialize
        if select_xaxis.value in discrete:
            kw['x_range'] = sorted(set(xs))
        if select_yaxis.value in discrete:
            kw['y_range'] = sorted(set(ys))
        if select_yaxis.value in time:
            kw['y_axis_type'] = 'datetime'
        if select_xaxis.value in time:
            kw['x_axis_type'] = 'datetime'
        kw['title']="%s vs %s" % (x_title, y_title)
        # create figure using optional keywords kw
        p4 = figure(plot_height=300, plot_width=600, tools='pan,box_zoom,reset',
                    **kw)
        # set axis label
        p4.xaxis.axis_label = x_title
        p4.yaxis.axis_label = y_title

        # strings at x axis ticks need a lot of space. solution: rotate label orientation
        if select_xaxis.value in discrete:
            p4.xaxis.major_label_orientation = pd.np.pi / 4 # rotates labels...

        # standard size of symbols
        sz = 9
        # custom size of symbols due to select_size
        if select_size.value != 'None':
            groups = pd.qcut(pd.to_numeric(par_df[select_size.value].values), len(SIZES))
            sz = [SIZES[xx] for xx in groups.codes]

        # standard color
        c = "#31AADE"        
        # custom color due to select_color
        if select_color.value != 'None':
            groups = pd.qcut(pd.to_numeric(par_df[select_color.value]).values, len(COLORS))
            c = [COLORS[xx] for xx in groups.codes]

        # create the plot using circles
        p4.circle(x=xs, y=ys, color=c, size=sz, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)
        return p4 #return the plot
    
    def callback_update_plot_1(attr, old, new):
        ''' Callback for update of figure 1 in parameters tab '''
        tabs.tabs[1].child.children[1] = plot_par()
        print(tabs.tabs[1].child.children[1])
        logger.debug('Parameter plot updated')
#        p4 = plot_par()

    def callback_update_p3():
        logger.debug('update plot 3')
        p3 = fit_mag_decay_all(polymer,par_df)
        return p3

    def callback_update_experiment(attr, old, new):
        """ Callback for the experiment chooser
        """
        ie = experiment_slider.value
        logger.debug('Callback experiment update, ie={}'.format(ie))
        fid_slider.end = polymer.getparvalue(ie,'BS')
        try:
            fid_slider.range=polymer.getparvalue(ie,'fid_range')
        except:
            startpoint = int(0.05 * polymer.getparvalue(ie,'BS'))
            endpoint = int(0.1 * polymer.getparvalue(ie,'BS'))
            fid_slider.range=(startpoint,endpoint)
        calculate_mag_dec(attr,old,new)
        
    def callback_load_more_data(attr,old,new):
        ''' callback for loading of data '''
        # TODO: implement
        logger.debug('callback for loading of data ')
        logger.error('Not implemented!')
        path=pathbox.value.strip()
        file=filebox.value.strip()
        if file=="*.sdf":
            logger.info('callback for loading data. filename: {}'.format(file))
            allsdf=filter(lambda x: x.endswith('.sdf'),os.listdir(path))
            for f in allsdf:
                sdf_list.append(sdf.StelarDataFile(f,path))
        else:
            sdf_list.append(sdf.StelarDataFile(file,path))
        
        filenames=[x.file() for x in sdf_list]
        filenames_df=pd.DataFrame(data=filenames,columns=['file'])
        table_source.data=ColumnDataSource.from_df(filenames_df)

    def callback_export_data(attr,old,new):
        logger.debug('callback_export_data has been called ')
        logger.error('Not implemented!')
        pass
    
    def callback_write_table_to_file(attr,old,new): ##FIXME
        logger.debug('callback_write_table_to_file has been called ')
        logger.error('Not implemented!')
        pass
#        path=export_text.value.strip()
#        exportdata=export_source.data
#        CustomJS(args=dict(source=export_source),
#                 code=open(join(dirname(__file__), "export_csv.js")).read())

    def callback_update_parameters():
        ''' callback for button
            function to call when button is clicked
            for updates parameters of polymer, since they can change during evaluation '''
        logger.debug('callback for button (update parameter).')
        par_df, columns, discrete, continuous, time, quantileable = polymer.scan_parameters()
        select_xaxis.options=columns
        select_yaxis.options=columns
        select_size.options=['None']+quantileable
        select_color.options=['None']+quantileable

    logger.info('Starting the script')
    ### This is the start of the script ###
    ### The callbacks are above ###

    #load data:
    # TODO: how to handle multiple datafiles?
    # New Tab for each datafile?
    # dropdown selection to choose datafile
    # complete new start of process? (probably not prefered)

    polymer = load_data('glyzerin_d3_300K.sdf')
    nr_experiments = polymer.get_number_of_experiments()
    start_ie = 1     # initially set ie = 1
    par_df, columns, discrete, continuous, time, quantileable = polymer.scan_parameters(20)
    # for the initial call get the dataframes without callback
    # they are being updated in following callbacks
    fid, df = get_data_frames(start_ie)
    source_fid = ColumnDataSource(data=ColumnDataSource.from_df(fid))
    source_mag_dec = ColumnDataSource(data=ColumnDataSource.from_df(df))
    # initialy creates the plots p1 and p2
    p1, p2 = create_plot_1_and_2(source_fid, source_mag_dec)
    
    ### initiates widgets, which will call the callback on change ###
    # initiate slider to choose experiment
    experiment_slider = Slider(start=1, end=nr_experiments, value=1, step=1,callback_policy='mouseup', width=800) #select experiment by value
    # initiate slider for the range in which fid shall be calculated
    # select the intervall from which magneitization is calculated from fid
    fid_slider = RangeSlider(start=1,end=polymer.getparvalue(start_ie,'BS'),
                             range=polymer.getparvalue(start_ie,'fid_range'),
                             step=1,callback_policy='mouseup', width=400)

    # fit magnetization decay for all experiments
    p3 = fit_mag_decay_all(polymer, par_df)
    # refit mag dec with updated ranges after button push
    button_refit = Button(label='Update',button_type="success")
    button_refit.on_click(callback_update_p3)

    # initialize empty source for experiment slider
    source = ColumnDataSource(data=dict(value=[]))
    # 'data' is the attribute. it's a field in source, which is a ColumnDataSource
    # initiate callback_update_experiment which is the callback
    source.on_change('data',callback_update_experiment) #source for experiment_slider
    experiment_slider.callback = CustomJS(args=dict(source=source),code="""
        source.data = { value: [cb_obj.value] }
    """)#unfortunately this customjs is needed to throttle the callback in current version of bokeh

    # initialize empty source for fid slider, same as above
    source2 = ColumnDataSource(data=dict(range=[], ie=[]))
    source2.on_change('data',calculate_mag_dec)
    fid_slider.callback=CustomJS(args=dict(source=source2),code="""
        source.data = { range: cb_obj.range }
    """)#unfortunately this customjs is needed to throttle the callback in current version of bokeh

    # same for the update button
    button_scan = Button(label='Scan Parameters',button_type="success")
    button_scan.on_click(callback_update_parameters)
    
    # here comes for callbacks for x, y, size, color
    select_xaxis = Select(title='X-Axis', value='ZONE', options=columns)
    select_xaxis.on_change('value', callback_update_plot_1)

    select_yaxis = Select(title='Y-Axis', value='TIME', options=columns)
    select_yaxis.on_change('value', callback_update_plot_1)

    select_size = Select(title='Size', value='None', options=['None'] + quantileable)
    select_size.on_change('value', callback_update_plot_1)

    select_color = Select(title='Color', value='None', options=['None'] + quantileable)
    select_color.on_change('value', callback_update_plot_1)

    controls_p4 = widgetbox([button_scan, select_xaxis,select_yaxis,select_color,select_size], width=150)
    #p4 = plot_par()
    layout_p4 = row(controls_p4,plot_par())
    logger.debug('layout for parameter plot created')

    ####
    #### TODO: write file input
    #### TODO: select files to import
    #### TODO: discard imported files
    ####

    # load more data:
    table_source=ColumnDataSource(data=dict())
    sdf_list=[polymer]
    # TODO: This is current plan, to save the different dataframes in a list, right?
    filenames=[x.file() for x in sdf_list]
    files_df=pd.DataFrame(data=filenames,columns=['file'])
    table_source.data=ColumnDataSource.from_df(files_df)
    t_columns = [
        TableColumn(field='file', title='Path / Filename'),
        #TableColumn(field='file', title='Filename'),
        ]
    table=DataTable(source=table_source,columns=t_columns)
    pathbox=TextInput(title="Path",value=os.path.curdir)
    filebox=TextInput(title="Filename",value="*.sdf")
    pathbox.on_change('value',callback_load_more_data)
    filebox.on_change('value',callback_load_more_data)
    layout_input=column(pathbox,filebox,table)

    # Data Out: export data from figures
    #         & export parameters

    export_source=ColumnDataSource(data=dict())
    export_columns=[]
    output_table=DataTable(source=export_source,columns=export_columns)
    export_slider = Slider(start=1, end=4, value=3, step=1,callback_policy='mouseup', width=200) #do we need mouseup on this?
    export_slider.on_change('value',callback_export_data)
    export_text = TextInput(title="Path",value=os.path.curdir)
    export_button = Button(label='Export to csv',button_type="success") # FIXME Callback  doesn't work yet
    export_button.on_click(callback_write_table_to_file)
 
    layout_output=row(column(export_slider,export_text,export_button),output_table)
    print('after layout_output')
    

    # set the layout of the tabs
    layout_p1 = column(experiment_slider, p1,
                       row(
                           column(fid_slider,p2),
                           column(button_refit, p3)
                           ),
                       )
    tab_relaxation = Panel(child = layout_p1, title = 'Relaxation')
    tab_parameters = Panel(child = layout_p4, title = 'Parameters')
    tab_input = Panel(child = layout_input, title = 'Data In')
    tab_output = Panel(child = layout_output, title = 'Data Out')

    # initialize tabs object with 3 tabs
    tabs = Tabs(tabs = [tab_relaxation, tab_parameters,
                        tab_input, tab_output])
    print('tabs')
    doc.add_root(tabs)
    doc.add_root(source) # i need to add source to detect changes
    doc.add_root(source2)
    print('tab tab')
Ejemplo n.º 3
0
def slider_cb(attr, old, new):
  working_copy_catchment_data['parameters'][0] = (qs0_slider.value * 4e-5) / 100 
  working_copy_catchment_data['parameters'][1] = lnTe_slider.value 
  working_copy_catchment_data['parameters'][2] = m_slider.value 
  working_copy_catchment_data['parameters'][3] = Sr0_slider.value 
  working_copy_catchment_data['parameters'][4] = Srmax_slider.value 
  working_copy_catchment_data['parameters'][5] = td_slider.value 
  working_copy_catchment_data['parameters'][7] = vr_slider.value 
  working_copy_catchment_data['parameters'][8] = k0_slider.value 
  working_copy_catchment_data['parameters'][9] = CD_slider.value 
  y = getTopModel(working_copy_catchment_data)
  model.data_source.data["y"] = y

# This data source is just used to communicate / trigger the real callback
source = ColumnDataSource(data=dict(value=[]))
source.on_change('data', slider_cb)

init_value = int((3.167914e-05 / 4e-5) * 100)
qs0_slider = Slider(start=1, end=100, value=init_value, step=0.1,
        title="Initial subsurface flow / unit area [% 0 - 4e-5 m]", 
        callback_policy="throttle", callback_throttle=300)
qs0_slider.callback = CustomJS(args=dict(source=source), code="""
  source.data = { value: [cb_obj.value] }
""")

lnTe_slider = Slider(start=-2, end=1, value=-5.990615e-01, step=.1,
                    title="Log of the areal average of T0 [m2/h]", callback_policy="throttle", callback_throttle=300)
lnTe_slider.callback = CustomJS(args=dict(source=source), code="""
  source.data = { value: [cb_obj.value] }
""")
    print('attr: {} old: {} new: {}'.format(attr, old, new))
    if new['1d']['indices']:
        art_index = new['1d']['indices'][0]
        print("article index", art_index)
        file = open("MC1 Data/MC1 Data/articles/" +
                    str(article_2021[art_index]) + ".txt",
                    "r",
                    encoding='ISO-8859-1')
        text = file.read()
        text = text + "\n"
    else:
        text = "Select article by clicking on circles"
    pre.text = text


circlesource.on_change('selected', handler)

# taptool = p.select(type=TapTool)
# taptool.callback = tap_update()

spacing = 120
worddf_up = make_df(entity_bag_hist, average_sentiment_array_hist, 'PERSON', 1,
                    spacing)
worddf_down = make_df(entity_bag_hist, average_sentiment_array_hist, 'ORG', -1,
                      spacing)

wordsource_up_hist = ColumnDataSource(worddf_up)
wordsource_down_hist = ColumnDataSource(worddf_down)

linesource = ColumnDataSource({
    'x':
Ejemplo n.º 5
0
""")


def get_window_size(attr, old, new):
    wi = width.data['width'][0]
    print('window width: ', wi)
    if wi:
        doc.candles.sizing_mode = 'stretch_height'
        doc.volume_plot.sizing_mode = 'stretch_height'
        f = 0.238
        border = 10
        doc.candles.width = int(wi * (1 - f) - border)
        doc.volume_plot.width = int(wi * f - border)


width.on_change('data', get_window_size)


class Document:
    def __init__(self, time1, granularity, dark_mode):
        self.time1 = time1  # datetime.datetime(2020, 4, 1)
        self.time2 = datetime.datetime.now()  # utcnow()
        self.granularity = granularity  # '5m'
        self.dark_mode = dark_mode
        if self.dark_mode:
            self.color_green = '#75bb36'
            self.color_red = '#dd4a4a'
            self.color_blue = 'light blue'
            self.color_black = 'white'
            self.color_gray = 'gray'
        else:
Ejemplo n.º 6
0
class ProfileTimePlot(object):
    """ Time plots of the current resource usage on the cluster

    This is two plots, one for CPU and Memory and another for Network I/O
    """
    def __init__(self, profiler, doc=None, **kwargs):
        if doc is not None:
            self.doc = weakref.ref(doc)
            try:
                self.key = doc.session_context.request.arguments.get(
                    'key', None)
            except AttributeError:
                self.key = None
            if isinstance(self.key, list):
                self.key = self.key[0]
            if isinstance(self.key, bytes):
                self.key = self.key.decode()
            self.task_names = ['All', self.key]
        else:
            self.key = None
            self.task_names = ['All']

        self.profiler = profiler
        self.start = None
        self.stop = None
        self.ts = {'count': [], 'time': []}
        self.state = profile.create()
        data = profile.plot_data(self.state,
                                 self.profiler.trigger_interval / 1000)
        self.states = data.pop('states')
        self.source = ColumnDataSource(data=data)

        def cb(attr, old, new):
            with log_errors():
                try:
                    ind = new['1d']['indices'][0]
                except IndexError:
                    return
                data = profile.plot_data(self.states[ind],
                                         self.profiler.trigger_interval / 1000)
                del self.states[:]
                self.states.extend(data.pop('states'))
                self.source.data.update(data)
                self.source.selected = old

        self.source.on_change('selected', cb)

        self.profile_plot = figure(tools='tap', height=400, **kwargs)
        self.profile_plot.quad('left',
                               'right',
                               'top',
                               'bottom',
                               color='color',
                               line_color='black',
                               source=self.source)

        hover = HoverTool(point_policy="follow_mouse",
                          tooltips="""
                <div>
                    <span style="font-size: 14px; font-weight: bold;">Name:</span>&nbsp;
                    <span style="font-size: 10px; font-family: Monaco, monospace;">@name</span>
                </div>
                <div>
                    <span style="font-size: 14px; font-weight: bold;">Filename:</span>&nbsp;
                    <span style="font-size: 10px; font-family: Monaco, monospace;">@filename</span>
                </div>
                <div>
                    <span style="font-size: 14px; font-weight: bold;">Line number:</span>&nbsp;
                    <span style="font-size: 10px; font-family: Monaco, monospace;">@line_number</span>
                </div>
                <div>
                    <span style="font-size: 14px; font-weight: bold;">Line:</span>&nbsp;
                    <span style="font-size: 10px; font-family: Monaco, monospace;">@line</span>
                </div>
                <div>
                    <span style="font-size: 14px; font-weight: bold;">Time:</span>&nbsp;
                    <span style="font-size: 10px; font-family: Monaco, monospace;">@time</span>
                </div>
                """)
        self.profile_plot.add_tools(hover)

        self.profile_plot.xaxis.visible = False
        self.profile_plot.yaxis.visible = False
        self.profile_plot.grid.visible = False

        self.ts_source = ColumnDataSource({'time': [], 'count': []})
        self.ts_plot = figure(title='Activity over time',
                              height=100,
                              x_axis_type='datetime',
                              active_drag='xbox_select',
                              tools='xpan,xwheel_zoom,xbox_select,reset',
                              **kwargs)
        self.ts_plot.line('time', 'count', source=self.ts_source)
        self.ts_plot.circle('time',
                            'count',
                            source=self.ts_source,
                            color=None,
                            selection_color='orange')
        self.ts_plot.yaxis.visible = False
        self.ts_plot.grid.visible = False

        def ts_change(attr, old, new):
            with log_errors():
                selected = self.ts_source.selected['1d']['indices']
                if selected:
                    start = self.ts_source.data['time'][min(selected)] / 1000
                    stop = self.ts_source.data['time'][max(selected)] / 1000
                    self.start, self.stop = min(start, stop), max(start, stop)
                else:
                    self.start = self.stop = None
                self.trigger_update(update_metadata=False)

        self.ts_source.on_change('selected', ts_change)

        self.reset_button = Button(label="Reset", button_type="success")
        self.reset_button.on_click(lambda: self.update(self.state))

        self.update_button = Button(label="Update", button_type="success")
        self.update_button.on_click(self.trigger_update)

        self.select = Select(value=self.task_names[-1],
                             options=self.task_names)

        def select_cb(attr, old, new):
            if new == 'All':
                new = None
            self.key = new
            self.trigger_update(update_metadata=False)

        self.select.on_change('value', select_cb)

        self.root = column(
            row(self.reset_button,
                self.update_button,
                sizing_mode='scale_width'), self.profile_plot, self.ts_plot,
            **kwargs)

    def update(self, state, metadata=None):
        with log_errors():
            self.state = state
            data = profile.plot_data(self.state,
                                     self.profiler.trigger_interval / 1000)
            self.states = data.pop('states')
            self.source.data.update(data)

            if metadata is not None and metadata['counts']:
                ts = metadata['counts']
                times, counts = zip(*ts)
                self.ts = {'count': counts, 'time': [t * 1000 for t in times]}

                self.ts_source.data.update(self.ts)

    def trigger_update(self, update_metadata=True):
        def cb():
            with log_errors():
                prof = self.profiler.get_profile(start=self.start,
                                                 stop=self.stop)
                if update_metadata:
                    metadata = self.profiler.get_profile_metadata()
                else:
                    metadata = None
                self.doc().add_next_tick_callback(
                    lambda: self.update(prof, metadata))

        self.profiler.io_loop.add_callback(cb)