Unable to update ColumnDataSource for whiskered-plot

I’m having issues with the following code (I’ve cut out
large pieces but I can add them back in – these seemed like the important
parts). In my main code, I set up a plot
(“sectionizePlot”) which is a simple variation on another whiskered-plot (https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html)). I’m looking to update them on the fly. In the same script, I’m using a heatmap (“ModifiedGenericHeatMap”)
which updates fine.

Any ideas how I might update my whiskered-plot? Updating the ColumnDataSource doesn’t seem to
work (which makes sense). I’m guessing
that I am running into issues with adding each circle/point individually onto
the plot.

One idea would be to clear the plot each time and manually
add the points onto the plot, but it would need to be cleared each time, which
I’m unsure of how to do.

Any help would be appreciated. I’m just a lowly Scientist trying to utilize
Bokeh in Pharma research.

def ModifiedgenericHeatMap(source, maxPct):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    #mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
    mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="derp",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1000, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count'),
    ]
    return globalDist

def sectionizePlot(source, source_error, type, base):
    print("sectionize plot created with typ: " + type)
    colors = []
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source_error, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        print("hit a row")
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

famData = dict()
e1FractSource = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))
e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)
rowSectTotSource = ColumnDataSource(data=dict(base=[]))
rowSectTotSource_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, "eSum Row", rowBase)

def update(selected=None):
    global famData
    famData = getFAMData(file_source_dt1, True)
    global e1Stack
    e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
    e1Stack = e1Fract.stack(dropna=False).reset_index()
    e1Stack.columns = ["rows", "cols", "count"]
    e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
    e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                              rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )

    rowData, colData = sectionize(famData['eSum'], rows, cols)
    rowData_lower, rowData_upper = getLowerUpper(rowData)
    rowBase = list(range(1, 17))
    rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper, )
    rowSectTotSource.data = dict(base=rowData)
    rowSectPlot_tot.title.text = "plot changed in update"

layout = column(e1FractSource, rowSectPlot_tot)
update()

curdoc().add_root(layout)
curdoc().title = "Specs"
print("ok")

Hi,

Update in response to what? Updating a ColumnDataSource is precisely the usual way to cause a plot to update, but it's usually done in a callback for a widget or other event, and you don't seem to have defined or set up any callbacks. It's good to start with simple examples to build understanding, The sliders.py example is a minimal example that is fairly prototypical of Bokeh app structure:

  https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py

Does that example make sense wrt to how the updates are being triggered and how they are performed?

Thanks,

Bryan

···

On Aug 1, 2018, at 12:35, [email protected] wrote:

I’m having issues with the following code (I’ve cut out large pieces but I can add them back in – these seemed like the important parts). In my main code, I set up a plot (“sectionizePlot”) which is a simple variation on another whiskered-plot (https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html). I’m looking to update them on the fly. In the same script, I’m using a heatmap (“ModifiedGenericHeatMap”) which updates fine.
Any ideas how I might update my whiskered-plot? Updating the ColumnDataSource doesn’t seem to work (which makes sense). I’m guessing that I am running into issues with adding each circle/point individually onto the plot.
One idea would be to clear the plot each time and manually add the points onto the plot, but it would need to be cleared each time, which I’m unsure of how to do.
Any help would be appreciated. I’m just a lowly Scientist trying to utilize Bokeh in Pharma research.

def ModifiedgenericHeatMap(source, maxPct):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    #mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
    mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="derp",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1000, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count'),
    ]
    return globalDist

def sectionizePlot(source, source_error, type, base):
    print("sectionize plot created with typ: " + type)
    colors =
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source_error, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        print("hit a row")
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

famData = dict()
e1FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))
e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)
rowSectTotSource = ColumnDataSource(data=dict(base=))
rowSectTotSource_error = ColumnDataSource(data=dict(base=, lower=, upper=))
rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, "eSum Row", rowBase)

def update(selected=None):
    global famData
    famData = getFAMData(file_source_dt1, True)
    global e1Stack
    e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
    e1Stack = e1Fract.stack(dropna=False).reset_index()
    e1Stack.columns = ["rows", "cols", "count"]
    e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
    e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                              rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )

    rowData, colData = sectionize(famData['eSum'], rows, cols)
    rowData_lower, rowData_upper = getLowerUpper(rowData)
    rowBase = list(range(1, 17))
    rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper, )
    rowSectTotSource.data = dict(base=rowData)
    rowSectPlot_tot.title.text = "plot changed in update"

layout = column(e1FractSource, rowSectPlot_tot)
update()

curdoc().add_root(layout)
curdoc().title = "Specs"
print("ok")

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/d15791f0-4907-4527-b697-5b252b7e5fb9%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

I understand how the updates are being performed in
sliders.py.

I left out part of the code to keep things short. I’m uploading an excel file and parsing it in
a callback (FAM_file_callback_dt1) and creating heatmaps (ModifiedGenericHeatmap)
and attempting to create whiskered plots (sectionizePlot). I’m updating the ColumnDataSources in the
callback and also in update (which is likely doing the same action twice), and
the correct data is generating and saving to the ColumnDataSources.

But in the case of my whiskered-plot (sectionizePlot), the
plot is not updating. I’m guessing that
this may be related to how I’m generating my plot in the sectionizePlot method
(which is based on https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html).

I’m manually generating the first whiskered plot in main, so
my plot creation method seems to be working.
So, I know my method plots, I just don’t know how to update it.

Larger code is attached below with some of the irrelevent methods minimized.

try:
    from functools import lru_cache
except ImportError:
    # Python 2 does stdlib does not have lru_cache so let's just
    # create a dummy decorator to avoid crashing
    print ("WARNING: Cache for this example is available on Python 3 only.")
    def lru_cache():
        def dec(f):
            def _(*args, **kws):
                return f(*args, **kws)
            return _
        return dec
from os.path import dirname, join
import pandas as pd
import numpy as np
from math import pi
from bokeh.io import output_file, show, curdoc
from bokeh.layouts import row, column, widgetbox
from bokeh.models import (
    ColumnDataSource,
    HoverTool,
    LinearColorMapper,
    BasicTicker,
    PrintfTickFormatter,
    ColorBar,
    Legend,
    Whisker,
)
from bokeh.models.widgets import PreText, Select, RadioGroup, TextInput
from bokeh.plotting import figure
from bokeh.transform import dodge, factor_cmap
import bokeh.plotting
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import Button
import io
import base64
import random
import statistics as stat
from bokeh.models.tickers import SingleIntervalTicker
from bokeh.plotting import figure, show

def labelWellCat(row):
    if ((row['Well'][2] == "1") or (row['Well'][2] == "2")) and (row['Well'][1] == "0"):
        return "Control"
    return "Sample"

def labelRow(row):
    return str(row['Well'][0].rstrip())

def labelCol(row):
    return str(int(row['Well'][1:].rstrip()))

def buildPlate():
    rows = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"]
    cols = [str(x) for x in range(1, 25)]

    #create a data frame out of info
    df = pd.read_csv("/Users/Jonathan_Erikson/Desktop/djangogirls/files/SpecifTemp.csv")
    df.columns.values[0] = "Well"
    df.columns.values[1] = "ID"

    df['WellCat'] = ""
    df['WellCat'] = df.apply(lambda row: labelWellCat(row), axis=1)
    df['row'] = df.apply(lambda row: labelRow(row), axis=1)
    df['col'] = df.apply(lambda row: labelCol(row), axis=1)
    cmap = {
        "Sample" : "#1f78b4",
        "Control" : "#d93b43",
    }
    source = ColumnDataSource(df)
    p = figure(plot_width=900, plot_height=500, title="This plot doest nothing besides looking pretty",
    #p = figure(plot_width=1800, plot_height=1000, title="Title Goes Here",
               x_range=cols, y_range=list(reversed(rows)), toolbar_location=None, tools="")
    #removing the legend
    #p.rect("col", "row", 0.95, 0.95, source=source, fill_alpha=0.6, legend="WellCat",
    p.rect("col", "row", 0.95, 0.95, source=source, fill_alpha=0.6,
           color=factor_cmap('WellCat', palette=list(cmap.values()), factors=list(cmap.keys())))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("col", -0.4, range=p.x_range)
    '''
    r = p.text(x=x, y="row", text="symbol", **text_props)
    r.glyph.text_font_style="bold"
    '''
    r = p.text(x=x, y=dodge("row", 0.3, range=p.y_range), text="Well", **text_props)
    r.glyph.text_font_size="8pt"
    r = p.text(x=x, y=dodge("row", -0.35, range=p.y_range), text="ID", **text_props)
    r.glyph.text_font_size="5pt"
    r = p.text(x=x, y=dodge("row", -0.2, range=p.y_range), text="RowHdr", **text_props)
    r.glyph.text_font_size="5pt"
    #this just blocks out individual blocks
    '''
    p.text(x=["3", "3"], y=["VI", "VII"], text=["LA", "AC"], text_align="center", text_baseline="middle")
    '''
    p.add_tools(HoverTool(tooltips = [
        #("Well", "@name"),
        ("Well", "@Well"),
        ("ID", "@ID"),
        ("RowHdr", "@RowHdr"),
    ]))
    p.outline_line_color = None
    p.grid.grid_line_color = None
    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_standoff = 0
    #leaving out the legend for now
    #p.legend.orientation = "horizontal"
    #p.legend.location ="top_right"
    return p

def getCodonData(codon, counts, printStats):
    codonDist = counts.loc[[codon]]
    #Max
    codonMax = codonDist.values.max()
    #Min
    codonMin = codonDist.values.min()
    #Total codon distribution
    codonTotal = float(codonDist.sum(axis=1))
    #Fraction of total distributed codons in each well
    codonDistFract = codonDist.divide(float(codonTotal), axis=1)
    #Get all wells above the threshold
    #DF of booleans
    threshold = 0.01
    codonAboveThreshAll = codonDistFract > threshold
    codonAboveThreshTot = codonAboveThreshAll.sum(axis=1)
    #get the relevant values
    codonAboveThreshCount = codonDist[codonAboveThreshAll].dropna(axis=1)
    #IDs
    codonAboveThreshID = codonAboveThreshCount.columns
    #Codons correct in well
    codonCorr = float(codonMax) / codonDist.sum(axis=1)
    #transform into a dataframe
    codonDistPlate = pd.DataFrame(columns=range(1, 25))
    rows = "ABCDEFGHIJKLMNOP"
    x = 0
    values = list(codonDistFract.loc[codon])
    for row in rows:
        codonDistPlate.loc[row] = values[x:(x + 24)]
        x += 24
    if (printStats == True):
        print("Using Codon {0}".format(codon))
        print("Max Codon Count is: " + str(codonMax))
        print("Min Codon Count is: " + str(codonMin))
        print("Total Codon Count is: " + str(codonTotal))
        print("Codons above threshold {0}: ".format(threshold))
        print(codonAboveThreshID)
    codonData = {}
    codonData['codon'] = codon
    codonData['codonDist'] = codonDist
    codonData['codonMax'] = codonMax
    codonData['codonMin'] = codonMin
    codonData['codonTotal'] = codonTotal
    #changed to filter out NaN values
    codonData['codonDistFract'] = codonDistFract.replace(np.nan, 0)
    codonData['threshhold'] = threshold
    codonData['codonAboveThreshAll'] = codonAboveThreshAll
    codonData['codonAboveThreshCount'] = codonAboveThreshCount
    codonData['codonAboveThreshID'] = codonAboveThreshID
    codonData['codonCorr'] = codonCorr
    codonData['codonDistPlate'] = codonDistPlate
    return codonData

'''
changed
temprarily commented out
this parses the file directy for the first page instead of being able to choose
    the file and open it up which deals with it differently
can change method name to signify
'''
def getSpecDataOld(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    #drop last column
    counts = counts.drop(counts.columns[384], axis=1)
    #last column is now dropped
    print("DF Dimensions: " + str(counts.shape))
    counts = counts.drop('Total')
    return counts

def getFAMData(file, ioStyle):
    if(ioStyle):
        print("Using the ioStyle")
        print('filename:', file.data['file_name'])
        raw_contents = file.data['file_contents'][0]
        prefix, b64_contents = raw_contents.split(",", 1)
        file_contents = base64.b64decode(b64_contents)
        file_io = io.BytesIO(file_contents)
        excel_object = pd.ExcelFile(file_io, engine='xlrd')
        fam = excel_object.parse("RawFAM")
    else:
        famFile = pd.ExcelFile(file)
        print("Sheet Names: " + str(famFile.sheet_names))
        fam = famFile.parse("RawFAM")
    fam.drop(fam.columns[[0, 1, 26, 27, 28, 29, 30]], axis=1, inplace=True)
    w1 = fam[2:18]
    w2 = fam[22:38]
    w3 = fam[42:58]
    e1 = fam[62:78]
    e2 = fam[82:98]
    e3 = fam[102:118]
    samples = fam[122:123]
    samples.rename(index={122: 'samples'})
    samples = samples.iloc[:, 0:8]
    samples.columns = ['S1', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'HB2tRNA']
    samplesSub = samples.subtract(samples['HB2tRNA'].iloc[0])
    rows = [x for x in "ABCDEFGHIJKLMNOP"]
    for x in [e1, e2, e3]:
        x.columns = [y for y in range(1, 25)]
        x['row'] = rows
        x.set_index('row', inplace=True)
    e1Sub = e1 - (e1.iloc[6, 0])
    e2Sub = e2 - (e2.iloc[6, 0])
    e3Sub = e3 - (e3.iloc[6, 0])
    eSum = e1Sub + e2Sub + e3Sub
    famData = {}
    famData["w1"] = w1
    famData["w2"] = w2
    famData["w3"] = w3
    famData["e1"] = e1
    famData["e1Sub"] = e1Sub
    famData["e2"] = e2
    famData["e2Sub"] = e2Sub
    famData["e3"] = e3
    famData["e3Sub"] = e3Sub
    famData["eSum"] = eSum
    famData["samples"] = samples
    famData["samplesSub"] = samplesSub
    return famData

'''
Input:
well - i.e. "A03"

Output:
row - row coordinate in DF
col - column coordinate in DF

Strategy:
This parses out the corresponding well and column of a DF for a specific well

'''
def getCoords(well):
    row = well[0]
    col = int(well[1:])
    rows = list("ABCDEFGHIJKLMNOP")
    row = rows.index(row)
    col = col - 1
    return row, col

'''
Input:
codonData
famData
counts

Output:
fractSig
codSig
specialNumber

Strategy:
This does the stuff on the whiteboard

'''
def calculateWhiteBoard(codonData, famData, counts):
    fractSig = codonData['codonDistPlate'] * famData['eSum']
    totalSig = fractSig.values.sum()
    codonMap, wellMap = getMaps(counts)
    well = codonMap[codonData['codon']]
    row, col = getCoords(well)
    #fractional signal of specific codon
    codSig = fractSig.iloc[row, col]
    #special number from the white board
    specialNumber = codSig / totalSig
    return fractSig, codSig, specialNumber

def ModifiedgenericHeatMap(source, maxPct):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    #mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
    mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="derp",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1000, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count'),
    ]
    return globalDist

'''
Strategy:

Input:

Output:

'''
def getSpecData(file, ioStyle):
    if(ioStyle):
        print("Using the ioStyle")
        print('filename:', file.data['file_name'])
        raw_contents = file.data['file_contents'][0]
        prefix, b64_contents = raw_contents.split(",", 1)
        file_contents = base64.b64decode(b64_contents)
        file_io = io.BytesIO(file_contents)
        excel_object = pd.ExcelFile(file_io, engine='xlrd')
        counts = excel_object.parse(N=0)
    else:
        specFile = pd.ExcelFile(file)
        print("Sheet Names: " + str(specFile.sheet_names))
        counts = specFile.parse(N=0)
    #drop last column
    counts = counts.drop(counts.columns[384], axis=1)
    #last column is now dropped
    print("DF Dimensions: " + str(counts.shape))
    counts = counts.drop('Total')
    return counts

'''
Strategy:

Input:

Output:

'''
def plateHeatMap(df, inverse):
    rows = []
    cols = []
    if inverse:
        for x in range(0, 24):
            for y in "ABCDEFGHIJKLMNOP":
                rows.append(y)
        for x in range(1, 25):
            for y in range(0, 16):
                cols.append(x)
    else:
        for x in "ABCDEFGHIJKLMNOP":
            for y in range(0, 24):
                rows.append(x)
        for x in range(0, 16):
            for y in range(1, 25):
                cols.append(y)
    df["rows"] = rows
    df['cols'] = cols
    if 'codon' in df.columns:
        df = df.rename(columns={df['codon']: 'count'})
    else:
        df = df.rename(columns={df.columns[0]: "count"})
    df["rows"] = rows
    df['cols'] = cols
    return df

'''
changed

need to denote that this gets the wells and codons directly from the file

'''
def getWellsCodons(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    wells = list(counts.columns.values)
    codons = list(counts.index.values)
    return wells, codons

def nix(val, lst):
    return [x for x in lst if x != val]

@lru_cache()
def load_codon(codon):
    return "derp"

@lru_cache()
def get_data(cod1):
    return "derp"

'''
Strategy:

Input:

Output:

'''
def getStats(codonData):
    output = ""
    # top codon destinations
    temp = codonData['codonAboveThreshCount'].transpose()
    # drop the top value
    #if there is a top value
    output += "For codon: " + codonData['codon'] + "\n"
    if not temp.empty:
        topCod = temp.drop(temp[codonData['codon']].idxmax())
        # get the percentages of other codon
        topCod['fract'] = (topCod[codonData['codon']] / codonData['codonTotal']) * 100
        wells = topCod.index.values
        wells = [x.split("-")[0] for x in wells]
        top = topCod['fract'].to_string()
        output += "Percentage of total codon distribution in the correct well:\t" + \
                  (100 * (codonData['codonCorr'])).to_string().split()[1] + \
                  "%\n"
        output += "Precentage of total codon distribution in wrong wells:\t" + \
                  (100 * (1 - (codonData['codonCorr']))).to_string().split()[1] + \
                  "%\n"
        output += "Top codon destinations:\n"
        output += str(wells) + "\n"
        output += topCod['fract'].to_string()
    else:
        output += "Percentage of total codon distribution in the correct well:\t" + \
                  (100 * (codonData['codonCorr'])).to_string().split()[1] + \
                  "%\n"
        output += "Precentage of total codon distribution in wrong wells:\t" + \
                  (100 * (1 - (codonData['codonCorr']))).to_string().split()[1] + \
                  "%\n"
    aboveThreshold = codonData['codonDistFract'][codonData['codonAboveThreshID']]
    names = [well for well in aboveThreshold.columns.values]
    values = [value for value in aboveThreshold.values][0].tolist()
    return output

'''
Strategy:

Input:

Output:

'''
def getWellIDs(wells):
    rows = []
    cols = []
    if (wells == 384):
        for x in "ABCDEFGHIJKLMNOP":
            rows.append(x)
        for x in range(1, 25):
            cols.append(str(x))
    if (wells == 96):
        for x in "ABCDEFGH":
            rows.append(x)
        for x in range(1, 17):
            cols.append(str(x))
    return cols, rows

'''
#this is backwards from the other one for codon distribution

Strategy:

Input:

Output:

'''
def plateHeatMapInverse(df):
    rows = []
    for x in range(0, 24):
        for y in "ABCDEFGHIJKLMNOP":
            rows.append(y)
    cols = []
    for x in range(1, 25):
        for y in range(0, 16):
            cols.append(x)
    df["rows"] = rows
    df['cols'] = cols
    df.columns.values[0] = 'count'
    cols = []
    for x in range(1, 25):
        cols.append(str(x))
    rows = []
    for x in "ABCDEFGHIJKLMNOP":
        rows.append(x)
    return df

'''
#gets the amount of globally distributed that ended up in the correct well

Strategy:

Input:

Output:

'''
def getGlobalCorr(counts):
    #grab the list of the codons
    codons = counts.index.values
    #get the percentage of codons correctly distributed to each well of global
    corr = np.array([])
    for codon in codons:
        codonData = getCodonData(codon, counts, False)
        corr = np.append(corr, float(codonData['codonCorr']))
    #remove NaN
    corr[np.isnan(corr)] = 0
    corrDF = pd.DataFrame(data=corr)
    #round the decimals
    globalCorr = plateHeatMap(corrDF, True)
    globalCorr['count'] = globalCorr['count'].apply(lambda x: round(x, 3))
    return globalCorr

'''
changed 20180620 1058
-removing the counts part because counts is now a globalvariable
-removing codons because does nothing

Strategy:

Input:

Output:

'''
def getGlobalDistHeatMap(globalCorr, item):
    source = ColumnDataSource(dict(cols=globalCorr["cols"], count=(globalCorr["count"] * 100), rows=globalCorr["rows"],
                                   codon=globalCorr[item],
                                   index=counts.index.values))
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    mapper = LinearColorMapper(palette=colors, low=90, high=100)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="Global codon that in to correct well (%)",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1080, plot_height=480,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    r = globalDist.text(x=x, y=dodge("rows", -0.35, range=globalDist.y_range), text="codon", **text_props)
    r.glyph.text_font_size = "5pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
        ('Codon:', '@codon'),
    ]
    return globalDist

'''
Strategy:

Input:

Output:

'''
def getWellData(well, wCounts):
    wellDist = wCounts.loc[[well]]
    # Max
    wellMax = wellDist.values.max()
    # Min
    wellMin = wellDist.values.min()
    # Total codon distribution
    wellTotal = float(wellDist.sum(axis=1))
    # Fraction of total distributed codons in each well
    wellDistFract = wellDist.divide(float(wellTotal), axis=1)

    # still need to verify that max codon is the correct codon

    # Get all wells above the threshold
    # DF of booleans
    threshold = 0.01
    wellAboveThreshAll = wellDistFract > threshold
    wellAboveThreshTot = wellAboveThreshAll.sum(axis=1)
    # get the relevant values
    wellAboveThreshCount = wellDist[wellAboveThreshAll].dropna(axis=1)
    # IDs
    wellAboveThreshID = wellAboveThreshCount.columns
    # Codons correct in well
    wellCorr = float(wellMax) / wellDist.sum(axis=1)
    # transform into a dataframe
    wellDistPlate = pd.DataFrame(columns=range(1, 25))
    rows = "ABCDEFGHIJKLMNOP"
    x = 0
    values = list(wellDistFract.loc[well])
    for row in rows:
        wellDistPlate.loc[row] = values[x::16]
        x += 1
    wellData = {}
    wellData['well'] = well
    wellData['wellDist'] = wellDist
    wellData['wellMax'] = wellMax
    wellData['wellMin'] = wellMin
    wellData['wellTotal'] = wellTotal
    # changed to filter out NaN values
    wellData['wellDistFract'] = wellDistFract.replace(np.nan, 0)
    wellData['threshold'] = threshold
    wellData['wellAboveThreshAll'] = wellAboveThreshAll
    wellData['wellAboveThreshCount'] = wellAboveThreshCount
    wellData['wellAboveThreshID'] = wellAboveThreshID
    wellData['wellCorr'] = wellCorr
    wellData['wellDistPlate'] = wellDistPlate
    return wellData

def getGlobalWellCorr(wCounts):
    #grab the list of the codons
    indexWells = wCounts.index.values
    #get the percentage of codons correctly distributed to each well of global
    corr = np.array([])
    for well in indexWells:
        wellData = getWellData(well, wCounts)
        corr = np.append(corr, float(wellData['wellCorr']))
    #remove NaN
    corr[np.isnan(corr)] = 0
    corrDF = pd.DataFrame(data=corr)
    #round the decimals
    globalCorr = plateHeatMap(corrDF, False)
    globalCorr['count'] = globalCorr['count'].apply(lambda x: round(x, 3))
    return globalCorr

def getMaps(counts):
    codonList = counts.index.values.tolist()
    wellList = counts.columns.values.tolist()
    wellList = [x.split("-")[0] for x in wellList]
    codonMap = {}
    wellMap = {}
    z= 0
    for x in range(0, 24):
        for y in range(x, 384, 24):
            codonMap[codonList[z]] = wellList[y]
            wellMap[wellList[y]] = codonList[z]
            z += 1
    return codonMap, wellMap

def getWellsCodons(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    wells = list(counts.columns.values)
    codons = list(counts.index.values)
    return wells, codons

'''
Widget Section
'''

stats = PreText(text='', width=1080, height=240)
fileSel = TextInput(value="default", title="File Name")

counts = pd.DataFrame()
cols, rows = getWellIDs(384)
globalCorr = pd.DataFrame(columns=["count", "rows", "cols", "codon"])

'''
Input:
source - a ColumnDataSource with:
    dict(count=[], cols=[], rows=[], index=[], codon=[])

Output:
globalDist - a heat map

Strategy:
This accepts a CDS and returns a heat map. This can be made with a CDS and then have the data updated with:
    globalDistSource.data = dict(cols=globalCorr["cols"], count=(globalCorr["count"] * 100),
                       rows=globalCorr["rows"], index=counts.index.values, codon=globalCorr['codon'],)
'''
def globalDist(source):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    mapper = LinearColorMapper(palette=colors, low=95, high=100)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"

    globalDist = figure(title="Global codon that in to correct well (%)",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=900, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    r = globalDist.text(x=x, y=dodge("rows", -0.35, range=globalDist.y_range), text="codon", **text_props)
    r.glyph.text_font_size = "5pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
        ('Codon:', '@codon'),
    ]
    return globalDist

'''
Input:
source - a ColumnDataSource with:
    dict(count=[], cols=[], rows=[], index=[], codon=[])

Output:
globalDist - a heat map

Strategy:
This accepts a CDS and returns a heat map. This can be made with a CDS and then have the data updated with:
    source.data = dict(cols=derp2["cols"], count=(derp2["count"] * 100),
    rows=derp2["rows"], index=derp2.index.values, )
'''
def codonDist(source):
    # source = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]

    # commenting out the mapper to replace in the method section
    # mapper = LinearColorMapper(palette=colors, low=df['count'].min(), high=df['count'].max())

    # previous correct one below - replacing with zero
    # mapper = LinearColorMapper(palette=colors, low=min(source.data['count']), high=max(source.data['count']))
    # changing this to high of
    mapper = LinearColorMapper(palette=colors, low=0, high=1)
    # mapper = LinearColorMapper(palette=colors, low=0, high=1)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    p = figure(title="temp",
               x_range=cols, y_range=list(reversed(rows)),
               x_axis_location="above", plot_width=900, plot_height=400,
               tools=TOOLS, toolbar_location='below')
    p.grid.grid_line_color = None
    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_text_font_size = "5pt"
    p.axis.major_label_standoff = 0
    p.xaxis.major_label_orientation = pi / 3
    p.rect(x="cols", y="rows", width=1, height=1,
           source=source,
           fill_color={'field': 'count', 'transform': mapper},
           line_color=None)
    # commenting out the mapper part to go into methods later

    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    p.add_layout(color_bar, 'right')

    p.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
    ]
    return p

'''
#this deals with the inputting of the file
'''
def FAM_file_callback_dt1(attr,old,new):
    global famData
    famData = getFAMData(file_source_dt1, True)

    global eSumStack
    eSumStack = famData['eSum'].stack(dropna=False).reset_index()
    eSumStack.columns = ["rows", "cols", "count"]
    eSumStack['count'] = eSumStack['count'].apply(lambda x: round(x, 1))

    global e1Stack
    e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
    e1Stack = e1Fract.stack(dropna=False).reset_index()
    e1Stack.columns = ["rows", "cols", "count"]
    e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
    e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                        rows=e1Stack["rows"], index=e1Stack.index.values, )
    #e1Fract.color_mapper.high = 100
    #e1Fract.color_bar.trigger('change')

    global e2Stack
    e2Fract = (famData['e2Sub'] / famData['eSum']) * 100
    e2Stack = e2Fract.stack(dropna=False).reset_index()
    e2Stack.columns = ["rows", "cols", "count"]
    e2Stack['count'] = e2Stack['count'].apply(lambda x: round(x, 1))
    e2FractSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                        rows=e2Stack["rows"], index=e2Stack.index.values, )

    global e3Stack
    e3Fract = (famData['e3Sub'] / famData['eSum']) * 100
    e3Stack = e3Fract.stack(dropna=False).reset_index()
    e3Stack.columns = ["rows", "cols", "count"]
    e3Stack['count'] = e3Stack['count'].apply(lambda x: round(x, 1))
    e3FractSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                        rows=e3Stack["rows"], index=e3Stack.index.values, )

    #lastPlot currently does nothing
    lastPlotSource.data = dict(count=[], cols=[], rows=[], index=[],)

    #the following code involved the whiskered-plots which are not updating

    rows = "ABCDEFGHIJKLMNOP"
    cols = 24
    rowBase = list(range(1, 17))
    colBase = list(range(1, 25))

    global rowData, rowData_lower, rowData_upper
    global rowDataE1, rowDataE1_lower, rowDataE1_upper
    global rowDataE2, rowDataE2_lower, rowDataE2_upper

    global colData, colData_lower, colData_upper
    global colDataE1, colDataE1_lower, colDataE1_upper
    global colDataE2, colDataE2_lower, colDataE2_upper

    #calculate the data here seems to work fine
    rowData, colData = sectionize(famData['eSum'], rows, cols)
    rowData_lower, rowData_upper = getLowerUpper(rowData)
    colData_lower, colData_upper = getLowerUpper(colData)
    rowDataE1, colDataE1 = sectionize(famData['e1Sub'], rows, cols)
    rowDataE1_lower, rowDataE1_upper = getLowerUpper(rowDataE1)
    colDataE1_lower, colDataE1_upper = getLowerUpper(colDataE1)
    rowDataE2, colDataE2 = sectionize(famData['e2Sub'], rows, cols)
    rowDataE2_lower, rowDataE2_upper = getLowerUpper(rowDataE2)
    colDataE2_lower, colDataE2_upper = getLowerUpper(colDataE2)

    #create the plots
    rowSectTotSource.data = dict(base=rowData)
    rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
    rowSectE1Source.data = dict(base=rowDataE1)
    rowSectE1Source_error.data = dict(base=rowBase, lower=rowDataE1_lower, upper=rowDataE1_upper)
    rowSectE2Source.data = dict(base=rowDataE2)
    rowSectE2Source_error.data = dict(base=rowBase, lower=rowDataE2_lower, upper=rowDataE2_upper)

    colSectTotSource.data = dict(base=colData)
    colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
    colSectE1Source.data = dict(base=colDataE1)
    colSectE1Source_error.data = dict(base=colBase, lower=colDataE1_lower, upper=colDataE1_upper)
    colSectE2Source.data = dict(base=colDataE2)
    colSectE2Source_error.data = dict(base=colBase, lower=colDataE2_lower, upper=colDataE2_upper)

    update()

'''
Strategy:
This does a simple bar chart for the various elution percentages along with an error bar.
(This can work for other non elution things)

Input:
groups - list of groups to plot
counts - list of counts
error - list standard deviation of counts
title - plot title

Output:
p - elution percentage plot with error bars

'''
def elutionPctPlot(groups, counts, error, title):
    upper = [x+e for x,e in zip(counts, error) ]
    lower = [x-e for x,e in zip(counts, error) ]

<details class='elided'>
<summary title='Show trimmed content'>&#183;&#183;&#183;</summary>

###
    #source point
    ###
    source = ColumnDataSource(data=dict(groups=groups, counts=counts, upper=upper, lower=lower))

    p = figure(x_range=groups, plot_height=350, toolbar_location=None, title=title, y_range=(0,100))
    p.vbar(x='groups', top='counts', width=0.9, source=source, legend="groups",
           line_color='white', fill_color=factor_cmap('groups', palette=["#962980","#295f96","#29966c","#968529"],
                                                      factors=groups))
    p.add_layout(
        Whisker(source=source, base="groups", upper="upper", lower="lower", level="overlay")
    )
    p.xgrid.grid_line_color = None
    p.legend.orientation = "horizontal"
    p.legend.location = "top_center"
    return p

'''
Strategy:
This returns 1 of 102 possible colors

Input:
None

Output:
a random color
'''
def getRandomColor():
    colors = ['aqua', 'aquamarine', 'black', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate',
         'coral', 'cornflowerblue', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen',
         'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon',
         'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
         'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'forestgreen', 'fuchsia', 'gold', 'goldenrod',
         'gray', 'green', 'greenyellow', 'grey', 'hotpink', 'indianred', 'indigo', 'khaki', 'lavender', 'lawngreen', 'lime',
         'limegreen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
         'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue',
         'navy', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue',
         'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'sienna', 'silver',
         'skyblue', 'slateblue', 'slategray', 'slategrey', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato',
              'turquoise', 'violet', 'yellow', 'yellowgreen']
    return colors[random.randint(0, 101)]

'''
Strategy:
This returns a list of random colors

Input:
numColors - the length of the random color list to return

Output:
colors- a list of random colors
'''
def createColorList(numColors):
    colors = []
    for x in range(0, numColors):
        colors.append(getRandomColor())
    return colors

'''
Strategy:
This "sectionizes" the df into a list of list of rows or columns.

Input:
df - a dataframe to sectionize
rows - row names (a, b, c etc.)
cols - number of columns

Output:
rowData - a list of lists of the rows
colData - a list of lists of the columns

'''
def sectionize(df, rows, cols):
    rowWise = df.stack()
    colWise = df.transpose().stack()
    rowData = []
    colData = []
    for x in rows:
        rowData.append(list(rowWise[x]))
    for x in range(1, (cols + 1)):
        colData.append(list(colWise[x]))
    return rowData, colData

'''
Strategy:
This creates a dot plot with error bars for either row-wise or column-wise data.
(This can work as a general method as well with minor modification)

Input:
data - a list of lists of the column or row data
type - "Row" or "Column"
base - a list of the range for the number of rows or columns

Output:
p - a plot of the sectional data
'''
def sectionizePlot(source, source_error, type, base):
    print("sectionize plot created with typ: " + type)
    colors = []
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source_error, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        print("hit a row")
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

#alternative to sectionizePlot using a single ColumnDataSource
def altSectionizePlot(source, type, base):
    print(source.data)
    #print(source.data["base"][0])
    print("alternative sectionize plot created with typ: " + type)
    colors = []
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        print("i: " + str(i) + str(sec))
        p.circle(x=source.data["base"][i], y=source.data["points"][i], color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

'''
Strategy:

Input:

Output:

'''
def getLowerUpper(data):
    lower, upper = [], []
    for x in data:
        if x:
            mean = stat.mean(x)
            std = stat.stdev(x)
            lower.append(mean - std)
            upper.append(mean + std)
        else:
            lower.append(0)
            upper.append(0)
    return lower, upper

famData = dict()
e1FractSource = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))
e2FractSource = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))
e3FractSource = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))
lastPlotSource = ColumnDataSource(dict(count=[], cols=[], rows=[], index=[]))

e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)
e2Fract = ModifiedgenericHeatMap(e2FractSource, 25)
e3Fract = ModifiedgenericHeatMap(e3FractSource, 10)
#last plot not in use
lastPlot = ModifiedgenericHeatMap(lastPlotSource, 100)

groups = []
counts = []
upper = []
lower = []
error = []
title = ""
eluPctPlot_source = ColumnDataSource(data=dict(groups=groups, counts=counts, upper=upper, lower=lower))

rowSectTotSource = ColumnDataSource(data=dict(base=[]))
rowSectTotSource_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
rowSectE1Source = ColumnDataSource(data=dict(base=[]))
rowSectE1Source_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
rowSectE2Source = ColumnDataSource(data=dict(base=[]))
rowSectE2Source_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))

colSectTotSource = ColumnDataSource(data=dict(base=[]))
colSectTotSource_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
colSectE1Source = ColumnDataSource(data=dict(base=[]))
colSectE1Source_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))
colSectE2Source = ColumnDataSource(data=dict(base=[]))
colSectE2Source_error = ColumnDataSource(data=dict(base=[], lower=[], upper=[]))

rowBase = list(range(1, 17))
colBase = list(range(1, 25))

rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, "eSum Row", rowBase)
colSectPlot_tot = sectionizePlot(colSectTotSource,colSectTotSource_error, "eSum Column", colBase)
rowSectPlot_e1 = sectionizePlot(rowSectE1Source,rowSectE1Source_error, "elu1 Row", rowBase)
colSectPlot_e1 = sectionizePlot(colSectE1Source,colSectE1Source_error, "elu1 Column", colBase)
rowSectPlot_e2 = sectionizePlot(rowSectE2Source,rowSectE2Source_error, "elu2 Row", rowBase)
colSectPlot_e2 = sectionizePlot(colSectE2Source,colSectE2Source_error, "elu2 Column", colBase)

#this plot does nothing for now
eluPctPlot = elutionPctPlot(groups, counts, error, title)

#this code manually generates a plot for rowSectPlotTot
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")
file = "/Users/Jonathan_Erikson/Desktop/Q1A1104.xlsm"
famData = getFAMData(file, False)
rows = "ABCDEFGHIJKLMNOP"
cols = 24
rowData, colData = sectionize(famData['eSum'], rows, cols)
rowData_lower, rowData_upper = getLowerUpper(rowData)
rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
print(rowSectTotSource_error.data)
rowSectTotSource.data = dict(base=rowData)
rowSectPlot_tot = sectionizePlot(rowSectTotSource, rowSectTotSource_error, "eSum Row", rowBase)
rowSectPlot_tot.title.text = "plot changed in main"
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")

#file upload section
file_source_dt1 = ColumnDataSource({'file_contents':[], 'file_name':[]})
file_source_dt1.on_change('data', FAM_file_callback_dt1)
button = Button(label="Upload FAM Excel File", button_type="success")
button.callback = CustomJS(args=dict(file_source=file_source_dt1), 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) {
    var b64string = event.target.result;
    file_source.data = {'file_contents' : [b64string], '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();
""")

def codon_change(attrname, old, new):
    #something something something
    update()

'''

likely changed something here

'''
def update(selected=None):
    if file_source_dt1.data['file_name']:
        global famData
        famData = getFAMData(file_source_dt1, True)

        global eSumStack
        eSumStack = famData['eSum'].stack().reset_index()
        eSumStack.columns = ["rows", "cols", "count"]
        eSumStack['count'] = eSumStack['count'].apply(lambda x: round(x, 1))
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24
        wells = []
        for row in rows:
            for col in range(1, (cols + 1)):
                wells.append(str(row + str(col)))

        global e1Stack
        e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
        e1Stack = e1Fract.stack(dropna=False).reset_index()
        e1Stack.columns = ["rows", "cols", "count"]
        e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
        e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                                  rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )
        #e1Fract.color_mapper.high = 100
        #e1Fract.color_bar.trigger('change')

        global e2Stack
        e2Fract = (famData['e2Sub'] / famData['eSum']) * 100
        e2Stack = e2Fract.stack(dropna=False).reset_index()
        e2Stack.columns = ["rows", "cols", "count"]
        e2Stack['count'] = e2Stack['count'].apply(lambda x: round(x, 1))
        e2FractSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                                  rows=e2Stack["rows"], index=e2Stack.index.values, codon=wells, )

        global e3Stack
        e3Fract = (famData['e3Sub'] / famData['eSum']) * 100
        e3Stack = e3Fract.stack(dropna=False).reset_index()
        e3Stack.columns = ["rows", "cols", "count"]
        e3Stack['count'] = e3Stack['count'].apply(lambda x: round(x, 1))
        e3FractSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                                  rows=e3Stack["rows"], index=e3Stack.index.values, codon=wells, )

        print(rowSectE2Source_error.data)

        global rowData, rowData_lower, rowData_upper
        global rowDataE1, rowDataE1_lower, rowDataE1_upper
        global rowDataE2, rowDataE2_lower, rowDataE2_upper

        global colData, colData_lower, colData_upper
        global colDataE1, colDataE1_lower, colDataE1_upper
        global colDataE2, colDataE2_lower, colDataE2_upper

        #problematic section
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24

        rowData, colData = sectionize(famData['eSum'], rows, cols)
        rowData_lower, rowData_upper = getLowerUpper(rowData)
        colData_lower, colData_upper = getLowerUpper(colData)
        rowDataE1, colDataE1 = sectionize(famData['e1Sub'], rows, cols)
        rowDataE1_lower, rowDataE1_upper = getLowerUpper(rowDataE1)
        colDataE1_lower, colDataE1_upper = getLowerUpper(colDataE1)
        rowDataE2, colDataE2 = sectionize(famData['e2Sub'], rows, cols)
        rowDataE2_lower, rowDataE2_upper = getLowerUpper(rowDataE2)
        colDataE2_lower, colDataE2_upper = getLowerUpper(colDataE2)

        rowBase = list(range(1, 17))
        colBase = list(range(1, 25))

        #STUFF FROM MAIN
        file = "/Users/Jonathan_Erikson/Desktop/Q1A1104.xlsm"
        famData = getFAMData(file, False)
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24
        rowBase = list(range(1, 17))
        colBase = list(range(1, 25))
        rowData, colData = sectionize(famData['eSum'], rows, cols)
        colData_lower, colData_upper = getLowerUpper(colData)

        rowSectTotSource.data = dict(base=rowData)
        rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
        rowSectE1Source.data = dict(base=rowDataE1)
        rowSectE1Source_error.data = dict(base=rowBase, lower=rowDataE1_lower, upper=rowDataE1_upper)
        rowSectE2Source.data = dict(base=rowDataE2)
        rowSectE2Source_error.data = dict(base=rowBase, lower=rowDataE2_lower, upper=rowDataE2_upper)

        colSectTotSource.data = dict(base=colData)
        colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
        colSectE1Source.data = dict(base=colDataE1)
        colSectE1Source_error.data = dict(base=colBase, lower=colDataE1_lower, upper=colDataE1_upper)
        colSectE2Source.data = dict(base=colDataE2)
        colSectE2Source_error.data = dict(base=colBase, lower=colDataE2_lower, upper=colDataE2_upper)

        rowSectPlot_tot.title.text = "plot changed in update"

    else:
        print("No file loaded yet.")
        #codonSource.data = dict(cols=[], count=[], rows=[], index=[], )
        e1FractSource.data = dict(cols=[], count=[], rows=[], index=[], )
        e2FractSource.data = dict(cols=[], count=[], rows=[], index=[], )
        e3FractSource.data = dict(cols=[], count=[], rows=[], index=[], )

        rowSectTotSource.data = dict(base=[])
        rowSectTotSource_error.data = dict(base=[], lower=[], upper=[])
        rowSectE1Source.data = dict(base=[])
        rowSectE1Source_error.data = dict(base=[], lower=[], upper=[])
        rowSectE2Source.data = dict(base=[])
        rowSectE2Source_error.data = dict(base=[], lower=[], upper=[])

        colSectTotSource.data = dict(base=[])
        colSectTotSource_error.data = dict(base=[], lower=[], upper=[])
        colSectE1Source.data = dict(base=[])
        colSectE1Source_error.data = dict(base=[], lower=[], upper=[])
        colSectE2Source.data = dict(base=[])
        colSectE2Source_error.data = dict(base=[], lower=[], upper=[])

def update_stats(codonData, codon):
    print("New codon (update stats): " + codon)
    derp = getStats(codonData)
    print(derp)
    stats.text = derp

#codonSel.on_change('value', codon_change)

def selection_change(attrname, old, new):
    codon = codonSel.value
    well = wellSel.value
    codonData = getCodonData(codon, counts, False)
    print("Selection changed: " + codon + " " + well)
    update_stats(codonData, cod)

def callback(window=None):
    #data = source.data
    m = cb_obj.active
    if m == "elu1":
        print("hit elu1")
        print(elu1Stack)
        lastPlotSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                                  rows=e1Stack["rows"], index=e1Stack.index.values, codon=e1Stack['well'], )
    elif m == "elu2":
        print("hit elu2")
        lastPlotSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                                  rows=e2Stack["rows"], index=e2Stack.index.values, codon=e2Stack['well'], )
    elif m == "elu3":
        print("hit elu3")
        lastPlotSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                                  rows=e3Stack["rows"], index=e3Stack.index.values, codon=e3Stack['well'], )
    else:
        print("hit none")
        lastPlotSource.data = dict(cols=[], count=[],
                                  rows=[], index=[], codon=[], )

    lastPlotSource.trigger('change')

input1 = bokeh.models.RadioGroup(labels=["elu1", "elu2", "elu3", "none"],active=0,
                   callback=bokeh.models.CustomJS.from_py_func(callback))

layout = column(button, input1, lastPlot, e1Fract, e2Fract, e3Fract, eluPctPlot, rowSectPlot_tot,
                colSectPlot_tot, rowSectPlot_e1, colSectPlot_e1, rowSectPlot_e2, colSectPlot_e2)

# initialize
update()
curdoc().add_root(layout)
curdoc().title = "Specs"
print("ok")

On Wednesday, 1 August 2018 14:06:02 UTC-7, Bryan Van de ven wrote:

Hi,

Update in response to what? Updating a ColumnDataSource is precisely the usual way to cause a plot to update, but it’s usually done in a callback for a widget or other event, and you don’t seem to have defined or set up any callbacks. It’s good to start with simple examples to build understanding, The sliders.py example is a minimal example that is fairly prototypical of Bokeh app structure:

    [https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py](https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py)

Does that example make sense wrt to how the updates are being triggered and how they are performed?

Thanks,

Bryan

On Aug 1, 2018, at 12:35, [email protected] wrote:

I’m having issues with the following code (I’ve cut out large pieces but I can add them back in – these seemed like the important parts). In my main code, I set up a plot (“sectionizePlot”) which is a simple variation on another whiskered-plot (https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html). I’m looking to update them on the fly. In the same script, I’m using a heatmap (“ModifiedGenericHeatMap”) which updates fine.

Any ideas how I might update my whiskered-plot? Updating the ColumnDataSource doesn’t seem to work (which makes sense). I’m guessing that I am running into issues with adding each circle/point individually onto the plot.

One idea would be to clear the plot each time and manually add the points onto the plot, but it would need to be cleared each time, which I’m unsure of how to do.

Any help would be appreciated. I’m just a lowly Scientist trying to utilize Bokeh in Pharma research.

def ModifiedgenericHeatMap(source, maxPct):

colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
#mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
globalDist = figure(title="derp",
                    x_range=cols, y_range=list(reversed(rows)),
                    x_axis_location="above", plot_width=1000, plot_height=400,
                    tools=TOOLS, toolbar_location='below')
globalDist.grid.grid_line_color = None
globalDist.axis.axis_line_color = None
globalDist.axis.major_tick_line_color = None
globalDist.axis.major_label_text_font_size = "5pt"
globalDist.axis.major_label_standoff = 0
globalDist.xaxis.major_label_orientation = pi / 3
globalDist.rect(x="cols", y="rows", width=1, height=1,
                source=source,
                fill_color={'field': 'count', 'transform': mapper},
                line_color=None)
color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     # fix this via using a formatter with accounts for
                     formatter=PrintfTickFormatter(format="%d%%"),
                     label_standoff=6, border_line_color=None, location=(0, 0))
text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
x = dodge("cols", -0.4, range=globalDist.x_range)
r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
r.glyph.text_font_size = "8pt"
globalDist.add_layout(color_bar, 'right')
globalDist.select_one(HoverTool).tooltips = [
    ('Well:', '@rows @cols'),
    ('Count:', '@count'),
]
return globalDist

def sectionizePlot(source, source_error, type, base):

print("sectionize plot created with typ: " + type)
colors = []
for x in range(0, len(base)):
    colors.append(getRandomColor())
title = type + "-wise Intensity Distribution"
p = figure(plot_width=600, plot_height=300, title=title)
p.add_layout(
    Whisker(source=source_error, base="base", upper="upper", lower="lower"))
for i, sec in enumerate(source.data['base']):
    p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
p.xaxis.axis_label = type
p.yaxis.axis_label = "Intensity"
if (type.split()[-1] == "Row"):
    print("hit a row")
    conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
    conv.pop(0)
    p.xaxis.major_label_overrides = conv
p.xaxis.ticker = SingleIntervalTicker(interval=1)
return p

famData = dict()

e1FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))

e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)

rowSectTotSource = ColumnDataSource(data=dict(base=))

rowSectTotSource_error = ColumnDataSource(data=dict(base=, lower=, upper=))

rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, “eSum Row”, rowBase)

def update(selected=None):

global famData
famData = getFAMData(file_source_dt1, True)
global e1Stack
e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
e1Stack = e1Fract.stack(dropna=False).reset_index()
e1Stack.columns = ["rows", "cols", "count"]
e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                          rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )
rowData, colData = sectionize(famData['eSum'], rows, cols)
rowData_lower, rowData_upper = getLowerUpper(rowData)
rowBase = list(range(1, 17))
rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper, )
rowSectTotSource.data = dict(base=rowData)
rowSectPlot_tot.title.text = "plot changed in update"

layout = column(e1FractSource, rowSectPlot_tot)

update()

curdoc().add_root(layout)

curdoc().title = “Specs”

print(“ok”)


You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/d15791f0-4907-4527-b697-5b252b7e5fb9%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi,

Respectfully I don't have the bandwidth to dive into that much code. The best example code for questions is minimal and complete, ideally 10-20 lines tops. In this instance, since you are are experiencing issues with updating whiskers, you should pare things down to the bare essentials of demonstrating that and nothing else. i.e. a plot with one Whisker driven by some simple dummy data in a CDS (no extra files), with a button that updates the CDS manually in some arbitrary way. Does that kind of minimal example work? If not, perhaps there is a bug. In any case, that's the sort of example I would be able to devote time to actually running and investigating, and could say whether there is a bug or usage problem with quickly.

Thanks,

Bryan

···

On Aug 2, 2018, at 11:02, [email protected] wrote:

I understand how the updates are being performed in sliders.py.
I left out part of the code to keep things short. I’m uploading an excel file and parsing it in a callback (FAM_file_callback_dt1) and creating heatmaps (ModifiedGenericHeatmap) and attempting to create whiskered plots (sectionizePlot). I’m updating the ColumnDataSources in the callback and also in update (which is likely doing the same action twice), and the correct data is generating and saving to the ColumnDataSources.
But in the case of my whiskered-plot (sectionizePlot), the plot is not updating. I’m guessing that this may be related to how I’m generating my plot in the sectionizePlot method (which is based on https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html).
I’m manually generating the first whiskered plot in main, so my plot creation method seems to be working. So, I know my method plots, I just don’t know how to update it.
Larger code is attached below with some of the irrelevent methods minimized.

try:
    from functools import lru_cache
except ImportError:
    # Python 2 does stdlib does not have lru_cache so let's just
    # create a dummy decorator to avoid crashing
    print ("WARNING: Cache for this example is available on Python 3 only.")
    def lru_cache():
        def dec(f):
            def _(*args, **kws):
                return f(*args, **kws)
            return _
        return dec
from os.path import dirname, join
import pandas as pd
import numpy as np
from math import pi
from bokeh.io import output_file, show, curdoc
from bokeh.layouts import row, column, widgetbox
from bokeh.models import (
    ColumnDataSource,
    HoverTool,
    LinearColorMapper,
    BasicTicker,
    PrintfTickFormatter,
    ColorBar,
    Legend,
    Whisker,
)
from bokeh.models.widgets import PreText, Select, RadioGroup, TextInput
from bokeh.plotting import figure
from bokeh.transform import dodge, factor_cmap
import bokeh.plotting
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import Button
import io
import base64
import random
import statistics as stat
from bokeh.models.tickers import SingleIntervalTicker
from bokeh.plotting import figure, show

def labelWellCat(row):
    if ((row['Well'][2] == "1") or (row['Well'][2] == "2")) and (row['Well'][1] == "0"):
        return "Control"
    return "Sample"

def labelRow(row):
    return str(row['Well'][0].rstrip())

def labelCol(row):
    return str(int(row['Well'][1:].rstrip()))

def buildPlate():
    rows = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"]
    cols = [str(x) for x in range(1, 25)]

    #create a data frame out of info
    df = pd.read_csv("/Users/Jonathan_Erikson/Desktop/djangogirls/files/SpecifTemp.csv")
    df.columns.values[0] = "Well"
    df.columns.values[1] = "ID"

    df['WellCat'] = ""
    df['WellCat'] = df.apply(lambda row: labelWellCat(row), axis=1)
    df['row'] = df.apply(lambda row: labelRow(row), axis=1)
    df['col'] = df.apply(lambda row: labelCol(row), axis=1)
    cmap = {
        "Sample" : "#1f78b4",
        "Control" : "#d93b43",
    }
    source = ColumnDataSource(df)
    p = figure(plot_width=900, plot_height=500, title="This plot doest nothing besides looking pretty",
    #p = figure(plot_width=1800, plot_height=1000, title="Title Goes Here",
               x_range=cols, y_range=list(reversed(rows)), toolbar_location=None, tools="")
    #removing the legend
    #p.rect("col", "row", 0.95, 0.95, source=source, fill_alpha=0.6, legend="WellCat",
    p.rect("col", "row", 0.95, 0.95, source=source, fill_alpha=0.6,
           color=factor_cmap('WellCat', palette=list(cmap.values()), factors=list(cmap.keys())))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("col", -0.4, range=p.x_range)
    '''
    r = p.text(x=x, y="row", text="symbol", **text_props)
    r.glyph.text_font_style="bold"
    '''
    r = p.text(x=x, y=dodge("row", 0.3, range=p.y_range), text="Well", **text_props)
    r.glyph.text_font_size="8pt"
    r = p.text(x=x, y=dodge("row", -0.35, range=p.y_range), text="ID", **text_props)
    r.glyph.text_font_size="5pt"
    r = p.text(x=x, y=dodge("row", -0.2, range=p.y_range), text="RowHdr", **text_props)
    r.glyph.text_font_size="5pt"
    #this just blocks out individual blocks
    '''
    p.text(x=["3", "3"], y=["VI", "VII"], text=["LA", "AC"], text_align="center", text_baseline="middle")
    '''
    p.add_tools(HoverTool(tooltips = [
        #("Well", "@name"),
        ("Well", "@Well"),
        ("ID", "@ID"),
        ("RowHdr", "@RowHdr"),
    ]))
    p.outline_line_color = None
    p.grid.grid_line_color = None
    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_standoff = 0
    #leaving out the legend for now
    #p.legend.orientation = "horizontal"
    #p.legend.location ="top_right"
    return p

def getCodonData(codon, counts, printStats):
    codonDist = counts.loc[[codon]]
    #Max
    codonMax = codonDist.values.max()
    #Min
    codonMin = codonDist.values.min()
    #Total codon distribution
    codonTotal = float(codonDist.sum(axis=1))
    #Fraction of total distributed codons in each well
    codonDistFract = codonDist.divide(float(codonTotal), axis=1)
    #Get all wells above the threshold
    #DF of booleans
    threshold = 0.01
    codonAboveThreshAll = codonDistFract > threshold
    codonAboveThreshTot = codonAboveThreshAll.sum(axis=1)
    #get the relevant values
    codonAboveThreshCount = codonDist[codonAboveThreshAll].dropna(axis=1)
    #IDs
    codonAboveThreshID = codonAboveThreshCount.columns
    #Codons correct in well
    codonCorr = float(codonMax) / codonDist.sum(axis=1)
    #transform into a dataframe
    codonDistPlate = pd.DataFrame(columns=range(1, 25))
    rows = "ABCDEFGHIJKLMNOP"
    x = 0
    values = list(codonDistFract.loc[codon])
    for row in rows:
        codonDistPlate.loc[row] = values[x:(x + 24)]
        x += 24
    if (printStats == True):
        print("Using Codon {0}".format(codon))
        print("Max Codon Count is: " + str(codonMax))
        print("Min Codon Count is: " + str(codonMin))
        print("Total Codon Count is: " + str(codonTotal))
        print("Codons above threshold {0}: ".format(threshold))
        print(codonAboveThreshID)
    codonData = {}
    codonData['codon'] = codon
    codonData['codonDist'] = codonDist
    codonData['codonMax'] = codonMax
    codonData['codonMin'] = codonMin
    codonData['codonTotal'] = codonTotal
    #changed to filter out NaN values
    codonData['codonDistFract'] = codonDistFract.replace(np.nan, 0)
    codonData['threshhold'] = threshold
    codonData['codonAboveThreshAll'] = codonAboveThreshAll
    codonData['codonAboveThreshCount'] = codonAboveThreshCount
    codonData['codonAboveThreshID'] = codonAboveThreshID
    codonData['codonCorr'] = codonCorr
    codonData['codonDistPlate'] = codonDistPlate
    return codonData

'''
changed
temprarily commented out
this parses the file directy for the first page instead of being able to choose
    the file and open it up which deals with it differently
can change method name to signify
'''
def getSpecDataOld(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    #drop last column
    counts = counts.drop(counts.columns[384], axis=1)
    #last column is now dropped
    print("DF Dimensions: " + str(counts.shape))
    counts = counts.drop('Total')
    return counts

def getFAMData(file, ioStyle):
    if(ioStyle):
        print("Using the ioStyle")
        print('filename:', file.data['file_name'])
        raw_contents = file.data['file_contents'][0]
        prefix, b64_contents = raw_contents.split(",", 1)
        file_contents = base64.b64decode(b64_contents)
        file_io = io.BytesIO(file_contents)
        excel_object = pd.ExcelFile(file_io, engine='xlrd')
        fam = excel_object.parse("RawFAM")
    else:
        famFile = pd.ExcelFile(file)
        print("Sheet Names: " + str(famFile.sheet_names))
        fam = famFile.parse("RawFAM")
    fam.drop(fam.columns[[0, 1, 26, 27, 28, 29, 30]], axis=1, inplace=True)
    w1 = fam[2:18]
    w2 = fam[22:38]
    w3 = fam[42:58]
    e1 = fam[62:78]
    e2 = fam[82:98]
    e3 = fam[102:118]
    samples = fam[122:123]
    samples.rename(index={122: 'samples'})
    samples = samples.iloc[:, 0:8]
    samples.columns = ['S1', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'HB2tRNA']
    samplesSub = samples.subtract(samples['HB2tRNA'].iloc[0])
    rows = [x for x in "ABCDEFGHIJKLMNOP"]
    for x in [e1, e2, e3]:
        x.columns = [y for y in range(1, 25)]
        x['row'] = rows
        x.set_index('row', inplace=True)
    e1Sub = e1 - (e1.iloc[6, 0])
    e2Sub = e2 - (e2.iloc[6, 0])
    e3Sub = e3 - (e3.iloc[6, 0])
    eSum = e1Sub + e2Sub + e3Sub
    famData = {}
    famData["w1"] = w1
    famData["w2"] = w2
    famData["w3"] = w3
    famData["e1"] = e1
    famData["e1Sub"] = e1Sub
    famData["e2"] = e2
    famData["e2Sub"] = e2Sub
    famData["e3"] = e3
    famData["e3Sub"] = e3Sub
    famData["eSum"] = eSum
    famData["samples"] = samples
    famData["samplesSub"] = samplesSub
    return famData

'''
Input:
well - i.e. "A03"

Output:
row - row coordinate in DF
col - column coordinate in DF

Strategy:
This parses out the corresponding well and column of a DF for a specific well

'''
def getCoords(well):
    row = well[0]
    col = int(well[1:])
    rows = list("ABCDEFGHIJKLMNOP")
    row = rows.index(row)
    col = col - 1
    return row, col

'''
Input:
codonData
famData
counts

Output:
fractSig
codSig
specialNumber

Strategy:
This does the stuff on the whiteboard

'''
def calculateWhiteBoard(codonData, famData, counts):
    fractSig = codonData['codonDistPlate'] * famData['eSum']
    totalSig = fractSig.values.sum()
    codonMap, wellMap = getMaps(counts)
    well = codonMap[codonData['codon']]
    row, col = getCoords(well)
    #fractional signal of specific codon
    codSig = fractSig.iloc[row, col]
    #special number from the white board
    specialNumber = codSig / totalSig
    return fractSig, codSig, specialNumber

def ModifiedgenericHeatMap(source, maxPct):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    #mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
    mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="derp",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1000, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count'),
    ]
    return globalDist

'''
Strategy:

Input:

Output:

'''
def getSpecData(file, ioStyle):
    if(ioStyle):
        print("Using the ioStyle")
        print('filename:', file.data['file_name'])
        raw_contents = file.data['file_contents'][0]
        prefix, b64_contents = raw_contents.split(",", 1)
        file_contents = base64.b64decode(b64_contents)
        file_io = io.BytesIO(file_contents)
        excel_object = pd.ExcelFile(file_io, engine='xlrd')
        counts = excel_object.parse(N=0)
    else:
        specFile = pd.ExcelFile(file)
        print("Sheet Names: " + str(specFile.sheet_names))
        counts = specFile.parse(N=0)
    #drop last column
    counts = counts.drop(counts.columns[384], axis=1)
    #last column is now dropped
    print("DF Dimensions: " + str(counts.shape))
    counts = counts.drop('Total')
    return counts

'''
Strategy:

Input:

Output:

'''
def plateHeatMap(df, inverse):
    rows =
    cols =
    if inverse:
        for x in range(0, 24):
            for y in "ABCDEFGHIJKLMNOP":
                rows.append(y)
        for x in range(1, 25):
            for y in range(0, 16):
                cols.append(x)
    else:
        for x in "ABCDEFGHIJKLMNOP":
            for y in range(0, 24):
                rows.append(x)
        for x in range(0, 16):
            for y in range(1, 25):
                cols.append(y)
    df["rows"] = rows
    df['cols'] = cols
    if 'codon' in df.columns:
        df = df.rename(columns={df['codon']: 'count'})
    else:
        df = df.rename(columns={df.columns[0]: "count"})
    df["rows"] = rows
    df['cols'] = cols
    return df

'''
changed

need to denote that this gets the wells and codons directly from the file

'''
def getWellsCodons(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    wells = list(counts.columns.values)
    codons = list(counts.index.values)
    return wells, codons

def nix(val, lst):
    return [x for x in lst if x != val]

@lru_cache()
def load_codon(codon):
    return "derp"

@lru_cache()
def get_data(cod1):
    return "derp"

'''
Strategy:

Input:

Output:

'''
def getStats(codonData):
    output = ""
    # top codon destinations
    temp = codonData['codonAboveThreshCount'].transpose()
    # drop the top value
    #if there is a top value
    output += "For codon: " + codonData['codon'] + "\n"
    if not temp.empty:
        topCod = temp.drop(temp[codonData['codon']].idxmax())
        # get the percentages of other codon
        topCod['fract'] = (topCod[codonData['codon']] / codonData['codonTotal']) * 100
        wells = topCod.index.values
        wells = [x.split("-")[0] for x in wells]
        top = topCod['fract'].to_string()
        output += "Percentage of total codon distribution in the correct well:\t" + \
                  (100 * (codonData['codonCorr'])).to_string().split()[1] + \
                  "%\n"
        output += "Precentage of total codon distribution in wrong wells:\t" + \
                  (100 * (1 - (codonData['codonCorr']))).to_string().split()[1] + \
                  "%\n"
        output += "Top codon destinations:\n"
        output += str(wells) + "\n"
        output += topCod['fract'].to_string()
    else:
        output += "Percentage of total codon distribution in the correct well:\t" + \
                  (100 * (codonData['codonCorr'])).to_string().split()[1] + \
                  "%\n"
        output += "Precentage of total codon distribution in wrong wells:\t" + \
                  (100 * (1 - (codonData['codonCorr']))).to_string().split()[1] + \
                  "%\n"
    aboveThreshold = codonData['codonDistFract'][codonData['codonAboveThreshID']]
    names = [well for well in aboveThreshold.columns.values]
    values = [value for value in aboveThreshold.values][0].tolist()
    return output

'''
Strategy:

Input:

Output:

'''
def getWellIDs(wells):
    rows =
    cols =
    if (wells == 384):
        for x in "ABCDEFGHIJKLMNOP":
            rows.append(x)
        for x in range(1, 25):
            cols.append(str(x))
    if (wells == 96):
        for x in "ABCDEFGH":
            rows.append(x)
        for x in range(1, 17):
            cols.append(str(x))
    return cols, rows

'''
#this is backwards from the other one for codon distribution

Strategy:

Input:

Output:

'''
def plateHeatMapInverse(df):
    rows =
    for x in range(0, 24):
        for y in "ABCDEFGHIJKLMNOP":
            rows.append(y)
    cols =
    for x in range(1, 25):
        for y in range(0, 16):
            cols.append(x)
    df["rows"] = rows
    df['cols'] = cols
    df.columns.values[0] = 'count'
    cols =
    for x in range(1, 25):
        cols.append(str(x))
    rows =
    for x in "ABCDEFGHIJKLMNOP":
        rows.append(x)
    return df

'''
#gets the amount of globally distributed that ended up in the correct well

Strategy:

Input:

Output:

'''
def getGlobalCorr(counts):
    #grab the list of the codons
    codons = counts.index.values
    #get the percentage of codons correctly distributed to each well of global
    corr = np.array()
    for codon in codons:
        codonData = getCodonData(codon, counts, False)
        corr = np.append(corr, float(codonData['codonCorr']))
    #remove NaN
    corr[np.isnan(corr)] = 0
    corrDF = pd.DataFrame(data=corr)
    #round the decimals
    globalCorr = plateHeatMap(corrDF, True)
    globalCorr['count'] = globalCorr['count'].apply(lambda x: round(x, 3))
    return globalCorr

'''
changed 20180620 1058
-removing the counts part because counts is now a globalvariable
-removing codons because does nothing

Strategy:

Input:

Output:

'''
def getGlobalDistHeatMap(globalCorr, item):
    source = ColumnDataSource(dict(cols=globalCorr["cols"], count=(globalCorr["count"] * 100), rows=globalCorr["rows"],
                                   codon=globalCorr[item],
                                   index=counts.index.values))
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    mapper = LinearColorMapper(palette=colors, low=90, high=100)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    globalDist = figure(title="Global codon that in to correct well (%)",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=1080, plot_height=480,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    r = globalDist.text(x=x, y=dodge("rows", -0.35, range=globalDist.y_range), text="codon", **text_props)
    r.glyph.text_font_size = "5pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
        ('Codon:', '@codon'),
    ]
    return globalDist

'''
Strategy:

Input:

Output:

'''
def getWellData(well, wCounts):
    wellDist = wCounts.loc[[well]]
    # Max
    wellMax = wellDist.values.max()
    # Min
    wellMin = wellDist.values.min()
    # Total codon distribution
    wellTotal = float(wellDist.sum(axis=1))
    # Fraction of total distributed codons in each well
    wellDistFract = wellDist.divide(float(wellTotal), axis=1)

    # still need to verify that max codon is the correct codon

    # Get all wells above the threshold
    # DF of booleans
    threshold = 0.01
    wellAboveThreshAll = wellDistFract > threshold
    wellAboveThreshTot = wellAboveThreshAll.sum(axis=1)
    # get the relevant values
    wellAboveThreshCount = wellDist[wellAboveThreshAll].dropna(axis=1)
    # IDs
    wellAboveThreshID = wellAboveThreshCount.columns
    # Codons correct in well
    wellCorr = float(wellMax) / wellDist.sum(axis=1)
    # transform into a dataframe
    wellDistPlate = pd.DataFrame(columns=range(1, 25))
    rows = "ABCDEFGHIJKLMNOP"
    x = 0
    values = list(wellDistFract.loc[well])
    for row in rows:
        wellDistPlate.loc[row] = values[x::16]
        x += 1
    wellData = {}
    wellData['well'] = well
    wellData['wellDist'] = wellDist
    wellData['wellMax'] = wellMax
    wellData['wellMin'] = wellMin
    wellData['wellTotal'] = wellTotal
    # changed to filter out NaN values
    wellData['wellDistFract'] = wellDistFract.replace(np.nan, 0)
    wellData['threshold'] = threshold
    wellData['wellAboveThreshAll'] = wellAboveThreshAll
    wellData['wellAboveThreshCount'] = wellAboveThreshCount
    wellData['wellAboveThreshID'] = wellAboveThreshID
    wellData['wellCorr'] = wellCorr
    wellData['wellDistPlate'] = wellDistPlate
    return wellData

def getGlobalWellCorr(wCounts):
    #grab the list of the codons
    indexWells = wCounts.index.values
    #get the percentage of codons correctly distributed to each well of global
    corr = np.array()
    for well in indexWells:
        wellData = getWellData(well, wCounts)
        corr = np.append(corr, float(wellData['wellCorr']))
    #remove NaN
    corr[np.isnan(corr)] = 0
    corrDF = pd.DataFrame(data=corr)
    #round the decimals
    globalCorr = plateHeatMap(corrDF, False)
    globalCorr['count'] = globalCorr['count'].apply(lambda x: round(x, 3))
    return globalCorr

def getMaps(counts):
    codonList = counts.index.values.tolist()
    wellList = counts.columns.values.tolist()
    wellList = [x.split("-")[0] for x in wellList]
    codonMap = {}
    wellMap = {}
    z= 0
    for x in range(0, 24):
        for y in range(x, 384, 24):
            codonMap[codonList[z]] = wellList[y]
            wellMap[wellList[y]] = codonList[z]
            z += 1
    return codonMap, wellMap

def getWellsCodons(file):
    specFile = pd.ExcelFile(file)
    print("Sheet Names: " + str(specFile.sheet_names))
    counts = specFile.parse(N=0)
    wells = list(counts.columns.values)
    codons = list(counts.index.values)
    return wells, codons

'''
Widget Section
'''

stats = PreText(text='', width=1080, height=240)
fileSel = TextInput(value="default", title="File Name")

counts = pd.DataFrame()
cols, rows = getWellIDs(384)
globalCorr = pd.DataFrame(columns=["count", "rows", "cols", "codon"])

'''
Input:
source - a ColumnDataSource with:
    dict(count=, cols=, rows=, index=, codon=)
    
Output:
globalDist - a heat map

Strategy:
This accepts a CDS and returns a heat map. This can be made with a CDS and then have the data updated with:
    globalDistSource.data = dict(cols=globalCorr["cols"], count=(globalCorr["count"] * 100),
                       rows=globalCorr["rows"], index=counts.index.values, codon=globalCorr['codon'],)
'''
def globalDist(source):
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
    mapper = LinearColorMapper(palette=colors, low=95, high=100)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"

    globalDist = figure(title="Global codon that in to correct well (%)",
                        x_range=cols, y_range=list(reversed(rows)),
                        x_axis_location="above", plot_width=900, plot_height=400,
                        tools=TOOLS, toolbar_location='below')
    globalDist.grid.grid_line_color = None
    globalDist.axis.axis_line_color = None
    globalDist.axis.major_tick_line_color = None
    globalDist.axis.major_label_text_font_size = "5pt"
    globalDist.axis.major_label_standoff = 0
    globalDist.xaxis.major_label_orientation = pi / 3
    globalDist.rect(x="cols", y="rows", width=1, height=1,
                    source=source,
                    fill_color={'field': 'count', 'transform': mapper},
                    line_color=None)
    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
    x = dodge("cols", -0.4, range=globalDist.x_range)
    r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
    r.glyph.text_font_size = "8pt"
    r = globalDist.text(x=x, y=dodge("rows", -0.35, range=globalDist.y_range), text="codon", **text_props)
    r.glyph.text_font_size = "5pt"
    globalDist.add_layout(color_bar, 'right')
    globalDist.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
        ('Codon:', '@codon'),
    ]
    return globalDist

'''
Input:
source - a ColumnDataSource with:
    dict(count=, cols=, rows=, index=, codon=)

Output:
globalDist - a heat map

Strategy:
This accepts a CDS and returns a heat map. This can be made with a CDS and then have the data updated with:
    source.data = dict(cols=derp2["cols"], count=(derp2["count"] * 100),
    rows=derp2["rows"], index=derp2.index.values, )
'''
def codonDist(source):
    # source = ColumnDataSource(dict(count=, cols=, rows=, index=))
    colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]

    # commenting out the mapper to replace in the method section
    # mapper = LinearColorMapper(palette=colors, low=df['count'].min(), high=df['count'].max())

    # previous correct one below - replacing with zero
    # mapper = LinearColorMapper(palette=colors, low=min(source.data['count']), high=max(source.data['count']))
    # changing this to high of
    mapper = LinearColorMapper(palette=colors, low=0, high=1)
    # mapper = LinearColorMapper(palette=colors, low=0, high=1)
    TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
    p = figure(title="temp",
               x_range=cols, y_range=list(reversed(rows)),
               x_axis_location="above", plot_width=900, plot_height=400,
               tools=TOOLS, toolbar_location='below')
    p.grid.grid_line_color = None
    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_text_font_size = "5pt"
    p.axis.major_label_standoff = 0
    p.xaxis.major_label_orientation = pi / 3
    p.rect(x="cols", y="rows", width=1, height=1,
           source=source,
           fill_color={'field': 'count', 'transform': mapper},
           line_color=None)
    # commenting out the mapper part to go into methods later

    color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         # fix this via using a formatter with accounts for
                         formatter=PrintfTickFormatter(format="%d%%"),
                         label_standoff=6, border_line_color=None, location=(0, 0))
    p.add_layout(color_bar, 'right')

    p.select_one(HoverTool).tooltips = [
        ('Well:', '@rows @cols'),
        ('Count:', '@count%'),
    ]
    return p

'''
#this deals with the inputting of the file
'''
def FAM_file_callback_dt1(attr,old,new):
    global famData
    famData = getFAMData(file_source_dt1, True)

    global eSumStack
    eSumStack = famData['eSum'].stack(dropna=False).reset_index()
    eSumStack.columns = ["rows", "cols", "count"]
    eSumStack['count'] = eSumStack['count'].apply(lambda x: round(x, 1))

    global e1Stack
    e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
    e1Stack = e1Fract.stack(dropna=False).reset_index()
    e1Stack.columns = ["rows", "cols", "count"]
    e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
    e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                        rows=e1Stack["rows"], index=e1Stack.index.values, )
    #e1Fract.color_mapper.high = 100
    #e1Fract.color_bar.trigger('change')

    global e2Stack
    e2Fract = (famData['e2Sub'] / famData['eSum']) * 100
    e2Stack = e2Fract.stack(dropna=False).reset_index()
    e2Stack.columns = ["rows", "cols", "count"]
    e2Stack['count'] = e2Stack['count'].apply(lambda x: round(x, 1))
    e2FractSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                        rows=e2Stack["rows"], index=e2Stack.index.values, )

    global e3Stack
    e3Fract = (famData['e3Sub'] / famData['eSum']) * 100
    e3Stack = e3Fract.stack(dropna=False).reset_index()
    e3Stack.columns = ["rows", "cols", "count"]
    e3Stack['count'] = e3Stack['count'].apply(lambda x: round(x, 1))
    e3FractSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                        rows=e3Stack["rows"], index=e3Stack.index.values, )

    #lastPlot currently does nothing
    lastPlotSource.data = dict(count=, cols=, rows=, index=,)

    #the following code involved the whiskered-plots which are not updating

    rows = "ABCDEFGHIJKLMNOP"
    cols = 24
    rowBase = list(range(1, 17))
    colBase = list(range(1, 25))

    global rowData, rowData_lower, rowData_upper
    global rowDataE1, rowDataE1_lower, rowDataE1_upper
    global rowDataE2, rowDataE2_lower, rowDataE2_upper

    global colData, colData_lower, colData_upper
    global colDataE1, colDataE1_lower, colDataE1_upper
    global colDataE2, colDataE2_lower, colDataE2_upper

    #calculate the data here seems to work fine
    rowData, colData = sectionize(famData['eSum'], rows, cols)
    rowData_lower, rowData_upper = getLowerUpper(rowData)
    colData_lower, colData_upper = getLowerUpper(colData)
    rowDataE1, colDataE1 = sectionize(famData['e1Sub'], rows, cols)
    rowDataE1_lower, rowDataE1_upper = getLowerUpper(rowDataE1)
    colDataE1_lower, colDataE1_upper = getLowerUpper(colDataE1)
    rowDataE2, colDataE2 = sectionize(famData['e2Sub'], rows, cols)
    rowDataE2_lower, rowDataE2_upper = getLowerUpper(rowDataE2)
    colDataE2_lower, colDataE2_upper = getLowerUpper(colDataE2)

    #create the plots
    rowSectTotSource.data = dict(base=rowData)
    rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
    rowSectE1Source.data = dict(base=rowDataE1)
    rowSectE1Source_error.data = dict(base=rowBase, lower=rowDataE1_lower, upper=rowDataE1_upper)
    rowSectE2Source.data = dict(base=rowDataE2)
    rowSectE2Source_error.data = dict(base=rowBase, lower=rowDataE2_lower, upper=rowDataE2_upper)

    colSectTotSource.data = dict(base=colData)
    colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
    colSectE1Source.data = dict(base=colDataE1)
    colSectE1Source_error.data = dict(base=colBase, lower=colDataE1_lower, upper=colDataE1_upper)
    colSectE2Source.data = dict(base=colDataE2)
    colSectE2Source_error.data = dict(base=colBase, lower=colDataE2_lower, upper=colDataE2_upper)

    update()

'''
Strategy:
This does a simple bar chart for the various elution percentages along with an error bar.
(This can work for other non elution things)

Input:
groups - list of groups to plot
counts - list of counts
error - list standard deviation of counts
title - plot title

Output:
p - elution percentage plot with error bars

'''
def elutionPctPlot(groups, counts, error, title):
    upper = [x+e for x,e in zip(counts, error) ]
    lower = [x-e for x,e in zip(counts, error) ]
    ###
    #source point
    ###
    source = ColumnDataSource(data=dict(groups=groups, counts=counts, upper=upper, lower=lower))

    p = figure(x_range=groups, plot_height=350, toolbar_location=None, title=title, y_range=(0,100))
    p.vbar(x='groups', top='counts', width=0.9, source=source, legend="groups",
           line_color='white', fill_color=factor_cmap('groups', palette=["#962980","#295f96","#29966c","#968529"],
                                                      factors=groups))
    p.add_layout(
        Whisker(source=source, base="groups", upper="upper", lower="lower", level="overlay")
    )
    p.xgrid.grid_line_color = None
    p.legend.orientation = "horizontal"
    p.legend.location = "top_center"
    return p

'''
Strategy:
This returns 1 of 102 possible colors

Input:
None

Output:
a random color
'''
def getRandomColor():
    colors = ['aqua', 'aquamarine', 'black', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate',
         'coral', 'cornflowerblue', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen',
         'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon',
         'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
         'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'forestgreen', 'fuchsia', 'gold', 'goldenrod',
         'gray', 'green', 'greenyellow', 'grey', 'hotpink', 'indianred', 'indigo', 'khaki', 'lavender', 'lawngreen', 'lime',
         'limegreen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
         'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue',
         'navy', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue',
         'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'sienna', 'silver',
         'skyblue', 'slateblue', 'slategray', 'slategrey', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato',
              'turquoise', 'violet', 'yellow', 'yellowgreen']
    return colors[random.randint(0, 101)]

'''
Strategy:
This returns a list of random colors

Input:
numColors - the length of the random color list to return

Output:
colors- a list of random colors
'''
def createColorList(numColors):
    colors =
    for x in range(0, numColors):
        colors.append(getRandomColor())
    return colors

'''
Strategy:
This "sectionizes" the df into a list of list of rows or columns.

Input:
df - a dataframe to sectionize
rows - row names (a, b, c etc.)
cols - number of columns

Output:
rowData - a list of lists of the rows
colData - a list of lists of the columns

'''
def sectionize(df, rows, cols):
    rowWise = df.stack()
    colWise = df.transpose().stack()
    rowData =
    colData =
    for x in rows:
        rowData.append(list(rowWise))
    for x in range(1, (cols + 1)):
        colData.append(list(colWise))
    return rowData, colData

'''
Strategy:
This creates a dot plot with error bars for either row-wise or column-wise data.
(This can work as a general method as well with minor modification)

Input:
data - a list of lists of the column or row data
type - "Row" or "Column"
base - a list of the range for the number of rows or columns

Output:
p - a plot of the sectional data
'''
def sectionizePlot(source, source_error, type, base):
    print("sectionize plot created with typ: " + type)
    colors =
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source_error, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        print("hit a row")
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

#alternative to sectionizePlot using a single ColumnDataSource
def altSectionizePlot(source, type, base):
    print(source.data)
    #print(source.data["base"][0])
    print("alternative sectionize plot created with typ: " + type)
    colors =
    for x in range(0, len(base)):
        colors.append(getRandomColor())
    title = type + "-wise Intensity Distribution"
    p = figure(plot_width=600, plot_height=300, title=title)
    p.add_layout(
        Whisker(source=source, base="base", upper="upper", lower="lower"))
    for i, sec in enumerate(source.data['base']):
        print("i: " + str(i) + str(sec))
        p.circle(x=source.data["base"][i], y=source.data["points"][i], color=colors[i])
    p.xaxis.axis_label = type
    p.yaxis.axis_label = "Intensity"
    if (type.split()[-1] == "Row"):
        conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
        conv.pop(0)
        p.xaxis.major_label_overrides = conv
    p.xaxis.ticker = SingleIntervalTicker(interval=1)
    return p

'''
Strategy:

Input:

Output:

'''
def getLowerUpper(data):
    lower, upper = ,
    for x in data:
        if x:
            mean = stat.mean(x)
            std = stat.stdev(x)
            lower.append(mean - std)
            upper.append(mean + std)
        else:
            lower.append(0)
            upper.append(0)
    return lower, upper

famData = dict()
e1FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))
e2FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))
e3FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))
lastPlotSource = ColumnDataSource(dict(count=, cols=, rows=, index=))

e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)
e2Fract = ModifiedgenericHeatMap(e2FractSource, 25)
e3Fract = ModifiedgenericHeatMap(e3FractSource, 10)
#last plot not in use
lastPlot = ModifiedgenericHeatMap(lastPlotSource, 100)

groups =
counts =
upper =
lower =
error =
title = ""
eluPctPlot_source = ColumnDataSource(data=dict(groups=groups, counts=counts, upper=upper, lower=lower))

rowSectTotSource = ColumnDataSource(data=dict(base=))
rowSectTotSource_error = ColumnDataSource(data=dict(base=, lower=, upper=))
rowSectE1Source = ColumnDataSource(data=dict(base=))
rowSectE1Source_error = ColumnDataSource(data=dict(base=, lower=, upper=))
rowSectE2Source = ColumnDataSource(data=dict(base=))
rowSectE2Source_error = ColumnDataSource(data=dict(base=, lower=, upper=))

colSectTotSource = ColumnDataSource(data=dict(base=))
colSectTotSource_error = ColumnDataSource(data=dict(base=, lower=, upper=))
colSectE1Source = ColumnDataSource(data=dict(base=))
colSectE1Source_error = ColumnDataSource(data=dict(base=, lower=, upper=))
colSectE2Source = ColumnDataSource(data=dict(base=))
colSectE2Source_error = ColumnDataSource(data=dict(base=, lower=, upper=))

rowBase = list(range(1, 17))
colBase = list(range(1, 25))

rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, "eSum Row", rowBase)
colSectPlot_tot = sectionizePlot(colSectTotSource,colSectTotSource_error, "eSum Column", colBase)
rowSectPlot_e1 = sectionizePlot(rowSectE1Source,rowSectE1Source_error, "elu1 Row", rowBase)
colSectPlot_e1 = sectionizePlot(colSectE1Source,colSectE1Source_error, "elu1 Column", colBase)
rowSectPlot_e2 = sectionizePlot(rowSectE2Source,rowSectE2Source_error, "elu2 Row", rowBase)
colSectPlot_e2 = sectionizePlot(colSectE2Source,colSectE2Source_error, "elu2 Column", colBase)

#this plot does nothing for now
eluPctPlot = elutionPctPlot(groups, counts, error, title)

#this code manually generates a plot for rowSectPlotTot
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")
file = "/Users/Jonathan_Erikson/Desktop/Q1A1104.xlsm"
famData = getFAMData(file, False)
rows = "ABCDEFGHIJKLMNOP"
cols = 24
rowData, colData = sectionize(famData['eSum'], rows, cols)
rowData_lower, rowData_upper = getLowerUpper(rowData)
rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
print(rowSectTotSource_error.data)
rowSectTotSource.data = dict(base=rowData)
rowSectPlot_tot = sectionizePlot(rowSectTotSource, rowSectTotSource_error, "eSum Row", rowBase)
rowSectPlot_tot.title.text = "plot changed in main"
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")

#file upload section
file_source_dt1 = ColumnDataSource({'file_contents':, 'file_name':})
file_source_dt1.on_change('data', FAM_file_callback_dt1)
button = Button(label="Upload FAM Excel File", button_type="success")
button.callback = CustomJS(args=dict(file_source=file_source_dt1), 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) {
    var b64string = event.target.result;
    file_source.data = {'file_contents' : [b64string], '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();
""")

def codon_change(attrname, old, new):
    #something something something
    update()

'''

likely changed something here

'''
def update(selected=None):
    if file_source_dt1.data['file_name']:
        global famData
        famData = getFAMData(file_source_dt1, True)

        global eSumStack
        eSumStack = famData['eSum'].stack().reset_index()
        eSumStack.columns = ["rows", "cols", "count"]
        eSumStack['count'] = eSumStack['count'].apply(lambda x: round(x, 1))
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24
        wells =
        for row in rows:
            for col in range(1, (cols + 1)):
                wells.append(str(row + str(col)))

        global e1Stack
        e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
        e1Stack = e1Fract.stack(dropna=False).reset_index()
        e1Stack.columns = ["rows", "cols", "count"]
        e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
        e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                                  rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )
        #e1Fract.color_mapper.high = 100
        #e1Fract.color_bar.trigger('change')

        global e2Stack
        e2Fract = (famData['e2Sub'] / famData['eSum']) * 100
        e2Stack = e2Fract.stack(dropna=False).reset_index()
        e2Stack.columns = ["rows", "cols", "count"]
        e2Stack['count'] = e2Stack['count'].apply(lambda x: round(x, 1))
        e2FractSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                                  rows=e2Stack["rows"], index=e2Stack.index.values, codon=wells, )

        global e3Stack
        e3Fract = (famData['e3Sub'] / famData['eSum']) * 100
        e3Stack = e3Fract.stack(dropna=False).reset_index()
        e3Stack.columns = ["rows", "cols", "count"]
        e3Stack['count'] = e3Stack['count'].apply(lambda x: round(x, 1))
        e3FractSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                                  rows=e3Stack["rows"], index=e3Stack.index.values, codon=wells, )

        print(rowSectE2Source_error.data)

        global rowData, rowData_lower, rowData_upper
        global rowDataE1, rowDataE1_lower, rowDataE1_upper
        global rowDataE2, rowDataE2_lower, rowDataE2_upper

        global colData, colData_lower, colData_upper
        global colDataE1, colDataE1_lower, colDataE1_upper
        global colDataE2, colDataE2_lower, colDataE2_upper

        #problematic section
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24

        rowData, colData = sectionize(famData['eSum'], rows, cols)
        rowData_lower, rowData_upper = getLowerUpper(rowData)
        colData_lower, colData_upper = getLowerUpper(colData)
        rowDataE1, colDataE1 = sectionize(famData['e1Sub'], rows, cols)
        rowDataE1_lower, rowDataE1_upper = getLowerUpper(rowDataE1)
        colDataE1_lower, colDataE1_upper = getLowerUpper(colDataE1)
        rowDataE2, colDataE2 = sectionize(famData['e2Sub'], rows, cols)
        rowDataE2_lower, rowDataE2_upper = getLowerUpper(rowDataE2)
        colDataE2_lower, colDataE2_upper = getLowerUpper(colDataE2)

        rowBase = list(range(1, 17))
        colBase = list(range(1, 25))

        #STUFF FROM MAIN
        file = "/Users/Jonathan_Erikson/Desktop/Q1A1104.xlsm"
        famData = getFAMData(file, False)
        rows = "ABCDEFGHIJKLMNOP"
        cols = 24
        rowBase = list(range(1, 17))
        colBase = list(range(1, 25))
        rowData, colData = sectionize(famData['eSum'], rows, cols)
        colData_lower, colData_upper = getLowerUpper(colData)

        rowSectTotSource.data = dict(base=rowData)
        rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper)
        rowSectE1Source.data = dict(base=rowDataE1)
        rowSectE1Source_error.data = dict(base=rowBase, lower=rowDataE1_lower, upper=rowDataE1_upper)
        rowSectE2Source.data = dict(base=rowDataE2)
        rowSectE2Source_error.data = dict(base=rowBase, lower=rowDataE2_lower, upper=rowDataE2_upper)

        colSectTotSource.data = dict(base=colData)
        colSectTotSource_error.data = dict(base=colBase, lower=colData_lower, upper=colData_upper)
        colSectE1Source.data = dict(base=colDataE1)
        colSectE1Source_error.data = dict(base=colBase, lower=colDataE1_lower, upper=colDataE1_upper)
        colSectE2Source.data = dict(base=colDataE2)
        colSectE2Source_error.data = dict(base=colBase, lower=colDataE2_lower, upper=colDataE2_upper)

        rowSectPlot_tot.title.text = "plot changed in update"

    else:
        print("No file loaded yet.")
        #codonSource.data = dict(cols=, count=, rows=, index=, )
        e1FractSource.data = dict(cols=, count=, rows=, index=, )
        e2FractSource.data = dict(cols=, count=, rows=, index=, )
        e3FractSource.data = dict(cols=, count=, rows=, index=, )

        rowSectTotSource.data = dict(base=)
        rowSectTotSource_error.data = dict(base=, lower=, upper=)
        rowSectE1Source.data = dict(base=)
        rowSectE1Source_error.data = dict(base=, lower=, upper=)
        rowSectE2Source.data = dict(base=)
        rowSectE2Source_error.data = dict(base=, lower=, upper=)

        colSectTotSource.data = dict(base=)
        colSectTotSource_error.data = dict(base=, lower=, upper=)
        colSectE1Source.data = dict(base=)
        colSectE1Source_error.data = dict(base=, lower=, upper=)
        colSectE2Source.data = dict(base=)
        colSectE2Source_error.data = dict(base=, lower=, upper=)

def update_stats(codonData, codon):
    print("New codon (update stats): " + codon)
    derp = getStats(codonData)
    print(derp)
    stats.text = derp

#codonSel.on_change('value', codon_change)

def selection_change(attrname, old, new):
    codon = codonSel.value
    well = wellSel.value
    codonData = getCodonData(codon, counts, False)
    print("Selection changed: " + codon + " " + well)
    update_stats(codonData, cod)

def callback(window=None):
    #data = source.data
    m = cb_obj.active
    if m == "elu1":
        print("hit elu1")
        print(elu1Stack)
        lastPlotSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
                                  rows=e1Stack["rows"], index=e1Stack.index.values, codon=e1Stack['well'], )
    elif m == "elu2":
        print("hit elu2")
        lastPlotSource.data = dict(cols=e2Stack["cols"], count=(e2Stack["count"]),
                                  rows=e2Stack["rows"], index=e2Stack.index.values, codon=e2Stack['well'], )
    elif m == "elu3":
        print("hit elu3")
        lastPlotSource.data = dict(cols=e3Stack["cols"], count=(e3Stack["count"]),
                                  rows=e3Stack["rows"], index=e3Stack.index.values, codon=e3Stack['well'], )
    else:
        print("hit none")
        lastPlotSource.data = dict(cols=, count=,
                                  rows=, index=, codon=, )

    lastPlotSource.trigger('change')

input1 = bokeh.models.RadioGroup(labels=["elu1", "elu2", "elu3", "none"],active=0,
                   callback=bokeh.models.CustomJS.from_py_func(callback))

layout = column(button, input1, lastPlot, e1Fract, e2Fract, e3Fract, eluPctPlot, rowSectPlot_tot,
                colSectPlot_tot, rowSectPlot_e1, colSectPlot_e1, rowSectPlot_e2, colSectPlot_e2)

# initialize
update()
curdoc().add_root(layout)
curdoc().title = "Specs"
print("ok")

On Wednesday, 1 August 2018 14:06:02 UTC-7, Bryan Van de ven wrote:
Hi,

Update in response to what? Updating a ColumnDataSource is precisely the usual way to cause a plot to update, but it's usually done in a callback for a widget or other event, and you don't seem to have defined or set up any callbacks. It's good to start with simple examples to build understanding, The sliders.py example is a minimal example that is fairly prototypical of Bokeh app structure:

        https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py

Does that example make sense wrt to how the updates are being triggered and how they are performed?

Thanks,

Bryan

> On Aug 1, 2018, at 12:35, [email protected] wrote:
>
> I’m having issues with the following code (I’ve cut out large pieces but I can add them back in – these seemed like the important parts). In my main code, I set up a plot (“sectionizePlot”) which is a simple variation on another whiskered-plot (https://bokeh.pydata.org/en/latest/docs/user_guide/examples/plotting_whisker.html). I’m looking to update them on the fly. In the same script, I’m using a heatmap (“ModifiedGenericHeatMap”) which updates fine.
> Any ideas how I might update my whiskered-plot? Updating the ColumnDataSource doesn’t seem to work (which makes sense). I’m guessing that I am running into issues with adding each circle/point individually onto the plot.
> One idea would be to clear the plot each time and manually add the points onto the plot, but it would need to be cleared each time, which I’m unsure of how to do.
> Any help would be appreciated. I’m just a lowly Scientist trying to utilize Bokeh in Pharma research.
>
> def ModifiedgenericHeatMap(source, maxPct):
> colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
> #mapper = LinearColorMapper(palette=colors, low=0, high=data['count'].max())
> mapper = LinearColorMapper(palette=colors, low=0, high=maxPct)
> TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
> globalDist = figure(title="derp",
> x_range=cols, y_range=list(reversed(rows)),
> x_axis_location="above", plot_width=1000, plot_height=400,
> tools=TOOLS, toolbar_location='below')
> globalDist.grid.grid_line_color = None
> globalDist.axis.axis_line_color = None
> globalDist.axis.major_tick_line_color = None
> globalDist.axis.major_label_text_font_size = "5pt"
> globalDist.axis.major_label_standoff = 0
> globalDist.xaxis.major_label_orientation = pi / 3
> globalDist.rect(x="cols", y="rows", width=1, height=1,
> source=source,
> fill_color={'field': 'count', 'transform': mapper},
> line_color=None)
> color_bar = ColorBar(color_mapper=mapper, major_label_text_font_size="5pt",
> ticker=BasicTicker(desired_num_ticks=len(colors)),
> # fix this via using a formatter with accounts for
> formatter=PrintfTickFormatter(format="%d%%"),
> label_standoff=6, border_line_color=None, location=(0, 0))
> text_props = {"source": source, "text_align": "left", "text_baseline": "middle"}
> x = dodge("cols", -0.4, range=globalDist.x_range)
> r = globalDist.text(x=x, y=dodge("rows", 0.3, range=globalDist.y_range), text="count", **text_props)
> r.glyph.text_font_size = "8pt"
> globalDist.add_layout(color_bar, 'right')
> globalDist.select_one(HoverTool).tooltips = [
> ('Well:', '@rows @cols'),
> ('Count:', '@count'),
> ]
> return globalDist
>
> def sectionizePlot(source, source_error, type, base):
> print("sectionize plot created with typ: " + type)
> colors =
> for x in range(0, len(base)):
> colors.append(getRandomColor())
> title = type + "-wise Intensity Distribution"
> p = figure(plot_width=600, plot_height=300, title=title)
> p.add_layout(
> Whisker(source=source_error, base="base", upper="upper", lower="lower"))
> for i, sec in enumerate(source.data['base']):
> p.circle(x=source_error.data["base"][i], y=sec, color=colors[i])
> p.xaxis.axis_label = type
> p.yaxis.axis_label = "Intensity"
> if (type.split()[-1] == "Row"):
> print("hit a row")
> conv = dict(enumerate(list("nABCDEFGHIJKLMNOP")))
> conv.pop(0)
> p.xaxis.major_label_overrides = conv
> p.xaxis.ticker = SingleIntervalTicker(interval=1)
> return p
>
> famData = dict()
> e1FractSource = ColumnDataSource(dict(count=, cols=, rows=, index=))
> e1Fract = ModifiedgenericHeatMap(e1FractSource, 100)
> rowSectTotSource = ColumnDataSource(data=dict(base=))
> rowSectTotSource_error = ColumnDataSource(data=dict(base=, lower=, upper=))
> rowSectPlot_tot = sectionizePlot(rowSectTotSource,rowSectTotSource_error, "eSum Row", rowBase)
>
> def update(selected=None):
> global famData
> famData = getFAMData(file_source_dt1, True)
> global e1Stack
> e1Fract = (famData['e1Sub'] / famData['eSum']) * 100
> e1Stack = e1Fract.stack(dropna=False).reset_index()
> e1Stack.columns = ["rows", "cols", "count"]
> e1Stack['count'] = e1Stack['count'].apply(lambda x: round(x, 1))
> e1FractSource.data = dict(cols=e1Stack["cols"], count=(e1Stack["count"]),
> rows=e1Stack["rows"], index=e1Stack.index.values, codon=wells, )
>
> rowData, colData = sectionize(famData['eSum'], rows, cols)
> rowData_lower, rowData_upper = getLowerUpper(rowData)
> rowBase = list(range(1, 17))
> rowSectTotSource_error.data = dict(base=rowBase, lower=rowData_lower, upper=rowData_upper, )
> rowSectTotSource.data = dict(base=rowData)
> rowSectPlot_tot.title.text = "plot changed in update"
>
> layout = column(e1FractSource, rowSectPlot_tot)
> update()
>
> curdoc().add_root(layout)
> curdoc().title = "Specs"
> print("ok")
>
> --
> You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/d15791f0-4907-4527-b697-5b252b7e5fb9%40continuum.io.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout.

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/e0820f56-b8e8-4cc6-b2ff-177a41f5f7dc%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.