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)
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')
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':
""") 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:
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> <span style="font-size: 10px; font-family: Monaco, monospace;">@name</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Filename:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@filename</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Line number:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@line_number</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Line:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@line</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Time:</span> <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)