Beispiel #1
0
def get_select(desc, values, default=None, labels=None):  # pylint: disable=unused-argument
    if default is None:
        # by default, make all selections active
        default = list(range(len(values)))

    if labels is None:
        labels = list(map(str, values))

    # misuse tags to store values without mapping to str
    group = CheckboxButtonGroup(labels=labels, active=default, tags=values)
    group.on_change('active', on_filter_change)

    return group
Beispiel #2
0
class RetrievalResultPlot:
    def __init__(self, z, p, retrieval):
        self.z = z
        self.p = p

        y = z

        self.retrieval = retrieval
        self.retrieval_quantities = retrieval.retrieval_quantities

        self.figures = dict([(rq,
                              ProfilePlot(self.z,
                                          self.p,
                                          rq.name,
                                          "rq_plot_" + rq.name,
                                          width=400))
                             for rq in self.retrieval_quantities])
        self.status = dict([(rq, True) for rq in self.retrieval_quantities])
        self.sources_x = dict([(rq, []) for rq in self.retrieval_quantities])
        self.sources_xa = dict([(rq, []) for rq in self.retrieval_quantities])
        self.sources_x0 = dict([(rq, []) for rq in self.retrieval_quantities])
        self.lines_x = dict([(rq, []) for rq in self.retrieval_quantities])
        self.lines_xa = dict([(rq, []) for rq in self.retrieval_quantities])
        self.lines_x0 = dict([(rq, []) for rq in self.retrieval_quantities])

        #
        # Get retrieval results as list.
        #
        if type(self.retrieval.results) is list:
            results = self.retrieval.results
        else:
            results = [self.retrieval.results]

        self.colors = Inferno[len(results) + 2][1:-1]

        #
        # Add plots for each retrieval quantity.
        #

        for i, rr in enumerate(self.retrieval.results):
            for rq in self.retrieval_quantities:
                xa = rr.get_result(rq, attribute="xa")
                x = rr.get_result(rq, attribute="x")
                x0 = rr.get_result(rq, attribute="x0")

                if xa is None:
                    continue

                self.sources_x[rq] += [ColumnDataSource(data=dict(x=x, y=y))]
                self.sources_xa[rq] += [ColumnDataSource(data=dict(x=xa, y=y))]
                self.sources_x0[rq] += [ColumnDataSource(data=dict(x=x0, y=y))]

                fig = self.figures[rq]
                fig.add_quantity(x,
                                 line_kwargs=dict(line_color=self.colors[i],
                                                  line_width=2))
                if i == 0:
                    fig.add_quantity(xa,
                                     line_kwargs=dict(
                                         line_dash="dashed",
                                         line_color=self.colors[i],
                                         line_width=2))
                #fig.add_quantity(x0, line_kwargs = dict(line_dash  = "dashdot",
                #                                        line_color = self.colors[i],
                #                                        line_width = 2))

        self.plots = row(*[self.figures[k].doc for k in self.figures],
                         name="retrieval_quantities")

        def update_plots(attrname, old, new):
            state = self.checks.active
            plots = curdoc().get_model_by_name('retrieval_quantities')

            print(state)
            for i, rq in enumerate(self.retrieval_quantities):
                if i in state:
                    if self.status[rq] == True:
                        continue
                    else:
                        self.status[rq] = True
                        plots.children.append(self.figures[rq].doc)
                else:
                    if self.status[rq] == False:
                        continue
                    else:
                        fig = curdoc().get_model_by_name("rq_plot_" + rq.name)
                        self.status[rq] = False
                        plots.children.remove(fig)

            print(plots.children)
            print(self.status)

        #
        # Checkbox button to hide plots
        #

        labels = [rq.name for rq in self.retrieval.retrieval_quantities]
        active = list(range(len(labels)))
        self.checks = CheckboxButtonGroup(labels=labels, active=active)
        self.checks.on_change("active", update_plots)

    def make_doc(self):
        title = Div(text="<h2>Retrieved quantities</h2>")
        c = column(title, self.checks, self.plots)
        return c
Beispiel #3
0
PROPERTY_TYPE_SELECT = MultiSelect(title='Property Type:',
                                   value=[],
                                   options=FILTER_PROPERTIES[c.PT])
PROPERTY_TYPE_SELECT.on_change(c.VALUE, update_data)

NEIGHBOURHOOD_SELECT = MultiSelect(title='Neighbourhood:',
                                   value=[],
                                   options=FILTER_PROPERTIES[c.NC])
NEIGHBOURHOOD_SELECT.on_change(c.VALUE, update_data)

# Checkbox Group (Multi Select) Widgets
NG_LIST = FILTER_PROPERTIES[c.NGC]
NEIGHBOURHOOD_GROUP = CheckboxButtonGroup(labels=NG_LIST,
                                          active=list(range(0, len(NG_LIST))))
NEIGHBOURHOOD_GROUP.on_change(c.ACTIVE, update_data)

RT_LIST = FILTER_PROPERTIES[c.RT]
ROOM_TYPE_GROUP = CheckboxButtonGroup(labels=FILTER_PROPERTIES[c.RT],
                                      active=list(range(0, len(RT_LIST))))
ROOM_TYPE_GROUP.on_change(c.ACTIVE, update_data)

# Single Select Widgets
PROPERTY_TYPE_HOST = Select(title='Property Type:',
                            value=c.EMPTY_STRING,
                            options=[c.EMPTY_STRING] + FILTER_PROPERTIES[c.PT])
N_HOST = Select(title='Neighbourhood:',
                value=c.EMPTY_STRING,
                options=[c.EMPTY_STRING] + FILTER_PROPERTIES[c.NC])
NG_HOST = Select(title='Neighbourhood Group:',
                 value=c.EMPTY_STRING,
            other_source.data = empty_dict

        if 1 in button_group.active:
            speed_source.data = gen_dict(speed)
        else:
            speed_source.data = empty_dict

        if 2 in button_group.active:
            drunk_source.data = gen_dict(drunk)
        else:
            drunk_source.data = empty_dict


slider.on_change('value', update_hour)
toggle.on_change('active', update_hour)
button_group.on_change('active', update_hour)

callback = CustomJS(args=dict(other=other_circles,
                              speed=speed_circles,
                              drunk=drunk_circles),
                    code="""
        other.glyph.radius = { value: cb_obj.get('value')*125 }
        other.data_source.trigger('change')

        speed.glyph.radius = { value: cb_obj.get('value')*125 }
        speed.data_source.trigger('change')

        drunk.glyph.radius = { value: cb_obj.get('value')*125 }
        drunk.data_source.trigger('change')
""")
Beispiel #5
0
    ('Num.of.flights: ', '@number_of_flights'),
])

tooltips_selected = OrderedDict([
    ('Name', '@name'),
])

p.add_tools( HoverTool(tooltips=tooltips, renderers=[circle_renderer]))
p.add_tools( HoverTool(tooltips=tooltips_selected, renderers=[circle_renderer_selected]))


controls = [reviews, genre, min_year, alpha]
for control in controls:
    control.on_change('value', lambda attr, old, new: update())

cb_group_le10.on_change('active', lambda attr, old, new: update())
cb_group_10_15.on_change('active', lambda attr, old, new: update())
cb_group_15_20.on_change('active', lambda attr, old, new: update())
cb_group_20_25.on_change('active', lambda attr, old, new: update())
cb_group_ge25.on_change('active', lambda attr, old, new: update())
controls.append(cb_group_le10)
controls.append(cb_group_10_15)
controls.append(cb_group_15_20)
controls.append(cb_group_20_25)
controls.append(cb_group_ge25)

source_hist = ColumnDataSource({'top': [], 'left': [], 'right': []})
p2 = figure(plot_width=800, plot_height=350)
p2.title.text = 'Histogram'
p2.quad(top='top', bottom=0, left='left', right='right', alpha=0.4, source=source_hist)
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
Beispiel #7
0
                    })

checkbox_button = CheckboxButtonGroup(
    labels=['Show x-axis label', 'Show y-axis label'])


def checkbox_button_click(attr, old, new):
    active_checkbox = checkbox_button.active  ##Getting checkbox value in list

    ## Get first checkbox value and show x-axis label

    if len(active_checkbox) != 0 and (0 in active_checkbox):
        plot_figure.xaxis.axis_label = 'X-Axis'
    else:
        plot_figure.xaxis.axis_label = None

    ## Get second checkbox value and show y-axis label

    if len(active_checkbox) != 0 and (1 in active_checkbox):
        plot_figure.yaxis.axis_label = 'Y-Axis'
    else:
        plot_figure.yaxis.axis_label = None


checkbox_button.on_change('active', checkbox_button_click)

layout = row(checkbox_button, plot_figure)

curdoc().add_root(layout)
curdoc().title = "Checkbox Button Bokeh Server"
Beispiel #8
0
                s = outputNames[ka]

                outputs[s]['dsource'].data = dict(x=x, y=y)
                outputs[s]['lsource'].data = dict(x=[x[0]], y=[y[0]])
                outputs[s]['psource'].data = dict(x=numpy.append(x, x[::-1]),
                                                  y=numpy.append(lowerband, upperband[::-1]))

                outputs[s]['line'].visible = False
                outputs[s]['patch'].visible = False
                outputs[s]['label'].visible = False

    vsource.data = dict(x=[slider[last['slider']]['value'], slider[last['slider']]['value']],
                        y=[last['vmin'], last['vmax']])

for s in slider:
    slider[s]['slider'].on_change('value', lambda attrname, old, new, nets=nets, svar=s: update_data(attrname, old, new, nets,  svar))
out_buttons.on_change('active', lambda attrname, old, new, nets=nets, svar='__buttons__': update_data(attrname, old, new, nets, svar))
cases_dropdown.on_change('value', lambda attrname, old, new, nets=nets, svar='__cases__': update_data(attrname, old, new, nets, svar))

# Set up layouts and add to document
if len(cases)>1:
    controls = widgetbox(*([cases_dropdown]+[slider[s]['slider'] for s in sorted(list(slider.keys()),key=lambda x:mapper_function(x).lower())]))
else:
    controls = widgetbox(*[slider[s]['slider'] for s in sorted(list(slider.keys()),key=lambda x:mapper_function(x).lower())])
curdoc().add_root(out_buttons)
curdoc().add_root(row(controls, column(plot, hold_button)))
curdoc().title = title

# refresh before starting
update_data(None, None, None, nets, list(slider.keys())[0])
def density_tab(doc):

	def make_dataset(param_list, range_start, range_end, bandwidth):

		xs = []
		ys = []
		colors = []
		labels = []

		for i, param in enumerate(param_list):
			subset = webs[param].drop(labels=[8]).transpose().iloc[0]

			# subset = subset.between(range_start,range_end)

			# subset= webs[(webs[param] >= range_start) and (webs[para] <= range_end)]

			# subset = webs[param].between(range_start,range_end)

			#subset = subset[subset[param].between(range_start,range_end)]

			kde = gaussian_kde(subset, bw_method=bandwidth)

			# Evenly space x values
			x = np.linspace(range_start, range_end, 100)

			y = kde.pdf(x)

			# Append the values to plot
			xs.append(list(x))
			ys.append(list(y))

			# Append the colors and label
			colors.append(para_colors[i])
			labels.append(param)

		new_src = ColumnDataSource(data={'x':xs, 'y':ys,
										'color':colors, 'label':labels})
		return new_src

	def make_plot(src):
		p = figure(plot_width = 700, plot_height = 700,
					title = 'Density Plot Parameters',
					x_axis_label = 'Performance Metric Probability Distribution', y_axis_label = 'Number of Websites')
		p.multi_line('x', 'y', color = 'color', legend = 'label',
					line_width = 3, source = src)
		hover = HoverTool(tooltips=[('parameter','@label'),
									#('Distribution', '@src'),
									#('Density', '@ys'),
									],
						  line_policy = 'next')

		p.add_tools(hover)

		p = style(p)
		return p

	def update(attr, old, new):

		parameters_to_plot = [param_selection.labels[i] for i in
							  param_selection.active]
		if bandwidth_choose.active == []:
			bandwidth = None
		else:
			bandwidth = bandwidth_select.value

		new_src = make_dataset(parameters_to_plot,
									range_start = range_select.value[0],
									range_end = range_select.value[1],
									bandwidth = bandwidth)
		src.data.update(new_src.data)

	def style(p):

		# Title
		p.title.align = 'center'
		p.title.text_font_size = '20pt'
		p.title.text_font = 'serif'

		# Axis titles
		p.xaxis.axis_label_text_font_size = '14pt'
		p.xaxis.axis_label_text_font_style = 'bold'
		p.yaxis.axis_label_text_font_size = '14pt'
		p.yaxis.axis_label_text_font_style = 'bold'

		# Tick labels
		p.xaxis.major_label_text_font_size = '12pt'
		p.yaxis.major_label_text_font_size = '12pt'
		return p

	# Parameter and colors
	available_parameters = list(webs.columns.get_level_values(0).drop_duplicates())[1:]
	available_parameters.sort()

	para_colors = Category20_16
	para_colors.sort()

	param_selection = CheckboxGroup(labels = available_parameters,
									active = [0,1])
	param_selection.on_change('active', update)

	range_select = RangeSlider(start = 0, end = 1, value = (0,1),
							   step = 0.0025, title = 'Range of Parameter')
	range_select.on_change('value', update)

	initial_parameter = [param_selection.labels[i] for
						i in param_selection.active]
	# Bandwidth of kernel
	bandwidth_select = Slider(start = 0.1, end = 5,
							  step = 0.1, value = 0.5,
							  title = 'Bandwidth for Density Plot')
	bandwidth_select.on_change('value', update)

	bandwidth_choose = CheckboxButtonGroup(
						labels = ['Choose Bandwidth (Else Auto)'], active = [])
	bandwidth_choose.on_change('active', update)

	# Make the density data source
	src = make_dataset(initial_parameter,
						range_start = range_select.value[0],
						range_end = range_select.value[1],
						bandwidth = bandwidth_select.value)

	p = make_plot(src)

	p = style(p)

	controls = WidgetBox(param_selection, range_select,
						bandwidth_select, bandwidth_choose)

	layout = row(controls, p)
	doc.title = "Density"
	doc.add_root(layout)
    """
    if 0 in nyquist_button.active:
        reveal_solution()
    else:
        hide_solution()


# create plots
initialize()

# add callback behaviour
f_input.on_change('value', on_function_changed)
sample_fun_input_f.on_change('value', sample_fun_input_changed)
t0_input.on_change('value', on_parameters_changed)
N_input.on_change('value', on_parameters_changed)
nyquist_button.on_change('active', on_nyquist_button_changed)

#Description
description_filename = join(dirname(__file__), "description.html")

description = LatexDiv(text=open(description_filename).read(),
                       render_as_text=False,
                       width=1250)

# create layout
controls = [f_input, sample_fun_input_f, t0_input, N_input, nyquist_button]
controls_box = widgetbox(controls, width=650)  # all controls
curdoc().add_root(
    column(
        description,
        row(column(plot_original, controls_box),
plot_figure = figure(title='Checkbox Button Group',plot_height=450, plot_width=600,
              tools="save,reset", toolbar_location="below")

plot_figure.scatter('x', 'y', source=source, size=10,color={'field': 'z', 'transform': color_mapper})

checkbox_button = CheckboxButtonGroup(labels=['Show x-axis label','Show y-axis label'])

def checkbox_button_click(attr,old,new):
    active_checkbox=checkbox_button.active ##Getting checkbox value in list

    ## Get first checkbox value and show x-axis label

    if len(active_checkbox)!=0 and (0 in active_checkbox):
        plot_figure.xaxis.axis_label='X-Axis'
    else:
        plot_figure.xaxis.axis_label = None

    ## Get second checkbox value and show y-axis label

    if len(active_checkbox)!=0 and (1 in active_checkbox):
        plot_figure.yaxis.axis_label='Y-Axis'
    else:
        plot_figure.yaxis.axis_label = None

checkbox_button.on_change('active',checkbox_button_click)

layout=row(checkbox_button, plot_figure)

curdoc().add_root(layout)
curdoc().title = "Checkbox Button Bokeh Server"
Beispiel #12
0
Set1 = Set1[7]

# Create plots, set title
title = "Sequence distribution of sample: {}".format(stats['sampleid'])
p1 = make_plot_hist(title, stats)
p2 = make_plot_kde(title, stats)

# Spacer for correct alignments
leftmetrics = Spacer(width=500)
topwidgetbox = Spacer(width=400, height=50)
topmetrics = Spacer(width=600, height=70)

# First set of radiobuttons
text1 = PreText(text="View histogram for:")
buttons1 = CheckboxButtonGroup(name="Active plots:", labels=["Reads", "Contigs", "Genes, complete", "Genes, truncated"], active=[0])
buttons1.on_change('active',update_hist)

# Second set of radiobuttons
text2 = PreText(text="View KD-estimation for:")
buttons2 = CheckboxButtonGroup(name="Active plots:", labels=["Reads", "Contigs", "Genes, complete", "Genes, truncated"], active=[0])
buttons2.on_change('active',update_kde)

# Sliders and selection inputs
sliderx = Slider(title="X scale", value=0, start=-100, end=100, step=10)
yaxis = Select(title="Y axis type", value='log', options=['log','linear'])

# Gather controls in controls, put the two figures in tabs and create csv table
controls = column(topwidgetbox, widgetbox(text1, buttons1, yaxis, sliderx, text2, buttons2, width=400))
tabs = Tabs(tabs=[p1, p2])

# Metric table (right)
Beispiel #13
0
    def update(attr, old, new):
        def sort(attr, old, new):
            did = False
            res = []
            temp = []
            for i in checkbox_button_group.active:
                for line in range(df_new.shape[0]):
                    #print(df_new[df_new.columns.values[4]][line])
                    if button_labels[i] == df_new[
                            df_new.columns.values[4]][line]:
                        temp.append(line)
                        did = True
                    if button_labels[i] == df_new[
                            df_new.columns.values[5]][line]:
                        temp.append(line)
                        did = True

            if did == True:
                res = [
                    item for item in df_new.index.values.tolist()
                    if item not in temp
                ]
            df_new_new = df_new.drop(res).reset_index(drop=True)
            source.data = {
                df_new_new.columns.values[column]:
                df_new_new[df_new_new.columns.values[column]]
                for column in range(df_new_new.shape[1])
            }

        df_new = df_initial
        for i in checkbox_group.active:
            df = pd.read_excel(join(dirname(__file__), 'docs', files[i]),
                               skiprows=5,
                               usecols=[0, 1, 3, 4, 5, 6, 9])
            df[df.columns.values[6]] = df[df.columns.values[6]].fillna('')
            for line in df[df.columns.values[6]].index:
                if df.loc[line, df.columns.values[6]] != '':
                    df.loc[line,
                           df.columns.values[6]] = ' '.join(directions[i][1:])
            df_new = pd.merge(df_new,
                              df,
                              how='outer',
                              on=df.columns.values.tolist())
            df_new = df_new.sort_values(by=df_new.columns.values[6],
                                        ascending=False)
            df_new = df_new.drop_duplicates(df_new.columns.values[1],
                                            keep='first')
            df_new = df_new.sort_values(by=df_new.columns.values[0])
        df_new = df_new.drop(df_new.columns.values[0],
                             axis=1).reset_index(drop=True)

        button_labels = pd.concat([
            df_new[df_new.columns.values[4]], df_new[df_new.columns.values[5]]
        ]).unique().tolist()
        del button_labels[button_labels.index('')]
        checkbox_button_group = CheckboxButtonGroup(labels=button_labels,
                                                    width=1000)
        control_button = widgetbox(checkbox_button_group)
        l.children[0] = control_button
        checkbox_button_group.on_change('active', sort)

        source.data = {
            df_new.columns.values[column]:
            df_new[df_new.columns.values[column]]
            for column in range(df_new.shape[1])
        }
Beispiel #14
0
            line_source.data["num_shootings"][i] for i in selected
        ]
        num_offenses = [line_source.data["num_offenses"][i] for i in selected]
        mean_line.location = mean(num_offenses)
        mean_shootings.location = mean(num_shootings)


def update_graphs():
    update_heatmap()
    update_top10()
    update_line()


selected_months.on_change('value_throttled',
                          lambda attr, old, new: update_graphs())
selected_districts.on_change('active', lambda attr, old, new: update_graphs())
line_source.selected.on_change('indices',
                               lambda attr, old, new: update_selection())

update_graphs()

controls = row(widgetbox(selected_months),
               widgetbox(selected_districts),
               sizing_mode='stretch_width')

curdoc().add_root(controls)

curdoc().add_root(
    layout([[num_offenses, num_shootings], [top10, heatmap]],
           sizing_mode='stretch_width'))
Beispiel #15
0
animals = data['animal'].unique().tolist()
animals.sort()
animal_select = Select(title='Animal', options=animals, value=animals[0])
animal_select.on_change('value', lambda attr, old, new: animal_changed())

date_select = MultiSelect(title='Dates', size=10)
date_select.on_change('value', lambda attr, old, new: update_plot())

groupby_options = {
    'masker level': 'masker_level',
    'sensation level': 'sens_level',
    'target center frequency': 'target_fc',
}

groupby_select = CheckboxButtonGroup(labels=list(groupby_options.keys()), active=[0])
groupby_select.on_change('active', lambda attr, old, new: update_plot())


animal_trials = ColumnDataSource()
animal_trials_plot = figure(title='number of trials', tools="", width=1000,
                             height=150)
animal_trials_plot.xaxis.axis_label = 'Session'
animal_trials_plot.yaxis.axis_label = 'Number of trials'
animal_trials_plot.line('session', 'trials', source=animal_trials)

animal_fa = ColumnDataSource()
animal_fa_plot = figure(title='False alarm rate', tools="", width=1000,
                        height=150, y_range=(0, 1))
animal_fa_plot.xaxis.axis_label = 'Session'
animal_fa_plot.yaxis.axis_label = 'FA rate'
animal_fa_plot.line('session', 'fa', source=animal_fa)
Beispiel #16
0
    def modify_plot(doc):     
        #######################################################################################################################
        # Update the checkbox values
        
        ## Checkbox for hour of the day values
        def update_hour(atrr, old, new): 
            data_to_plot = [int(checkbox_group_hour.labels[i]) for i in checkbox_group_hour.active] 
            new_data = data[data.pickup_hour.isin(data_to_plot)]
            source.data = dict(
                latp = new_data[latitude_column[0]].tolist(),
                lonp = new_data[longitude_column[0]].tolist(),
                latd = new_data[latitude_column[1]].tolist(),
                lond = new_data[longitude_column[1]].tolist(),
                size = new_data[size_column].tolist(),
                color = new_data[color_column].tolist()
            )
            
        hours = data.pickup_hour.unique().tolist()
        hours.sort()
        str1 = [str(i) for i in hours]
        checkbox_group_hour = CheckboxButtonGroup(labels = str1, active=[0, 1])
        
        ## Adding a slider for the hour also as another option
        
        def update_hour_slider(atrr, old, new): 
            hour = slider_hour.value
            new_data = data[data.pickup_hour == hour]
            source.data = dict(
                latp = new_data[latitude_column[0]].tolist(),
                lonp = new_data[longitude_column[0]].tolist(),
                latd = new_data[latitude_column[1]].tolist(),
                lond = new_data[longitude_column[1]].tolist(),
                size = new_data[size_column].tolist(),
                color = new_data[color_column].tolist()
                )

        slider_hour = Slider(title='Hour of the day', start = 0, end = 23, step = 1, value = 17)
        
        ## Checkbox for weekday values
        def update_weekday(atrr, old, new): 
            data_to_plot = [checkbox_group_weekday.labels[i] for i in checkbox_group_weekday.active] 
            new_data = data[data.pickup_weekday.isin(data_to_plot)]
            source.data = dict(
                latp = new_data[latitude_column[0]].tolist(),
                lonp = new_data[longitude_column[0]].tolist(),
                latd = new_data[latitude_column[1]].tolist(),
                lond = new_data[longitude_column[1]].tolist(),
                size = new_data[size_column].tolist(),
                color = new_data[color_column].tolist()
            )
            
        weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
        checkbox_group_weekday = CheckboxButtonGroup(labels = weekdays, active=[0, 1])
        
        
        #########################################################################################################
        # CREATE THE PLOT
        # Assigning map options
        map_options = GMapOptions(lat = data[latitude_column[0]].mean(), lng = data[longitude_column[0]].mean(), 
                                      map_type = 'roadmap', zoom = 10)
        
        assert len(latitude_column) == len(longitude_column), "latitude and longitude list should be same"
            
        # Pickup plot
        plotP = GMapPlot(x_range = Range1d(), y_range = Range1d(), map_options = map_options, 
                        plot_width = 500, plot_height = 400)
        
        # Dropoff plot
        plotD = GMapPlot(x_range = Range1d(), y_range = Range1d(), map_options = map_options, 
                        plot_width = 500, plot_height = 400)
        
        # ASsigning the Google API keys
        plotP.api_key = api_key
        plotD.api_key = api_key
        
        source = ColumnDataSource(
            data = dict(
                latp = data[latitude_column[0]].tolist(),
                lonp = data[longitude_column[0]].tolist(),
                latd = data[latitude_column[1]].tolist(),
                lond = data[longitude_column[1]].tolist(),
                size = data[size_column].tolist(),
                color = data[color_column].tolist()
            )
        )
        
        plotP.title.text = "NYC taxi pickup locations {}".format(
                                                      data.pickup_datetime.dt.year.unique().tolist())
        
        plotD.title.text = "NYC taxi dropoff locations {}".format(
                                                      data.dropoff_datetime.dt.year.unique().tolist())
        #RdYlGn5, RdBu4
        # Add color mapper for the color bar
        color_mapper = LinearColorMapper(palette = "RdYlGn8", low = np.percentile(data[color_column], 1), 
                                                           high = np.percentile(data[color_column], 99))
        
        # Add the scatter points
        circleP = Circle(x = "lonp", y = "latp", fill_alpha = 0.8, size = "size", 
                        fill_color={'field': 'color', 'transform': color_mapper}, line_color = None)

        circleD = Circle(x = "lond", y = "latd", fill_alpha = 0.8, size = "size", 
                        fill_color={'field': 'color', 'transform': color_mapper}, line_color = None)
        
        # Only the user selected scatter points will be highlighted
        #selected_circle = Circle(fill_alpha = 1) #, fill_color = "firebrick", line_color = None)
        nonselected_circle = Circle(fill_alpha = 0.1, fill_color = "grey", line_color= None)
        ###############
        
        plotP.add_glyph(source, circleP, nonselection_glyph = nonselected_circle)#, selection_glyph = selected_circle, )
        plotD.add_glyph(source, circleD, nonselection_glyph = nonselected_circle)#, selection_glyph = selected_circle, )
        
        
        # Add color bar. ADding to only one of the plots becaue their x and y axis are scaled together
        color_bar = ColorBar(color_mapper = color_mapper, ticker = BasicTicker(),
                             label_standoff = 12, border_line_color = None, location = (0,0), title = color_column)
        
        plotD.add_layout(color_bar, 'right')
        
        # Add the basic interactive tools
        plotP.add_tools(PanTool(), WheelZoomTool(), BoxSelectTool(), ResetTool(), SaveTool())
        plotD.add_tools(PanTool(), WheelZoomTool(), BoxSelectTool(), ResetTool(), SaveTool())
        #########################################################################################################
        
        #plots.append(plot)
            
        # Keep the ranges same for both plots so that when one plot is zoomed in the other will too
        # For now switching this off because when zooming in or panning one plot the points in other plot were swaying off
        # their original geo locations
        #plotD.x_range = plotP.x_range
        #plotD.y_range = plotP.y_range
        
        # Create the layout with widgets and actual plots
        if slider:
            rowl = row(plotP, plotD)
            layout = column(checkbox_group_weekday, widgetbox(slider_hour), rowl)#)
            slider_hour.on_change('value', update_hour_slider)
        else:
            rowl = row(plotP, plotD)
            layout = column(checkbox_group_hour, checkbox_group_weekday, rowl)#row(plotP, plotD))
            checkbox_group_hour.on_change('active', update_hour)
        
        checkbox_group_weekday.on_change('active', update_weekday)
        
        # add the layout to curdoc
        doc.add_root(layout)
        #output_file("../data/interim/images/interactive_JFK_trips.html")
        output_notebook()
Beispiel #17
0
def modify_doc(symbol):

    global nearestExpiryDate
    df = optionUtility.getProcessedOptionChainData(symbol)
    nearestExpiryDate = optionUtility.nearestExpiryDate
    expiryDates = [nearestExpiryDate, "All Above"]
    latestData[symbol] = df
    allSources = {}

    def update(attr, old, new):
        selected_expiryDate = expiry_date_selector.value
        #selectedStrikePrice = allUniqueStrikePrice[strikePrice_selector.active];
        activeStrikePriceIndexes = strikePrice_selector.active
        # will take top of selected if number is greater
        activeStrikePriceIndexes.sort()
        # starting one will be selected
        index = 0
        selectedStrikeNumber = activeStrikePriceIndexes.__sizeof__()
        processed = []
        #print(activeStrikePriceIndexes)
        for source in allWorkingSources:
            if (index > (selectedStrikeNumber - 1)):
                break
                # in case less number of strike is selected don't through error
            strikeIndex = activeStrikePriceIndexes[index]
            selectedStrikePrice = allUniqueStrikePrice[strikeIndex]
            new_src = 0
            new_src = dashboard_tool.make_dataset(int(selectedStrikePrice),
                                                  selected_expiryDate, symbol,
                                                  isForTodayOnly)
            source.data.update(new_src.data)
            index = index + 1
            processed.append(selectedStrikePrice)
            #print(selectedStrikePrice) # shown prices are these..
        #print(processed, activeStrikePriceIndexes);

    allUniqueStrikePrice = latestData[symbol]['strikePrice'].apply(
        str).unique().tolist()
    ATMStrikeindex = int(np.floor(len(allUniqueStrikePrice) / 2))
    expiry_date_selector = Select(value=nearestExpiryDate, options=expiryDates)
    strikePrice_selector = CheckboxButtonGroup(
        labels=allUniqueStrikePrice,
        active=[
            ATMStrikeindex - 2, ATMStrikeindex - 1, ATMStrikeindex,
            ATMStrikeindex + 1, ATMStrikeindex + 2
        ])  # in case multiple to be shown at once#
    # strikePrice_selector = RadioButtonGroup(
    #     labels=allUniqueStrikePrice, active=ATMStrikeindex);
    #
    strikePrice_selector.on_change('active', update)
    expiry_date_selector.on_change('value', update)

    selected_expiryDate = expiry_date_selector.value
    #selectedStrikePrice = allUniqueStrikePrice[strikePrice_selector.active];

    activeStrikePriceIndexes = strikePrice_selector.active
    allplots = []
    allWorkingSources = []
    for oneindex in activeStrikePriceIndexes:
        selectedStrikePrice = allUniqueStrikePrice[oneindex]
        src = dashboard_tool.make_dataset(int(selectedStrikePrice),
                                          selected_expiryDate, symbol,
                                          isForTodayOnly)
        allSources[selectedStrikePrice] = src
        allWorkingSources.append(src)
        p = dashboard_tool.make_plot(src, selectedStrikePrice)
        allplots.append(p)
    allplotslayout = column(allplots)
    layout = column(row(expiry_date_selector, strikePrice_selector),
                    allplotslayout)
    tab = Panel(child=layout, title=symbol)
    return tab
Beispiel #18
0
            other_source.data = empty_dict

        if 1 in button_group.active:
            speed_source.data = gen_dict(speed)
        else:
            speed_source.data = empty_dict

        if 2 in button_group.active:
            drunk_source.data = gen_dict(drunk)
        else:
            drunk_source.data = empty_dict


slider.on_change('value', update_hour)
toggle.on_change('active', update_hour)
button_group.on_change('active', update_hour)

callback = CustomJS(args=dict(other=other_circles, speed=speed_circles, drunk=drunk_circles), code="""
        other.glyph.radius = { value: cb_obj.get('value')*125 }
        other.data_source.trigger('change')

        speed.glyph.radius = { value: cb_obj.get('value')*125 }
        speed.data_source.trigger('change')

        drunk.glyph.radius = { value: cb_obj.get('value')*125 }
        drunk.data_source.trigger('change')
""")

size_slider = Slider(title="Dot Size", start=1, end=100, orientation="horizontal",
                value=100, step=1, callback=callback, callback_policy="mouseup")
Beispiel #19
0
        types, counts = zip(*sorted(Counter(cars_ar).items()))
        for i, type_check in enumerate(car_type_list):
            if type_check in types:
                count_changer.append(counts[holdcount])
                holdcount += 1
            else:
                count_changer.append(0)
        int_source.data['Count'] = count_changer
    else:
        int_source.data['Count'] = np.zeros(7)


p.xaxis.major_tick_line_color = None
p.xaxis.minor_tick_line_color = None

p.yaxis.major_tick_line_color = None
p.yaxis.minor_tick_line_color = None

p.xaxis.major_label_text_font_size = '0pt'
p.yaxis.major_label_text_font_size = '0pt'
"""


p_int.yaxis.major_label_orientation = np.pi / 2
p_int.xaxis.major_label_orientation = -np.pi / 6
p_int.xaxis.axis_label = 'Traffic Through Select Points (For Given)'
"""
source.on_change('selected', update)
CBG.on_change('active', update)
curdoc().add_root(column(row(p, p_int), CBG))
Beispiel #20
0
    TableColumn(field="rank", title="Global Rank"),
    TableColumn(field="company", title="Company"),
    TableColumn(field="freq", title="Frequency Count"),
    TableColumn(field="london", title="London Registered Company")
]

table = DataTable(source=table_source,
                  columns=columns,
                  width=800,
                  sortable=True)
years.on_change('value', lambda attr, old, new: update())
months.on_change('value', lambda attr, old, new: update())
data_choice.on_change('active', lambda attr, old, new: update())
cities.on_change('value', lambda attr, old, new: update())
cities2.on_change('value', lambda attr, old, new: update())
london_filter.on_change('active', lambda attr, old, new: update())
topic_choice.on_change('value', lambda attr, old, new: update())
search_word.on_change('value', lambda attr, old, new: update())
pca_slider.on_change('value', lambda attr, old, new: update())

update()

#############
# Structure #
#############

saplot = column(space, sa_title, p, select)
head = row(data_choice, sizing_mode='scale_width')
b1 = row(london_filter, london_filter_txt)
b = column(space, space, sacity_title, sizing_mode='scale_width')
mid = row(cities, cities2)
Beispiel #21
0
class Query:
    def __init__(self, sources, categories, dvhs, rad_bio, roi_viewer,
                 time_series, correlation, regression, mlc_analyzer,
                 custom_title, data_tables):
        self.sources = sources
        self.selector_categories = categories.selector
        self.range_categories = categories.range
        self.correlation_variables = categories.correlation_variables
        self.dvhs = dvhs
        self.rad_bio = rad_bio
        self.roi_viewer = roi_viewer
        self.time_series = time_series
        self.correlation = correlation
        self.regression = regression
        self.mlc_analyzer = mlc_analyzer

        self.uids = {n: [] for n in GROUP_LABELS}
        self.allow_source_update = True
        self.current_dvh = []
        self.anon_id_map = []
        self.colors = itertools.cycle(palette)

        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        # Selection Filter UI objects
        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        category_options = list(self.selector_categories)
        category_options.sort()

        # Add Current row to source
        self.add_selector_row_button = Button(label="Add Selection Filter",
                                              button_type="primary",
                                              width=200)
        self.add_selector_row_button.on_click(self.add_selector_row)

        # Row
        self.selector_row = Select(value='1',
                                   options=['1'],
                                   width=50,
                                   title="Row")
        self.selector_row.on_change('value', self.selector_row_ticker)

        # Category 1
        self.select_category1 = Select(value="ROI Institutional Category",
                                       options=category_options,
                                       width=300,
                                       title="Category 1")
        self.select_category1.on_change('value', self.select_category1_ticker)

        # Category 2
        cat_2_sql_table = self.selector_categories[
            self.select_category1.value]['table']
        cat_2_var_name = self.selector_categories[
            self.select_category1.value]['var_name']
        self.category2_values = DVH_SQL().get_unique_values(
            cat_2_sql_table, cat_2_var_name)
        self.select_category2 = Select(value=self.category2_values[0],
                                       options=self.category2_values,
                                       width=300,
                                       title="Category 2")
        self.select_category2.on_change('value', self.select_category2_ticker)

        # Misc
        self.delete_selector_row_button = Button(label="Delete",
                                                 button_type="warning",
                                                 width=100)
        self.delete_selector_row_button.on_click(self.delete_selector_row)
        self.group_selector = CheckboxButtonGroup(
            labels=["Group 1", "Group 2"], active=[0], width=180)
        self.group_selector.on_change('active',
                                      self.ensure_selector_group_is_assigned)
        self.selector_not_operator_checkbox = CheckboxGroup(labels=['Not'],
                                                            active=[])
        self.selector_not_operator_checkbox.on_change(
            'active', self.selector_not_operator_ticker)

        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        # Range Filter UI objects
        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        category_options = list(self.range_categories)
        category_options.sort()

        # Add Current row to source
        self.add_range_row_button = Button(label="Add Range Filter",
                                           button_type="primary",
                                           width=200)
        self.add_range_row_button.on_click(self.add_range_row)

        # Row
        self.range_row = Select(value='', options=[''], width=50, title="Row")
        self.range_row.on_change('value', self.range_row_ticker)

        # Category
        self.select_category = Select(value=options.SELECT_CATEGORY_DEFAULT,
                                      options=category_options,
                                      width=240,
                                      title="Category")
        self.select_category.on_change('value', self.select_category_ticker)

        # Min and max
        self.text_min = TextInput(value='', title='Min: ', width=150)
        self.text_min.on_change('value', self.min_text_ticker)
        self.text_max = TextInput(value='', title='Max: ', width=150)
        self.text_max.on_change('value', self.max_text_ticker)

        # Misc
        self.delete_range_row_button = Button(label="Delete",
                                              button_type="warning",
                                              width=100)
        self.delete_range_row_button.on_click(self.delete_range_row)
        self.group_range = CheckboxButtonGroup(labels=["Group 1", "Group 2"],
                                               active=[0],
                                               width=180)
        self.group_range.on_change('active',
                                   self.ensure_range_group_is_assigned)
        self.range_not_operator_checkbox = CheckboxGroup(labels=['Not'],
                                                         active=[])
        self.range_not_operator_checkbox.on_change(
            'active', self.range_not_operator_ticker)

        self.query_button = Button(label="Query",
                                   button_type="success",
                                   width=100)
        self.query_button.on_click(self.update_data)

        # define Download button and call download.js on click
        menu = [("All Data", "all"), ("Lite", "lite"), ("Only DVHs", "dvhs"),
                ("Anonymized DVHs", "anon_dvhs")]
        self.download_dropdown = Dropdown(label="Download",
                                          button_type="default",
                                          menu=menu,
                                          width=100)
        self.download_dropdown.callback = CustomJS(
            args=dict(source=sources.dvhs,
                      source_rxs=sources.rxs,
                      source_plans=sources.plans,
                      source_beams=sources.beams),
            code=open(join(dirname(dirname(__file__)), "download.js")).read())

        self.layout = column(
            Div(text="<b>DVH Analytics v%s</b>" % '0.5.10'),
            row(custom_title['1']['query'], Spacer(width=50),
                custom_title['2']['query'], Spacer(width=50),
                self.query_button, Spacer(width=50), self.download_dropdown),
            Div(text="<b>Query by Categorical Data</b>",
                width=1000), self.add_selector_row_button,
            row(self.selector_row, Spacer(width=10), self.select_category1,
                self.select_category2,
                self.group_selector, self.delete_selector_row_button,
                Spacer(width=10), self.selector_not_operator_checkbox),
            data_tables.selection_filter, Div(text="<hr>", width=1050),
            Div(text="<b>Query by Numerical Data</b>",
                width=1000), self.add_range_row_button,
            row(self.range_row,
                Spacer(width=10), self.select_category, self.text_min,
                Spacer(width=30), self.text_max, Spacer(width=30),
                self.group_range, self.delete_range_row_button,
                Spacer(width=10), self.range_not_operator_checkbox),
            data_tables.range_filter)

    def get_query(self, group=None):

        if group:
            if group == 1:
                active_groups = [1]
            elif group == 2:
                active_groups = [2]
        else:
            active_groups = [1, 2]

        # Used to accumulate lists of query strings for each table
        # Will assume each item in list is complete query for that SQL column
        queries = {'Plans': [], 'Rxs': [], 'Beams': [], 'DVHs': []}

        # Used to group queries by variable, will combine all queries of same variable with an OR operator
        # e.g., queries_by_sql_column['Plans'][key] = list of strings, where key is sql column
        queries_by_sql_column = {
            'Plans': {},
            'Rxs': {},
            'Beams': {},
            'DVHs': {}
        }

        for active_group in active_groups:

            # Accumulate categorical query strings
            data = self.sources.selectors.data
            for r in data['row']:
                r = int(r)
                if data['group'][r - 1] in {active_group, 3}:
                    var_name = self.selector_categories[data['category1'][
                        r - 1]]['var_name']
                    table = self.selector_categories[data['category1'][
                        r - 1]]['table']
                    value = data['category2'][r - 1]
                    if data['not_status'][r - 1]:
                        operator = "!="
                    else:
                        operator = "="

                    query_str = "%s %s '%s'" % (var_name, operator, value)

                    # Append query_str in query_by_sql_column
                    if var_name not in queries_by_sql_column[table].keys():
                        queries_by_sql_column[table][var_name] = []
                    queries_by_sql_column[table][var_name].append(query_str)

            # Accumulate numerical query strings
            data = self.sources.ranges.data
            for r in data['row']:
                r = int(r)
                if data['group'][r - 1] in {active_group, 3}:
                    var_name = self.range_categories[data['category'][
                        r - 1]]['var_name']
                    table = self.range_categories[data['category'][r -
                                                                   1]]['table']

                    value_low, value_high = data['min'][r - 1], data['max'][r -
                                                                            1]
                    if data['category'][r - 1] != 'Simulation Date':
                        value_low, value_high = float(value_low), float(
                            value_high)

                    # Modify value_low and value_high so SQL interprets values as dates, if applicable
                    if var_name in {'sim_study_date', 'birth_date'}:
                        value_low = "'%s'" % value_low
                        value_high = "'%s'" % value_high

                    if data['not_status'][r - 1]:
                        query_str = var_name + " NOT BETWEEN " + str(
                            value_low) + " AND " + str(value_high)
                    else:
                        query_str = var_name + " BETWEEN " + str(
                            value_low) + " AND " + str(value_high)

                    # Append query_str in query_by_sql_column
                    if var_name not in queries_by_sql_column[table]:
                        queries_by_sql_column[table][var_name] = []
                    queries_by_sql_column[table][var_name].append(query_str)

        for table in queries:
            temp_str = []
            for v in queries_by_sql_column[table].keys():
                # collect all constraints for a given sql column into one list
                q_by_sql_col = [q for q in queries_by_sql_column[table][v]]

                # combine all constraints for a given sql column with 'or' operators
                temp_str.append("(%s)" % ' OR '.join(q_by_sql_col))

            queries[table] = ' AND '.join(temp_str)
            print(str(datetime.now()),
                  '%s = %s' % (table, queries[table]),
                  sep=' ')

        # Get a list of UIDs that fit the plan, rx, and beam query criteria.  DVH query criteria will not alter the
        # list of UIDs, therefore dvh_query is not needed to get the UID list
        print(str(datetime.now()), 'getting uids', sep=' ')
        uids = get_study_instance_uids(plans=queries['Plans'],
                                       rxs=queries['Rxs'],
                                       beams=queries['Beams'])['union']

        # uids: a unique list of all uids that satisfy the criteria
        # queries['DVHs']: the dvh query string for SQL
        return uids, queries['DVHs']

    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # Functions for Querying by categorical data
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    def update_select_category2_values(self):
        new = self.select_category1.value
        table_new = self.selector_categories[new]['table']
        var_name_new = self.selector_categories[new]['var_name']
        new_options = DVH_SQL().get_unique_values(table_new, var_name_new)
        self.select_category2.options = new_options
        self.select_category2.value = new_options[0]

    def ensure_selector_group_is_assigned(self, attr, old, new):
        if not self.group_selector.active:
            self.group_selector.active = [-old[0] + 1]
        self.update_selector_source()

    def update_selector_source(self):
        if self.selector_row.value:
            r = int(self.selector_row.value) - 1
            group = sum([i + 1 for i in self.group_selector.active])
            group_labels = ['1', '2', '1 & 2']
            group_label = group_labels[group - 1]
            not_status = ['', 'Not'
                          ][len(self.selector_not_operator_checkbox.active)]

            patch = {
                'category1': [(r, self.select_category1.value)],
                'category2': [(r, self.select_category2.value)],
                'group': [(r, group)],
                'group_label': [(r, group_label)],
                'not_status': [(r, not_status)]
            }
            self.sources.selectors.patch(patch)

    def add_selector_row(self):
        if self.sources.selectors.data['row']:
            temp = self.sources.selectors.data

            for key in list(temp):
                temp[key].append('')
            temp['row'][-1] = len(temp['row'])

            self.sources.selectors.data = temp
            new_options = [str(x + 1) for x in range(len(temp['row']))]
            self.selector_row.options = new_options
            self.selector_row.value = new_options[-1]
            self.select_category1.value = options.SELECT_CATEGORY1_DEFAULT
            self.select_category2.value = self.select_category2.options[0]
            self.selector_not_operator_checkbox.active = []
        else:
            self.selector_row.options = ['1']
            self.selector_row.value = '1'
            self.sources.selectors.data = dict(row=[1],
                                               category1=[''],
                                               category2=[''],
                                               group=[],
                                               group_label=[''],
                                               not_status=[''])
        self.update_selector_source()

        clear_source_selection(self.sources, 'selectors')

    def select_category1_ticker(self, attr, old, new):
        self.update_select_category2_values()
        self.update_selector_source()

    def select_category2_ticker(self, attr, old, new):
        self.update_selector_source()

    def selector_not_operator_ticker(self, attr, old, new):
        self.update_selector_source()

    def selector_row_ticker(self, attr, old, new):
        if self.sources.selectors.data[
                'category1'] and self.sources.selectors.data['category1'][-1]:
            r = int(self.selector_row.value) - 1
            category1 = self.sources.selectors.data['category1'][r]
            category2 = self.sources.selectors.data['category2'][r]
            group = self.sources.selectors.data['group'][r]
            not_status = self.sources.selectors.data['not_status'][r]

            self.select_category1.value = category1
            self.select_category2.value = category2
            self.group_selector.active = [[0], [1], [0, 1]][group - 1]
            if not_status:
                self.selector_not_operator_checkbox.active = [0]
            else:
                self.selector_not_operator_checkbox.active = []

    def update_selector_row_on_selection(self, attr, old, new):
        if new:
            self.selector_row.value = self.selector_row.options[min(new)]

    def delete_selector_row(self):
        if self.selector_row.value:
            new_selectors_source = self.sources.selectors.data
            index_to_delete = int(self.selector_row.value) - 1
            new_source_length = len(
                self.sources.selectors.data['category1']) - 1

            if new_source_length == 0:
                clear_source_data(self.sources, 'selector')
                self.selector_row.options = ['']
                self.selector_row.value = ''
                self.group_selector.active = [0]
                self.selector_not_operator_checkbox.active = []
                self.select_category1.value = options.SELECT_CATEGORY1_DEFAULT
                self.select_category2.value = self.select_category2.options[0]
            else:
                for key in list(new_selectors_source):
                    new_selectors_source[key].pop(index_to_delete)

                for i in range(index_to_delete, new_source_length):
                    new_selectors_source['row'][i] -= 1

                self.selector_row.options = [
                    str(x + 1) for x in range(new_source_length)
                ]
                if self.selector_row.value not in self.selector_row.options:
                    self.selector_row.value = self.selector_row.options[-1]
                self.sources.selectors.data = new_selectors_source

            clear_source_selection(self.sources, 'selectors')

    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # Functions for Querying by numerical data
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    def add_range_row(self):
        if self.sources.ranges.data['row']:
            temp = self.sources.ranges.data

            for key in list(temp):
                temp[key].append('')
            temp['row'][-1] = len(temp['row'])
            self.sources.ranges.data = temp
            new_options = [str(x + 1) for x in range(len(temp['row']))]
            self.range_row.options = new_options
            self.range_row.value = new_options[-1]
            self.select_category.value = options.SELECT_CATEGORY_DEFAULT
            self.group_range.active = [0]
            self.range_not_operator_checkbox.active = []
        else:
            self.range_row.options = ['1']
            self.range_row.value = '1'
            self.sources.ranges.data = dict(row=['1'],
                                            category=[''],
                                            min=[''],
                                            max=[''],
                                            min_display=[''],
                                            max_display=[''],
                                            group=[''],
                                            group_label=[''],
                                            not_status=[''])

        self.update_range_titles(reset_values=True)
        self.update_range_source()

        clear_source_selection(self.sources, 'ranges')

    def update_range_source(self):
        if self.range_row.value:
            table = self.range_categories[self.select_category.value]['table']
            var_name = self.range_categories[
                self.select_category.value]['var_name']

            r = int(self.range_row.value) - 1
            group = sum([i + 1 for i in self.group_range.active
                         ])  # a result of 3 means group 1 & 2
            group_labels = ['1', '2', '1 & 2']
            group_label = group_labels[group - 1]
            not_status = ['',
                          'Not'][len(self.range_not_operator_checkbox.active)]

            if self.select_category.value == 'Simulation Date':
                min_value = str(parse(self.text_min.value).date())
                min_display = min_value

                max_value = str(parse(self.text_max.value).date())
                max_display = max_value
            else:

                try:
                    min_value = float(self.text_min.value)
                except ValueError:
                    try:
                        min_value = float(DVH_SQL().get_min_value(
                            table, var_name))
                    except TypeError:
                        min_value = ''

                try:
                    max_value = float(self.text_max.value)
                except ValueError:
                    try:
                        max_value = float(DVH_SQL().get_max_value(
                            table, var_name))
                    except TypeError:
                        max_value = ''

                if min_value or min_value == 0.:
                    min_display = "%s %s" % (
                        str(min_value), self.range_categories[
                            self.select_category.value]['units'])
                else:
                    min_display = 'None'

                if max_value or max_value == 0.:
                    max_display = "%s %s" % (
                        str(max_value), self.range_categories[
                            self.select_category.value]['units'])
                else:
                    max_display = 'None'

            patch = {
                'category': [(r, self.select_category.value)],
                'min': [(r, min_value)],
                'max': [(r, max_value)],
                'min_display': [(r, min_display)],
                'max_display': [(r, max_display)],
                'group': [(r, group)],
                'group_label': [(r, group_label)],
                'not_status': [(r, not_status)]
            }
            self.sources.ranges.patch(patch)

            self.group_range.active = [[0], [1], [0, 1]][group - 1]
            self.text_min.value = str(min_value)
            self.text_max.value = str(max_value)

    def update_range_titles(self, reset_values=False):
        table = self.range_categories[self.select_category.value]['table']
        var_name = self.range_categories[
            self.select_category.value]['var_name']
        min_value = DVH_SQL().get_min_value(table, var_name)
        self.text_min.title = 'Min: ' + str(
            min_value) + ' ' + self.range_categories[
                self.select_category.value]['units']
        max_value = DVH_SQL().get_max_value(table, var_name)
        self.text_max.title = 'Max: ' + str(
            max_value) + ' ' + self.range_categories[
                self.select_category.value]['units']

        if reset_values:
            self.text_min.value = str(min_value)
            self.text_max.value = str(max_value)

    def range_row_ticker(self, attr, old, new):
        if self.sources.ranges.data['category'] and self.sources.ranges.data[
                'category'][-1]:
            r = int(new) - 1
            category = self.sources.ranges.data['category'][r]
            min_new = self.sources.ranges.data['min'][r]
            max_new = self.sources.ranges.data['max'][r]
            group = self.sources.ranges.data['group'][r]
            not_status = self.sources.ranges.data['not_status'][r]

            self.allow_source_update = False
            self.select_category.value = category
            self.text_min.value = str(min_new)
            self.text_max.value = str(max_new)
            self.update_range_titles()
            self.group_range.active = [[0], [1], [0, 1]][group - 1]
            self.allow_source_update = True
            if not_status:
                self.range_not_operator_checkbox.active = [0]
            else:
                self.range_not_operator_checkbox.active = []

    def select_category_ticker(self, attr, old, new):
        if self.allow_source_update:
            self.update_range_titles(reset_values=True)
            self.update_range_source()

    def min_text_ticker(self, attr, old, new):
        if self.allow_source_update:
            self.update_range_source()

    def max_text_ticker(self, attr, old, new):
        if self.allow_source_update:
            self.update_range_source()

    def range_not_operator_ticker(self, attr, old, new):
        if self.allow_source_update:
            self.update_range_source()

    def delete_range_row(self):
        if self.range_row.value:
            new_range_source = self.sources.ranges.data
            index_to_delete = int(self.range_row.value) - 1
            new_source_length = len(self.sources.ranges.data['category']) - 1

            if new_source_length == 0:
                clear_source_data(self.sources, 'ranges')
                self.range_row.options = ['']
                self.range_row.value = ''
                self.group_range.active = [0]
                self.range_not_operator_checkbox.active = []
                self.select_category.value = options.SELECT_CATEGORY_DEFAULT
                self.text_min.value = ''
                self.text_max.value = ''
            else:
                for key in list(new_range_source):
                    new_range_source[key].pop(index_to_delete)

                for i in range(index_to_delete, new_source_length):
                    new_range_source['row'][i] -= 1

                self.range_row.options = [
                    str(x + 1) for x in range(new_source_length)
                ]
                if self.range_row.value not in self.range_row.options:
                    self.range_row.value = self.range_row.options[-1]
                self.sources.ranges.data = new_range_source

            clear_source_selection(self.sources, 'ranges')

    def ensure_range_group_is_assigned(self, attr, old, new):
        if not self.group_range.active:
            self.group_range.active = [-old[0] + 1]
        self.update_range_source()

    def update_range_row_on_selection(self, attr, old, new):
        if new:
            self.range_row.value = self.range_row.options[min(new)]

    # main update function
    def update_data(self):
        global BAD_UID
        BAD_UID = {n: [] for n in GROUP_LABELS}
        old_update_button_label = self.query_button.label
        old_update_button_type = self.query_button.button_type
        self.query_button.label = 'Updating...'
        self.query_button.button_type = 'warning'
        print(str(datetime.now()),
              'Constructing query for complete dataset',
              sep=' ')
        uids, dvh_query_str = self.get_query()
        print(str(datetime.now()), 'getting dvh data', sep=' ')
        self.current_dvh = DVH(uid=uids, dvh_condition=dvh_query_str)
        if self.current_dvh.count:
            print(str(datetime.now()),
                  'initializing source data ',
                  self.current_dvh.query,
                  sep=' ')
            self.time_series.update_current_dvh_group(
                self.update_dvh_data(self.current_dvh))
            if not options.LITE_VIEW and \
                    (options.OPTIONAL_TABS['Time-Series'] or options.OPTIONAL_TABS['Correlation'] or
                     options.OPTIONAL_TABS['Regression']):
                print(str(datetime.now()), 'updating correlation data')
                self.correlation.update_data(self.correlation_variables)
                print(str(datetime.now()), 'correlation data updated')
            self.dvhs.update_source_endpoint_calcs()
            if not options.LITE_VIEW:
                self.dvhs.calculate_review_dvh()
                self.rad_bio.initialize()
                self.time_series.y_axis.value = ''
                self.roi_viewer.update_mrn()
                try:
                    self.mlc_analyzer.update_mrn()
                except:
                    pass
        else:
            print(str(datetime.now()), 'empty dataset returned', sep=' ')
            self.query_button.label = 'No Data'
            self.query_button.button_type = 'danger'
            time.sleep(2.5)

        self.query_button.label = old_update_button_label
        self.query_button.button_type = old_update_button_type

    # updates beam ColumnSourceData for a given list of uids
    def update_beam_data(self, uids):

        cond_str = "study_instance_uid in ('" + "', '".join(uids) + "')"
        beam_data = QuerySQL('Beams', cond_str)

        groups = self.get_group_list(beam_data.study_instance_uid)

        anon_id = [
            self.anon_id_map[beam_data.mrn[i]]
            for i in range(len(beam_data.mrn))
        ]

        attributes = [
            'mrn', 'beam_dose', 'beam_energy_min', 'beam_energy_max',
            'beam_mu', 'beam_mu_per_deg', 'beam_mu_per_cp', 'beam_name',
            'beam_number', 'beam_type', 'scan_mode', 'scan_spot_count',
            'control_point_count', 'fx_count', 'fx_grp_beam_count',
            'fx_grp_number', 'gantry_start', 'gantry_end', 'gantry_rot_dir',
            'gantry_range', 'gantry_min', 'gantry_max', 'collimator_start',
            'collimator_end', 'collimator_rot_dir', 'collimator_range',
            'collimator_min', 'collimator_max', 'couch_start', 'couch_end',
            'couch_rot_dir', 'couch_range', 'couch_min', 'couch_max',
            'radiation_type', 'ssd', 'treatment_machine'
        ]
        for i in ['min', 'mean', 'median', 'max']:
            for j in ['area', 'complexity', 'cp_mu', 'x_perim', 'y_perim']:
                attributes.append('%s_%s' % (j, i))
        data = {attr: getattr(beam_data, attr) for attr in attributes}
        data['anon_id'] = anon_id
        data['group'] = groups
        if len(data['group']) != len(data['anon_id']):
            data['group'] = ['unknown'] * len(data['anon_id'])
        data['uid'] = beam_data.study_instance_uid

        self.sources.beams.data = data

    # updates plan ColumnSourceData for a given list of uids
    def update_plan_data(self, uids):

        cond_str = "study_instance_uid in ('" + "', '".join(uids) + "')"
        plan_data = QuerySQL('Plans', cond_str)

        # Determine Groups
        groups = self.get_group_list(plan_data.study_instance_uid)

        anon_id = [
            self.anon_id_map[plan_data.mrn[i]]
            for i in range(len(plan_data.mrn))
        ]

        attributes = [
            'mrn', 'age', 'birth_date', 'dose_grid_res', 'fxs',
            'patient_orientation', 'patient_sex', 'physician', 'rx_dose',
            'sim_study_date', 'total_mu', 'tx_modality', 'tx_site',
            'heterogeneity_correction', 'complexity'
        ]
        data = {attr: getattr(plan_data, attr) for attr in attributes}
        data['anon_id'] = anon_id
        data['group'] = groups
        data['uid'] = plan_data.study_instance_uid

        self.sources.plans.data = data

    # updates rx ColumnSourceData for a given list of uids
    def update_rx_data(self, uids):

        cond_str = "study_instance_uid in ('" + "', '".join(uids) + "')"
        rx_data = QuerySQL('Rxs', cond_str)

        groups = self.get_group_list(rx_data.study_instance_uid)

        anon_id = [
            self.anon_id_map[rx_data.mrn[i]] for i in range(len(rx_data.mrn))
        ]

        attributes = [
            'mrn', 'plan_name', 'fx_dose', 'rx_percent', 'fxs', 'rx_dose',
            'fx_grp_count', 'fx_grp_name', 'fx_grp_number',
            'normalization_method', 'normalization_object'
        ]
        data = {attr: getattr(rx_data, attr) for attr in attributes}
        data['anon_id'] = anon_id
        data['group'] = groups
        data['uid'] = rx_data.study_instance_uid

        self.sources.rxs.data = data

    def get_group_list(self, uids):

        groups = []
        for r in range(len(uids)):
            if uids[r] in self.uids['1']:
                if uids[r] in self.uids['2']:
                    groups.append('Group 1 & 2')
                else:
                    groups.append('Group 1')
            else:
                groups.append('Group 2')

        return groups

    def update_dvh_data(self, dvh):

        dvh_group_1, dvh_group_2 = [], []
        group_1_constraint_count, group_2_constraint_count = group_constraint_count(
            self.sources)

        if group_1_constraint_count and group_2_constraint_count:
            extra_rows = 12
        elif group_1_constraint_count or group_2_constraint_count:
            extra_rows = 6
        else:
            extra_rows = 0

        print(str(datetime.now()), 'updating dvh data', sep=' ')
        line_colors = [
            color
            for j, color in itertools.izip(range(dvh.count +
                                                 extra_rows), self.colors)
        ]

        x_axis = np.round(
            np.add(np.linspace(0, dvh.bin_count, dvh.bin_count) / 100., 0.005),
            3)

        print(str(datetime.now()), 'beginning stat calcs', sep=' ')

        if self.dvhs.radio_group_dose.active == 1:
            stat_dose_scale = 'relative'
            x_axis_stat = dvh.get_resampled_x_axis()
        else:
            stat_dose_scale = 'absolute'
            x_axis_stat = x_axis
        if self.dvhs.radio_group_volume.active == 0:
            stat_volume_scale = 'absolute'
        else:
            stat_volume_scale = 'relative'

        print(str(datetime.now()), 'calculating patches', sep=' ')

        if group_1_constraint_count == 0:
            self.uids['1'] = []
            clear_source_data(self.sources, 'patch_1')
            clear_source_data(self.sources, 'stats_1')
        else:
            print(str(datetime.now()), 'Constructing Group 1 query', sep=' ')
            self.uids['1'], dvh_query_str = self.get_query(group=1)
            dvh_group_1 = DVH(uid=self.uids['1'], dvh_condition=dvh_query_str)
            self.uids['1'] = dvh_group_1.study_instance_uid
            stat_dvhs_1 = dvh_group_1.get_standard_stat_dvh(
                dose_scale=stat_dose_scale, volume_scale=stat_volume_scale)

            if self.dvhs.radio_group_dose.active == 1:
                x_axis_1 = dvh_group_1.get_resampled_x_axis()
            else:
                x_axis_1 = np.add(
                    np.linspace(0, dvh_group_1.bin_count,
                                dvh_group_1.bin_count) / 100., 0.005)

            self.sources.patch_1.data = {
                'x_patch':
                np.append(x_axis_1, x_axis_1[::-1]).tolist(),
                'y_patch':
                np.append(stat_dvhs_1['q3'], stat_dvhs_1['q1'][::-1]).tolist()
            }
            self.sources.stats_1.data = {
                'x': x_axis_1.tolist(),
                'min': stat_dvhs_1['min'].tolist(),
                'q1': stat_dvhs_1['q1'].tolist(),
                'mean': stat_dvhs_1['mean'].tolist(),
                'median': stat_dvhs_1['median'].tolist(),
                'q3': stat_dvhs_1['q3'].tolist(),
                'max': stat_dvhs_1['max'].tolist()
            }
        if group_2_constraint_count == 0:
            self.uids['2'] = []
            clear_source_data(self.sources, 'patch_2')
            clear_source_data(self.sources, 'stats_2')

        else:
            print(str(datetime.now()), 'Constructing Group 2 query', sep=' ')
            self.uids['2'], dvh_query_str = self.get_query(group=2)
            dvh_group_2 = DVH(uid=self.uids['2'], dvh_condition=dvh_query_str)
            self.uids['2'] = dvh_group_2.study_instance_uid
            stat_dvhs_2 = dvh_group_2.get_standard_stat_dvh(
                dose_scale=stat_dose_scale, volume_scale=stat_volume_scale)

            if self.dvhs.radio_group_dose.active == 1:
                x_axis_2 = dvh_group_2.get_resampled_x_axis()
            else:
                x_axis_2 = np.add(
                    np.linspace(0, dvh_group_2.bin_count,
                                dvh_group_2.bin_count) / 100., 0.005)

            self.sources.patch_2.data = {
                'x_patch':
                np.append(x_axis_2, x_axis_2[::-1]).tolist(),
                'y_patch':
                np.append(stat_dvhs_2['q3'], stat_dvhs_2['q1'][::-1]).tolist()
            }
            self.sources.stats_2.data = {
                'x': x_axis_2.tolist(),
                'min': stat_dvhs_2['min'].tolist(),
                'q1': stat_dvhs_2['q1'].tolist(),
                'mean': stat_dvhs_2['mean'].tolist(),
                'median': stat_dvhs_2['median'].tolist(),
                'q3': stat_dvhs_2['q3'].tolist(),
                'max': stat_dvhs_2['max'].tolist()
            }

        print(str(datetime.now()), 'patches calculated', sep=' ')

        if self.dvhs.radio_group_dose.active == 0:
            x_scale = ['Gy'] * (dvh.count + extra_rows + 1)
            self.dvhs.plot.xaxis.axis_label = "Dose (Gy)"
        else:
            x_scale = ['%RxDose'] * (dvh.count + extra_rows + 1)
            self.dvhs.plot.xaxis.axis_label = "Relative Dose (to Rx)"
        if self.dvhs.radio_group_volume.active == 0:
            y_scale = ['cm^3'] * (dvh.count + extra_rows + 1)
            self.dvhs.plot.yaxis.axis_label = "Absolute Volume (cc)"
        else:
            y_scale = ['%Vol'] * (dvh.count + extra_rows + 1)
            self.dvhs.plot.yaxis.axis_label = "Relative Volume"

        # new_endpoint_columns = [''] * (dvh.count + extra_rows + 1)

        x_data, y_data = [], []
        for n in range(dvh.count):
            if self.dvhs.radio_group_dose.active == 0:
                x_data.append(x_axis.tolist())
            else:
                x_data.append(np.divide(x_axis, dvh.rx_dose[n]).tolist())
            if self.dvhs.radio_group_volume.active == 0:
                y_data.append(
                    np.multiply(dvh.dvh[:, n], dvh.volume[n]).tolist())
            else:
                y_data.append(dvh.dvh[:, n].tolist())

        y_names = ['Max', 'Q3', 'Median', 'Mean', 'Q1', 'Min']

        # Determine Population group (blue (1) or red (2))
        dvh_groups = []
        for r in range(len(dvh.study_instance_uid)):

            current_uid = dvh.study_instance_uid[r]
            current_roi = dvh.roi_name[r]

            if dvh_group_1:
                for r1 in range(len(dvh_group_1.study_instance_uid)):
                    if dvh_group_1.study_instance_uid[
                            r1] == current_uid and dvh_group_1.roi_name[
                                r1] == current_roi:
                        dvh_groups.append('Group 1')

            if dvh_group_2:
                for r2 in range(len(dvh_group_2.study_instance_uid)):
                    if dvh_group_2.study_instance_uid[
                            r2] == current_uid and dvh_group_2.roi_name[
                                r2] == current_roi:
                        if len(dvh_groups) == r + 1:
                            dvh_groups[r] = 'Group 1 & 2'
                        else:
                            dvh_groups.append('Group 2')

            if len(dvh_groups) < r + 1:
                dvh_groups.append('error')

        dvh_groups.insert(0, 'Review')

        for n in range(6):
            if group_1_constraint_count > 0:
                dvh.mrn.append(y_names[n])
                dvh.roi_name.append('N/A')
                x_data.append(x_axis_stat.tolist())
                current = stat_dvhs_1[y_names[n].lower()].tolist()
                y_data.append(current)
                dvh_groups.append('Group 1')
            if group_2_constraint_count > 0:
                dvh.mrn.append(y_names[n])
                dvh.roi_name.append('N/A')
                x_data.append(x_axis_stat.tolist())
                current = stat_dvhs_2[y_names[n].lower()].tolist()
                y_data.append(current)
                dvh_groups.append('Group 2')

        # Adjust dvh object to include stats data
        attributes = [
            'rx_dose', 'volume', 'surface_area', 'min_dose', 'mean_dose',
            'max_dose', 'dist_to_ptv_min', 'dist_to_ptv_median',
            'dist_to_ptv_mean', 'dist_to_ptv_max', 'dist_to_ptv_centroids',
            'ptv_overlap', 'cross_section_max', 'cross_section_median',
            'spread_x', 'spread_y', 'spread_z', 'toxicity_grade'
        ]
        if extra_rows > 0:
            dvh.study_instance_uid.extend(['N/A'] * extra_rows)
            dvh.institutional_roi.extend(['N/A'] * extra_rows)
            dvh.physician_roi.extend(['N/A'] * extra_rows)
            dvh.roi_type.extend(['Stat'] * extra_rows)
        if group_1_constraint_count > 0:
            for attr in attributes:
                getattr(dvh,
                        attr).extend(calc_stats(getattr(dvh_group_1, attr)))

        if group_2_constraint_count > 0:
            for attr in attributes:
                getattr(dvh,
                        attr).extend(calc_stats(getattr(dvh_group_2, attr)))

        # Adjust dvh object for review dvh
        dvh.dvh = np.insert(dvh.dvh, 0, 0, 1)
        dvh.count += 1
        dvh.mrn.insert(0, self.dvhs.select_reviewed_mrn.value)
        dvh.study_instance_uid.insert(0, '')
        dvh.institutional_roi.insert(0, '')
        dvh.physician_roi.insert(0, '')
        dvh.roi_name.insert(0, self.dvhs.select_reviewed_dvh.value)
        dvh.roi_type.insert(0, 'Review')
        dvh.rx_dose.insert(0, 0)
        dvh.volume.insert(0, 0)
        dvh.surface_area.insert(0, '')
        dvh.min_dose.insert(0, '')
        dvh.mean_dose.insert(0, '')
        dvh.max_dose.insert(0, '')
        dvh.dist_to_ptv_min.insert(0, 'N/A')
        dvh.dist_to_ptv_mean.insert(0, 'N/A')
        dvh.dist_to_ptv_median.insert(0, 'N/A')
        dvh.dist_to_ptv_max.insert(0, 'N/A')
        dvh.dist_to_ptv_centroids.insert(0, 'N/A')
        dvh.ptv_overlap.insert(0, 'N/A')
        dvh.cross_section_max.insert(0, 'N/A')
        dvh.cross_section_median.insert(0, 'N/A')
        dvh.spread_x.insert(0, 'N/A')
        dvh.spread_y.insert(0, 'N/A')
        dvh.spread_z.insert(0, 'N/A')
        dvh.toxicity_grade.insert(0, -1)
        line_colors.insert(0, options.REVIEW_DVH_COLOR)
        x_data.insert(0, [0])
        y_data.insert(0, [0])

        # anonymize ids
        self.anon_id_map = {mrn: i for i, mrn in enumerate(list(set(dvh.mrn)))}
        anon_id = [self.anon_id_map[dvh.mrn[i]] for i in range(len(dvh.mrn))]

        print(str(datetime.now()), "writing sources.dvhs.data", sep=' ')
        groups = [['unknown'] * len(dvh.mrn),
                  dvh_groups][len(dvh.mrn) == len(dvh_groups)]
        self.sources.dvhs.data = {
            'mrn': dvh.mrn,
            'anon_id': anon_id,
            'group': groups,
            'uid': dvh.study_instance_uid,
            'roi_institutional': dvh.institutional_roi,
            'roi_physician': dvh.physician_roi,
            'roi_name': dvh.roi_name,
            'roi_type': dvh.roi_type,
            'rx_dose': dvh.rx_dose,
            'volume': dvh.volume,
            'surface_area': dvh.surface_area,
            'min_dose': dvh.min_dose,
            'mean_dose': dvh.mean_dose,
            'max_dose': dvh.max_dose,
            'dist_to_ptv_min': dvh.dist_to_ptv_min,
            'dist_to_ptv_mean': dvh.dist_to_ptv_mean,
            'dist_to_ptv_median': dvh.dist_to_ptv_median,
            'dist_to_ptv_max': dvh.dist_to_ptv_max,
            'dist_to_ptv_centroids': dvh.dist_to_ptv_centroids,
            'ptv_overlap': dvh.ptv_overlap,
            'cross_section_max': dvh.cross_section_max,
            'cross_section_median': dvh.cross_section_median,
            'spread_x': dvh.spread_x,
            'spread_y': dvh.spread_y,
            'spread_z': dvh.spread_z,
            'x': x_data,
            'y': y_data,
            'color': line_colors,
            'x_scale': x_scale,
            'y_scale': y_scale,
            'toxicity_grade': dvh.toxicity_grade
        }

        print(str(datetime.now()),
              'begin updating beam, plan, rx data sources',
              sep=' ')
        self.update_beam_data(dvh.study_instance_uid)
        self.update_plan_data(dvh.study_instance_uid)
        self.update_rx_data(dvh.study_instance_uid)
        print(str(datetime.now()), 'all sources set', sep=' ')

        return {'1': dvh_group_1, '2': dvh_group_2}
def main():
    """
        Main-Methode, wird am Anfang aufgerufen.
    """
    # Daten aus den Argumenten auslesen
    dataFiles = read_arguments()
    files_list = dataFiles[0]
    index_file = dataFiles[1]
    colors = dataFiles[2]
    # Eingestellte Werte in der Anwendung
    chromosom = "1"
    start = "10400"
    end = "11000"
    raw_algorithm = [0]
    sample_class_diff = 0
    line = False
    error = True
    absolute_bar = True
    color_input_list = []

    # Figure definieren, auf der alles abgebildet wird
    p = figure(height=500, width=1000, name='plot')

    # Bei jedem Update der Widgets wird diese aufgerufen
    def start_routine():
        """
            Startet die passenden Methoden zum Veraendern der Grafik.
        """
        nonlocal chromosom, start, end, sample_class_diff, raw_algorithm, p

        # Entfernen der alten Figur
        if final_gridplot.children[0].name == 'plot':
            final_gridplot.children.remove(final_gridplot.children[0])
        # Anlegen einer neuen Figur, die die neuen Daten uebergeben bekommt
        p = figure(width=1000, height=500, name='plot')
        # setzen von sample und difference, je nachdem was gerade aktiv ist
        sample = True
        difference = False
        # sample ist aktiv, difference muss dann auf False gesetzt werden
        if sample_class_diff == 0:
            sample = True
            difference = False
        # Klasse ist aktiv
        elif sample_class_diff == 1:
            sample = False
            difference = False
        # Unterschied wurde ausgewaehlt, da dieser nur mit Klassen angezeigt
        # wird, muss sample ebenfalls auf False gesetzt werden
        else:
            sample = False
            difference = True
        # Bei Farbauswahl wird die Farbe dementsprechend angepasst
        for i, color_string in enumerate(color_input_list):
            color = color_string.value.split(",")
            try:
                color[0] = int(color[0])
                color[1] = int(color[1])
                color[2] = int(color[2])
            except ValueError:
                error_message.text = ("Bitte eine Zahl" +
                                      " zwischen 0 und 255 eingeben.")
                return
            if (color[0] < 0 or color[0] > 255 or color[1] < 0
                    or color[1] > 255 or color[2] < 0 or color[2] > 255):
                error_message.text = "Eine Zahl zwischen 0 und 255 eingeben."
                return
            colors[i] = (color[0], color[1], color[2])

        # Sollen Rohdaten angezeigt werden
        if 0 in raw_algorithm:
            sumed_data = prepare_data(chromosom, start, end, True, sample,
                                      files_list, index_file, error_message)
            if sumed_data is None:
                # Einfuegen der Figur
                final_gridplot.children.insert(0, p)
                return
            calculated_methylation = calculate_methylation_level(sumed_data)
            calculated_data = calculated_methylation[0]
            cpg_position = calculated_methylation[1]
            display_data_raw(calculated_data, cpg_position, difference, line,
                             error, absolute_bar, p, colors)
        # Sollen Algorithmendaten angezeigt werden
        if 1 in raw_algorithm:
            pre_data = prepare_data(chromosom, start, end, False, sample,
                                    files_list, index_file, error_message)
            prepared_data = pre_data[1]
            cpg_position_samples = []
            # Dictionary fuer Index Positionen anlegen
            for index_sample in pre_data[0]:
                # Soll bei Null liegen
                index_value = [0 for i in index_sample]
                cpg_position = {
                    'index_position': index_sample,
                    'index_position_value': index_value
                }
                cpg_position_samples.append(cpg_position)
            if prepared_data is None:
                # Einfuegen der Figur
                final_gridplot.children.insert(0, p)
                return
            calculated_data = make_data_algorithm(prepared_data[0],
                                                  prepared_data[1],
                                                  prepared_data[2])
            display_data_algorithm(calculated_data, cpg_position_samples, p,
                                   difference, error, colors, line)
        # Einfuegen der Figur
        final_gridplot.children.insert(0, p)

    # Restliche Widgets fuer Bedienung definieren
    def changes_raw_algorithm(attr, old, new):
        """
            Bei Veraenderungen bei der checkbox_raw_algorithm startet
            start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal raw_algorithm
        raw_algorithm = []
        for x in new:
            raw_algorithm.append(x)
        start_routine()

    def changes_sample_class_diff(attr, old, new):
        """
            Bei Veraenderungen bei der radio_button_sample_class startet
            start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal sample_class_diff
        sample_class_diff = new
        start_routine()

    def changes_chromosom(attr, old, new):
        """
            Bei Veraenderungen bei choose_chromosom startet start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal chromosom
        chromosom = new
        start_routine()

    def changes_start(attr, old, new):
        """
            Bei Veraenderungen bei start_value startet start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal start
        start = new
        start_routine()

    def changes_end(attr, old, new):
        """
            Bei Veraenderungen bei end_value startet start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal end
        end = new
        start_routine()

    def changes_line(attr, old, new):
        """
            Bei Veraenderungen von checkbox_button_line_circle startet
            start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal line
        if not new:
            line = False
        else:
            line = True
        start_routine()

    def changes_error(attr, old, new):
        """
            Bei Veraenderungen von checkbox_button_error startet
            start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """
        nonlocal error
        if not new:
            error = False
        else:
            error = True
        start_routine()

    def changes_absolute_bar(attr, old, new):
        """
            Bei Veraenderungen von checkbox_button_error startet
            start_routine()

            Params:
                attr (str) : Gibt an, welches Attribut veraendert wurde
                old (bokeh.core.property.containers.PropertyValueList) :
                    Liste der alten Werte
                new (bokeh.core.property.containers.PropertyValueList) :
                    Liste der nun aktiven Werte

        """

        nonlocal absolute_bar
        if not new:
            absolute_bar = False
        else:
            absolute_bar = True
        start_routine()

    def changes_color(attr, old, new):
        """
            Startet die Routine, um die Farbwerte neu anzupassen
        """

        start_routine()

    # Auswahl zwischen Rohdaten, Klassen und Klassenunterschied
    checkbox_raw_algorithm = CheckboxButtonGroup(
        labels=['Rohdaten', 'Algorithmus'], active=[0])
    checkbox_raw_algorithm.on_change('active', changes_raw_algorithm)
    # Auswahl zwischen Sample und Klassen
    radio_button_sample_class = RadioButtonGroup(
        labels=['Sample', 'Klassen', 'Unterschied'], active=0)
    radio_button_sample_class.on_change('active', changes_sample_class_diff)
    # Auswahl fuer Liniendarstellung
    checkbox_button_line_circle = CheckboxButtonGroup(labels=["Linie"])
    checkbox_button_line_circle.on_change('active', changes_line)
    # Auswahl fuer Fehlerdarstellung
    checkbox_button_error = CheckboxButtonGroup(labels=["Fehler"], active=[0])
    checkbox_button_error.on_change('active', changes_error)
    # Auswahl fuer Darstellung der absoluten Daten
    checkbox_button_absolute = CheckboxButtonGroup(labels=["Absolute Werte"],
                                                   active=[0])
    checkbox_button_absolute.on_change('active', changes_absolute_bar)

    #DropDown Menue fuer Chromosomenauswahl, Start- und Endauswahl
    chromosoms = list(index_file.keys())
    choose_chromosom = Select(title='Chromosom', value="1", options=chromosoms)
    choose_chromosom.on_change('value', changes_chromosom)

    start_value = TextInput(value='10400', title="Start")
    start_value.on_change('value', changes_start)

    end_value = TextInput(value='11000', title="Ende")
    end_value.on_change('value', changes_end)

    # Fuer das Setzen der Farbwerte
    for i, color_value in enumerate(colors):
        color_input = TextInput(
            value=(str(color_value[0]) + "," + str(color_value[1]) + "," +
                   str(color_value[2])),
            title="Farbwert " + str(i))
        color_input.on_change('value', changes_color)
        color_input_list.append(color_input)

    # Textfelder fuer Fehlermeldungen in der Anwendung
    error_message = Div(text="", width=300, height=10)

    final_gridplot = layout(children=[
        p,
        [
            column(
                widgetbox(checkbox_raw_algorithm, radio_button_sample_class,
                          choose_chromosom)),
            widgetbox(checkbox_button_line_circle, checkbox_button_error,
                      checkbox_button_absolute),
            row(widgetbox(start_value, end_value)), error_message
        ], color_input_list
    ],
                            toolbar_location='left')
    curdoc().add_root(final_gridplot)
Beispiel #23
0
def players_performance_tab(player_info_df, player_stats_df, results_df):
    def create_ds(team, positions):
        """Returns DataFrame filtered team and positions.

        :param team: str. If 'None' is passed, all teams are selected.
        :param positions: list of str.
        :returns: DataFrame.
        """

        # Default Values
        SIZE = 8
        SIZES = [s for s in range(5, 38, 4)]
        COLOR = 'blueviolet'
        MAX_COLORS = len(Category20_20)

        if team == 'All':
            ds = pd.DataFrame(
                joined_player_df[joined_player_df['position'].isin(positions)])
        else:
            ds = pd.DataFrame(
                joined_player_df[(joined_player_df['position'].isin(positions))
                                 & (joined_player_df['team'] == team)])

        # Add sizes
        if size.value != 'None':
            if len(ds[size.value].unique()) > len(SIZES):
                groups = pd.qcut(ds[size.value].values,
                                 len(SIZES),
                                 duplicates='drop')
            else:
                groups = pd.Categorical(ds[size.value].values)

            ds['Size'] = np.array([SIZES[x] for x in groups.codes])

        else:
            ds['Size'] = SIZE

        # Add colors
        if color.value != 'None':
            if len(ds[color.value].unique()) > MAX_COLORS:
                groups = pd.qcut(ds[color.value].values,
                                 MAX_COLORS,
                                 duplicates='drop')
            else:
                groups = pd.Categorical(ds[color.value].values)

            ds['Color'] = np.array([Category20_20[x] for x in groups.codes])

        else:
            ds['Color'] = COLOR

        return ds

    def plot_stats():
        """Creates and returns a figure."""

        pos = [positions[i] for i in select_position.active]
        team = select_team.value
        ds = create_ds(team, pos)
        source = ColumnDataSource(ds)

        p = figure(plot_height=600,
                   plot_width=800,
                   title=f'{x.value} vs {y.value}',
                   tools='pan,box_zoom,reset')

        p.circle(x=x.value,
                 y=y.value,
                 size='Size',
                 color='Color',
                 alpha=0.5,
                 source=source,
                 hover_color='navy')

        hover = HoverTool(tooltips=[('Player', '@name'), (
            'Team',
            '@team'), (f'{x.value}',
                       f'@{{{x.value}}}'), (
                           f'{y.value}',
                           f'@{{{y.value}}}'), (f'Opponent', f'@Opponent')])

        if size.value != 'None':
            hover.tooltips.append((f'{size.value}', f'@{{{size.value}}}'))
        if color.value != 'None':
            hover.tooltips.append((f'{color.value}', f'@{{{color.value}}}'))
        hover.point_policy = 'follow_mouse'

        p.add_tools(hover)
        p.xaxis.axis_label = x.value
        p.yaxis.axis_label = y.value

        return p

    def update(atrrname, old, new):
        layout.children[1] = plot_stats()

    # Create merged dataFrame of players stats and info
    joined_player_df = pd.merge(player_stats_df,
                                player_info_df,
                                on='pid',
                                how='inner')
    # joined_player_df.drop(columns=['index_x'], inplace=True)
    # Add columns: result (w/l/d), opponent
    joined_player_df['Opponent'] = joined_player_df.apply(get_opponent,
                                                          args=(results_df, ),
                                                          axis=1)
    joined_player_df['result'] = joined_player_df.apply(get_gw_match_result,
                                                        args=(results_df, ),
                                                        axis=1)

    # Data filtering widgets by Team and Position
    teams = ['All'] + sorted(list(player_info_df['team'].unique()))
    select_team = Select(title='Filter by Team', value='All', options=teams)
    select_team.on_change('value', update)

    positions = ['GK', 'Defender', 'Midfielder', 'Forward']
    select_position = CheckboxButtonGroup(labels=positions,
                                          active=[0, 1, 2, 3])
    select_position.on_change('active', update)

    # Select stats to plot
    columns = [
        x for x in sorted(player_stats_df.columns)
        if x not in ['index', 'pid', 'gameweek', 'season']
    ]
    x = Select(title='X Axis', value='minutes', options=columns)
    x.on_change('value', update)
    y = Select(title='Y Axis', value='passes', options=columns)
    y.on_change('value', update)
    size = Select(title='Add Size Dimension',
                  value='None',
                  options=['None'] + columns)
    size.on_change('value', update)
    color = Select(title='Add Color Segmentation',
                   value='None',
                   options=['None', 'result', 'gameweek', 'position'])
    color.on_change('value', update)

    widgets = widgetbox([select_team, select_position, x, y, size, color])

    layout = row(widgets, plot_stats())
    tab = Panel(child=layout, title='Players Performances')

    return tab
Beispiel #24
0
def density_tab(flights):

    # Dataset for density plot based on carriers, range of delays,
    # and bandwidth for density estimation
    def make_dataset(carrier_list, range_start, range_end, bandwidth):

        xs = []
        ys = []
        colors = []
        labels = []

        for i, carrier in enumerate(carrier_list):
            subset = flights[flights['name'] == carrier]
            subset = subset[subset['arr_delay'].between(
                range_start, range_end)]
            kde = gaussian_kde(subset['arr_delay'], bw_method=bandwidth)

            # Evenly space x values
            x = np.linspace(range_start, range_end, 100)
            # Evaluate pdf at every value of x
            y = kde.pdf(x)

            # Append the values to plot
            xs.append(list(x))
            ys.append(list(y))

            # Append the colors and label
            colors.append(airline_colors[i])
            labels.append(carrier)

        new_src = ColumnDataSource(data={
            'x': xs,
            'y': ys,
            'color': colors,
            'label': labels
        })
        return new_src

    def make_plot(src):
        p = figure(plot_width=700,
                   plot_height=700,
                   title='Density Plot of Arrival Delays by Airline',
                   x_axis_label='Delay (min)',
                   y_axis_label='Density')
        p.multi_line('x',
                     'y',
                     color='color',
                     legend='label',
                     line_width=3,
                     source=src)

        # Hover tool with next line policy
        hover = HoverTool(tooltips=[('Carrier', '@label'), ('Delay', '$x'),
                                    ('Density', '$y')],
                          line_policy='next')

        # Add the hover tool and styling
        p.add_tools(hover)

        p = style(p)

        return p

    def update(attr, old, new):
        # List of carriers to plot
        carriers_to_plot = [
            carrier_selection.labels[i] for i in carrier_selection.active
        ]

        # If no bandwidth is selected, use the default value
        if bandwidth_choose.active == []:
            bandwidth = None
        # If the bandwidth select is activated, use the specified bandwith
        else:
            bandwidth = bandwidth_select.value

        new_src = make_dataset(carriers_to_plot,
                               range_start=range_select.value[0],
                               range_end=range_select.value[1],
                               bandwidth=bandwidth)
        src.data.update(new_src.data)

    def style(p):
        # Title
        p.title.align = 'center'
        p.title.text_font_size = '20pt'
        p.title.text_font = 'serif'

        # Axis titles
        p.xaxis.axis_label_text_font_size = '14pt'
        p.xaxis.axis_label_text_font_style = 'bold'
        p.yaxis.axis_label_text_font_size = '14pt'
        p.yaxis.axis_label_text_font_style = 'bold'

        # Tick labels
        p.xaxis.major_label_text_font_size = '12pt'
        p.yaxis.major_label_text_font_size = '12pt'

        return p

    # Carriers and colors
    available_carriers = sorted(set(flights['name']))

    airline_colors = Category20_16
    airline_colors.sort()

    # Carriers to plot
    carrier_selection = CheckboxGroup(labels=available_carriers, active=[0, 1])
    carrier_selection.on_change('active', update)

    # Range to plot
    range_select = RangeSlider(start=-60,
                               end=180,
                               value=(-60, 120),
                               step=5,
                               title='Delay Range (min)')
    range_select.on_change('value', update)

    # Initial carriers and data source
    initial_carriers = [
        carrier_selection.labels[i] for i in carrier_selection.active
    ]

    # Bandwidth of kernel
    bandwidth_select = Slider(start=0.1,
                              end=5,
                              step=0.1,
                              value=0.5,
                              title='Bandwidth for Density Plot')
    bandwidth_select.on_change('value', update)

    # Whether to set the bandwidth or have it done automatically
    bandwidth_choose = CheckboxButtonGroup(
        labels=['Choose Bandwidth (Else Auto)'], active=[])
    bandwidth_choose.on_change('active', update)

    # Make the density data source
    src = make_dataset(initial_carriers,
                       range_start=range_select.value[0],
                       range_end=range_select.value[1],
                       bandwidth=bandwidth_select.value)

    # Make the density plot
    p = make_plot(src)

    # Add style to the plot
    p = style(p)

    # Put controls in a single element
    controls = WidgetBox(carrier_selection, range_select, bandwidth_select,
                         bandwidth_choose)

    # Create a row layout
    layout = row(controls, p)

    # Make a tab with the layout
    tab = Panel(child=layout, title='Density Plot')

    return tab
Beispiel #25
0
def timeseries_tab(ts, hist_ts):
    # Set up plot
    def make_lineplot(source):
        ts_list = source.column_names
        ts_list.remove('index')
        ts_list.remove('time')

        ttp = [("Time", "$x"), ("Value", "$y")]

        plot = figure(plot_height=400, plot_width=600, tooltips=ttp,
                      title="Plot Name", x_axis_label="Axis label",
                      y_axis_label="Axis label",
                      tools="hover, pan, zoom_in, zoom_out, reset, save")
        for i, name in enumerate(ts_list):
            plot.line('time', name, source=source, line_width=3,
                      line_color=ts_colors[i], legend_label=name)

        plot.legend.location = "top_right"
        plot.legend.click_policy = "hide"
        plot.title.text_font_size = '14pt'
        plot.xaxis.axis_label_text_font_size = '12pt'
        plot.xaxis.axis_label_text_font_style = 'bold'
        plot.yaxis.axis_label_text_font_size = '12pt'
        plot.yaxis.axis_label_text_font_style = 'bold'

        return plot

    # Set up callbacks
    def update_title(attrname, old, new):
        plot.title.text = text.value

    def update_x_ax_label(attrname, old, new):
        plot.xaxis.axis_label = text2.value

    def update_y_ax_label(attrname, old, new):
        plot.yaxis.axis_label = text3.value

    def update_window(attrname, old, new):
        if window_select.value == 0:

            raw_source = ColumnDataSource(data=ts)
            source.data.update(raw_source.data)
        else:
            if rolling_method.value == "Mean":
                # Apply moving average to pandas dataframe, export to CDS type.
                ts_rmean = rolling_mean(ts, window=window_select.value)
                new_source = ColumnDataSource(data=ts_rmean)
            else:
                # Apply moving std to pandas dataframe, export to CDS type.
                ts_rstd = rolling_std(ts, window=window_select.value)
                new_source = ColumnDataSource(data=ts_rstd)

            source.data.update(new_source.data)

    # Set up widgets
    text = TextInput(title="Title of Plot", value='Plot Name')
    text.on_change('value', update_title)
    text2 = TextInput(title="x-axis Label", value='Axis Label')
    text2.on_change('value', update_x_ax_label)
    text3 = TextInput(title="y-axis Label", value='Axis Label')
    text3.on_change('value', update_y_ax_label)

    rolling_method = Select(value='Mean', title='Statistic',
                            options=['Mean', 'Std. Dev.'])
    rolling_method.on_change('value', update_window)

    window_select = Slider(start=0, end=50, step=1, value=10,
                           title='Window Size')
    window_select.on_change('value', update_window)

    div1 = Div(text="""<b>Plot Attributes:</b> <br> Modify axis labels. <br>""")
    div2 = Div(text="""<b>Rolling Window Functions:</b> <br> Specify the size and statistic for a rolling window function. <br>""")
    div3 = Div(text="""<b>Data Distribution:</b> <br> Examine the distribution of time series data points. <br>""")

    source = ColumnDataSource(data=ts)
    plot = make_lineplot(source)

    # Set up layouts and add to document
    # Put controls in a single element.
    lineplot_controls = WidgetBox(text, div1, text2, text3, div2, window_select,
                                  rolling_method)

# Make plot with histogram
    # Find maximum range of ts.

    hist_ts_range = hist_ts.apply(lambda x: x.max() - x.min())
    range_max = hist_ts_range.max()

    # Function to make a dataset for histogram based on a list of
    # timeseries, using a default histogram bin width of 5
    def make_dataset(timeseries_list, bin_width=5):
        # Dataframe to hold information
        df_to_plot = pd.DataFrame(columns=['proportion', 'left', 'right',
                                           'f_proportion', 'f_interval',
                                           'name', 'color'])

        # Iterate through all the TS.
        for i, timeseries_name in enumerate(timeseries_list):
            # Subset to the carrier
            subset = hist_ts[timeseries_name]

            # Create a histogram with default 5 minute bins
            arr_hist, edges = np.histogram(subset,
                                           bins=int(range_max / bin_width))

            # Divide the counts by the total to get a proportion
            arr_df = pd.DataFrame({'proportion': arr_hist / np.sum(arr_hist),
                                   'left': edges[:-1], 'right': edges[1:]})

            # Format the proportion
            arr_df['f_proportion'] = ['%0.5f' % proportion for
                                      proportion in arr_df['proportion']]

            # Format the interval
            arr_df['f_interval'] = ['%d to %d units' % (left, right) for left,
                                    right in zip(arr_df['left'],
                                    arr_df['right'])]

            # Assign the carrier for labels
            arr_df['name'] = timeseries_name

            # Color each carrier differently
            arr_df['color'] = Category20_16[i]

            # Add to the overall dataframe
            df_to_plot = df_to_plot.append(arr_df)

        # Overall dataframe
        df_to_plot = df_to_plot.sort_values(['name', 'left'])

        return ColumnDataSource(df_to_plot)

    def style(hist):
        # Title
        hist.title.align = 'left'
        hist.title.text_font_size = '14pt'

        # Axis titles
        hist.xaxis.axis_label_text_font_size = '12pt'
        hist.xaxis.axis_label_text_font_style = 'bold'
        hist.yaxis.axis_label_text_font_size = '12pt'
        hist.yaxis.axis_label_text_font_style = 'bold'

        # Tick labels
        hist.xaxis.major_label_text_font_size = '12pt'
        hist.yaxis.major_label_text_font_size = '12pt'

        return hist

    def make_plot(hist_src):
        # Blank plot with correct labels
        hist = figure(plot_width=700, plot_height=700,
                      title='Histogram of Times Series Data Points',
                      x_axis_label='Bin width', y_axis_label='Proportion')

        # Quad glyphs to create a histogram
        hist.quad(source=hist_src, bottom=0, top='proportion', left='left',
                  right='right',
                  color='color',
                  fill_alpha=0.7, hover_fill_color='color', legend='name',
                  hover_fill_alpha=1.0, line_color='black')

        # Hover tool with vline mode
        hover = HoverTool(tooltips=[('Times Series',
                                     '@name'),
                                    ('x', '@f_interval'),
                                    ('Proportion',
                                    '@f_proportion')], mode='vline')

        hist.add_tools(hover)

        # Styling.
        hist = style(hist)

        return hist

    def update(attr, old, new):
        hist_ts_to_plot = [hist_ts_selection.labels[i]
                           for i in hist_ts_selection.active]
        new_hist_src = make_dataset(hist_ts_to_plot,
                                    bin_width=binwidth_select.value)
        hist_src.data.update(new_hist_src.data)

    # Widgets for interactivity.
    # Carriers and colors
    available_hist_ts = hist_ts.columns.tolist()
    available_hist_ts.sort()

    hist_ts_selection = CheckboxButtonGroup(labels=available_hist_ts,
                                            active=[0, 1])
    hist_ts_selection.on_change('active', update)

    binwidth_select = Slider(start=1, end=10,
                             step=1, value=5,
                             title='Bin Width')
    binwidth_select.on_change('value', update)

    # Call to set initial dataset.
    print(hist_ts_selection.labels, hist_ts_selection.active)
    # Initial ts and data source
    initial_hist_ts = available_hist_ts

    hist_src = make_dataset(initial_hist_ts, bin_width=binwidth_select.value)

    hist = make_plot(hist_src)

    # Put controls in a single element.
    histogram_controls = WidgetBox(div3, hist_ts_selection, binwidth_select)

    # Create a row layout
    grid = gridplot([[lineplot_controls, plot], [histogram_controls, hist]],
                    plot_width=500, plot_height=500)

    # Make a tab with the layout
    tab = Panel(child=grid, title='Time Series Plots')

    return tab
Beispiel #26
0
# select_linac[2].on_change('value', plot.update_source)

avg_len_input = TextInput(title='Avg. Len:', value='10', width=100)
avg_len_input.on_change('value', plot.update_source)

percentile_input = TextInput(title='Percentile:', value='90', width=100)
percentile_input.on_change('value', plot.update_source)

start_date_picker = DatePicker(title='Start Date:', value=plot.x[0])
end_date_picker = DatePicker(title='End Date:', value=plot.x[-1])
start_date_picker.on_change('value', plot.update_source)
end_date_picker.on_change('value', plot.update_source)

gamma_options = ['5.0%/3.0mm', '3.0%/3.0mm', '3.0%/2.0mm', 'Any']
checkbox_button_group = CheckboxButtonGroup(labels=gamma_options, active=[3])
checkbox_button_group.on_change('active', plot.update_source)

text = {key: Div() for key in [1, 2]}

plot.update_source(None, None, None)

layout = column(row(select_y, avg_len_input, percentile_input),
                row(start_date_picker, end_date_picker),
                row(Div(text='Gamma Criteria: '), checkbox_button_group),
                text[1], text[2], row(Spacer(width=10), plot.fig),
                Spacer(height=50), row(Spacer(width=10), plot.histogram),
                Spacer(height=50), row(Spacer(width=10), ichart.figure),
                row(ichart.div_center_line, ichart.div_ucl, ichart.div_lcl))

curdoc().add_root(layout)
curdoc().title = "ArcCheck Trending"
Beispiel #27
0
	range_select.on_change('value', update)

	# Initial carriers and data source
	initial_carriers = [carrier_selection.labels[i] for
						i in carrier_selection.active]

	# Bandwidth of kernel
	bandwidth_select = Slider(start=0.1, end=5,
							  step=0.1, value=0.5,
							  title='Bandwidth for Density Plot')
	bandwidth_select.on_change('value', update)

	# Whether to set the bandwidth or have it done automatically
	bandwidth_choose = CheckboxButtonGroup(
		labels=['Choose Bandwidth (Else Auto)'], active=[])
	bandwidth_choose.on_change('active', update)



	# FUNDS_EARMARKED_FOR_GOAL
	fund_input = TextInput(value="100000", title="Funds for Goal:")

	contribution_input = TextInput(value="1000", title="Contribution Amount:")

	income_input = TextInput(value="100000", title="Annual Salary:")

	fga_input = TextInput(value="100000", title="Future Goal Amount:")


	retirementage_select = Slider(start = 20, end = 100, step = 1, value = 1, title = 'Projected Retirement Age')
	#retirementage_select.on_change('value', update)
Beispiel #28
0
class Interface:
    def __init__(self):

        self.grepolis = Grepolis()

        imgRessource = []
        for v in ["Bois", "Pierre", "Argent"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgRessource.append(Image(d))
        colRess = column(*[img.figure for img in imgRessource])
        self.inputRess = [
            TextInput(value="", title=el + " :", width=150)
            for el in ["Bois", "Pierre", "Argent"]
        ]
        colinputRess = column(*self.inputRess)

        imgDieu = []
        for v in ["Athena", "Artemis", "Hades", "Zeus", "Poseidon", "Hera"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgDieu.append(Image(d, multiplier=3))
        rowDieu = [HFill(5)]
        for img in imgDieu:
            rowDieu.append(HFill(5))
            rowDieu.append(img.figure)
        rowDieu = row(*rowDieu)

        imgAtt = []
        for v in ["Att_hack", "Att_sharp", "Att_distance"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgAtt.append(Image(d))
        colAtt = column(*[img.figure for img in imgAtt])
        self.inputAtt = [
            TextInput(value="", title=el + " :", width=150)
            for el in ["Contondantes", "Blanches", "De Jet"]
        ]
        colinputAtt = column(*self.inputAtt)

        imgDef = []
        for v in ["Def_hack", "Def_sharp", "Def_distance"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgDef.append(Image(d))
        colDef = column(*[img.figure for img in imgDef])

        self.inputDef = [
            TextInput(value="", title=el + " :", width=150)
            for el in ["Contondantes", "Blanches", "De Jet"]
        ]
        rowinputDef = column(*self.inputDef)

        imgOther = []
        for v in ["Vitesse", "Butin", "Faveur"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgOther.append(Image(d))

        colOther = column(*[img.figure for img in imgOther])

        self.inputFavBut = [
            TextInput(value="", title=el + " :", width=150)
            for el in ["Vitesse", "Butin", "Faveur"]
        ]
        self.inputOther = column(*self.inputFavBut)

        self.imgUnit = []
        for v in [
                "Combattant", "Frondeur", "Archer", "Hoplite", "Cavalier",
                "Char", "Envoye", "Centaure", "Pegase"
        ]:
            r = "static/" + v + ".jpg"
            d = dict(url=[r])
            self.imgUnit.append(Image(d, multiplier=2))
        rowUnit = row(HFill(10), *[img.figure for img in self.imgUnit])

        imgDefAtt = []
        for v in ["Pop", "Attaque", "Defense"]:
            r = "static/" + v + ".png"
            d = dict(url=[r])
            imgDefAtt.append(Image(d))

        rowInputUnit = [HFill(10)]
        self.unitInput = [
            TextInput(value="", title=el + " :", width=80) for el in [
                "Combattant", "Frondeur", "Archer", "Hoplite", "Cavalier",
                "Char", "Envoye", "Centaure", "Pegase"
            ]
        ]
        for inp in self.unitInput:
            rowInputUnit.append(inp)
            rowInputUnit.append(HFill(30))
        rowInputUnit = row(HFill(10), *rowInputUnit)

        self.selectUnit = CheckboxButtonGroup(labels=[
            "Combattant", "Frondeur", "Archer", "Hoplite", "Cavalier", "Char",
            "Envoye", "Centaure", "Pegase"
        ],
                                              active=[i for i in range(9)])
        self.selectUnit.on_change("active", self.updateSelectUnit)
        self.Dieu = RadioButtonGroup(
            labels=["Athena", "Artemis", "Hades", "Zeus", "Poseidon", "Hera"],
            active=0,
            width=1110)
        self.Dieu.on_change('active', self.updateUnit)

        self.attdef = RadioButtonGroup(labels=["Attaque", "Defense"],
                                       active=0,
                                       width=200)
        self.attdef.on_change('active', self.switchAttDef)

        self.typeAtt = RadioGroup(
            labels=["Armes Contondantes", "Armes Blanches", "Armes de Jet"],
            active=0,
            width=150)
        self.typeAtt.on_change('active', self.process2)
        self.imgFaveur = Image(dict(url=["static/" + "Faveur" + ".png"]))

        self.launch = Button(label="Lancer")
        self.launch.on_click(self.process)

        self.inputPop = TextInput(value="1500",
                                  title="Population : ",
                                  width=120)
        self.inputPop.on_change("value", self.process2)

        self.inputFav = TextInput(value="1500",
                                  title="Faveur Max : ",
                                  width=120)
        self.inputFav.on_change("value", self.process2)

        rowPop = row(HFill(10), self.typeAtt, imgDefAtt[1].figure, self.attdef,
                     HFill(30), imgDefAtt[2].figure, HFill(50),
                     imgDefAtt[0].figure, self.inputPop, HFill(50),
                     self.imgFaveur.figure, self.inputFav, HFill(50))
        self.doc = column(
            rowDieu, self.Dieu, VFill(20), rowPop, VFill(20), self.selectUnit,
            rowUnit, rowInputUnit, VFill(20),
            row(HFill(50), colRess, colinputRess,
                HFill(40), colAtt, colinputAtt, HFill(40), colDef, rowinputDef,
                HFill(40), colOther, self.inputOther))
        #curdoc().add_root(column(rowDieu,self.Dieu,VFill(20),rowPop,VFill(20),self.selectUnit,rowUnit,rowInputUnit,VFill(20),row(HFill(50),colRess,colinputRess,HFill(40),colAtt,colinputAtt,HFill(40),colDef,rowinputDef,HFill(40),colOther,self.inputOther)))
        self.process(None)
        #curdoc().title = "Grepolis"

    def updateUnit(self, attrname, old, new):
        L = ["Athena", "Artemis", "Hades", "Zeus", "Poseidon", "Hera"]
        print(self.selectUnit.active)
        if L[new] == "Poseidon":
            self.imgUnit[-1].figure.visible = False
            self.unitInput[-1].visible = False
            self.selectUnit.active = [1, 2, 3, 4, 5, 6, 7]
        else:
            self.imgUnit[-1].figure.visible = True
            self.unitInput[-1].visible = True
            self.selectUnit.active = [1, 2, 3, 4, 5, 6, 7, 8]
        self.grepolis.setDieu(L[new])
        unit = Add(L[new])
        self.selectUnit.labels = [
            "Combattant", "Frondeur", "Archer", "Hoplite", "Cavalier", "Char",
            "Envoye"
        ] + unit
        for i, v in enumerate(unit):
            r = "static/" + v + ".jpg"
            d = dict(url=[r])
            self.imgUnit[-2 + i].update(d)
            self.unitInput[-2 + i].title = v + " : "
        self.process(None)

    def process2(self, attrname, old, new):
        self.process(None)

    def switchAttDef(self, attrname, old, new):
        if self.attdef.active == 0:
            self.typeAtt.disabled = False
        else:
            self.typeAtt.disabled = True
        self.process(None)

    def updateSelectUnit(self, attrname, old, new):
        N = len(self.selectUnit.labels)
        active = self.selectUnit.active
        zeros = [i for i in range(N) if i not in active]
        for inp in [self.unitInput[i] for i in zeros]:
            inp.value = str(0)
        self.process(None)

    def process(self, attrname):
        try:
            pop = int(self.inputPop.value)
            favmax = int(self.inputFav.value)
            active = self.selectUnit.active
            type = self.typeAtt.active
            if self.attdef.active == 0:
                X, Att, Def, Prix, Speed, Pops, butin = self.grepolis.optimAttaque(
                    pop=pop, favmax=favmax, active=active, type=type)

            else:
                X, Att, Def, Prix, Speed, Pops, butin = self.grepolis.optimDefense(
                    pop=pop, favmax=favmax, active=active)
            for v, inp in zip(X, [self.unitInput[i] for i in active]):
                inp.value = str(v)
            for v, inp in zip(Att, self.inputAtt):
                inp.value = str(v) + " /u - " + str(int(v * pop))
            for v, inp in zip(Def, self.inputDef):
                inp.value = str(v) + " /u - " + str(int(v * pop))
            for v, inp in zip(Prix, self.inputRess):
                inp.value = str(v) + " /u - " + str(int(v * pop))
            for i, (v, inp) in enumerate(
                    zip([Speed, butin, Prix[3]], self.inputFavBut)):
                #add = ""
                #if i > 0:
                #    add = + " /u - " +str(int(v*pop))
                #print(v,add)
                inp.value = str(v) + " /u - " + str(int(
                    v * pop)) if i != 0 else str(v)
        except:
            pass
def attention_tab(beers):
	
	# Dataset for density plot based on Genres and range of ratings
	# and bandwidth for density estimation
	def make_dataset(
		genre_list, 
		range_start, 
		range_end, 
		bandwidth
		):

		xs = []
		ys = []
		colors = []
		labels = []

		for i, genre in enumerate(genre_list):
			subset = beers[beers['style_genre'] == genre]
			subset = subset[subset['ratings'].between(range_start, 
														range_end)]

			kde = gaussian_kde(subset['ratings'], bw_method=bandwidth)
			
			# Evenly space x values
			x = np.linspace(range_start, range_end, 6500)
			# Evaluate pdf at every value of x
			y = kde.pdf(x)

			# Append the values to plot
			xs.append(list(x))
			ys.append(list(y))

			# Append the colors and label
			colors.append(genre_colors[i])
			labels.append(genre)

		new_src = ColumnDataSource(data={'x': xs, 'y': ys, 
								   'color': colors, 'label': labels})

		return new_src

	def make_plot(src):
		p = figure(plot_width = 700, plot_height = 650,
				   title = 'Distribution of Beer Genre Attention',
				   x_axis_label = 'Attention of Genre (Number of Ratings of Beer)', y_axis_label = 'Density')


		p.multi_line('x', 'y', color = 'color', legend = 'label', 
					 line_width = 3,
					 source = src)

		# Hover tool with next line policy
		hover = HoverTool(tooltips=[('Genre', '@label'), 
									('Ratings', '$x'),
									('Density', '$y')],
						  line_policy = 'next')

		# Add the hover tool and styling
		p.add_tools(hover)

		p = p_style(p)

		return p
	
	def update(attr, old, new):
		# List of genres to plot
		genres_to_plot = [genre_selection.labels[i] for i in 
							genre_selection.active]
		
		# If no bandwidth is selected, use the default value
		if bandwidth_choose.active == []:
			bandwidth = None
		# If the bandwidth select is activated, use the specified bandwith
		else:
			bandwidth = bandwidth_select.value
			
		
		new_src = make_dataset(genres_to_plot,
									range_start = range_select.value[0],
									range_end = range_select.value[1],
									bandwidth = bandwidth)
		
		src.data.update(new_src.data)
		
	def p_style(p):
		# Title 
		p.title.align = 'center'
		p.title.text_font_size = '20pt'
		p.title.text_font = 'serif'

		# Axis titles
		p.xaxis.axis_label_text_font_size = '14pt'
		p.xaxis.axis_label_text_font_style = 'bold'
		p.yaxis.axis_label_text_font_size = '14pt'
		p.yaxis.axis_label_text_font_style = 'bold'

		# Tick labels
		p.xaxis.major_label_text_font_size = '12pt'
		p.yaxis.major_label_text_font_size = '12pt'

		return p
	
	# genres and colors
	available_genres = list(set(beers['style_genre']))
	available_genres.sort()

	genre_colors = Category20_16
	genre_colors.sort()

	# Genres to plot
	genre_selection = CheckboxGroup(labels=available_genres, 
									   active = [0, 1])
	genre_selection.on_change('active', update)
	
	range_select = RangeSlider(start = 0, end = 500, value = (0, 200),
							   step = 50, title = 'Range of Attention (Number of Ratings)')
	range_select.on_change('value', update)
	
	# intial genres and data source
	initial_genres = [genre_selection.labels[i] for 
						i in genre_selection.active]
	
	# Bandwidth of kernel
	bandwidth_select = Slider(start = 0.1, end = 5, 
							  step = 0.1, value = 2,
							  title = 'Bandwidth for Density Plot')
	bandwidth_select.on_change('value', update)
	
	# Whether to set the bandwidth or have it done automatically
	bandwidth_choose = CheckboxButtonGroup(
		labels=['Choose Bandwidth (Else Auto)'], active = [])
	bandwidth_choose.on_change('active', update)

	# Make the density data source
	src = make_dataset(initial_genres, 
						range_start = range_select.value[0],
						range_end = range_select.value[1],
						bandwidth = bandwidth_select.value) 
	
	sidetext = Div(
		text="""Please use the filters below to adjust the <b>Attention Density Plot</b> as needed.""",
		width=250, height=50)

	# Make the density plot
	p = make_plot(src)
	
	# Add style to the plot
	p = p_style(p)
	
	# Put controls in a single element
	controls = WidgetBox(sidetext, genre_selection, range_select, 
						 bandwidth_select, bandwidth_choose)
	
	# Create a row layout
	layout = row(controls, p)
	
	# Make a tab with the layout 
	tab = Panel(child=layout, title = 'Distribution of Beer Genre Attention')

	return tab
Beispiel #30
0
def load_page(experiment_df, experiment_db):

    ########## bokeh plots ##########

    # general plot tools
    plot_tools = 'wheel_zoom, pan, reset, save, hover'
    hover = HoverTool(tooltips=[("(x,y)", "($x, $y)")])

    # progress curve plots
    global raw_source
    raw_source = ColumnDataSource(data=dict(x=[], y=[], yr=[], yfit=[]))
    global raw
    raw = figure(title="Initial Rate Fit",
                 x_axis_label="Time",
                 y_axis_label="Signal",
                 plot_width=350,
                 plot_height=300,
                 tools=plot_tools)
    raw.circle('x',
               'y',
               size=2,
               source=raw_source,
               color='gray',
               selection_color="black",
               alpha=0.6,
               nonselection_alpha=0.2,
               selection_alpha=0.6)
    raw.line('x', 'yfit', source=raw_source, color='red')
    global warning_source
    warning_source = ColumnDataSource(data=dict(
        x=[0],
        y=[0],
        t=[
            'Please enter transform equation! \nMust convert signal to [substrate] \nin Schnell-Mendoza mode (e.g. via \nx/6.22/0.45/0.001 for sample data). \nNote: this transform may need \nto be inverted through multiplying \nby -1 when analyzing experiments \nthat measure increasing product \nconcentration over time)'
        ]))
    global warning
    warning = raw.text(x='x',
                       y='y',
                       text='t',
                       text_font_size='12pt',
                       angle=0,
                       source=warning_source)
    warning.visible = False
    global circles_source
    circles_source = ColumnDataSource(
        data=dict(x=[-.05, -.05, 1.6, 1.6], y=[0, 0.6, 0, 0.6]))
    global circles
    circles = raw.circle(x='x', y='y', alpha=0., source=circles_source)
    circles.visible = False
    global resi
    resi = figure(title="Initial Rate Fit Residuals",
                  x_axis_label="Time",
                  y_axis_label="Residual",
                  plot_width=700,
                  plot_height=200,
                  tools='wheel_zoom,pan,reset')
    resi.yaxis.formatter = BasicTickFormatter(precision=2, use_scientific=True)
    resi.circle('x', 'yr', size=5, source=raw_source, color='grey', alpha=0.6)

    # model plot for titration experiments
    global model_data_source
    model_data_source = ColumnDataSource(
        data=dict(xt=[], yt=[], n=[], ct=[], et=[]))
    global model_plot_source
    model_plot_source = ColumnDataSource(
        data=dict(xp=[], yp=[], l=[], u=[], cp=[], ep=[]))
    global model_fit_source
    model_fit_source = ColumnDataSource(data=dict(x=[], y=[]))
    global varea_source
    varea_source = ColumnDataSource(data=dict(x=[], r1=[], r2=[]))
    global model
    model = figure(title='Model Fit',
                   x_axis_label='Concentration',
                   y_axis_label='Rate',
                   plot_width=350,
                   plot_height=300,
                   tools=plot_tools)
    model.circle('xp',
                 'yp',
                 size=8,
                 source=model_plot_source,
                 color='cp',
                 alpha=0.6)
    model.add_layout(
        Whisker(source=model_plot_source, base='xp', upper='u', lower='l'))
    model.line('x',
               'y',
               source=model_fit_source,
               line_width=3,
               color='black',
               alpha=0.8)
    model.varea('x', 'r1', 'r2', source=varea_source, color='grey', alpha=0.3)

    ########## bokeh widgets ##########

    # button for selecting progress curve fitting routine
    global fit_button
    fit_button = RadioButtonGroup(labels=[
        'Maximize Slope Magnitude', 'Linear Fit', 'Logarithmic Fit',
        'Schnell-Mendoza'
    ],
                                  active=0,
                                  width=375)
    fit_button.on_change('active', widget_callback)

    # button for selecting progress curve fitting routine
    global scalex_box
    scalex_box = CheckboxButtonGroup(
        labels=["transform x-axis to Log10 scale"], active=[])
    scalex_box.on_change('active', widget_callback)

    # dropdown menu for selecting titration experiment model
    global model_select
    model_select = Select(
        title='Choose Model',
        value='Michaelis-Menten',
        options=['Michaelis-Menten', 'pEC50/pIC50', 'High-Throughput Screen'],
        width=350)
    model_select.on_change('value', widget_callback)

    # dropdown menu for selecting blank sample to subtract from remaining titration samples
    global subtract_select
    subtract_select = Select(title='Select Blank Sample for Subtraction',
                             value='',
                             options=list(experiment_df)[1:] + [''],
                             width=350)
    subtract_select.on_change('value', widget_callback)

    # dropdown menu for selecting titration sample to plot in current view
    global sample_select
    sample_select = Select(title='Y Axis Sample',
                           value=list(experiment_df)[-1],
                           options=list(experiment_df)[1:],
                           width=350)
    sample_select.on_change('value', sample_callback)

    # text input box for transforming slopes to rates
    global transform_input
    transform_input = TextInput(value='',
                                title="Enter Transform Equation",
                                width=350)
    transform_input.on_change('value', widget_callback)

    # text input box for setting delay time in logarithmic progress curve fitting
    global offset_input
    offset_input = TextInput(value='',
                             title="Enter Time Between Mixing and First Read",
                             width=350)
    offset_input.on_change('value', widget_callback)

    # text input boxes for fixing EC/IC50 parameters
    global bottom_fix
    bottom_fix = TextInput(value='', title="Fix pIC50/pEC50 Bottom")
    bottom_fix.on_change('value', widget_callback)

    global top_fix
    top_fix = TextInput(value='', title="Fix pIC50/pEC50 Top")
    top_fix.on_change('value', widget_callback)

    global slope_fix
    slope_fix = TextInput(value='', title="Fix pIC50/pEC50 Hill Slope")
    slope_fix.on_change('value', widget_callback)

    # text input boxes for progress curve xrange selection
    global start_time
    start_time = TextInput(value=str(
        experiment_df[list(experiment_df)[0]].values[0]),
                           title="Enter Start Time")
    global end_time
    end_time = TextInput(value=str(
        experiment_df[list(experiment_df)[0]].values[-1]),
                         title='Enter End Time')
    start_time.on_change('value', xbox_callback)
    end_time.on_change('value', xbox_callback)

    # range slider to select threshold for hit detection in HTS mode
    global threshold_slider
    threshold_slider = Slider(start=0,
                              end=5,
                              value=2,
                              step=0.1,
                              title='HTS Hit Threshold (Standard Deviation)',
                              width=350)
    threshold_slider.on_change('value', threshold_callback)

    # range slider to update plots according to progress cuve xrange selection
    xmin = experiment_df[experiment_df.columns[0]].values[0]
    xmax = experiment_df[experiment_df.columns[0]].values[-1]
    global range_slider
    range_slider = RangeSlider(
        start=xmin,
        end=xmax,
        value=(xmin, xmax),
        step=experiment_df[experiment_df.columns[0]].values[1] - xmin,
        title='Fine Tune X-Axis Range',
        width=650)
    range_slider.on_change('value', slider_callback)

    # button to upload local data file
    global file_source
    file_source = ColumnDataSource(data=dict(file_contents=[], file_name=[]))
    file_source.on_change('data', file_callback)
    try:
        output_filename = 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=350)
    upload_button.callback = CustomJS(args=dict(file_source=file_source),
                                      code=open(
                                          join(dirname(__file__),
                                               "upload.js")).read())

    # table containing rate fits and errors
    template = """
    <div style="background:<%=ct%>"; color="white";>
    <%= value %></div>
    """
    formatter = HTMLTemplateFormatter(template=template)
    columns = [
        TableColumn(field='n', title='Sample'),
        TableColumn(field='yt',
                    title='Slope (Initial Rate)',
                    formatter=formatter),
        TableColumn(field='et', title='Std. Error')
    ]
    global rate_table
    rate_table = DataTable(source=model_data_source,
                           columns=columns,
                           width=350,
                           height=250,
                           selectable=True,
                           editable=True)

    # tables containing model fits and errors
    global mm_source
    mm_source = ColumnDataSource(dict(label=[], Km=[], Vmax=[]))
    columns = [
        TableColumn(field='label', title=''),
        TableColumn(field='Vmax', title='Vmax'),
        TableColumn(field='Km', title='Km')
    ]
    global mm_table
    mm_table = DataTable(source=mm_source,
                         columns=columns,
                         width=350,
                         height=75,
                         selectable=True,
                         editable=True)
    global ic_source
    ic_source = ColumnDataSource(
        dict(label=[], Bottom=[], Top=[], Slope=[], p50=[]))
    columns = [
        TableColumn(field='label', title=''),
        TableColumn(field='Bottom', title='Bottom'),
        TableColumn(field='Top', title='Top'),
        TableColumn(field='Slope', title='Slope'),
        TableColumn(field='p50', title='pEC/IC50')
    ]
    global ic_table
    ic_table = DataTable(source=ic_source,
                         columns=columns,
                         width=350,
                         height=75,
                         selectable=True,
                         editable=True)

    # button for copying rate data table to clipboard
    global copy_button
    copy_button = Button(label="Copy Table to Clipboard",
                         button_type="primary",
                         width=350)
    copy_button.callback = CustomJS(args=dict(source=model_data_source),
                                    code=open(
                                        join(dirname(__file__),
                                             "copy.js")).read())

    # button for downloading rate data table to local csv file
    global download_button
    download_button = Button(label="Download Table to CSV",
                             button_type="primary",
                             width=350)
    download_button.callback = CustomJS(args=dict(source=model_data_source,
                                                  file_name=output_filename),
                                        code=open(
                                            join(dirname(__file__),
                                                 "download.js")).read())

    ########## document formatting #########

    desc = Div(text=open(join(dirname(__file__), "description.html")).read(),
               width=1400)

    advanced = Div(
        text="""<strong>Advanced Settings for \npEC/IC50 Analysis</strong>""")

    widgets = widgetbox(model_select, sample_select, subtract_select,
                        transform_input, offset_input, advanced, scalex_box,
                        bottom_fix, top_fix, slope_fix)
    table = widgetbox(rate_table)
    main_row = row(
        column(upload_button, widgets),
        column(fit_button, row(raw, model), resi, row(start_time, end_time),
               range_slider),
        column(download_button, copy_button, table, mm_table, ic_table,
               threshold_slider))

    sizing_mode = 'scale_width'
    l = layout([[desc], [main_row]], sizing_mode=sizing_mode)

    update()
    curdoc().clear()
    curdoc().add_root(l)
    curdoc().title = "ICEKAT"
Beispiel #31
0
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"
Beispiel #32
0
            'flags': df_slice['all_flags'],
            'single_flag': df_slice['single_flag'],
            'sim_age': df_slice['sim_age']
        }).data


slider = RangeSlider(start=0,
                     end=30,
                     value=(0, 30),
                     step=1,
                     title='Simulated Age')
slider.on_change('value', callback)

buttons = CheckboxButtonGroup(labels=buttonlabels,
                              active=[0, 1, 2, 3, 4, 5, 6])
buttons.on_change('active', callback)

select = Select(title='Vectorization',
                value='Bag of Words',
                options=['Bag of Words', 'Doc2Vec'])
select.on_change('value', callback)

tooltips = [('Comment', '@text'), ('Flags', '@flags'), ('Age (d)', '@sim_age')]

n_obs = df.shape[0]
manif = 't-SNE'
title = '{} visualization of {} observations'.format(manif, n_obs)

p = figure(plot_width=figsize[0],
           plot_height=figsize[1],
           title=title,
def density_tab(flights):
	
	# Dataset for density plot based on carriers, range of delays,
	# and bandwidth for density estimation
	def make_dataset(carrier_list, range_start, range_end, bandwidth):

		xs = []
		ys = []
		colors = []
		labels = []

		for i, carrier in enumerate(carrier_list):
			subset = flights[flights['name'] == carrier]
			subset = subset[subset['arr_delay'].between(range_start, 
														range_end)]

			kde = gaussian_kde(subset['arr_delay'], bw_method=bandwidth)
			
			# Evenly space x values
			x = np.linspace(range_start, range_end, 100)
			# Evaluate pdf at every value of x
			y = kde.pdf(x)

			# Append the values to plot
			xs.append(list(x))
			ys.append(list(y))

			# Append the colors and label
			colors.append(airline_colors[i])
			labels.append(carrier)

		new_src = ColumnDataSource(data={'x': xs, 'y': ys, 
								   'color': colors, 'label': labels})

		return new_src

	def make_plot(src):
		p = figure(plot_width = 700, plot_height = 700,
				   title = 'Density Plot of Arrival Delays by Airline',
				   x_axis_label = 'Delay (min)', y_axis_label = 'Density')


		p.multi_line('x', 'y', color = 'color', legend = 'label', 
					 line_width = 3,
					 source = src)

		# Hover tool with next line policy
		hover = HoverTool(tooltips=[('Carrier', '@label'), 
									('Delay', '$x'),
									('Density', '$y')],
						  line_policy = 'next')

		# Add the hover tool and styling
		p.add_tools(hover)

		p = style(p)

		return p
	
	def update(attr, old, new):
		# List of carriers to plot
		carriers_to_plot = [carrier_selection.labels[i] for i in 
							carrier_selection.active]
		
		# If no bandwidth is selected, use the default value
		if bandwidth_choose.active == []:
			bandwidth = None
		# If the bandwidth select is activated, use the specified bandwith
		else:
			bandwidth = bandwidth_select.value
			
		
		new_src = make_dataset(carriers_to_plot,
									range_start = range_select.value[0],
									range_end = range_select.value[1],
									bandwidth = bandwidth)
		
		src.data.update(new_src.data)
		
	def style(p):
		# Title 
		p.title.align = 'center'
		p.title.text_font_size = '20pt'
		p.title.text_font = 'serif'

		# Axis titles
		p.xaxis.axis_label_text_font_size = '14pt'
		p.xaxis.axis_label_text_font_style = 'bold'
		p.yaxis.axis_label_text_font_size = '14pt'
		p.yaxis.axis_label_text_font_style = 'bold'

		# Tick labels
		p.xaxis.major_label_text_font_size = '12pt'
		p.yaxis.major_label_text_font_size = '12pt'

		return p
	
	# Carriers and colors
	available_carriers = list(set(flights['name']))
	available_carriers.sort()

	airline_colors = Category20_16
	airline_colors.sort()

	# Carriers to plot
	carrier_selection = CheckboxGroup(labels=available_carriers, 
									   active = [0, 1])
	carrier_selection.on_change('active', update)
	
	range_select = RangeSlider(start = -60, end = 180, value = (-60, 120),
							   step = 5, title = 'Range of Delays (min)')
	range_select.on_change('value', update)
	
	# Initial carriers and data source
	initial_carriers = [carrier_selection.labels[i] for 
						i in carrier_selection.active]
	
	# Bandwidth of kernel
	bandwidth_select = Slider(start = 0.1, end = 5, 
							  step = 0.1, value = 0.5,
							  title = 'Bandwidth for Density Plot')
	bandwidth_select.on_change('value', update)
	
	# Whether to set the bandwidth or have it done automatically
	bandwidth_choose = CheckboxButtonGroup(
		labels=['Choose Bandwidth (Else Auto)'], active = [])
	bandwidth_choose.on_change('active', update)

	# Make the density data source
	src = make_dataset(initial_carriers, 
						range_start = range_select.value[0],
						range_end = range_select.value[1],
						bandwidth = bandwidth_select.value) 
	
	# Make the density plot
	p = make_plot(src)
	
	# Add style to the plot
	p = style(p)
	
	# Put controls in a single element
	controls = WidgetBox(carrier_selection, range_select, 
						 bandwidth_select, bandwidth_choose)
	
	# Create a row layout
	layout = row(controls, p)
	
	# Make a tab with the layout 
	tab = Panel(child=layout, title = 'Density Plot')

	return tab