def set_up_widgets(p, source, source1, source2, source3, df, text_dsn, table): dsn = text_dsn.value # Set up widgets text_title = TextInput(title="Title:", value="{} Data".format(dsn)) text_save = TextInput(title="Save As:", value=dsn) max_for_dsn = df.row_timestamp.max() min_day, max_day = day_limits(table) calendar = DatePicker(title="Day:", value=date(max_for_dsn.year, max_for_dsn.month, max_for_dsn.day + 1), max_date=date(max_day.year, max_day.month, max_day.day + 1), min_date=date(min_day.year, min_day.month, min_day.day + 1)) button = Button(label="Update", button_type="success") # Set up callbacks def update_title(attrname, old, new): p.title.text = text_title.value def update_save(attrname, old, new): p.tools[0].save_name = text_save.value def update(): text_dsn.value = text_dsn.value.strip(" ") # Get rid of extra space # Make sure time is valid date_start = "{} 00:00:00".format(calendar.value) date_end = "{} 23:59:59".format(calendar.value) df_new = update_data(p, text_title, text_save, source, source1, source2, source3, text_dsn.value, table, dates=[date_start, date_end]) # if df_new is going to be used, make sure it's not empty: # if df_new is empty... # day = df_new.row_timestamp.max() # min_day = df_new.row_timestamp.min() # calendar.value = date(day.year, day.month, day.day+1) # calendar.max_date = date(day.year, day.month, day.day+1) # calendar.min_date = date(min_day.year, min_day.month,min_day.day+1) text_title.on_change('value', update_title) text_save.on_change('value', update_save) button.on_click(update) button.js_on_click(CustomJS(args=dict(p=p), code="""p.reset.emit()""")) # Set up layouts and add to document inputs = widgetbox(text_title, text_save, calendar, button) curdoc().add_root(row(inputs, p, width=1300))
def init(): output_notebook() display(Javascript(_init_js)) but = '<img src="resources/show.png" width="34" height="25" style="display: inline" alt="Slideshow button" title="Enter/Exit RISE Slideshow">' txt = Div(text='<h2>You can now start the slideshow!</h3>' + f'<h3 style="margin: 0.5em 0;">Just click the RISE slideshow button above - the one that looks like: {but}<br/>' + '(or you can press alt+R on your keyboard instead if you prefer).</h3>') clearbutton = Button(label="Clear") clearbutton.js_on_click(CustomJS(code='primes_clear();')) cleartext = Paragraph(text='Clear all plots and outputs (e.g. before restarting slideshow).') increm = Toggle(label='Incremental', active=True) increm.js_on_click(CustomJS(code='primes_incremental(cb_obj.active)')) incremtext = Paragraph(text='Update timing plots incrementally (disable for static slide show).') repeats = Slider(start=1, end=10, value=3) repeats.js_on_change('value', CustomJS(code='primes_repeats(cb_obj.value)')) repeatstext = Paragraph(text='Repeats for timing measurements (higher is more accurate, but slower).') controls = layout([[clearbutton, cleartext], [increm, incremtext], [repeats, repeatstext]]) show(column(txt, controls, sizing_mode='stretch_width'))
from bokeh.plotting import show from bokeh.layouts import column from bokeh.models import CustomJS from bokeh.models.widgets import Button from fontawesome_icon import FontAwesomeIcon btn = Button(icon=FontAwesomeIcon(icon_name="thumbs-o-up", size=2), label="It works!") btn.js_on_click(CustomJS(code="alert('It works!')")) show(column(btn))
class signalHandler: def __init__(self, signalFilename="", lyricsFilename="", signal=[], sampleRate=0, color="red"): self.path = os.getcwd() logger.logData(source="Signal handler", priority="INFO", msgType="Setup start", msgData=()) self.setupVariables() self.color = color self.setupMapper() self.setupColorBar() self.lyricsImported = 0 if lyricsFilename: self.setupLyricTable(lyricsFilename) self.lyricsImported = 1 self.setupPlotWindow() self.setupControls() self.setupGUI() if signalFilename: self.importFile(signalFilename) if len(signal): self.addSignal(signal, sampleRate) logger.logData(source="Signal handler", priority="INFO", msgType="Setup done", msgData=((self.signalImported))) def setupGUI(self): """Wraps the plot, slider, and tool column into one layout""" audioCol = column(self.p, self.colorBar, self.timeWindowSlider, height=self.figureHeight) # dtgCol = column(self.dtg.gui,width=400) if self.lyricsImported: # self.gui = self.lyricTable self.gui = row(self.lyricsGui, audioCol, self.controls, height=self.figureHeight - 110) else: self.gui = row(audioCol, self.controls, height=self.figureHeight - 110) def setupVariables(self): """sets up important variables to the tool, including figure size dummy variables to use before file import tool options - loop, button sizes, button delay """ try: self.masterPath = os.getcwd() #use when running from Sublime os.listdir(self.masterPath) except: self.masterPath = os.path.join("soundTools", "") #use when running from Bokeh os.listdir(self.masterPath) self.subtitlePath = os.path.join(self.masterPath, "lyrics") self.audioPath = os.path.join(self.masterPath, "audio") self.webpagePath = os.path.join(self.masterPath, "webpages") self.figureWidth = 1000 self.figureHeight = 500 self.buttonWidth = 200 self.buttonHeight = 15 self.numXTicks = 4 self.soundPlaying = 0 self.signalImported = 0 self.lastChunkIndex = 0 self.strideMultiplier = 100 self.sweepStartSample = 0 self.sweepEndSample = 10 self.activeChannels = [] self.yRange = (-1, 1) self.channelAnchorYs = np.arange(0, self.yRange[1], 2) self.plotStyle = 0 self.glyphsSetup = 0 self.loop = 0 self.plotMode = 0 self.outputFilename = "output" self.updateDelay = 12 #delay period in milliseconds befwen timeline update while playing the active signal self.windowChunkLength = 10 #seconds def showGui(self): output_file(os.path.join("webpages", "signalHandler.html")) logger.logData(source="Signal handler", priority="INFO", msgType="Show", msgData=()) show(self.gui) curdoc().add_root(self.gui) def addSignal(self, signalIn, sampleRate): """Adds a prexisting list/mutliDim ndarray (with known sample rate) as the active signal and updates plot""" #keep the original in case of a reset self.originalSignal = signalIn #signal gets changed on update of time slider self.signal = self.originalSignal #activeSignal gets changed on update of of signal AND update of active channels self.activeSignal = self.signal self.sampleRate = sampleRate self.signalImported = 1 logger.logData(source="Signal handler", priority="INFO", msgType="Signal add", msgData=()) self.analyzeSignal() def importFile(self, filename): """imports a wav file into the tool and updates the plot and tools""" #check to make sure the filename is valid try: self.sampleRate, self.originalSignal = wavfile.read( os.path.join( self.audioPath, filename)) #keep the original for master reference except: logger.logData(source="Signal handler", priority="WARN", msgType="Import file fail", msgData=(filename)) return #update tool's internal filename self.filename = filename #import the wav file self.signal = self.originalSignal self.activeSignal = self.signal self.signalImported = 1 logger.logData(source="Signal handler", priority="INFO", msgType="Import file", msgData=(filename)) #get relevant signal info and update plot self.analyzeSignal() def analyzeSignal(self): """Parses the metadata from the active signal and updates plot and tools""" self.glyphsSetup = 0 #get number of channels of signal try: self.numChannels = self.signal.shape[1] except: #if it's single channel its imported as a list, make it a 1D ndarray self.numChannels = 1 self.signal = np.transpose(np.array([self.signal])) self.activeChannels = list(range(self.numChannels)) self.channelButtons.labels = list(map(str, self.activeChannels)) self.channelButtons.active = self.activeChannels if not np.any(self.signal): logger.logData(source="Signal handler", priority="WARN", msgType="Empty", msgData=()) return self.numSamples = len(self.signal) self.sampleIndices = range(self.numSamples) self.messedUpTs = self.sampleIndices self.updateMapperHigh(self.numSamples) self.updateColorBar(self.sampleIndices) self.signalDuration = self.numSamples / float(self.sampleRate) self.windowChunks = int( (self.signalDuration / self.windowChunkLength)) + 1 #update the time slider with the imported signal's duration self.timeWindowSlider.end = self.signalDuration self.timeWindowSlider.value = [0, self.signalDuration] self.sweepStartSample = 0 self.sweepEndSample = self.numSamples #setup the ticker to replace indices with timestamps self.setMasterXAxisTicker() #PLOT SCATTER PARAMS #get max amplitude of signal to adjust y range and channel spacing self.sigPeak = np.amax(self.signal) self.yRange = (0, 2 * self.numChannels * self.sigPeak) #generate offsets to space multiple channels out in the y axis self.channelAnchorYs = np.arange(self.sigPeak, self.yRange[1], 2 * self.sigPeak) logger.logData(source="Signal handler", priority="INFO", msgType="Analyze", msgData=(round(self.signalDuration, 3), self.numChannels, self.numSamples, self.sampleRate)) self.drawActivePlot() # self.drawFullSignal() def setMasterXAxisTicker(self): #ticker dictionary to rpaplce x axis index ticks with their coirrosponding timestamps self.masterTicker = list( range(0, self.numSamples, int(self.numSamples / self.numXTicks))) self.masterXAxisOverrideDict = {} timeLabels = np.linspace(0, self.signalDuration, self.numXTicks) for sampleInd, timeLabel in zip(self.masterTicker, timeLabels): self.masterXAxisOverrideDict[sampleInd] = str(round(timeLabel, 3)) #set up the size and duration of the sub-chunks displayed while the signal is playing self.samplesPerChunk = int(self.numSamples / self.windowChunks) self.chunkDuration = self.samplesPerChunk / float(self.sampleRate) #the absolute index values comprising the x axis ticks self.chunkTicker = list( range(0, self.samplesPerChunk, int(self.samplesPerChunk / self.numXTicks))) # self.chunkLabels = np.linspace(0,self.chunkDuration,10) # self.chunkTickOverride = {} # for sampleInd,timeLabel in zip(self.chunkTicker,self.chunkLabels): # self.chunkTickOverride[sampleInd] = str(round(timeLabel,3)) def fileCallback(self, attr, old, new): """Callback assigned to choosing a file from the file browser""" filename = new['file_name'][0] self.importFile(filename) def fileButtonSetup(self): """Creates a "File opener" button and assigns a javascript callback to it that opens an os-independent file picker window imports chosen file into the class""" fileSource = ColumnDataSource({'file_name': []}) self.fileImportButton.callback = CustomJS( args=dict(file_source=fileSource), code=""" function read_file(filename) { var reader = new FileReader(); reader.onload = load_handler; reader.onerror = error_handler; // readAsDataURL represents the file's data as a base64 encoded string reader.readAsDataURL(filename); } function load_handler(event) { file_source.data = {'file_name':[input.files[0].name]}; file_source.trigger("change"); } function error_handler(evt) { if(evt.target.error.name == "NotReadableError") { alert("Can't read file!"); } } var input = document.createElement('input'); input.setAttribute('type', 'file'); input.onchange = function(){ if (window.FileReader) { read_file(input.files[0]); } else { alert('FileReader is not supported in this browser'); } } input.click(); """) fileSource.on_change('data', self.fileCallback) def setupControls(self): """Called on setup, creates buttons and sliders to: open a local audio file set loop mode update the active timespan play the active timespan set filename to save active signal to save active signal to that filename """ #check boxes to choose what plots to display self.plotModeButtons = RadioButtonGroup( labels=["Wav", "FFT", "Spectrogram"], active=self.plotMode, button_type="warning", width=self.buttonWidth, height=self.buttonHeight) self.plotModeButtons.on_change("active", self.plotModeCallback) #choose betwen line or scatter plot self.plotStyleButtons = RadioButtonGroup(labels=["Line", "Scatter"], active=0, button_type="danger", width=self.buttonWidth, height=self.buttonHeight) self.plotStyleButtons.on_change("active", self.plotStyleCallback) channelTitle = Div(text="""<b>Audio Channels:</b>""", width=self.buttonWidth, height=2) self.channelButtons = CheckboxButtonGroup(labels=["-"], active=[0], button_type="primary", width=self.buttonWidth, height=self.buttonHeight) self.channelButtonRow = column(channelTitle, self.channelButtons, width=self.buttonWidth, height=self.buttonHeight * 2) self.channelButtons.on_change("active", self.channelButtonCallback) #creates a filebutton and assigns it a callback linked to a broser-based file browser self.fileImportButton = Button(label="Import File", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.fileButtonSetup() #create a loop toggle button and assigns a callback to it self.loopAudioToggle = Toggle(label="Loop", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.loopAudioToggle.on_click(self.loopAudioCallback) #double ended slider to clip audio by time self.timeWindowSlider = RangeSlider(start=0, end=1, value=[0, 1], step=.05, title="Wav File Window", width=self.figureWidth, height=self.buttonHeight) self.timeWindowSlider.on_change("value", self.timeSliderCallback) #button to commit clip changes to active signal self.updateButton = Button(label="Update", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.updateButton.on_click(self.updateButtonCallback) #button to play active signal, self.playButton = Button(label="Play", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.playButton.on_click(self.playSound) self.filenameBox = TextInput(value="output", title="Output Filename:", width=self.buttonWidth) #button to write active signal to file self.writeFileButton = Button(label="Write Active File", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.writeFileButton.on_click(self.writeFileButtonCallback) #button to reset tool to state right after signal import self.resetButton = Button(label="Reset", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.resetButton.on_click(self.resetButtonCallback) self.resetZoomButton = Button(label="Reset Zoom", button_type="success", width=self.buttonWidth, height=self.buttonHeight) self.resetZoomButton.js_on_click( CustomJS(args=dict(p=self.p), code=""" p.reset.emit() """)) self.generalControlsColumn = column(self.plotModeButtons, self.plotStyleButtons, self.filenameBox, self.channelButtonRow, width=self.buttonWidth) self.buttonColumn = column( self.resetZoomButton, self.fileImportButton, self.updateButton, self.loopAudioToggle, self.playButton, self.writeFileButton, self.resetButton, width=self.buttonWidth) #,height=self.figureHeight) self.controls = row(self.generalControlsColumn, self.buttonColumn) #wrap buttons and text box in a column of fixed width # self.buttonColumn = column(self.plotModeButtons,self.plotStyleButtons,self.channelButtonRow,self.resetZoomButton,self.fileImportButton,self.updateButton,self.loopToggle,self.playButton,self.writeFileButton,self.resetButton,self.filenameBox,width=self.buttonWidth)#,height=self.figureHeight) #choose active channels def channelButtonCallback(self, attr, old, new): if not self.signalImported: return try: self.activeChannels = new self.activeSignal = self.signal[:, self.activeChannels] self.glyphsSetup = 0 self.drawActivePlot() logger.logData(source="Signal handler", priority="INFO", msgType="Channel update", msgData=((old, new))) except: logger.logData(source="Signal handler", priority="WARN", msgType="Channel fail", msgData=(old)) return #choose between line or scatter plot def plotStyleCallback(self, attr, old, new): self.plotStyle = new self.glyphsSetup = 0 # self.drawFullSignal() self.drawActivePlot() def plotModeCallback(self, att, old, new): self.plotMode = new self.drawActivePlot() def loopAudioCallback(self, event): """Called on toggling of the loop button, binary inverts previous loop val""" self.loop = 1 - self.loop def writeFileButtonCallback(self): """Called on click of the write Fiile button Writes the active signal to the filename set by the textbox""" outputFilename = self.filenameBox.value + ".wav" outputPath = os.path.join(self.path, "audio", outputFilename) numChannels = len(self.activeChannels) logger.logData(source="Signal handler", priority="INFO", msgType="Write", msgData=(outputFilename, numChannels, self.sampleRate, self.signalDuration)) wavfile.write(outputPath, self.sampleRate, self.activeSignal) # def resetZoomCallback(self): # print(1) def resetButtonCallback(self): """Returns the tool to state it was immediately after file was imported""" #if no signal is imported, do nothing if not self.signalImported: return #reset active to signal to the original, unclipped signal self.signal = self.originalSignal logger.logData(source="Signal handler", priority="INFO", msgType="Reset", msgData=()) #return variables and plot to original state self.analyzeSignal() def updateButtonCallback(self): """Called on press of the update button, clips the signsal by the estart and end trimes decreed by the time slider, resets the plot to like the clipped signal is the new full signal""" #if no signal is imported, do nothing if not self.signalImported: logger.logData(source="Signal handler", priority="WARN", msgType="Update failed", msgData=()) return #clip all channel samples corresponding to the times on slider self.signal = self.signal[self.sweepStartSample:self.sweepEndSample, :] logger.logData(source="Signal handler", priority="INFO", msgType="Update signal", msgData=()) #update variables and plot with clipped signal self.analyzeSignal() def timeSliderCallback(self, attr, old, new): """Called on update of the time slider moves the sweep start/end lines used for clipping the signal when the update button is pressed""" if not self.signalImported: return try: #convert the start and end times to integer sample numbers and update internal locations self.sweepStartSample = int(new[0] * self.sampleRate) self.sweepEndSample = int(new[1] * self.sampleRate) #update sweep line graphics startLine = self.p.select_one({'name': 'sweepStartLine'}) startLine.data_source.data = { 'x': [self.sweepStartSample, self.sweepStartSample], 'y': self.yRange } endLine = self.p.select_one({'name': 'sweepEndLine'}) endLine.data_source.data = { 'x': [self.sweepEndSample, self.sweepEndSample], 'y': self.yRange } except: return def shiftSamples(self, channelIndex): """Element wise adds to the channel's vector to offset a channel so it can vbe plotted alongside other channels""" channelSamples = self.signal[:, channelIndex] reducedSamples = channelSamples[::self.strideMultiplier] return reducedSamples + self.channelAnchorYs[channelIndex] def setupPlotWindow(self): """Creates a window containing the channel plots""" p = figure(height=300, width=self.figureWidth, x_range=(0, 1), y_range=(0, 1), tools="box_zoom", toolbar_location=None, output_backend="webgl") # p.toolbar.active_scroll = "auto" p.yaxis.visible = False p.grid.visible = False self.p = p def updateFigureForSpectrogram(self): self.p.x_range.end = self.numSamples self.p.y_range.end = self.yRange[1] self.p.xaxis.ticker = self.masterTicker self.p.xaxis.major_label_overrides = self.masterXAxisOverrideDict def plotSpectrogram(self): """Plots a log spectrogram of the active audio, returns figure object""" #max freq represetnedf (nyquist constrained) imgHeight = self.sampleRate / 2 self.p.y_range.end = imgHeight * self.numChannels imgWidth = self.signalDuration self.p.x_range.end = imgWidth for channelNum in self.activeChannels: channelSignal = self.signal[:, channelNum] freqs, times, data = self.log_specgram(channelSignal, self.sampleRate) self.p.image(image=[data], x=0, y=imgHeight * channelNum, dw=imgWidth, dh=imgHeight, palette="Spectral11") def log_specgram(self, audio, sampleRate, window_size=20, step_size=10, eps=1e-10): """Kraggin log spectrogram useful for MFCC analysis""" nperseg = int(round(window_size * sampleRate / 1e3)) noverlap = int(round(step_size * sampleRate / 1e3)) freqs, times, spec = spectrogram(audio, fs=sampleRate, window='hann', nperseg=nperseg, noverlap=noverlap, detrend=False) return freqs, times, np.log(spec.T.astype(np.float32) + eps) def setupPlotScatterGlyphs(self): self.p.line([self.sweepStartSample, self.sweepStartSample], self.yRange, color="blue", line_width=2, name="sweepStartLine") self.p.line([self.sweepEndSample, self.sweepEndSample], self.yRange, color="blue", line_width=2, name="sweepEndLine") self.p.line([0, 0], self.yRange, color='red', line_width=2, name='timeLine') # self.scatterSource = {"x":[],"place":[]} self.scatterSources = [] for channelNum in self.activeChannels: self.scatterSources.append( ColumnDataSource({ "x": list(self.sampleIndices), "y": list(self.sampleIndices), "place": self.messedUpTs })) # self.p.scatter(x=[],y=[],radius=.1, fill_color={'field':"place",'transform': self.mapper},name="audioLine" + str(channelNum)) self.p.scatter(x="x", y="y", radius=1, source=self.scatterSources[channelNum], fill_color={ 'field': "place", 'transform': self.mapper }, line_color={ 'field': "place", 'transform': self.mapper }, name="audioLine" + str(channelNum)) def setupLinePlotGlyphs(self): self.p.line([self.sweepStartSample, self.sweepStartSample], self.yRange, color="blue", line_width=2, name="sweepStartLine") self.p.line([self.sweepEndSample, self.sweepEndSample], self.yRange, color="blue", line_width=2, name="sweepEndLine") self.p.line([0, 0], self.yRange, color='red', line_width=2, name='timeLine') for channelNum in self.activeChannels: self.p.line(x=[], y=[], line_width=.3, color=self.color, name="audioLine" + str(channelNum)) def drawActivePlot(self): if not self.signalImported: return if self.plotMode == 0: self.drawFullSignal() elif self.plotMode == 1: self.getFFT() else: self.plotSpectrogram() def drawFullSignal(self): if self.glyphsSetup == 0: self.p.renderers = [] if self.plotStyle: self.setupPlotScatterGlyphs() else: self.setupLinePlotGlyphs() self.glyphsSetup = 1 """redraws each channel of the full plot and updates the xaxis to the full signal duration""" for channelNum in self.activeChannels: shiftedSamples = self.shiftSamples(channelNum) reducedSampleIndices = self.sampleIndices[::self.strideMultiplier] if self.plotStyle: self.scatterSources[channelNum].data = { 'x': reducedSampleIndices, 'y': list(shiftedSamples), "place": reducedSampleIndices } else: channelLine = self.p.select_one( {'name': 'audioLine' + str(channelNum)}) channelLine.data_source.data = { 'x': reducedSampleIndices, 'y': shiftedSamples, "place": reducedSampleIndices } #update x axis with full timespan self.p.x_range.end = self.numSamples self.p.y_range.end = self.yRange[1] self.p.xaxis.ticker = self.masterTicker self.p.xaxis.major_label_overrides = self.masterXAxisOverrideDict def playSound(self): """Starts playing the signal, and draws a sweeping vertical line on actively updating sub-samples of the audfio""" #if the "Play" button is pushed during play, it acts as a stop button if self.soundPlaying == 1: logger.logData(source="Signal handler", priority="INFO", msgType="Pause", msgData=()) self.stopAudio() return #if no signal is imported, do nothing if not self.signalImported: return #hide sweep lines until their chunk occurs startLine = self.p.select_one({'name': 'sweepStartLine'}) startLine.visible = False endLine = self.p.select_one({'name': 'sweepEndLine'}) endLine.visible = False ##Chunk-specific sweep lines self.startLineAdded = 0 self.endLineAdded = 0 #precompute which chunk the sweep lines are in for speed self.sweepStartChunk = int( np.floor(self.sweepStartSample / (self.samplesPerChunk + 1))) self.sweepEndChunk = int( np.floor(self.sweepEndSample / (self.samplesPerChunk + 1))) #precompute their indices in their chunk self.shiftedSweepStart = self.sweepStartSample - self.sweepStartChunk * self.samplesPerChunk self.shiftedSweepEnd = self.sweepEndSample - self.sweepEndChunk * self.samplesPerChunk if self.p.select_one({'name': 'sweepEndLineChunk'}) == None: #preadd the lines for speed self.p.line([self.shiftedSweepStart, self.shiftedSweepStart], self.yRange, color="blue", line_width=2, visible=False, name="sweepStartLineChunk") self.p.line([self.shiftedSweepEnd, self.shiftedSweepEnd], self.yRange, color="blue", line_width=2, visible=False, name="sweepEndLineChunk") #update the x axis with the sub-chunk values self.p.x_range.end = self.samplesPerChunk self.p.xaxis.ticker = self.chunkTicker self.p.xaxis.major_label_overrides = self.createChunkXAxisOverrideDict( 0) #set the play button to read "Pause" to pull double duty self.playButton.label = "Pause" logger.logData(source="Signal handler", priority="INFO", msgType="Play", msgData=()) #log start time to keep track of where the time line should be self.startTime = time.time() #start playing the sound try: sd.play(self.activeSignal, self.sampleRate, loop=self.loop, blocking=False) except: logger.logData(source="Signal handler", priority="CRIT", msgType="Play failed", msgData=()) self.playButton.label = "Play" return self.soundPlaying = 1 #add a call callback to trigger periodcially and update the timeline and sub-samples self.perCallback = curdoc().add_periodic_callback( self.update, self.updateDelay) def createChunkXAxisOverrideDict(self, chunkIndex): """ creates a dictionary replacing absolute index ticks on the x axis with their corrosponding times """ #get the time labels corrosponding to this chunk chunkTimeLabels = np.linspace(self.chunkDuration * chunkIndex, self.chunkDuration * (chunkIndex + 1), self.numXTicks) chunkTickOverride = {} for sampleInd, timeLabel in zip(self.chunkTicker, chunkTimeLabels): #replace each sample index x tick with the time label chunkTickOverride[sampleInd] = str(round(timeLabel, 3)) return chunkTickOverride def update(self): """Set to be called periodically when audio is playing to draw the active time line on the audio signal""" if self.loop: #mod the time played by total signal duration to keep the time line accurate for multiple plays deltaTime = ( time.time() - self.startTime ) % self.signalDuration #get time elapsed since the file started playing else: deltaTime = time.time( ) - self.startTime #get time elapsed since the file started playing #if signal not done playing if deltaTime < self.signalDuration: #number of samples elapsed dSamples = deltaTime * self.sampleRate #get the active chunk chunkIndex = int(self.windowChunks * (dSamples / self.numSamples)) #if the chunk is different, need to update the audio plot window to the next chunk if self.lastChunkIndex != chunkIndex: #get the starting and ending sample indices for the next chunk chunkStartIndex = self.samplesPerChunk * chunkIndex chunkEndIndex = self.samplesPerChunk * (chunkIndex + 1) #check if any of the sweep lines lie in this chunk if self.startLineAdded: self.p.select_one({ 'name': 'sweepStartLineChunk' }).visible = False self.startLineAdded = 0 if chunkIndex == self.sweepStartChunk: self.p.select_one({ 'name': 'sweepStartLineChunk' }).visible = True self.startLineAdded = 1 if self.endLineAdded: self.p.select_one({ 'name': 'sweepEndLineChunk' }).visible = False self.endLineAdded = 0 if chunkIndex == self.sweepEndChunk: self.p.select_one({ 'name': 'sweepEndLineChunk' }).visible = True self.endLineAdded = 1 #get the signal samples from this chunk and downsample them and shift them by channel reducedChunkSamps = self.signal[ chunkStartIndex:chunkEndIndex:self. strideMultiplier] + self.channelAnchorYs reducedPlaces = list( range(chunkStartIndex, chunkEndIndex, self.strideMultiplier)) #original # chunkSamps = self.signal[chunkStartIndex:chunkEndIndex] # shiftedChunkSamps = chunkSamps + self.channelAnchorYs reducedSampleIndices = list( range(0, self.samplesPerChunk, self.strideMultiplier)) #update plot for each channel for channelIndex in self.activeChannels: if self.plotMode == 0: audioLine = self.p.select_one( {'name': "audioLine" + str(channelIndex)}) audioLine.data_source.data = { 'x': reducedSampleIndices, 'y': reducedChunkSamps[:, channelIndex], "place": reducedPlaces } # audioLine.data_source.data = {'x': reducedSampleIndices, 'y': shiftedChunkSamps[:,channelIndex],"place":reducedPlaces} else: self.scatterSources[channelIndex].data = { "x": reducedSampleIndices, "y": self.sampleIndices, "place": self.messedUpTs } #update the x-axis ticks with the new times self.p.xaxis.major_label_overrides = self.createChunkXAxisOverrideDict( chunkIndex) #update chunk index with new one self.lastChunkIndex = chunkIndex ##time line update #get the glyph for the time line timeLine = self.p.select_one({'name': 'timeLine'}) #sample index of the timeline is total samples elapsed less the number of samples in all previous chunks timeLineIndex = dSamples - chunkIndex * self.samplesPerChunk #update the time line with the new times timeLine.data_source.data = { 'x': [timeLineIndex, timeLineIndex], 'y': self.yRange } #signal IS done playing else: if self.loop: return else: self.stopAudio() def stopAudio(self): """Stops the audio playing, returns the plot to state before audio started playing""" #stop the updating of the time line curdoc().remove_periodic_callback(self.perCallback) #stop playing the signal sd.stop() self.soundPlaying = 0 #change play button back to play from pause self.playButton.label = "Play" logger.logData(source="Signal handler", priority="INFO", msgType="Play done", msgData=()) #restore plot to full signal self.drawActivePlot() #redraw sweep lines on the full signal plot startLine = self.p.select_one({'name': 'sweepStartLine'}) startLine.visible = True endLine = self.p.select_one({'name': 'sweepEndLine'}) endLine.visible = True #return time line to t=0 timeLine = self.p.select_one({'name': 'timeLine'}) timeLine.data_source.data["x"] = [0, 0] def setupMapper(self): self.mapper = LinearColorMapper(palette="Inferno256", low=0, high=10) def updateMapperPalette(self, newColors): self.mapper.palette = newColors def updateMapperHigh(self, newHigh): self.mapper.high = newHigh def updateColorBar(self, times): colorBarPlot = self.gui.select_one({'name': 'colorBarPlot'}) colorBarPlot.x_range.end = self.numSamples colorBar = self.gui.select_one({'name': 'colorBar'}) self.messedUpTs = times self.colorSource.data = { "x": self.sampleIndices, "place": self.messedUpTs } # if self.plotMode == 1: # for channelInd in self.activeChannels: # self.scatterSources[channelIndex].data = {"x":self.sampleIndices,"y":self.sampleIndices,"place":self.messedUpTs} def setupColorBar(self): colorTimeline = figure(height=30, y_range=(-.5, .5), width=self.figureWidth, x_range=(0, 10), toolbar_location=None, output_backend="webgl", name="colorBarPlot", tools="") colorTimeline.axis.visible = False colorTimeline.grid.visible = False # colorTimeline.image(image=range(self.numSamples),x=0,y=.5,dh=1,dw=1,fill_color={'field':"x",'transform': self.mappers[colorBarType-1]}, # name="cbar" + str(colorBarType)) self.colorSource = ColumnDataSource({ "x": range(10), "place": range(10) }) # colorTimeline.rect(x="x", y=0, width=1, height=1,fill_color={'field':"place",'transform': self.mapper},name="colorBar", # line_width=0.0,line_color= None,line_alpha = 0.0,source=colorSource # ) colorBar = Rect(x="x", y=0, width=1, height=1, fill_color={ 'field': "place", 'transform': self.mapper }, name="colorBar", line_width=0.0, line_color=None, line_alpha=0.0) colorTimeline.add_glyph(self.colorSource, colorBar) self.colorBar = colorTimeline def getFFT(self): """Plots the fast fourier transform of the active audio, returns a figure object""" fftHeight = self.numChannels self.p.y_range.end = fftHeight maxFreq = self.sampleRate / 2 self.p.x_range.end = maxFreq for channelNum in self.activeChannels: sigPadded = self.signal[:, channelNum] # Determine frequencies f = np.fft.fftfreq(self.numSamples) * self.sampleRate #pull out only positive frequencies (upper half) upperHalf = int(len(f) / 2) fHalf = f[:upperHalf] # Compute power spectral density psd = np.abs(np.fft.fft(sigPadded))**2 / self.numSamples #pull out only power densities for the positive frequencies psdHalf = psd[:upperHalf] #nromalize y vals psdHalf = psdHalf / max(psdHalf) #shift them to allow multiple channels psdHalf += channelNum self.p.line(fHalf, psdHalf) def lyricModeCallback(self, event): self.lyricMode = 1 - self.lyricMode if self.lyricMode: self.lyricsHandler.lyricModeButton.label = "Change to start lyric" else: self.lyricsHandler.lyricModeButton.label = "Change to end lyric" def dataTableCallback(self, att, old, new): if not self.activeChannels: logger.logData(source="Signal handler", priority="WARN", msgType="Lyric empty", msgData=()) return selectionIndex = self.lyricsHandler.lyricTableHandler.source.selected.indices[ 0] timestamp = self.lyricsHandler.lyricTableHandler.source.data[ "timestamps"][selectionIndex] lyricText = self.lyricsHandler.lyricTableHandler.source.data["lyrics"][ selectionIndex] timestampSeconds = timestamp.seconds lyricSample = int(timestampSeconds * self.sampleRate) if self.lyricMode == 0: #update sweep line graphics self.sweepStartSample = lyricSample startLine = self.p.select_one({'name': 'sweepStartLine'}) startLine.data_source.data = { 'x': [lyricSample, lyricSample], 'y': self.yRange } logger.logData(source="Lyrics", priority="INFO", msgType="Start lyric", msgData=(timestamp, lyricText)) else: self.sweepEndSample = lyricSample endLine = self.p.select_one({'name': 'sweepEndLine'}) endLine.data_source.data = { 'x': [lyricSample, lyricSample], 'y': self.yRange } logger.logData(source="Lyrics", priority="INFO", msgType="End lyric", msgData=(timestamp, lyricText)) def setupLyricTable(self, lyricsFilename): lyricsPath = os.path.join(self.path, "lyrics", lyricsFilename) self.lyricsHandler = lyricsHandler(lyricsPath) self.lyricMode = 0 self.lyricsHandler.lyricTableHandler.source.selected.on_change( 'indices', self.dataTableCallback) #create a loop toggle button and assigns a callback to it self.lyricsHandler.lyricModeButton.on_click(self.lyricModeCallback) self.lyricsGui = self.lyricsHandler.gui
//addresses IE if(navigator.msSaveBlob){ navigator.msSaveBlob(blob, filename); } else{ const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; link.target = '_blank'; link.style.visibility = 'hidden'; link.dispatchEvent(new MouseEvent('click')); } """) """Callback Assignments""" Connect.js_on_click(callback_status) Save.js_on_click(callback_Save) def update(): s = slice(10) new_x = source.data['time'][s] + np.random.uniform(-0.1, 0.1, size=10) new_y = source.data['raw_data'][s] + np.random.uniform(-1, 1, size=10) source.patch({'time': [(s, new_x)], 'raw_data': [(s, new_y)]}) #-----------# # GUI # #-----------# """Front End""" Comm_Panel = row(Port_input, Comm_Status_Message)
mut_bohr[i] = computeBohrParameter(mut_R, mut_ep_r, c[i], mut_ka, mut_ki, mut_ep_ai, mut_n); var ref_bohr = computeBohrParameter(ref_R, ref_ep_r, c[i], ref_ka, ref_ki, ref_ep_ai, ref_n); source.data['ref_bohr'][i] = ref_bohr; mut_delta_bohr[i] = mut_bohr[i] - ref_bohr; } source.change.emit(); """) # Define the buttons ref_reset = Button(label='reset reference to default', callback=reset_ref) mut_reset = Button(label='reset mutant to reference', callback=reset_mut) ref_reset.js_on_click(callback) mut_reset.js_on_click(callback) # Assemble controls ref_controls = [ ref_reset, ref_R_slider, ref_epRA_slider, ref_ka_slider, ref_ki_slider, ref_epAI_slider, ref_n_slider ] mut_controls = [ mut_reset, mut_R_slider, mut_epRA_slider, mut_ka_slider, mut_ki_slider, mut_epAI_slider, mut_n_slider ] for rc, mc in zip(ref_controls[1:], mut_controls[1:]): rc.callback = callback mc.callback = callback
j for j, sent in enumerate(source_sentences.data['sentence']) if sent == sentence ] source_sentences.selected.indices = ind text_input.on_change('value', update_sentences) ################################################### # ADD RESET BUTTON ################################################### reset_button = Button(label='ALL WORDS', button_type='primary') reset_button.js_on_click( CustomJS(args=dict(source=source_words_visible, words=source_words, p=p), code=""" p.reset.emit() source.data = words.data """)) ################################################### # CREATION OF THE LAYOUT ################################################### window = row( p, column(row(widgetbox(text_input), column(Div(text="", height=9), reset_button)), p_w, width=600)) curdoc().title = 'Interligua Visualization'
data['dates'] = newdatedata['x'] source.change.emit(); reviews.text = newtextdata[q][0]; """) #for (var i = 0; i < x.length; i++) { # y[i] = newy[i] # } #query.js_on_change('value', callback) update_plots_button.js_on_click(callback) def update_app(attrname, old, new): app_name = app_select.value unique_dates = unique_dates_dict[app_name] #just to reset the slider date_range.start = unique_dates[0] date_range.end = unique_dates[-1] date_range.value = (unique_dates[0], unique_dates[-1])
value=today) end_date.on_change('value', refresh_plot) end_hour = select = Select(title='hour', value="23", options=hours, width=70) end_minute = select = Select(title='min', value="59", options=minutes, width=70) end_hour.on_change('value', refresh_plot) end_minute.on_change('value', refresh_plot) ## live button live_button = Button(width=130, margin=[15, 10, 15, 10], label="live", button_type="default") live_button.js_on_click(CustomJS(code=""" window.location.href='./live'; """)) ## force update_data() history_button = Button(width=130, margin=[15, 10, 15, 10], label="history", button_type="primary") history_button.on_click(plot_data) tz_text = Paragraph(text=f"timezone: {timezone}", width=340) controls = column(row(live_button, history_button), instrum_select, row(start_date, start_hour, start_minute), row(end_date, end_hour, end_minute), tz_text) # plot
for _ in range(num_edges): vertices = sample(graph.vertices.keys(), 2) # TODO check if edge already exists graph.add_edge(vertices[0], vertices[1]) bokeh_graph = BokehGraph(graph, draw_components=draw_components) bokeh_graph.show() if __name__ == '__main__': if len(argv) == 4: NUM_VERTICES = int(argv[1]) NUM_EDGES = int(argv[2]) DRAW_COMPONENTS = bool(int(argv[3])) main(NUM_VERTICES, NUM_EDGES, DRAW_COMPONENTS) else: print('Expected arguments: num_vertices num_edges draw_components') print('Both numbers should be integers, draw_components should be 0/1') rando_button = Button(label='Randomize', button_type='success') show(widgetbox(rando_button)) source = ColumnDataSource(data=bokeh_graph.vertices) callback = CustomJS(args=dict(source=source), code=""" console.log('clicked') """) rando_button.js_on_click(callback)
file_source_populations.on_change('data', file_callback_populations) file_source_patient.on_change('data', file_callback_pat) file_source_clinical.on_change('data', file_callback_clinical) # upload tree files menu_tree = [("Upload cluster coordinates", "coordinates"), ("Upload graph edges", "edges")] tree_dropdown = Dropdown(label="Upload tree structure", button_type="warning", menu=menu_tree, css_classes=['dropdowns']) tree_dropdown.callback = CustomJS(args=dict(file_source=file_source_tree), code=open(join(dirname(__file__), "static/js/upload.js")).read()) # upload patients data upload_patients = Button(label="upload patients data") upload_patients.js_on_click(CustomJS(args=dict(file_source=file_source_patient), code=open(join(dirname(__file__), "static/js/upload_multiple.js")).read())) # upload population list upload_populations = Button(label="upload population list") upload_populations.js_on_click(CustomJS(args=dict(file_source=file_source_populations), code=open(join(dirname(__file__), "static/js/upload.js")).read())) # select patient patient = Select(title='Patient', value='None', options=['None'] + df_viz.columns.tolist()) patient.on_change('value', select_patient) # interaction with the plot x = Select(title='X-Axis', value='x', options=df_viz.columns.tolist()) y = Select(title='Y-Axis', value='y', options=df_viz.columns.tolist()) size = Select(title='Size', value='None', options=['None'] + df_viz.columns.tolist())
observe_segment.on_click(segment_func) cluster_select_data = OD cluster_select_table_Columns = [ TableColumn(field=Ci, title=Ci) for Ci in cluster_select_data.columns ] cluster_select_table_source = ColumnDataSource( cluster_select_data.round(decimals=2)) cluster_select_table = DataTable(columns=cluster_select_table_Columns, source=cluster_select_table_source, width=table_width, height=table_height) download_button = Button(label="Download", button_type="success") download_button.js_on_click( CustomJS(args=dict(source=cluster_select_table_source), code=open(join(dirname(__file__), "download.js")).read())) cluster_select_panel = Panel(child=column( row(cluster_select_table, width=table_width, height=table_height), download_button), title='Cluster Table') """ END OF SEGMNENTATION """ #Data Description and Selected Data panel
source.data = dict(url=[url]) file_input = FileInput(accept=".jpeg") file_input.on_change('value', upload_data) ######################################################################## btn4 = Button(label="Download Image", button_type="success") btn4.js_on_click( CustomJS(args=dict(source=source), code=""" var data = source.data; value1=data['url']; var file = new Blob([value1], {type: 'image/jpeg'}); var elem = window.document.createElement('output'); elem.href = window.URL.createObjectURL(file); elem.download = 'downloaded_image.jpeg'; document.body.appendChild(elem); elem.click(); document.body.removeChild(elem); """)) doc = curdoc() doc.add_root( row(column(file_input, p), column(btn1, gsmooth, btn2, threshold, btn3, btn4))) curdoc.title = "Image Processing Demo" #bokeh serve server_folder --show
def explore_tab(df): def get_dataset(src, name, words, start, end): df = src[src.user == name].copy() mask = (df['timestamp'] > start) & (df['timestamp'] <= end) df = df[mask] words = [str(i) for i in words.split()] safe_words = [] for word in words: word = re.escape(word) word = "(?=.*{})".format(word) safe_words.append(word) df = df[df['texts'].str.contains(''.join(safe_words))] source = ColumnDataSource(data=dict()) cols = ['texts', 'displaySource', 'source'] df[cols] = df[cols].replace({',': '', ',,': '', ';': ''}, regex=True) source.data = { # 'index': df.index, 'impressionTime': df.impressionTime, 'impressionOrder': df.impressionOrder, 'source': df.source, 'fblinktype': df.fblinktype, 'texts': df.texts, 'textsize': df.textsize, 'publicationTime': df.publicationTime, 'permaLink': df.permaLink, 'nature': df.nature, 'ANGRY': df.ANGRY, 'HAHA': df.HAHA, 'LIKE': df.LIKE, 'LOVE': df.LOVE, 'SAD': df.SAD, 'WOW': df.WOW, 'displaySource': df.displaySource, 'id': df.id, 'timestamp': df.timestamp, # 'images': df.images, # 'opengraph': df.opengraph, 'postId': df.postId, # 'semanticCount': df.semanticCount, # 'semanticId': df.semanticId, 'sourceLink': df.sourceLink, 'timeline': df.timeline, 'user': df.user, # 'videoautoplay': df.videoautoplay } return source def make_table(source): # Columns of tablem table_columns = [ TableColumn(field='impressionTime', title='Time'), TableColumn(field='impressionOrder', title='Order'), TableColumn(field='source', title='Source'), TableColumn(field='fblinktype', title='Type'), TableColumn(field='texts', title='Text'), TableColumn(field='textsize', title='Text Size'), TableColumn(field='publicationTime', title='Publication Time'), TableColumn(field='permaLink', title='Link'), TableColumn(field='nature', title='Nature'), TableColumn(field='ANGRY', title='Angry'), TableColumn(field='HAHA', title='Haha'), TableColumn(field='LIKE', title='Like'), TableColumn(field='LOVE', title='Love'), TableColumn(field='SAD', title='Sad'), TableColumn(field='WOW', title='Wow') ] user_table = DataTable(source=source, columns=table_columns, width=1400) return user_table def update(attrname, old, new): name = name_select.value text_filter = text_input.value start = date_slider.value[0] end = date_slider.value[1] src = get_dataset(df, name, text_filter, start, end) source.data.update(src.data) name = df.user.iloc[0] words = '' names = df.user.unique() start = df.timestamp.min() end = df.timestamp.max() name_select = Select(value=name, title='User', options=sorted(names)) text_input = TextInput(value="", title="Filter text:") date_slider = DateRangeSlider(title="Date Range: ", start=df.timestamp.min(), end=date.today(), value=(df.timestamp.min(), date.today()), step=1, callback_policy='mouseup') button = Button(label="Download", button_type="success") source = get_dataset(df, name, words, start, end) table = make_table(source) name_select.on_change('value', update) text_input.on_change('value', update) date_slider.on_change('value', update) button.js_on_click( CustomJS(args=dict(source=source), code=open(join(dirname(__file__), "download.js")).read())) controls = column(name_select, date_slider, text_input, button) tab = Panel(child=row(table, controls), title='Explore') return tab
def load_page(plate): ''' Load new page ''' global well_id well_id = (0, 0) global sample sample = plate[well_id] # Button to upload local file global file_source file_source = ColumnDataSource(data=dict(file_contents = [], file_name = [])) file_source.on_change('data', file_callback) try: output_file_name = file_source.data['file_name'] + '-out.csv' except: output_filename = 'output.csv' global upload_button upload_button = Button(label="Upload local file", button_type="success", width=200, height=30) upload_button.js_on_click(CustomJS(args=dict(file_source=file_source), code=open(join(dirname(__file__), "upload.js")).read())) # Text boxes for setting fit parameters global bottom_set_text bottom_set_text = TextInput(value='', title="Set initial value for Fmin", width=200, height=50) bottom_set_text.on_change('value', parameter_set_callback) global top_set_text top_set_text = TextInput(value='', title="Set initial value for Fmax", width=200, height=50) top_set_text.on_change('value', parameter_set_callback) global slope_set_text slope_set_text = TextInput(value='', title="Set initial value for a", width=200, height=50) slope_set_text.on_change('value', parameter_set_callback) # Radio button group for setting plate type global plate_type_buttons global plate_type plate_type_buttons = RadioButtonGroup(labels=['96 well', '384 well'], width=200, height=25, active=plate_type) plate_type_buttons.on_change('active', plate_type_callback) # Radio button group for setting data layout global plate_layout_buttons global plate_layout plate_layout_buttons = RadioButtonGroup(labels=['by row', 'by column'], width=200, height=25, active=plate_layout) plate_layout_buttons.on_change('active', plate_layout_callback) # Checkbox groups for fixing fit parameters global fix_bottom_checkbox fix_bottom_checkbox = CheckboxButtonGroup(labels=['Fix min fluoresence (Fmin)'], width=200, height=30) fix_bottom_checkbox.on_change('active', parameter_set_callback) global fix_top_checkbox fix_top_checkbox = CheckboxButtonGroup(labels=['Fix max fluorescence (Fmax)'], width=200, height=30) fix_top_checkbox.on_change('active', parameter_set_callback) global fix_slope_checkbox fix_slope_checkbox = CheckboxButtonGroup(labels=['Fix curve shape parameter (a)'], width=200, height=30) fix_slope_checkbox.on_change('active', parameter_set_callback) # Slider for selecting data to fit global df xmin = df[df.columns[0]].values[0] xstep = df[df.columns[0]].values[1] - xmin xstart = sample.data['x'].values[0] xend = sample.data['x'].values[-1] xmax = df[df.columns[0]].values[-1] global range_slider range_slider = RangeSlider(start=xmin, end=xmax, value=(xstart, xend), step=xstep, title='Fine tune temperature range', width=550) range_slider.on_change('value', slider_callback) # Scatter plot for fitting individual samples global sample_source sample_source = ColumnDataSource(data=dict(x=sample.data.x, y=sample.data.y, fit=sample.y_fit, residuals=sample.residuals)) global sample_scatter plot_tools = 'wheel_zoom, pan, reset, save' sample_scatter = figure(title="Boltzman sigmoidal fit", x_axis_label='Temperature ('+degree_sign+'C)', y_axis_label="Fluoresence intensity", plot_width=600, plot_height=300, tools=plot_tools) sample_scatter.circle(x='x', y='y', color='grey', size=8, alpha=0.6, source=sample_source) sample_scatter.line(x='x', y='fit', color='black', line_width=2, alpha=1.0, source=sample_source) sample_scatter.title.text = sample.name + ' fit' # Scatter plot for residuals of individual sample fit global residual_scatter residual_scatter = figure(title="Fit residuals", x_axis_label='Temperature ('+degree_sign+'C)', y_axis_label="Residual", plot_width=600, plot_height=200, tools='wheel_zoom,pan,reset') residual_scatter.yaxis.formatter = BasicTickFormatter(precision=2, use_scientific=True) residual_scatter.circle('x', 'residuals', size=8, source=sample_source, color='grey', alpha=0.6) # Heatmap for displaying all Tm values in dataset global plate_source letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'] w, n, t, e = [], [], [], [] if plate_type_buttons.active == 1: rows = 16 columns = 24 else: rows = 8 columns = 12 for i in range(rows): for j in range(columns): w.append(letters[i]+str(j+1)) try: n.append(plate[(i, j)].name) t.append(plate[(i, j)].v50_fit) e.append(plate[(i, j)].v50_err) except: n.append('') t.append(np.nan) e.append(np.nan) xname = [x[1:] for x in w] yname = [y[0] for y in w] plate_source = ColumnDataSource(dict(w=w, n=n, t=t, e=e, xname=xname, yname=yname)) plate_columns = [ TableColumn(field='w', title='Well ID'), TableColumn(field='n', title='Sample name'), TableColumn(field='t', title='Tm ('+degree_sign+'C)'), TableColumn(field='e', title='Error ('+degree_sign+'C)'), ] plate_map_hover = HoverTool(tooltips=""" <div> <div> <span style="font-size: 14px; font-weight: bold; ">@n:</span> <span style="font-size: 14px; font-weight: bold; ">@t</span> </div> </div> """ ) if plate_type_buttons.active == 1: plate_map = figure(title="Plate view", x_axis_location="above", height=400, width=620, tools=["save, tap, reset", plate_map_hover], x_range=[str(x+1) for x in range(0, columns)]+['', 'Tm ('+degree_sign+'C)'], y_range=letters[:rows][::-1]) else: plate_map = figure(title="Plate view", x_axis_location="above", height=400, width=620, tools=["save, tap, reset", plate_map_hover], x_range=[str(x+1) for x in range(0, columns)]+['Tm ('+degree_sign+'C)'], y_range=letters[:rows][::-1]) taptool = plate_map.select(type=TapTool) plate_map.on_event(Tap, plate_select) global mapper mapper = linear_cmap(field_name='t', palette=RdBu[8], low=min(t), high=max(t)) global color_bar color_bar = ColorBar(color_mapper=mapper['transform'], width=10, height=250, name='Tm ('+degree_sign+'C)') plate_map.add_layout(color_bar, 'right') plate_map.grid.grid_line_color = None plate_map.axis.axis_line_color = None plate_map.axis.major_tick_line_color = None plate_map.axis.major_label_text_font_size = "10pt" plate_map.axis.major_label_standoff = 0 plate_map.rect('xname', 'yname', .95, .95, source=plate_source, color=mapper, line_color='black', line_width=1) # Table listing all Tm values in dataset global plate_table plate_table = DataTable(source=plate_source, columns=plate_columns, width=500, height=500, selectable=True, editable=True) plate_table.source.selected.on_change('indices', table_select) # Table showing fitting parameters for current sample global sample_table_source sample_table_source = ColumnDataSource(data=dict(l=['Fit value', 'Std. error'], b=[sample.bottom_fit, sample.bottom_err], t=[sample.top_fit, sample.top_err], v=[sample.v50_fit, sample.v50_err], s=[sample.slope_fit, sample.slope_err])) sample_table_columns = [ TableColumn(field='l', title=''), TableColumn(field='b', title='Fmin'), TableColumn(field='t', title='Fmax'), TableColumn(field='v', title='Tm ('+degree_sign+'C)'), TableColumn(field='s', title='a') ] global sample_table sample_table = DataTable(source=sample_table_source, columns=sample_table_columns, width=600, height=200, selectable=False, editable=False) # Button to re-fit all with current parameter settings global refit_all_button refit_all_button = Button(label="Re-fit all samples", button_type='danger', width=200, height=30) refit_all_button.on_click(refit_all_callback) # Button to download Tm table to csv file global download_button download_button = Button(label="Download table to CSV", button_type="primary", width=200, height=30) download_button.js_on_click(CustomJS(args=dict(source=plate_source, file_name=output_filename), code=open(join(dirname(__file__), "download.js")).read())) # Button to copy Tm table to clipboard global copy_button copy_button = Button(label="Copy table to clipboard", button_type="primary", width=200, height=30) copy_button.js_on_click(CustomJS(args=dict(source=plate_source), code=open(join(dirname(__file__), "copy.js")).read())) # page formatting desc = Div(text=open(join(dirname(__file__), "description.html")).read(), width=1200) main_row = row(column(plate_type_buttons, plate_layout_buttons, upload_button, fix_bottom_checkbox, bottom_set_text, fix_top_checkbox, top_set_text, fix_slope_checkbox, slope_set_text, refit_all_button, download_button, copy_button), column(sample_scatter, residual_scatter, range_slider, sample_table), column(plate_map, plate_table)) sizing_mode = 'scale_width' l = layout([ [desc], [main_row] ], sizing_mode=sizing_mode) update() curdoc().clear() curdoc().add_root(l) curdoc().title = "DSF"
class SeparationDash(): """ A dashboard that displays separation data. Pass a reference to the Bokeh document for threading access. """ def __init__(self, model): """ Construct separation dashboard """ # Save reference to model self.model = model ################################ # Process button ################################ self.process = Button(label="Generate", button_type="primary", name='process', sizing_mode='scale_width', css_classes=['generate']) self.process.js_on_click(CustomJS(code="toggleLoading()")) ################################ # Widgets ################################ # Data type selection self.data_type = RadioButtonGroup( labels=["All Data", "Experimental", "Simulated"], active=0, css_classes=['dtypes']) # Adsorbate drop-down selections self.g1_sel = Select(title="Adsorbate 1", options=self.model.ads_list, value=self.model.g1, css_classes=['g-selectors']) self.g2_sel = Select(title="Adsorbate 2", options=self.model.ads_list, value=self.model.g2) # Temperature selection self.t_absolute = Spinner(value=self.model.t_abs, title='Temperature:', css_classes=['t-abs']) self.t_tolerance = Spinner(value=self.model.t_tol, title='Tolerance:', css_classes=['t-tol']) # Combined in a layout self.dsel_widgets = layout([ [self.data_type], [self.g1_sel, self.g2_sel, self.t_absolute, self.t_tolerance], ], sizing_mode='scale_width', name="widgets") ################################ # KPI Plots ################################ # Top graph generation tooltip = load_tooltip() self.p_henry, rend1 = self.top_graph("K", "Henry coefficient (log)", self.model.data, self.model.errors, tooltip) self.p_loading, rend2 = self.top_graph( "L", "Uptake at selected pressure (bar)", self.model.data, self.model.errors, tooltip) self.p_wc, rend3 = self.top_graph( "W", "Working capacity in selected range (bar)", self.model.data, self.model.errors, tooltip) # Give graphs the same hover and select effect sel = Circle(fill_alpha=1, fill_color="red", line_color=None) nonsel = Circle(fill_alpha=0.2, fill_color="blue", line_color=None) for rend in [rend1, rend2, rend3]: rend.selection_glyph = sel rend.nonselection_glyph = nonsel rend.hover_glyph = sel # Pressure slider self.p_slider = Slider( title="Pressure (bar)", value=0.5, start=0, end=20, step=0.5, callback_policy='throttle', callback_throttle=200, ) # Working capacity slider self.wc_slider = RangeSlider( title="Working capacity (bar)", value=(0.5, 5), start=0, end=20, step=0.5, callback_policy='throttle', callback_throttle=200, ) # Material datatable self.mat_list = DataTable( columns=[ TableColumn(field="labels", title="Material", width=300), TableColumn(field="sel", title="KH2/KH1", width=35, formatter=NumberFormatter(format='‘0.0a’')), TableColumn(field="psa_W", title="PSA-API", width=35, formatter=NumberFormatter(format='‘0.0a’')), ], source=self.model.data, index_position=None, selectable='checkbox', scroll_to_selection=True, width=400, fit_columns=True, ) # Custom css classes for interactors self.p_henry.css_classes = ['g-henry'] self.p_loading.css_classes = ['g-load'] self.p_wc.css_classes = ['g-wcap'] self.mat_list.css_classes = ['t-details'] # Generate the axis labels self.top_graph_labels() self.kpi_plots = layout([ [ gridplot([[self.mat_list, self.p_henry], [self.p_loading, self.p_wc]], sizing_mode='scale_width') ], [self.p_slider, self.wc_slider], ], sizing_mode='scale_width', name="kpiplots") self.kpi_plots.children[0].css_classes = ['kpi'] self.kpi_plots.children[1].css_classes = ['p-selectors'] ################################ # Isotherm details explorer ################################ # Isotherm display graphs self.p_g1iso = self.bottom_graph(self.model.g1_iso_sel, self.model.g1) self.p_g2iso = self.bottom_graph(self.model.g2_iso_sel, self.model.g2) # Isotherm display palette self.c_cyc = cycle(gen_palette(20)) self.detail_plots = layout([ [self.p_g1iso, self.p_g2iso], ], sizing_mode='scale_width', name="detailplots") self.detail_plots.children[0].css_classes = ['isotherms'] # ######################################################################### # Graph generators def top_graph(self, ind, title, d_source, e_source, tooltip, **kwargs): """Generate the top graphs (KH, uptake, WC).""" # Generate figure dict plot_side_size = 400 fig_dict = dict(tools="pan,wheel_zoom,tap,reset,save", active_scroll="wheel_zoom", plot_width=plot_side_size, plot_height=plot_side_size, title=title) fig_dict.update(kwargs) # Create a colour mapper for number of isotherms mapper = log_cmap(field_name='{0}_n'.format(ind), palette="Viridis256", low_color='grey', high_color='yellow', low=3, high=100) # Create a new plot graph = figure(**fig_dict) # Add the hover tooltip graph.add_tools( HoverTool(names=["{0}_data".format(ind)], tooltips=tooltip.render(p=ind))) # Plot the data rend = graph.circle("{0}_x".format(ind), "{0}_y".format(ind), source=d_source, size=10, line_color=mapper, color=mapper, name="{0}_data".format(ind)) # Plot guide line graph.add_layout( Slope(gradient=1, y_intercept=0, line_color='black', line_dash='dashed', line_width=2)) # Plot the error margins graph.segment('{0}_x0'.format(ind), '{0}_y0'.format(ind), '{0}_x1'.format(ind), '{0}_y1'.format(ind), source=e_source, color="black", line_width=2, line_cap='square', line_dash='dotted') # Plot labels next to selected materials graph.add_layout( LabelSet( x='{0}_x'.format(ind), y='{0}_y'.format(ind), source=e_source, text='labels', level='glyph', x_offset=5, y_offset=5, render_mode='canvas', text_font_size='10pt', )) # Add the colorbar to the side graph.add_layout( ColorBar(color_mapper=mapper['transform'], ticker=LogTicker(desired_num_ticks=10), width=8, location=(0, 0)), 'right') return graph, rend def top_graph_labels(self): """Generate the top graph labels from selected ads_list.""" self.p_loading.xaxis.axis_label = '{0} (mmol/g)'.format(self.model.g1) self.p_loading.yaxis.axis_label = '{0} (mmol/g)'.format(self.model.g2) self.p_henry.xaxis.axis_label = '{0} (mmol/bar)'.format(self.model.g1) self.p_henry.yaxis.axis_label = '{0} (mmol/bar)'.format(self.model.g2) self.p_wc.xaxis.axis_label = '{0} (mmol/g)'.format(self.model.g1) self.p_wc.yaxis.axis_label = '{0} (mmol/g)'.format(self.model.g2) def bottom_graph(self, source, ads): """Generate the bottom graphs (isotherm display).""" graph = figure(tools="pan,wheel_zoom,reset", active_scroll="wheel_zoom", plot_width=400, plot_height=250, x_range=(-0.01, 0.01), y_range=(-0.01, 0.01), title='Isotherms {0}'.format(ads)) rend = graph.multi_line('x', 'y', source=source, alpha=0.6, line_width=3, hover_line_alpha=1.0, hover_line_color="black", line_color='color') # Make clicking a graph open the NIST database graph.add_tools( HoverTool(show_arrow=False, line_policy='nearest', tooltips="""Click for details""")) graph.add_tools( TapTool(renderers=[rend], callback=CustomJS(args={ 'tp': load_details().render(), }, code=load_details_js()))) source.selected.js_on_change( 'indices', CustomJS( code= 'if (cb_obj.indices.length == 0) document.getElementById("iso-details").style.display = \"none\"' )) graph.xaxis.axis_label = 'Pressure (bar)' graph.yaxis.axis_label = 'Uptake (mmol/g)' return graph
def create_layout(): """Inclui o gráficos e os controles no curdoc do Bokeh Server.""" plot_html = ColumnDataSource(dict(file_html=["Title"], html=[""])) plot = figure( title="Title", sizing_mode="stretch_both", tools="wheel_zoom,box_zoom,pan,,crosshair,reset,save", # tooltips=[("y", "$y"), ("x", "$x")], active_scroll="wheel_zoom", toolbar_location="above", output_backend="webgl", ) plot.xaxis.axis_label = "X" plot.yaxis.axis_label = "Y" plot.add_layout(Legend()) plot.legend.click_policy = "hide" plot.legend.background_fill_alpha = 0.6 table_source = ColumnDataSource() side_controls = column(width=400, height=200) series_source_controls = row(sizing_mode="scale_width") tabs = Tabs() models.COLORS = cycle(Category10_10) models.Series.labels = [] def upload_callback(attr, old, new): """Função que atualiza os dados do arquivo aberto.""" file_contents = base64.b64decode(new) file_contents_bytes = io.BytesIO(file_contents) table_source.data = pd.read_csv(file_contents_bytes).to_dict("list") colmmns = list(table_source.data.keys()) for widget in list(values_selectors.values()): widget.options = colmmns datatable.columns = [TableColumn(field=_, title=_) for _ in colmmns] def update_plot_html(event): title = plot.title.text file_name = title + ".html" # output_file(file_name, title=title, mode="inline") # save(plot) html = file_html(plot, INLINE, title) plot_html.data = dict(file_name=[file_name], html=[html]) # Widgets (controls) ====================================================== # Plot controls plot_title = TextInput(title="Plot title", value="Title") x_title = TextInput(title="X title", value="X") y_title = TextInput(title="Y title", value="Y") positions = [_.replace("_", "-") for _ in list(LegendLocation)] legend_position = Select(title="Legend position", options=positions) download_button = Button(label="Download saved", button_type="success", align="end") save_button = Button(label="Save", align="end") save_button.on_click(update_plot_html) with open("bokeh_chart_maker/download.js") as f: callback = CustomJS(args=dict(source=plot_html), code=f.read()) download_button.js_on_click(callback) plot_controls = row(plot_title, x_title, y_title, legend_position, save_button, download_button) def update_plot(attr, old, new): plot.title.text = plot_title.value plot.xaxis.axis_label = x_title.value plot.yaxis.axis_label = y_title.value plot.legend.location = legend_position.value.replace("-", "_") for widget in plot_controls.children: if hasattr(widget, "value"): widget.on_change("value", update_plot) legend_position.value = "top_left" # Series controls upload_button = FileInput(accept=".csv") upload_button.on_change("value", upload_callback) columns = [ TableColumn(field=_, title=_, width=10) for _ in table_source.data.keys() ] datatable = DataTable(source=table_source, columns=columns, width=390, height=200) values_selectors = {} glyph_type = Select(title="Glyph type", options=["line", "scatter"], width=100) def update_series_source_controls(attr, old, new): colmmns = list(table_source.data.keys()) kw = dict(options=colmmns, width=80) values_selectors["x"] = Select(title=f"x-values", **kw) values_selectors["y"] = Select(title=f"y-values", **kw) series_source_controls.children = list(values_selectors.values()) glyph_type.on_change("value", update_series_source_controls) glyph_type.value = "line" add_button = Button(label="Add glyph", button_type="success", width=50, align="end") side_controls.children = [ Div(text="<h3>Load file</h3>", height=35), upload_button, datatable, row(glyph_type, series_source_controls, add_button, width=390), Div(text="<h3>Glyphs</h3>", height=35), tabs, ] def add_series(event): any_col = list(table_source.data.keys())[0] source = ColumnDataSource() for key, selector in values_selectors.items(): column_name = selector.value or any_col source.data[key] = table_source.data[column_name] vars_map = dict((k, str(k)) for k in values_selectors.keys()) if glyph_type.value == "line": series = models.line_series(plot, source=source, **vars_map) elif glyph_type.value == "scatter": series = models.scatter_series(plot, source=source, **vars_map) def delete_series(event): plot.renderers = [ r for r in plot.renderers if r.glyph != series.glyph ] legend_items = list(plot.legend.items) plot.legend.items = [ item for item in legend_items if series.glyph != item.renderers[0].glyph ] tabs.tabs = [panel for panel in tabs.tabs if panel != series.panel] series.delete_button.on_click(delete_series) tabs.tabs.append(series.panel) add_button.on_click(add_series) return [ side_controls, column(plot_controls, plot, sizing_mode="stretch_width") ]
} else { var link = document.createElement("a"); link = document.createElement('a') link.href = URL.createObjectURL(blob); link.download = filename link.target = "_blank"; link.style.visibility = 'hidden'; link.dispatchEvent(new MouseEvent('click')) } """) annotation_select = RadioButtonGroup(labels=["N", "V", "Q", "Delete Bin", "Noise Bin"], callback=cb_rgrp_button,height=15) refresh = Button(label="Refresh ", button_type="success", callback = callback,sizing_mode='scale_height',width=100,height=10) refresh.js_on_click(callback) change_button = Button(label="Change ", button_type="success", sizing_mode='scale_width',callback = callback,width=100,height=10) button = Button(label="Download Changed Annotations", button_type="success", callback = cb_button,height=0) figure = row(p1, column(div3,slider,div,checkboxes,div2,annotation_select,row(change_button, refresh), button),p2) show(figure)
def nn(): ###------------------------PARAMETER DEFAULTS-----------------------------### # range[Lower, Upper, Step Size] ### - SAMPLING Parameters d_nsamp, r_nsamp = 500, [100, 2000, 50] # Number of samples plot_data = figure( plot_height=400, plot_width=400, title="Simulated points (x,y)", toolbar_location="above", x_axis_label="x", y_axis_label="y", tools="pan,save,box_zoom,wheel_zoom", ) source = ColumnDataSource(data=dict(x=[], y=[], z=[])) source.data = dict(x=np.zeros([1, 1]), y=np.zeros([1, 1]), z=np.zeros([1, 1])) surface_title = Div( text="<b> Surafce plot of the joint distribution z = p(x,y) </b>") surface = Surface3d(x="x", y="y", z="z", data_source=source) plot_conditional = figure( plot_height=400, plot_width=800, title="Conditional density p(y/x=X)", toolbar_location="above", x_axis_label="y", y_axis_label="CDF", tools="pan,save,box_zoom,wheel_zoom", ) style(plot_conditional) plot_clear = Button(label="Clear All", button_type="warning") # Simulation of GMM ctl_title = Div(text="<h3>Simulator</h3>") div1 = Div( text= """<p style="border:3px; border-style:solid; border-color:grey; padding: 1em;"> Hyperparameters of bi-GMM components (refer to the blog post for details)<br /> - n_kernels: Nb of componenets<br /> - means_loc: mean of a normal distribution from where the means of components are sampled. <br /> - means_scale: associated scale. <br /> - covariance_x_loc: mean of a normal distribution from where the covariances of X are simpled <br /> - covariance_x_scale: associated scale. <br /> - covariance_y_loc: mean of a normal distribution from where the covariances of Y are simpled <br /> - covariance_y_scale: associated scale. <br /> </p>""", width=300, height=330, ) ctl_nsamp = Slider( title="Number of samples", value=d_nsamp, start=r_nsamp[0], end=r_nsamp[1], step=r_nsamp[2], ) n_kernels = Slider(title="Number of mixtures", value=5, start=1, end=10, step=1) means_loc = TextInput(title="means_loc", value="0.0") means_scale = TextInput(title="means_scale", value="4.0") covariance_x_loc = TextInput(title="covariance_x_loc", value="1.0") covariance_x_scale = TextInput(title="covariance_x_scale", value="0.5") covariance_y_loc = TextInput(title="covariance_y_loc", value="1.0") covariance_y_scale = TextInput(title="covariance_y_scale", value="0.5") plot_sim = Button(label="Simulate", button_type="primary") simulate = widgetbox( ctl_title, div1, ctl_nsamp, plot_sim, n_kernels, means_loc, means_scale, covariance_x_loc, covariance_x_scale, covariance_y_loc, covariance_y_scale, ) ### MDN mdn_title = Div(text="<h3>MDN Training </h3>") mdn_text = Div(text="Choose training parameters") n_gaussians = Slider(title="Number of mixtures to fit", value=10, start=1, end=20, step=1) n_layers = Slider(title="Number of hidden layers", value=1, start=1, end=3, step=1) n_hidden = Slider(title="Size of hidden neurons", value=20, start=5, end=10, step=1) dropout = Slider(title="Dropout regularization", value=0.05, start=0, end=0.2, step=0.01) l2 = Slider(title="L2 regularization", value=0.001, start=0, end=0.1, step=0.001) epochs = Slider(title="Nb of epochs", value=500, start=1, end=1500, step=50) text_output = Paragraph(text="", width=200, height=20) train = Button(label="Train model", button_type="success") mdn_box = widgetbox( mdn_title, mdn_text, n_gaussians, n_layers, n_hidden, dropout, l2, epochs, train, text_output, ) # Plot of p(y/x) fit_title = Div( text= "<h3>Plot Conditional Distribution P(y/x=X) </h3> - You can plot the real p(y/x) after simulating data. <br /> - You can plot estimated p(y/x) after taining the model." ) at_X = TextInput(title="X", value="1.0") fit_sim = Button(label="Plot real p(y/x)", button_type="success") fit_sim_mdn = Button(label="Plot estimated p(y/x)", button_type="success") fit1 = widgetbox(fit_title, at_X, fit_sim, fit_sim_mdn) ###-----------------------------------------------------------------------### ###-----------------------BASE-LEVEL FUNCTIONS----------------------------### def make_data(): # Sample points bi_gmm = SimulateBiGMM( int(n_kernels.value), float(means_loc.value), float(means_scale.value), float(covariance_x_loc.value), float(covariance_x_scale.value), float(covariance_y_loc.value), float(covariance_y_scale.value), ) (x, y) = bi_gmm.simulate_xy(int(ctl_nsamp.value)) return x, y, bi_gmm ###-----------------------------------------------------------------------### ###------------------DATA SOURCES AND INITIALIZATION----------------------### source1 = ColumnDataSource(data=dict(x=[], y=[])) plot_data.scatter("x", "y", source=source1, size=3, color="#3A5785", alpha=0.6) source2 = ColumnDataSource(data=dict(x=[], prob=[])) source3 = ColumnDataSource(data=dict(x=[], prob=[])) plot_conditional.line("x", "prob", source=source2, color="#21b093", alpha=0.8, legend="True CDF") plot_conditional.line("x", "prob", source=source3, color="orange", alpha=0.8, legend="Estimated CDF") def click_simulate(): # Make it global to be used later global x_points, y_points global bi_gmm_ # reset pdf source2.data = dict(x=[], prob=[]) source3.data = dict(x=[], prob=[]) x_points, y_points, bi_gmm_ = make_data() source1.data = dict(x=x_points, y=y_points) plot_data.y_range.start = y_points.min() - 1 plot_data.y_range.end = y_points.max() + 1 plot_data.x_range.start = x_points.min() - 1 plot_data.x_range.end = x_points.max() + 1 plot_data.xaxis.axis_label = "x" plot_data.yaxis.axis_label = "y" # 3d surface plot xx, yy, zz = bi_gmm_.compute_pdf(x_points.min(), x_points.max(), y_points.min(), y_points.max()) source.data = dict(x=xx, y=yy, z=zz) plot_sim.on_click(click_simulate) # Real P(y/x) def plot_real_conditional(): source3.data = dict(x=[], prob=[]) ys = np.linspace(y_points.min() - 1, y_points.max() + 1, 1000) prob = bi_gmm_.compute_cdf(float(at_X.value), ys) source2.data = dict(x=ys, prob=prob) fit_sim.on_click(plot_real_conditional) # Fit MDN def fit_mdn(): global mdn_model mdn_model = MDN_network( int(n_hidden.value), int(n_layers.value), int(n_gaussians.value), float(dropout.value), ) optimizer = torch.optim.Adam(mdn_model.parameters(), weight_decay=float(l2.value)) x_tensor = torch.from_numpy(np.float32(x_points)) y_tensor = torch.from_numpy(np.float32(y_points)) for e in range(int(epochs.value)): l = train_epoch(mdn_model, (x_tensor, y_tensor), optimizer) text_output.text = "Taining is done." code = "cds.text = 'Training the model... Please wait.';" callback = CustomJS(args={"cds": text_output}, code=code) train.js_on_click(callback) train.on_click(fit_mdn) def plot_estimated_conditional(): ys = np.linspace(y_points.min() - 1, y_points.max() + 1, 1000) prob = simulate_condprob_trained(float(at_X.value), mdn_model, ys) source3.data = dict(x=ys, prob=prob) fit_sim_mdn.on_click(plot_estimated_conditional) # Behavior when the "Clear" button is clicked def clear_plot(): source1.data = dict(x=[], y=[]) source2.data = dict(x=[], prob=[]) source3.data = dict(x=[], prob=[]) source.data = dict(x=np.zeros([1, 1]), y=np.zeros([1, 1]), z=np.zeros([1, 1])) text_output.text = "" plot_clear.on_click(clear_plot) ###-----------------------------------------------------------------------### ###----------------------------PAGE LAYOUT--------------------------------### col_inputs = column(simulate) col_output = column(mdn_box, fit1, plot_clear) # col_plots = column(plot_data, s3) plot_3d = column(surface_title, surface) col_plots = layout([[plot_data, plot_3d], [plot_conditional]]) row_page = row(col_inputs, col_plots, col_output, width=1200) # Make a tab with the layout tab = Panel(child=row_page, title="Neual Network - Conditional Density Estimation") return tab
def plot_3DModel_bokeh(filename, map_data_all_slices, map_depth_all_slices, \ color_range_all_slices, profile_data_all, boundary_data, \ style_parameter): ''' Plot shear velocity maps and velocity profiles using bokeh Input: filename is the filename of the resulting html file map_data_all_slices contains the velocity model parameters saved for map view plots map_depth_all_slices is a list of depths color_range_all_slices is a list of color ranges profile_data_all constains the velocity model parameters saved for profile plots boundary_data is a list of boundaries style_parameter contains plotting parameters Output: None ''' xlabel_fontsize = style_parameter['xlabel_fontsize'] # colorbar_data_all_left = [] colorbar_data_all_right = [] map_view_ndepth = style_parameter['map_view_ndepth'] ncolor = len(palette) colorbar_top = [0.1 for i in range(ncolor)] colorbar_bottom = [0 for i in range(ncolor)] map_data_all_slices_depth = [] for idepth in range(map_view_ndepth): color_min = color_range_all_slices[idepth][0] color_max = color_range_all_slices[idepth][1] color_step = (color_max - color_min) * 1. / ncolor colorbar_left = np.linspace(color_min, color_max - color_step, ncolor) colorbar_right = np.linspace(color_min + color_step, color_max, ncolor) colorbar_data_all_left.append(colorbar_left) colorbar_data_all_right.append(colorbar_right) map_depth = map_depth_all_slices[idepth] map_data_all_slices_depth.append( 'Depth: {0:8.1f} km'.format(map_depth)) # palette_r = palette[::-1] # data for the colorbar colorbar_data_one_slice = {} colorbar_data_one_slice['colorbar_left'] = colorbar_data_all_left[ style_parameter['map_view_default_index']] colorbar_data_one_slice['colorbar_right'] = colorbar_data_all_right[ style_parameter['map_view_default_index']] colorbar_data_one_slice_bokeh = ColumnDataSource(data=dict(colorbar_top=colorbar_top,colorbar_bottom=colorbar_bottom,\ colorbar_left=colorbar_data_one_slice['colorbar_left'],\ colorbar_right=colorbar_data_one_slice['colorbar_right'],\ palette_r=palette_r)) colorbar_data_all_slices_bokeh = ColumnDataSource(data=dict(colorbar_data_all_left=colorbar_data_all_left,\ colorbar_data_all_right=colorbar_data_all_right)) # map_view_label_lon = style_parameter['map_view_depth_label_lon'] map_view_label_lat = style_parameter['map_view_depth_label_lat'] map_data_one_slice_depth = map_data_all_slices_depth[ style_parameter['map_view_default_index']] map_data_one_slice_depth_bokeh = ColumnDataSource(data=dict(lat=[map_view_label_lat], lon=[map_view_label_lon], map_depth=[map_data_one_slice_depth], left=[style_parameter['profile_plot_xmin']], \ right=[style_parameter['profile_plot_xmax']])) # map_view_default_index = style_parameter['map_view_default_index'] #map_data_one_slice = map_data_all_slices[map_view_default_index] # map_color_all_slices = [] for i in range(len(map_data_all_slices)): vmin, vmax = color_range_all_slices[i] map_color = val_to_rgb(map_data_all_slices[i], palette_r, vmin, vmax) map_color_2d = map_color.view('uint32').reshape(map_color.shape[:2]) map_color_all_slices.append(map_color_2d) map_color_one_slice = map_color_all_slices[map_view_default_index] # map_data_one_slice_bokeh = ColumnDataSource(data=dict(x=[style_parameter['map_view_image_lon_min']],\ y=[style_parameter['map_view_image_lat_min']],dw=[style_parameter['nlon']*style_parameter['dlon']],\ dh=[style_parameter['nlat']*style_parameter['dlat']],map_data_one_slice=[map_color_one_slice])) map_data_all_slices_bokeh = ColumnDataSource(data=dict(map_data_all_slices=map_color_all_slices,\ map_data_all_slices_depth=map_data_all_slices_depth)) # ------------------------------ nprofile = len(profile_data_all) grid_lat_list = [] grid_lon_list = [] width_list = [] height_list = [] for iprofile in range(nprofile): aprofile = profile_data_all[iprofile] grid_lat_list.append(aprofile['lat']) grid_lon_list.append(aprofile['lon']) width_list.append(style_parameter['map_view_grid_width']) height_list.append(style_parameter['map_view_grid_height']) grid_data_bokeh = ColumnDataSource(data=dict(lon=grid_lon_list,lat=grid_lat_list,\ width=width_list, height=height_list)) profile_default_index = style_parameter['profile_default_index'] selected_dot_on_map_bokeh = ColumnDataSource(data=dict(lat=[grid_lat_list[profile_default_index]], \ lon=[grid_lon_list[profile_default_index]], \ width=[style_parameter['map_view_grid_width']],\ height=[style_parameter['map_view_grid_height']],\ index=[profile_default_index])) # ------------------------------ profile_vs_all = [] profile_depth_all = [] profile_ndepth = style_parameter['profile_ndepth'] profile_lat_label_list = [] profile_lon_label_list = [] for iprofile in range(nprofile): aprofile = profile_data_all[iprofile] vs_raw = aprofile['vs'] top_raw = aprofile['top'] profile_lat_label_list.append('Lat: {0:12.1f}'.format(aprofile['lat'])) profile_lon_label_list.append('Lon: {0:12.1f}'.format(aprofile['lon'])) vs_plot = [] depth_plot = [] for idepth in range(profile_ndepth): vs_plot.append(vs_raw[idepth]) depth_plot.append(top_raw[idepth]) vs_plot.append(vs_raw[idepth]) depth_plot.append(top_raw[idepth + 1]) profile_vs_all.append(vs_plot) profile_depth_all.append(depth_plot) profile_data_all_bokeh = ColumnDataSource(data=dict(profile_vs_all=profile_vs_all, \ profile_depth_all=profile_depth_all)) selected_profile_data_bokeh = ColumnDataSource(data=dict(vs=profile_vs_all[profile_default_index],\ depth=profile_depth_all[profile_default_index])) selected_profile_lat_label_bokeh = ColumnDataSource(data=\ dict(x=[style_parameter['profile_lat_label_x']], y=[style_parameter['profile_lat_label_y']],\ lat_label=[profile_lat_label_list[profile_default_index]])) selected_profile_lon_label_bokeh = ColumnDataSource(data=\ dict(x=[style_parameter['profile_lon_label_x']], y=[style_parameter['profile_lon_label_y']],\ lon_label=[profile_lon_label_list[profile_default_index]])) all_profile_lat_label_bokeh = ColumnDataSource(data=dict( profile_lat_label_list=profile_lat_label_list)) all_profile_lon_label_bokeh = ColumnDataSource(data=dict( profile_lon_label_list=profile_lon_label_list)) # button_ndepth = style_parameter['button_ndepth'] button_data_all_vs = [] button_data_all_vp = [] button_data_all_rho = [] button_data_all_top = [] for iprofile in range(nprofile): aprofile = profile_data_all[iprofile] button_data_all_vs.append(aprofile['vs'][:button_ndepth]) button_data_all_vp.append(aprofile['vp'][:button_ndepth]) button_data_all_rho.append(aprofile['rho'][:button_ndepth]) button_data_all_top.append(aprofile['top'][:button_ndepth]) button_data_all_bokeh = ColumnDataSource(data=dict(button_data_all_vs=button_data_all_vs,\ button_data_all_vp=button_data_all_vp,\ button_data_all_rho=button_data_all_rho,\ button_data_all_top=button_data_all_top)) # ============================== map_view = Figure(plot_width=style_parameter['map_view_plot_width'], plot_height=style_parameter['map_view_plot_height'], \ tools=style_parameter['map_view_tools'], title=style_parameter['map_view_title'], \ y_range=[style_parameter['map_view_figure_lat_min'], style_parameter['map_view_figure_lat_max']],\ x_range=[style_parameter['map_view_figure_lon_min'], style_parameter['map_view_figure_lon_max']]) # map_view.image_rgba('map_data_one_slice',x='x',\ y='y',dw='dw',dh='dh', source=map_data_one_slice_bokeh, level='image') depth_slider_callback = CustomJS(args=dict(map_data_one_slice_bokeh=map_data_one_slice_bokeh,\ map_data_all_slices_bokeh=map_data_all_slices_bokeh,\ colorbar_data_all_slices_bokeh=colorbar_data_all_slices_bokeh,\ colorbar_data_one_slice_bokeh=colorbar_data_one_slice_bokeh,\ map_data_one_slice_depth_bokeh=map_data_one_slice_depth_bokeh), code=""" var d_index = Math.round(cb_obj.value) var map_data_all_slices = map_data_all_slices_bokeh.data map_data_one_slice_bokeh.data['map_data_one_slice'] = [map_data_all_slices['map_data_all_slices'][d_index]] map_data_one_slice_bokeh.change.emit() var color_data_all_slices = colorbar_data_all_slices_bokeh.data colorbar_data_one_slice_bokeh.data['colorbar_left'] = color_data_all_slices['colorbar_data_all_left'][d_index] colorbar_data_one_slice_bokeh.data['colorbar_right'] = color_data_all_slices['colorbar_data_all_right'][d_index] colorbar_data_one_slice_bokeh.change.emit() map_data_one_slice_depth_bokeh.data['map_depth'] = [map_data_all_slices['map_data_all_slices_depth'][d_index]] map_data_one_slice_depth_bokeh.change.emit() """) depth_slider = Slider(start=0, end=style_parameter['map_view_ndepth']-1, \ value=map_view_default_index, step=1, \ width=style_parameter['map_view_plot_width'],\ title=style_parameter['depth_slider_title'], height=50) depth_slider.js_on_change('value', depth_slider_callback) depth_slider_callback.args["depth_index"] = depth_slider # ------------------------------ # add boundaries to map view # country boundaries map_view.multi_line(boundary_data['country']['longitude'],\ boundary_data['country']['latitude'],color='black',\ line_width=2, level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # marine boundaries map_view.multi_line(boundary_data['marine']['longitude'],\ boundary_data['marine']['latitude'],color='black',\ level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # shoreline boundaries map_view.multi_line(boundary_data['shoreline']['longitude'],\ boundary_data['shoreline']['latitude'],color='black',\ line_width=2, level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # state boundaries map_view.multi_line(boundary_data['state']['longitude'],\ boundary_data['state']['latitude'],color='black',\ level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # ------------------------------ # add depth label map_view.rect(style_parameter['map_view_depth_box_lon'], style_parameter['map_view_depth_box_lat'], \ width=style_parameter['map_view_depth_box_width'], height=style_parameter['map_view_depth_box_height'], \ width_units='screen',height_units='screen', color='#FFFFFF', line_width=1., line_color='black', level='underlay') map_view.text('lon', 'lat', 'map_depth', source=map_data_one_slice_depth_bokeh,\ text_font_size=style_parameter['annotating_text_font_size'],text_align='left',level='underlay') # ------------------------------ map_view.rect('lon', 'lat', width='width', \ width_units='screen', height='height', \ height_units='screen', line_color='gray', line_alpha=0.5, \ selection_line_color='gray', selection_line_alpha=0.5, selection_fill_color=None,\ nonselection_line_color='gray',nonselection_line_alpha=0.5, nonselection_fill_color=None,\ source=grid_data_bokeh, color=None, line_width=1, level='glyph') map_view.rect('lon', 'lat',width='width', \ width_units='screen', height='height', \ height_units='screen', line_color='#00ff00', line_alpha=1.0, \ source=selected_dot_on_map_bokeh, fill_color=None, line_width=3.,level='glyph') # ------------------------------ grid_data_js = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh, \ grid_data_bokeh=grid_data_bokeh,\ profile_data_all_bokeh=profile_data_all_bokeh,\ selected_profile_data_bokeh=selected_profile_data_bokeh,\ selected_profile_lat_label_bokeh=selected_profile_lat_label_bokeh,\ selected_profile_lon_label_bokeh=selected_profile_lon_label_bokeh, \ all_profile_lat_label_bokeh=all_profile_lat_label_bokeh, \ all_profile_lon_label_bokeh=all_profile_lon_label_bokeh, \ ), code=""" var inds = cb_obj.indices var grid_data = grid_data_bokeh.data selected_dot_on_map_bokeh.data['lat'] = [grid_data['lat'][inds]] selected_dot_on_map_bokeh.data['lon'] = [grid_data['lon'][inds]] selected_dot_on_map_bokeh.data['index'] = [inds] selected_dot_on_map_bokeh.change.emit() var profile_data_all = profile_data_all_bokeh.data selected_profile_data_bokeh.data['vs'] = profile_data_all['profile_vs_all'][inds] selected_profile_data_bokeh.data['depth'] = profile_data_all['profile_depth_all'][inds] selected_profile_data_bokeh.change.emit() var all_profile_lat_label = all_profile_lat_label_bokeh.data['profile_lat_label_list'] var all_profile_lon_label = all_profile_lon_label_bokeh.data['profile_lon_label_list'] selected_profile_lat_label_bokeh.data['lat_label'] = [all_profile_lat_label[inds]] selected_profile_lon_label_bokeh.data['lon_label'] = [all_profile_lon_label[inds]] selected_profile_lat_label_bokeh.change.emit() selected_profile_lon_label_bokeh.change.emit() """) grid_data_bokeh.selected.js_on_change('indices', grid_data_js) # ------------------------------ # change style map_view.title.text_font_size = style_parameter['title_font_size'] map_view.title.align = 'center' map_view.title.text_font_style = 'normal' map_view.xaxis.axis_label = style_parameter['map_view_xlabel'] map_view.xaxis.axis_label_text_font_style = 'normal' map_view.xaxis.axis_label_text_font_size = xlabel_fontsize map_view.xaxis.major_label_text_font_size = xlabel_fontsize map_view.yaxis.axis_label = style_parameter['map_view_ylabel'] map_view.yaxis.axis_label_text_font_style = 'normal' map_view.yaxis.axis_label_text_font_size = xlabel_fontsize map_view.yaxis.major_label_text_font_size = xlabel_fontsize map_view.xgrid.grid_line_color = None map_view.ygrid.grid_line_color = None map_view.toolbar.logo = None map_view.toolbar_location = 'above' map_view.toolbar_sticky = False # ============================== # plot colorbar colorbar_fig = Figure(tools=[], y_range=(0,0.1),plot_width=style_parameter['map_view_plot_width'], \ plot_height=style_parameter['colorbar_plot_height'],title=style_parameter['colorbar_title']) colorbar_fig.toolbar_location = None colorbar_fig.quad(top='colorbar_top',bottom='colorbar_bottom',left='colorbar_left',right='colorbar_right',\ color='palette_r',source=colorbar_data_one_slice_bokeh) colorbar_fig.yaxis[0].ticker = FixedTicker(ticks=[]) colorbar_fig.xgrid.grid_line_color = None colorbar_fig.ygrid.grid_line_color = None colorbar_fig.xaxis.axis_label_text_font_size = xlabel_fontsize colorbar_fig.xaxis.major_label_text_font_size = xlabel_fontsize colorbar_fig.xaxis[0].formatter = PrintfTickFormatter(format="%5.2f") colorbar_fig.title.text_font_size = xlabel_fontsize colorbar_fig.title.align = 'center' colorbar_fig.title.text_font_style = 'normal' # ============================== profile_xrange = Range1d(start=style_parameter['profile_plot_xmin'], end=style_parameter['profile_plot_xmax']) profile_yrange = Range1d(start=style_parameter['profile_plot_ymax'], end=style_parameter['profile_plot_ymin']) profile_fig = Figure(plot_width=style_parameter['profile_plot_width'], plot_height=style_parameter['profile_plot_height'],\ x_range=profile_xrange, y_range=profile_yrange, tools=style_parameter['profile_tools'],\ title=style_parameter['profile_title']) profile_fig.line('vs', 'depth', source=selected_profile_data_bokeh, line_width=2, line_color='black') # ------------------------------ # add lat, lon profile_fig.rect([style_parameter['profile_label_box_x']], [style_parameter['profile_label_box_y']],\ width=style_parameter['profile_label_box_width'], height=style_parameter['profile_label_box_height'],\ width_units='screen', height_units='screen', color='#FFFFFF', line_width=1., line_color='black',\ level='underlay') profile_fig.text('x', 'y', 'lat_label', source=selected_profile_lat_label_bokeh) profile_fig.text('x', 'y', 'lon_label', source=selected_profile_lon_label_bokeh) # ------------------------------ # change style profile_fig.xaxis.axis_label = style_parameter['profile_xlabel'] profile_fig.xaxis.axis_label_text_font_style = 'normal' profile_fig.xaxis.axis_label_text_font_size = xlabel_fontsize profile_fig.xaxis.major_label_text_font_size = xlabel_fontsize profile_fig.yaxis.axis_label = style_parameter['profile_ylabel'] profile_fig.yaxis.axis_label_text_font_style = 'normal' profile_fig.yaxis.axis_label_text_font_size = xlabel_fontsize profile_fig.yaxis.major_label_text_font_size = xlabel_fontsize profile_fig.xgrid.grid_line_dash = [4, 2] profile_fig.ygrid.grid_line_dash = [4, 2] profile_fig.title.text_font_size = style_parameter['title_font_size'] profile_fig.title.align = 'center' profile_fig.title.text_font_style = 'normal' profile_fig.toolbar_location = 'above' profile_fig.toolbar_sticky = False profile_fig.toolbar.logo = None # ============================== profile_slider_callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\ grid_data_bokeh=grid_data_bokeh, \ profile_data_all_bokeh=profile_data_all_bokeh, \ selected_profile_data_bokeh=selected_profile_data_bokeh,\ selected_profile_lat_label_bokeh=selected_profile_lat_label_bokeh,\ selected_profile_lon_label_bokeh=selected_profile_lon_label_bokeh, \ all_profile_lat_label_bokeh=all_profile_lat_label_bokeh, \ all_profile_lon_label_bokeh=all_profile_lon_label_bokeh), code=""" var p_index = Math.round(cb_obj.value) var grid_data = grid_data_bokeh.data selected_dot_on_map_bokeh.data['lat'] = [grid_data['lat'][p_index]] selected_dot_on_map_bokeh.data['lon'] = [grid_data['lon'][p_index]] selected_dot_on_map_bokeh.data['index'] = [p_index] selected_dot_on_map_bokeh.change.emit() var profile_data_all = profile_data_all_bokeh.data selected_profile_data_bokeh.data['vs'] = profile_data_all['profile_vs_all'][p_index] selected_profile_data_bokeh.data['depth'] = profile_data_all['profile_depth_all'][p_index] selected_profile_data_bokeh.change.emit() var all_profile_lat_label = all_profile_lat_label_bokeh.data['profile_lat_label_list'] var all_profile_lon_label = all_profile_lon_label_bokeh.data['profile_lon_label_list'] selected_profile_lat_label_bokeh.data['lat_label'] = [all_profile_lat_label[p_index]] selected_profile_lon_label_bokeh.data['lon_label'] = [all_profile_lon_label[p_index]] selected_profile_lat_label_bokeh.change.emit() selected_profile_lon_label_bokeh.change.emit() """) profile_slider = Slider(start=0, end=nprofile-1, value=style_parameter['profile_default_index'], \ step=1, title=style_parameter['profile_slider_title'], \ width=style_parameter['profile_plot_width'], height=50) profile_slider_callback.args['profile_index'] = profile_slider profile_slider.js_on_change('value', profile_slider_callback) # ============================== simple_text_button_callback = CustomJS(args=dict(button_data_all_bokeh=button_data_all_bokeh,\ selected_dot_on_map_bokeh=selected_dot_on_map_bokeh), \ code=""" var index = selected_dot_on_map_bokeh.data['index'] var button_data_vs = button_data_all_bokeh.data['button_data_all_vs'][index] var button_data_vp = button_data_all_bokeh.data['button_data_all_vp'][index] var button_data_rho = button_data_all_bokeh.data['button_data_all_rho'][index] var button_data_top = button_data_all_bokeh.data['button_data_all_top'][index] var csvContent = "" var i = 0 var temp = csvContent temp += "# Layer Top (km) Vs(km/s) Vp(km/s) Rho(g/cm^3) \\n" while(button_data_vp[i]) { temp+=button_data_top[i].toPrecision(6) + " " + button_data_vs[i].toPrecision(4) + " " + \ button_data_vp[i].toPrecision(4) + " " + button_data_rho[i].toPrecision(4) + "\\n" i = i + 1 } const blob = new Blob([temp], { type: 'text/csv;charset=utf-8;' }) const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = 'vel_model.txt'; link.target = '_blank' link.style.visibility = 'hidden' link.dispatchEvent(new MouseEvent('click')) """) simple_text_button = Button( label=style_parameter['simple_text_button_label'], button_type='default', width=style_parameter['button_width']) simple_text_button.js_on_click(simple_text_button_callback) # ------------------------------ model96_button_callback = CustomJS(args=dict(button_data_all_bokeh=button_data_all_bokeh,\ selected_dot_on_map_bokeh=selected_dot_on_map_bokeh), \ code=""" var index = selected_dot_on_map_bokeh.data['index'] var lat = selected_dot_on_map_bokeh.data['lat'] var lon = selected_dot_on_map_bokeh.data['lon'] var button_data_vs = button_data_all_bokeh.data['button_data_all_vs'][index] var button_data_vp = button_data_all_bokeh.data['button_data_all_vp'][index] var button_data_rho = button_data_all_bokeh.data['button_data_all_rho'][index] var button_data_top = button_data_all_bokeh.data['button_data_all_top'][index] var csvContent = "" var i = 0 var temp = csvContent temp += "MODEL." + index + " \\n" temp += "ShearVelocityModel Lat: "+ lat +" Lon: " + lon + "\\n" temp += "ISOTROPIC \\n" temp += "KGS \\n" temp += "SPHERICAL EARTH \\n" temp += "1-D \\n" temp += "CONSTANT VELOCITY \\n" temp += "LINE08 \\n" temp += "LINE09 \\n" temp += "LINE10 \\n" temp += "LINE11 \\n" temp += " H(KM) VP(KM/S) VS(KM/S) RHO(GM/CC) QP QS ETAP ETAS FREFP FREFS \\n" while(button_data_vp[i+1]) { var thickness = button_data_top[i+1] - button_data_top[i] temp+=" " +thickness.toPrecision(6) + " " + button_data_vp[i].toPrecision(4) + " " + button_data_vs[i].toPrecision(4) \ + " " + button_data_rho[i].toPrecision(4) + " 0.00 0.00 0.00 0.00 1.00 1.00" + "\\n" i = i + 1 } const blob = new Blob([temp], { type: 'text/csv;charset=utf-8;' }) const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = 'vel_model96.txt'; link.target = '_blank' link.style.visibility = 'hidden' link.dispatchEvent(new MouseEvent('click')) """) model96_button = Button(label=style_parameter['model96_button_label'], button_type='default', width=style_parameter['button_width']) model96_button.js_on_click(model96_button_callback) # ============================== # annotating text annotating_fig01 = Div(text=style_parameter['annotating_html01'], \ width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height']) annotating_fig02 = Div(text=style_parameter['annotating_html02'],\ width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height']) # ============================== output_file(filename, title=style_parameter['html_title'], mode=style_parameter['library_source']) left_column = Column(depth_slider, map_view, colorbar_fig, annotating_fig01, width=style_parameter['left_column_width']) button_pannel = Row(simple_text_button, model96_button) right_column = Column(profile_slider, profile_fig, button_pannel, annotating_fig02, width=style_parameter['right_column_width']) layout = Row(left_column, right_column) save(layout)
def plot_iv(doc): init_calc = iv.iv_data(72, 800, 25, 45.9, 9.25, 37.2, 8.76, 7.47, 100) source = ColumnDataSource(data=init_calc[0]) source_translated = ColumnDataSource(data=init_calc[1]) res_source = ColumnDataSource(data=init_calc[2]) status_param = init_calc[3] print(status_param) plot = Figure(plot_width=600, plot_height=600, y_range=(-1, 10), x_range=(0, 60)) plot.xaxis.axis_label = 'Voltage (V)' plot.yaxis.axis_label = 'Current (I)' plot.scatter( 'x', 'y', source=source, line_width=3, line_alpha=0.6, ) plot.scatter( 'x', 'y', source=source_translated, line_width=3, line_alpha=0.6, line_color='red', ) sig_plot = Figure(plot_width=300, plot_height=300, x_axis_label='Series Resistance (Rs)', y_axis_label='Shunt Resistance (Rsh)', title='Calculated Resistances') sig_plot.scatter('x', 'y', source=res_source, line_width=10) vline = Span(location=0, dimension='height', line_color='red', line_width=3) # Horizontal line hline = Span(location=0, dimension='width', line_color='green', line_width=3) sig_plot.renderers.extend([vline, hline]) error_plt = Figure( plot_width=100, plot_height=50, toolbar_location=None, ) if (status_param.success == True): print('Successful Entry to the landing page') cite = Label(text='Success', render_mode='css', text_color='white', border_line_color='green', background_fill_color='green') else: print('Inside fail') cite = Label(text='False', render_mode='css', text_color='white', border_line_color='red', background_fill_color='red') error_plt.add_layout(cite) error_plt.add_layout( Label(text='Success', render_mode='css', text_color='white', border_line_color='green', background_fill_color='green')) Ncell_input = TextInput(value='72', title='No. of cells') Irrad_input = TextInput(value='800', title='Irradiance') Temp_input = TextInput(value='25', title='Temperature (Celcius)') Isc_input = TextInput(value='9.25', title='I_sc at STC') Im_input = TextInput(value='8.76', title='I_m') Voc_input = TextInput(value='45.9', title='V_oc') Vm_input = TextInput(value='37.2', title='V_m') Isc_N_input = TextInput(value='7.47', title='I_sc at NOTC(G=800, T=45C)') Data_input = TextInput(value='100', title='Data Size') submit = Button(label='Submit', button_type='success') download_button_STC = Button(label='Download data (STC)') download_button_GT = Button(label='Download data (Translated)') def get_inputs(): return (float(Ncell_input.value), float(Irrad_input.value), float(Temp_input.value), float(Voc_input.value), float(Isc_input.value), float(Vm_input.value), float(Im_input.value), float(Isc_N_input.value), float(Data_input.value)) def update_plot(event): N, G, T, V, I, Vm, Im, I_N, datapoints = get_inputs() print('#' * 30) print('Updating the plot') print('#' * 30) updated_data = iv.iv_data(N, G, T, V, I, Vm, Im, I_N, datapoints) source.data = updated_data[0] source_translated.data = updated_data[1] res_source.data = updated_data[2] global status_param status_param = updated_data[3] print(status_param) if (status_param.success == True): print('Inside success') cite = Label(text='Successful Parameter Extraction', render_mode='css', text_color='white', border_line_color='green', background_fill_color='green') else: print('Inside fail') cite = Label(text='Parameter extraction not converging', render_mode='css', text_color='white', border_line_color='red', background_fill_color='red') error_plt = Figure( plot_width=100, plot_height=50, toolbar_location=None, ) error_plt.add_layout(cite) layout.children[2].children[1] = error_plt def update_success(): if (status_param.success == True): print('Inside success') cite = Label(text='Success', render_mode='css', text_color='white', border_line_color='green', background_fill_color='green') else: print('Inside fail') cite = Label(text='False', render_mode='css', text_color='white', border_line_color='red', background_fill_color='red') error_plt = Figure( plot_width=100, plot_height=50, toolbar_location=None, ) error_plt.add_layout(cite) layout.children[2].children[1] = error_plt submit.on_click(update_plot) download_button_STC.js_on_click( CustomJS(args=dict(source=source), code=open(join(dirname(__file__), "download.js")).read())) download_button_GT.js_on_click( CustomJS(args=dict(source=source_translated), code=open(join(dirname(__file__), "download.js")).read())) #doc.add_periodic_callback(update_success, 1000) layout = row( plot, column(Ncell_input, Irrad_input, Temp_input, Isc_input, Im_input, Voc_input, Vm_input, Isc_N_input, Data_input, submit, download_button_STC, download_button_GT), column(sig_plot, error_plt)) return (layout)
from __future__ import print_function from bokeh.util.browser import view from bokeh.document import Document from bokeh.embed import file_html from bokeh.resources import INLINE from bokeh.models import CustomJS, WidgetBox from bokeh.models.widgets import ( Button, Toggle, Dropdown, CheckboxGroup, RadioGroup, CheckboxButtonGroup, RadioButtonGroup, ) button = Button(label="Button (enabled) - has click event", button_type="primary") button.js_on_click(CustomJS(code="console.log('button: click', this.toString())")) button_disabled = Button(label="Button (disabled) - no click event", button_type="primary", disabled=True) button_disabled.js_on_click(CustomJS(code="console.log('button_disabled: click', this.toString())")) toggle_inactive = Toggle(label="Toggle button (initially inactive)", button_type="success") toggle_inactive.js_on_click(CustomJS(code="console.log('toggle_inactive: ' + this.active, this.toString())")) toggle_active = Toggle(label="Toggle button (initially active)", button_type="success", active=True) toggle_active.js_on_click(CustomJS(code="console.log('toggle_active: ' + this.active, this.toString())")) menu = [("Item 1", "item_1_value"), ("Item 2", "item_2_value"), None, ("Item 3", "item_3_value")] dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu) dropdown.js_on_click(CustomJS(code="console.log('dropdown: ' + this.value, this.toString())")) dropdown_disabled = Dropdown(label="Dropdown button (disabled)", button_type="warning", disabled=True, menu=menu) dropdown_disabled.js_on_click(CustomJS(code="console.log('dropdown_disabled: ' + this.value, this.toString())"))
def create_vp_plot(data): ds = ColumnDataSource(data) # tools_to_show = "box_zoom, pan,save, hover, reset, wheel_zoom" var_label = '@{' + str(data.columns[0] + '}') try: var_tooltip_label = str(data.variable_metadata['long_name']) except KeyError: var_tooltip_label = str(data.variable_metadata['standard_name']) try: units = list({'unit', 'units'}.intersection(data.variable_metadata))[0] x_axis_label = " ".join( [var_tooltip_label, '[', data.variable_metadata[units], ']']) except IndexError: print('no units found') x_axis_label = var_tooltip_label p = figure(toolbar_location="above", tools="crosshair,box_zoom, pan,save, reset, wheel_zoom", x_axis_type="linear", x_axis_label=x_axis_label) p.sizing_mode = 'stretch_width' if len(data.dataset_metadata['dimension']) == 2: try: vertical_level, time_level = data.dataset_metadata['dimension'] except KeyError: vertical_level, time_level = ('obsdepth', 'time') else: vertical_level = data.dataset_metadata['dimension'][0] try: var_tooltip_label = str(data.variable_metadata['long_name']) except KeyError: var_tooltip_label = str(data.variable_metadata['standard_name']) # if " " in var_label: # var_label = '@{' + var_label + '}' # else: # var_label = var_label # var_label = var_label hover = HoverTool(tooltips=[("Depth", "@" + vertical_level), (var_tooltip_label, var_label)]) p.add_tools(hover) p.y_range.flipped = True p.min_border_left = 80 p.min_border_right = 80 p.background_fill_color = "SeaShell" p.background_fill_alpha = 0.5 line_renderer = p.line(data.columns[0], vertical_level, source=ds, line_alpha=0.6, color='RoyalBlue', ) point_renderer = p.circle(data.columns[0], vertical_level, source=ds, color='RoyalBlue', size=3, fill_alpha=0.5, fill_color='white', legend_label=data.columns[0], ) p.legend.location = "top_left" p.legend.click_policy = "hide" if len(list(data.columns)) >= 2: # Div html_text = get_datetime_string(list(data.columns)[0]) par = Div(text=html_text) # Slider Labels end_label = Div(text=list(data.columns)[-1]) start_label = Div(text=list(data.columns)[0]) # Buttons left_btn = Button(label='<', width=30) right_btn = Button(label='>', width=30) # Spacer sp = Spacer(width=50) # Slider Labels end_label = Div(text=list(data.columns)[-1].split('T')[0] + \ '<br>' \ + list(data.columns)[-1].split('T')[1], style={'text-align': 'right'}) start_label = Div(text=list(data.columns)[0].split('T')[0] + \ '<br>' \ + list(data.columns)[0].split('T')[1], style={'text-align': 'left'}) select = Select(title="Profile-record:", options=list(data.columns), value=list(data.columns)[0]) slider = Slider(title="Profile #", value=0, start=0, end=len(data.columns) - 1, step=1, show_value=True, tooltips=False) # select_handler = CustomJS(args=dict(line_renderer=line_renderer, point_renderer=point_renderer, slider=slider, par=par), code=""" line_renderer.glyph.x = {field: cb_obj.value}; point_renderer.glyph.x = {field: cb_obj.value}; slider.value = cb_obj.options.indexOf(cb_obj.value); var date_time = cb_obj.value.split("T"); var date = date_time[0]; var time = date_time[1]; par.text = `<ul style="text-align:left;"><li>Date: <b>`+date+`</b></li><li>Time: <b>`+time+`</b></li></ul>`; """) select.js_on_change('value', select_handler) slider_handler = CustomJS(args=dict(select=select), code=""" select.value = select.options[cb_obj.value]; """) slider.js_on_change('value', slider_handler) # Left button cb left_btn_args = dict(slider=slider) left_btn_handler = """ if(slider.value > slider.start) { slider.value = slider.value - 1; slider.change.emit(); } """ left_btn_callback = CustomJS(args=left_btn_args, code=left_btn_handler) left_btn.js_on_click(left_btn_callback) # Right button cb right_btn_args = dict(slider=slider) right_btn_handler = """ if(slider.value <= slider.end - 1) { slider.value = slider.value + 1; slider.change.emit(); } """ right_btn_callback = CustomJS(args=right_btn_args, code=right_btn_handler) right_btn.js_on_click(right_btn_callback) # buttons = row(left_btn, right_btn) # inputs = row(sp,slider,buttons, par) # return column(select, slider, p, par, sizing_mode="stretch_width") # return column(p, select, inputs, sizing_mode="stretch_width") # Set up layouts and add to document # slider_wrapper = layout([ # [slider], # [start_label, Spacer(sizing_mode="stretch_width"), end_label] # ]) slider_wrapper = layout([ [sp, sp, slider, left_btn, right_btn, par], [sp, start_label, sp, sp, end_label, sp, sp], ]) # buttons = row(left_btn, right_btn) # inputs = row(sp, start_label, left_btn, sp, slider, sp, right_btn, end_label, par) return column(select, p, slider_wrapper, sizing_mode="stretch_width") else: return column(p, sizing_mode="stretch_width")
## live time delta time_slider = Slider(start=0.1, end=24, value=4, step=.1, title="time delta (hours)", width=300) time_slider.on_change('value_throttled', refresh_plot) ## streaming refresh time stream_slider = Slider(start=1, end=60, value=10, step=1, title="refresh (seconds)", width=300) stream_slider.on_change('value_throttled', refresh_stream) ## force update_data() live_button = Button(width=130, margin=[15, 10, 15, 10], label="live", button_type="primary") live_button.on_click(plot_data) history_button = Button(width=130, margin=[15, 10, 15, 10], label="history", button_type="default") history_button.js_on_click(CustomJS(code=""" window.location.href='./history'; """)) tz_text = Paragraph(text=f"timezone: {timezone}", width=340) controls = column(row(live_button, history_button), instrum_select, time_slider, stream_slider, tz_text) # plot plot_data() stream = curdoc().add_periodic_callback(stream_data, stream_slider.value * 1000) # periodically refresh plot timeout = curdoc().add_periodic_callback(plot_data, 1024 * 1000)
bipot.sweep = "Anodic" def update_voltammetry_mode(attr, old, new): if new is 0: bipot.mode = bipot.SINGLE Voltage_WE2.visible = False elif new is 1: bipot.mode = bipot.DUAL Voltage_WE2.visible = True """Callback Assignments""" callback_update_plot = None callback_acquire_data_fake = None Connect.on_click(callback_Connect_eLoaD_BLE) Save.js_on_click(callback_Save) Start.on_click(callback_Start) Random_test.on_click(callback_Random_4) Gain.on_change('value', update_gain) Scan_rate.on_change('value', update_scan_rate) Segments.on_change('value', update_segments) Voltage_Start.on_change('value', update_v1_start) Voltage_WE2.on_change('value', update_v2) Voltage_Window.on_change('value', update_v1_window) Sweep_direction.on_change('active', update_sweep) Voltammetry_Mode.on_change('active', update_voltammetry_mode) #---------------------------# # Callbacks (Threads) # #---------------------------# #Plotting has no priority, also slower
def set_up_widgets(p, source, source1, source2, source3, source4, source5, df, all_dates, text_dsn): '''Set up widgets needed after an initial dsn is entered''' dsn = text_dsn.value # Set up widgets text_title = TextInput(title="Title:", value="{} Data".format(dsn)) text_save = TextInput(title="Save As:", value=dsn) max_for_dsn = df.timestamp.max() min_day = date_of_file( all_dates[0]) # works if sorted, needs to be formatted... max_day = date_of_file(all_dates[-1]) plus_one = max_for_dsn + timedelta(days=1) calendar = DatePicker(title="Day:", value=date(plus_one.year, plus_one.month, plus_one.day), max_date=max_day, min_date=min_day) button = Button(label="Update", button_type="success") columns = [ TableColumn(field="day", title="Date", formatter=DateFormatter(format="%m/%d/%Y")), TableColumn(field="hr", title="Avg HR", formatter=NumberFormatter(format="0.0")), TableColumn(field="o2", title="Avg O2", formatter=NumberFormatter(format="0.0")), TableColumn(field="temp", title="Avg Temp", formatter=NumberFormatter(format="0.0")) ] # table_title = Div(text="""Daily Averages:""", width=200) # daily_avg = get_daily_avgs(df_full) # data = { # 'day' : daily_avg.index, # 'hr' : daily_avg.heart_rate_avg, # 'o2' : daily_avg.oxygen_avg, # 'temp' : daily_avg.skin_temperature # } # table_source = ColumnDataSource(data=data) # data_table = DataTable(source=table_source, columns=columns, width=280, height=180, index_position=None) # export_png(data_table, filename="table.png") # save_table = Button(label='Save Daily Averages Table', button_type="primary") # Set up callbacks def update_title(attrname, old, new): p.title.text = text_title.value def update_save(attrname, old, new): p.tools[0].save_name = text_save.value def update(): text_dsn.value = text_dsn.value.strip(" ") # Get rid of extra space # Make sure time is valid update_data(p, source, source1, source2, source3, source4, source5, df, text_dsn.value, all_dates, date=str(calendar.value)) # Title/save update dsn text_title.value = text_dsn.value + " Data" text_save.value = text_dsn.value def save(): export_png(data_table, filename="{}_averages.png".format(text_dsn.value)) text_title.on_change('value', update_title) text_save.on_change('value', update_save) button.on_click(update) button.js_on_click(CustomJS(args=dict(p=p), code="""p.reset.emit()""")) # save_table.on_click(save) # Set up layouts and add to document inputs = widgetbox(text_title, text_save, calendar, button) #, table_title, data_table, save_table) curdoc().add_root(row(inputs, p, width=1300))
'salary': current.salary, 'years_experience': current.years_experience, } slider = RangeSlider(title="Max Salary", start=10000, end=110000, value=(10000, 50000), step=1000, format="0,0") slider.on_change('value', lambda attr, old, new: update()) button = Button(label="Download", button_type="success") button.js_on_click( CustomJS(args=dict(source=source), code=open(join(dirname(__file__), "download.js")).read())) columns = [ TableColumn(field="name", title="Employee Name"), TableColumn(field="salary", title="Income", formatter=NumberFormatter(format="$0,0.00")), TableColumn(field="years_experience", title="Experience (years)") ] data_table = DataTable(source=source, columns=columns, width=800) controls = column(slider, button) curdoc().add_root(row(controls, data_table))
console.log("Clicked button") timeslider.value = timeslider.start console.log("Set to beginning") step_length_ms = 300 num_steps = end-1 inc = 1 playback_interval = setInterval(function(){ timeslider.value = timeslider.value+inc; console.log(timeslider.value); }, step_length_ms) setTimeout(function(){clearInterval(playback_interval)}, step_length_ms*num_steps) """) playbutton.js_on_click(animateSlider) #################################################### BAR PLOT #################################################### fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries'] counts = [5, 3, 4, 2, 4, 6] barplot = figure(x_range=fruits, plot_height=250, title="Fruit Counts", toolbar_location=None, tools="") barplot.vbar(x=fruits, top=counts, width=0.9) barplot.xgrid.grid_line_color = None barplot.y_range.start = 0
from bokeh.models import CustomJS from bokeh.models.layouts import WidgetBox from bokeh.models.widgets import ( Button, Toggle, Dropdown, CheckboxGroup, RadioGroup, CheckboxButtonGroup, RadioButtonGroup, ) button = Button(label="Button (enabled) - has click event", button_type="primary") button.on_click(lambda: print('button: click')) button.js_on_click( CustomJS(code="console.log('button: click', this.toString())")) button_disabled = Button(label="Button (disabled) - no click event", button_type="primary", disabled=True) button_disabled.on_click(lambda: print('button_disabled: click')) button_disabled.js_on_click( CustomJS(code="console.log('button_disabled: click', this.toString())")) toggle_inactive = Toggle(label="Toggle button (initially inactive)", button_type="success") toggle_inactive.on_click(lambda value: print('toggle_inactive: %s' % value)) toggle_inactive.js_on_click( CustomJS( code="console.log('toggle_inactive: ' + this.active, this.toString())") )
def button2_cb(): global p global mysource start = mysource.data["time"][0] end = mysource.data["time"][-1] p.x_range = DataRange1d(start, end) def button3_cb(): print("button3 blick") p.line(x="time", y="y", source=mysource) #p.line([1,2,3,4],[1,2,3,4]) button = Button(label="stream") button.on_click(button_cb) button2 = Button(label="set something") button.on_click(button2_cb) button3 = Button(label="reset") button3.js_on_click(CustomJS(args=dict(p=p), code=""" p.reset.emit() """)) button3.on_click(button3_cb) curdoc().add_root(row([p, button, button2, button3])) curdoc().add_periodic_callback(update, 1000)