def __init__(self, master):
        tk.Frame.__init__(self, master)
        
        mainWindow = tk.Frame(self)
        mainWindow.pack(side=tk.TOP,padx=10,pady=10)

        tk.Label(mainWindow,text='Adjust clustering hyperparameters:').pack()
        sliderWindow = tk.Frame(mainWindow)
        sliderWindow.pack()
        sliderList = ipe.createParameterAdjustmentSliders(sliderWindow,ods.clusterParameterDict[clusteringMethod],ods.clusterParameterBoundsDict)
        
        dimRedBool = tk.BooleanVar()
        cb = tk.Checkbutton(mainWindow,text='Create cluster-downsampled dimensional reduction?',variable=dimRedBool,pady=20)
        cb.select() 
        cb.pack()

        def collectInputs():
            #Do the clustering with slider value hyperparameters
            parametersForClusteringFunction = ipe.getSliderValues(sliderList,ods.clusterParameterDict[clusteringMethod])
            currentClusteringParameters = parametersForClusteringFunction.copy()
            scaledData = pickle.load(open('outputData/analysisFiles/scaledData/'+dataSelectionFileName,'rb'))
            clusterdf = ods.clusterData(scaledData,clusteringMethod,parametersForClusteringFunction) 
            clusterdf.columns.name = 'Feature'
            ods.savePostProcessedFile(clusterdf,dataSubsetTitle,'cluster',clusteringMethod,currentClusteringParameters)
            #Switch to cluster based downsampling/dimensional reduction page
            if dimRedBool.get():
                clusteringTitle = ods.getFileName(dataSubsetTitle,'cluster',clusteringMethod,currentClusteringParameters)[0].split('.')[0]
                print(clusteringTitle)
                master.switch_frame(ClusterBasedDimRedPage,clusterdf,clusteringTitle)
            else:
                master.switch_frame(backpage,folderName,secondaryhomepage)    
            
        buttonWindow = tk.Frame(self)
        buttonWindow.pack(side=tk.TOP,pady=10)

        tk.Button(buttonWindow, text="OK",command=lambda: collectInputs()).grid(row=5,column=0)
        tk.Button(buttonWindow, text="Back",command=lambda: master.switch_frame(ClusteringHomePage,folderName,secondaryhomepage,backpage)).grid(row=5,column=1)
        tk.Button(buttonWindow, text="Quit",command=quit).grid(row=5,column=2)
    def __init__(self, master,scaledData,reducedData,clusteredData = []):
        #Initialize class
        self.root = master.root
        tk.Frame.__init__(self, master)
         
        #Initialize default variables
        clusterComparisonList = []
        clusterComparisonDict = {}
        clusterCentroidList2 = [] 
        clusterCentroidList = [] 
        clusterCentroidDict = {}
        clusterCentroidDict2 = {}
        palette = sns.color_palette().as_hex()
        self.paletteIndex = 0
        self.GUI_Selection_Index=0
        #Use order of variables in original dataframe
        experimentParametersBool = False
        for fn in os.listdir('misc'):
            for dataType in ['cell','cyt']:
                if 'experimentParameters' in fn:
                    if dataType in fn:
                        experimentParametersBool = True
                        experimentParameters = json.load(open('misc/experimentParameters-'+folderName+'-'+dataType+'.json','r'))
                        break
        if experimentParametersBool:
            trueLabelDict = experimentParameters['levelLabelDict'] 
        else:
            if 'Event' in scaledData.index.names or 'event' in scaledData.index.names:
                h5FileBool = False
                for fileName in os.listdir('outputData/pickleFiles'):
                    if '.h5' in fileName:
                        h5FileBool = True
                        break
                if h5FileBool:
                    ogname = 'outputData/pickleFiles/'+'initialSingleCellDf-channel-'+folderName+'.pkl'
                    newname = ogname.split('.')[0]+'.h5'
                    newdf = pd.read_hdf(newname, 'df')
                    originalDf = newdf
                else:
                    originalDf = pickle.load(open('outputData/pickleFiles/'+'initialSingleCellDf-channel-'+folderName+'.pkl','rb'))
            else:
                originalDf = scaledData.copy()
            trueLabelDict = createLabelDict(originalDf)
            with open('misc/experimentParameters-'+folderName+'-cell.json', 'w') as fp:
                json.dump({'levelLabelDict':trueLabelDict}, fp)

        figheight = 5 
        figwidth = 5
        widthscale = 1.4
        heightscale = 1.2
        plotFrameVisual = tk.Frame(self,borderwidth=1,relief='groove')
        plotFrameVisual.grid(row=0,column=0,sticky=tk.W+tk.E)
        figVisual = plt.figure(figsize=(figwidth*(widthscale+0.1), figheight*heightscale))
        figVisual.subplots_adjust(bottom=heightscale-1,left=widthscale-1)
        gsVisual = figVisual.add_gridspec(1, 1)
        maxFeatureLen = 0
        for feature in scaledData.columns:
            for splitfeature in feature.split(','):
                if len(splitfeature) > maxFeatureLen:
                    maxFeatureLen = len(splitfeature)
                    print(splitfeature)
        featureScaleFactor = 5 
        #featureScaleFactor = 5*2.5
        self.canvasVisual = FigureCanvasTkAgg(figVisual,master=plotFrameVisual)
        self.canvasVisual.draw()
        self.canvasVisual.get_tk_widget().pack()
        
        #Cluster visualization
        defaultGroupCompDict  = {}
        levelPlotAxis = figVisual.add_subplot(gsVisual[0])
        levelPlotAxis.set_title('Data Visualization')
        if isinstance(clusteredData,list):
            visualPlottingDfForLegend = reducedData.reset_index()
            visualPlottingDf = pd.concat([reducedData,scaledData],axis=1).reset_index()
            levelList = list(scaledData.index.names)+['None']
            featureList = list(scaledData.columns)
            defaultClusterBool = False
        else:
            visualPlottingDfForLegend = reducedData.reset_index()
            visualPlottingDf = pd.concat([reducedData,scaledData],axis=1).reset_index()
            visualPlottingDf['Cluster'] = list(clusteredData.index.get_level_values('Cluster'))
            levelList = list(clusteredData.index.names)+['None']
            featureList = list(scaledData.columns)
            defaultClusterBool = True
        defaultplotkwargs,defaultDict = ipe.getDefaultKwargs(visualPlottingDfForLegend)
        if defaultClusterBool:
            defaultDict['hue'] = 'Cluster'
        #Widgets
        #Frame
        visualizationParameterWindow = tk.Frame(self)
        visualizationParameterWindow.grid(row=1,column=0)
        levelPlotWindow = tk.Frame(visualizationParameterWindow)
        levelPlotWindow.grid(row=0,column=0)
        #Dropdowns
        levelParameterList = ['hue','style','size']
        levelParameterValueDict = {}
        for level in levelParameterList:
            if level == 'hue' or level == 'size':
                levelParameterValueDict[level] = levelList.copy()+featureList.copy()
            else:
                levelParameterValueDict[level] = levelList.copy()
        dropdownList,dropdownVarsDict,levelDropdown,levelValueDropdown = ipe.createParameterSelectionDropdownsWithIndividualLevels(levelPlotWindow,levelParameterList,levelParameterValueDict,defaultDict,visualPlottingDf,experimentParameters)
        #Plot
        sizeParam = {}
        if 'Event' in visualPlottingDf.columns or 'event' in visualPlottingDf.columns:
            sizeParam['s'] = 3 
        ipe.updateDropdownControlledPlot(self.canvasVisual,levelPlotAxis,visualPlottingDf,dropdownVarsDict,'Dimension 1','Dimension 2',alpha=0.4,legendoffset=-0.2,trueLabelDict = trueLabelDict,levelDropdown = levelDropdown,levelValueDropdown=levelValueDropdown)
        levelPlotAxis.set_title('Data Visualization')
        self.originalxlims = levelPlotAxis.get_xlim()
        self.originalylims = levelPlotAxis.get_ylim()
        self.currentxlims = levelPlotAxis.get_xlim()
        self.currentylims = levelPlotAxis.get_ylim()
        #Button
        def zoomIn():
            clusterSelectionBox = toggle_selector2.RS.corners
            ll = np.array([clusterSelectionBox[0][0], clusterSelectionBox[1][0]])  # lower-left
            ur = np.array([clusterSelectionBox[0][2], clusterSelectionBox[1][2]])  # upper-right
            
            inidx = np.all(np.logical_and(ll <= reducedData.values[:,:2], reducedData.values[:,:2] <= ur), axis=1)
            inbox = reducedData.loc[inidx]
            bufferval = 0.1
            xlims = [min(inbox['Dimension 1'])-bufferval,max(inbox['Dimension 1'])+bufferval]
            ylims = [min(inbox['Dimension 2'])-bufferval,max(inbox['Dimension 2'])+bufferval]
            self.currentxlims = xlims
            self.currentylims = ylims
            levelPlotAxis.set_xlim(self.currentxlims)
            levelPlotAxis.set_ylim(self.currentylims)
            clusterSelectionAxis.set_xlim(self.currentxlims)
            clusterSelectionAxis.set_ylim(self.currentylims)
            self.canvasVisual.draw()
            self.canvasSelection.draw()
        def zoomOut():
            levelPlotAxis.set_xlim(self.originalxlims)
            levelPlotAxis.set_ylim(self.originalylims)
            clusterSelectionAxis.set_xlim(self.originalxlims)
            clusterSelectionAxis.set_ylim(self.originalylims)
            self.currentxlims = self.originalxlims 
            self.currentylims = self.originalylims
            self.canvasVisual.draw()
            self.canvasSelection.draw()
        def update():
            ipe.updateDropdownControlledPlot(self.canvasVisual,levelPlotAxis,visualPlottingDf,dropdownVarsDict,'Dimension 1','Dimension 2',alpha=0.4,legendoffset=-0.2,trueLabelDict = trueLabelDict,levelDropdown=levelDropdown,levelValueDropdown=levelValueDropdown,axisLimits = [levelPlotAxis.get_xlim(),levelPlotAxis.get_ylim()])
            levelPlotAxis.set_title('Data Visualization')
            levelPlotAxis.set_xlim(self.currentxlims)
            levelPlotAxis.set_ylim(self.currentylims)
            clusterSelectionAxis.set_xlim(self.currentxlims)
            clusterSelectionAxis.set_ylim(self.currentylims)
            self.canvasVisual.draw()
            self.canvasSelection.draw()
        #Click and drag widget
        def line_select_callback2(eclick, erelease):
            'eclick and erelease are the press and release events'
            x1, y1 = eclick.xdata, eclick.ydata
            x2, y2 = erelease.xdata, erelease.ydata
        def toggle_selector2(event):
            if event.key in ['Q', 'q'] and toggle_selector2.RS.active:
                toggle_selector2.RS.set_active(False)
            if event.key in ['A', 'a'] and not toggle_selector2.RS.active:
                toggle_selector2.RS.set_active(True)
        rectpropsdict2 = {'facecolor':'grey','alpha':0.2,'edgecolor':'grey'}
        toggle_selector2.RS = RectangleSelector(levelPlotAxis, line_select_callback2,drawtype='box', useblit=True,button=[1, 3], minspanx=5, minspany=5,spancoords='pixels',interactive=True,rectprops=rectpropsdict2)
        self.ts2 = toggle_selector2.RS
        self.canvasVisual.mpl_connect('key_press_event', toggle_selector2)
        
        zoomWindow = tk.Frame(visualizationParameterWindow)
        zoomWindow.grid(row=0,column=1)
        tk.Button(zoomWindow, text="Zoom in",command=lambda: zoomIn()).grid(row=0,column=0,sticky=tk.W)
        tk.Button(zoomWindow, text="Zoom out",command=lambda: zoomOut()).grid(row=1,column=0,sticky=tk.W)
        
        tk.Button(visualizationParameterWindow, text="Update visualization plot",command=lambda: update()).grid(row=1,column=0,columnspan=2)
        tk.Button(visualizationParameterWindow, text="Save visualization plot",command=lambda: exportFigure('visualization')).grid(row=2,column=0,columnspan=2)

        #Cluster selection
        plotFrameSelection = tk.Frame(self,borderwidth=1,relief='groove')
        plotFrameSelection.grid(row=0,column=1,sticky=tk.W+tk.E)
        figSelection = plt.figure(figsize=(figwidth, figheight*heightscale))
        figSelection.subplots_adjust(bottom=heightscale-1)#,left=widthscale-1)
        gsSelection = figSelection.add_gridspec(1, 1)
        self.canvasSelection = FigureCanvasTkAgg(figSelection,master=plotFrameSelection)
        self.canvasSelection.draw()
        self.canvasSelection.get_tk_widget().pack()
        #Plot
        clusterSelectionAxis = figSelection.add_subplot(gsSelection[0])
        clusterSelectionAxis.set_title('Group Selection')
        reducedPlottingDf = reducedData.reset_index()
        g1 = sns.scatterplot(data=reducedPlottingDf,x='Dimension 1',y='Dimension 2',ax=clusterSelectionAxis,alpha=0.7,color='#808080',**sizeParam)
        if clusterSelectionAxis.legend_ is not None:
            clusterSelectionAxis.legend_.remove()
        #Click and drag widget
        def line_select_callback(eclick, erelease):
            'eclick and erelease are the press and release events'
            x1, y1 = eclick.xdata, eclick.ydata
            x2, y2 = erelease.xdata, erelease.ydata

        def toggle_selector(event):
            if event.key in ['Q', 'q'] and toggle_selector.RS.active:
                toggle_selector.RS.set_active(False)
            if event.key in ['A', 'a'] and not toggle_selector.RS.active:
                toggle_selector.RS.set_active(True)
        rectpropsdict = {'facecolor':palette[self.paletteIndex],'alpha':0.2,'edgecolor':palette[self.paletteIndex]}
        toggle_selector.RS = RectangleSelector(clusterSelectionAxis, line_select_callback,drawtype='box', useblit=True,button=[1, 3], minspanx=5, minspany=5,spancoords='pixels',interactive=True,rectprops=rectpropsdict)
        self.ts = toggle_selector.RS
        self.canvasSelection.mpl_connect('key_press_event', toggle_selector)
        
        #Functions
        def updateSelectionPlot():
            featureDfList = []
            selectionPlottingDf = reducedPlottingDf.copy()
            selectionPlottingDf['Cluster'] = ['0']*reducedData.shape[0]
            for i in clusterComparisonDict:
                featureDfList.append(scaledData.iloc[clusterComparisonDict[i],:])
                selectionPlottingDf.loc[:,'Cluster'].iloc[clusterComparisonDict[i]] = str(i+1)
            clusterSelectionAxis.clear()
            #selectionPlottingDf['Cluster'] = clusterLabelList
            newpalette = ['#808080']+palette[:len(clusterComparisonDict.keys())]
            if len(selectionPlottingDf[selectionPlottingDf['Cluster'] == '0']) == 0:
                newpalette = newpalette[1:]
            g1 = sns.scatterplot(data=selectionPlottingDf,x='Dimension 1',y='Dimension 2',hue='Cluster',ax=clusterSelectionAxis,alpha=0.7,palette=newpalette,**sizeParam)
            if clusterSelectionAxis.legend_ is not None:
                clusterSelectionAxis.legend_.remove()
            for clusterCentroid in clusterCentroidList:
                g1.annotate(clusterCentroid[0],xy=clusterCentroid[1])
            clusterSelectionAxis.set_xlim(self.currentxlims)
            clusterSelectionAxis.set_ylim(self.currentylims)
            #rainbow_text(0.2, 1.05, "Group1;vs.;4,5;vs.;6".split(';'),[palette[0],'black', palette[1],'black', palette[2]],size=18)
            #returnGroupTitle(clusterSelectionAxis)
            clusterSelectionAxis.set_title('Group Selection')
            self.canvasSelection.draw()
        def addPredeterminedToCluster():
            predeterminedCluster = clusterVar.get()

            tempDf = pd.concat([reducedData,scaledData],axis=1).reset_index()
            tempDf['Cluster'] = list(clusteredData.index.get_level_values('Cluster'))
            #tempDf = visualPlottingDf.copy()
            tempDf['index'] = range(tempDf.shape[0])
            #inidx = np.all(tempDf['Cluster'] == predeterminedCluster)
            if predeterminedCluster == 'All Not Selected':
                tempSelDf = reducedPlottingDf.copy() 
                tempSelDf['Cluster'] = ['0']*reducedData.shape[0]
                for clusterIndex in clusterComparisonDict:
                    tempSelDf.loc[:,'Cluster'].iloc[clusterComparisonDict[clusterIndex]] = '-1' 
                inbox = tempDf.loc[tempSelDf['Cluster'] != '-1']
            else:
                inbox = tempDf.loc[tempDf['Cluster'] == predeterminedCluster]
            predetCentroid = get_cluster_centroids(inbox,singleCluster=True)
            tupleList = []
            if self.paletteIndex not in clusterComparisonDict.keys():
                clusterComparisonDict[self.paletteIndex] = list(map(int,list(inbox.values[:,-1])))
            else:
                clusterComparisonDict[self.paletteIndex] += list(map(int,list(inbox.values[:,-1])))
            clusterCentroidList.append(predetCentroid[0])
            clusterCentroidList2.append(predetCentroid[0])
            updateSelectionPlot()
        def addToCluster():
            clusterSelectionBox = toggle_selector.RS.corners
            ll = np.array([clusterSelectionBox[0][0], clusterSelectionBox[1][0]])  # lower-left
            ur = np.array([clusterSelectionBox[0][2], clusterSelectionBox[1][2]])  # upper-right
            
            tempDf = reducedData.copy()
            tempDf['index'] = range(tempDf.shape[0])

            inidx = np.all(np.logical_and(ll <= tempDf.values[:,:2], tempDf.values[:,:2] <= ur), axis=1)
            inbox = tempDf.loc[inidx]
            selectionCentroid = get_cluster_centroids(inbox,singleCluster=True)
            selectionCentroid[0][0] = letters[self.GUI_Selection_Index] 
            self.GUI_Selection_Index+=1
            tupleList = []
            if self.paletteIndex not in clusterComparisonDict.keys():
                clusterComparisonDict[self.paletteIndex] = list(map(int,list(inbox.values[:,-1])))
            else:
                clusterComparisonDict[self.paletteIndex] += list(map(int,list(inbox.values[:,-1])))
            clusterCentroidList.append(selectionCentroid[0])
            clusterCentroidList2.append(selectionCentroid[0])
            updateSelectionPlot()
        def returnGroupTitle(axis):
            #rainbow_text(0.2, 1.05, "1,2,3;vs.;4,5;vs.;6".split(';'),[palette[0],'black', palette[1],'black', palette[2]],size=18)
            titleColorList = []
            fullTitleList = []
            palette = sns.color_palette(sns.color_palette(),len(clusterCentroidDict))
            for i,group in enumerate(clusterCentroidDict):
                titleList = []
                for clusterCentroid in clusterCentroidDict[group]:
                    fullName = clusterCentroid[0]
                    titleList.append(fullName)
                selectionsInGroup = ','.join(titleList)
                fullTitleList.append(selectionsInGroup)
                titleColorList+=[palette[i],'black']
            fullTitleString = ';vs.;'.join(fullTitleList)
            titleColorList = titleColorList[:-1]
            axis.set_title('')
            xpos = ((max(visualPlottingDf['Dimension 1'])-min(visualPlottingDf['Dimension 1']))/2)+min(visualPlottingDf['Dimension 1'])
            ypos = max(visualPlottingDf['Dimension 2'])+2
            rainbow_text(xpos, ypos, fullTitleString.split(';'),titleColorList,size=10,ax=axis)

        def grabSamplesInCluster(): 
            clusterComparisonList.append(clusterComparisonDict[self.paletteIndex])
            clusterCentroidDict[str(self.paletteIndex)] = clusterCentroidList.copy()
            clusterCentroidDict2[str(self.paletteIndex)] = clusterCentroidList2.copy()
            del clusterCentroidList2[:]
            self.paletteIndex+=1
            #returnGroupTitle(clusterSelectionAxis)
            rectpropsdict = {'facecolor':palette[self.paletteIndex],'alpha':0.2,'edgecolor':palette[self.paletteIndex]}
            toggle_selector.RS = RectangleSelector(clusterSelectionAxis, line_select_callback,drawtype='box', useblit=True,button=[1, 3], minspanx=5, minspany=5,spancoords='pixels',interactive=True,rectprops=rectpropsdict)
            self.ts = toggle_selector.RS
            self.canvasSelection.draw()
        def clearClusters():
            clusterComparisonAxis.clear()
            clusterSelectionAxis.clear()
            groupCompositionAxis.clear()
            clusterSelectionAxis.set_title('Group Selection')
            clusterComparisonAxis.set_title('Group Comparison')
            groupCompositionAxis.set_title('Group Composition')
            g1 = sns.scatterplot(data=reducedPlottingDf,x='Dimension 1',y='Dimension 2',ax=clusterSelectionAxis,alpha=0.7,color='#808080',**sizeParam)
            if clusterSelectionAxis.legend_ is not None:
                clusterSelectionAxis.legend_.remove()
            del clusterComparisonList[:]
            clusterComparisonDict.clear()
            del clusterCentroidList[:]
            clusterCentroidDict.clear()
            del clusterCentroidList2[:]
            clusterCentroidDict2.clear()
            self.paletteIndex = 0
            self.GUI_Selection_Index=0
            rectpropsdict = {'facecolor':palette[self.paletteIndex],'alpha':0.2,'edgecolor':palette[self.paletteIndex]}
            toggle_selector.RS = RectangleSelector(clusterSelectionAxis, line_select_callback,drawtype='box', useblit=True,button=[1, 3], minspanx=5, minspany=5,spancoords='pixels',interactive=True,rectprops=rectpropsdict)
            self.ts = toggle_selector.RS
            clusterSelectionAxis.set_xlim(self.currentxlims)
            clusterSelectionAxis.set_ylim(self.currentylims)
            self.canvasSelection.draw()
        def compareClusters():
            updateSelectionPlot()
            updateComparisonPlot(sliderList,radiobuttonVars,radiobuttonVars2)
        #Widgets
        #Frame
        selectionParameterWindow = tk.Frame(self)
        selectionParameterWindow.grid(row=1,column=1)
        plotButtonWindow = tk.Frame(selectionParameterWindow)
        plotButtonWindow.grid(row=0,column=0)
        plotButtonWindow.root = master.root
        #Buttons
        #Interactive selection
        tk.Label(plotButtonWindow,text='GUI Selection').grid(row=0,column=0)
        tk.Button(plotButtonWindow, text="Add To Current Group",command=lambda: addToCluster()).grid(row=1,column=0,sticky=tk.W)
        
        #Cluster dropdown selection
        preDetWindow = tk.Frame(plotButtonWindow)
        preDetWindow.grid(row=0,column=1)
        if not isinstance(clusteredData,list):
            tk.Label(preDetWindow,text='Cluster: ').grid(row=0,column=0,sticky=tk.E)
            clusters = list(pd.unique(clusteredData.index.get_level_values('Cluster')))
            sortedClusters = list(map(str,sorted(list(map(int,clusters)))))+['All Not Selected']
            clusterVar = tk.StringVar()
            clusterMenu = tk.OptionMenu(preDetWindow,clusterVar,*sortedClusters)
            clusterMenu.grid(row=0,column=1)
            setMaxWidth(sortedClusters,clusterMenu)
            tk.Button(plotButtonWindow, text="Add To Current Group",command=lambda: addPredeterminedToCluster()).grid(row=1,column=1,sticky=tk.E)

        #Common to both
        tk.Button(plotButtonWindow, text="Store Current Group",command=lambda: grabSamplesInCluster()).grid(row=2,column=0,columnspan=2)
        tk.Button(plotButtonWindow, text="Clear Groups",command=lambda: clearClusters()).grid(row=3,column=0,columnspan=2)
        tk.Button(selectionParameterWindow, text="Compare Groups",command=lambda: compareClusters()).grid(row=1,column=0)
        tk.Button(selectionParameterWindow, text="Save selection plot",command=lambda: exportFigure('selection')).grid(row=2,column=0)
        
        #Group Comparison
        plotFrameComparison = tk.Frame(self,borderwidth=1,relief='groove')
        plotFrameComparison.grid(row=0,column=2,sticky=tk.W+tk.E)
        figComparison = plt.figure(figsize=(2*figwidth, figheight*heightscale))
        figComparison.subplots_adjust(bottom=heightscale-1)#,left=widthscale-1)
        gsComparison = figComparison.add_gridspec(1, 2)
        self.canvasComparison = FigureCanvasTkAgg(figComparison,master=plotFrameComparison)
        self.canvasComparison.draw()
        self.canvasComparison.get_tk_widget().pack()
        #Plot
        clusterComparisonAxis = figComparison.add_subplot(gsComparison[0:2])
        clusterComparisonAxis.set_title('Group Comparison')
        #Group composition
        self.comparisonPlottingDf = []
        #Functions
        def updateComparisonPlot(sliderList,rbVarList,rbVarList2):
            clusterComparisonAxis.clear()
            featureDfList = []
            featureDfWithClusters = scaledData.copy()
            featureDfWithClusters['Cluster'] = ['0']*scaledData.shape[0]
            for i,clusterComparison in enumerate(clusterComparisonList):
                featureDfList.append(scaledData.iloc[clusterComparison,:])
                featureDfWithClusters.loc[:,'Cluster'].iloc[clusterComparison] = str(i+1)
            clusterLabelList = featureDfWithClusters['Cluster'] 
            comparisonDf = pd.concat(featureDfList,keys=list(map(str,list(range(1,len(clusterComparisonList)+1)))),names=['Cluster'])
            comparisonDf.columns.name = 'Feature'
            comparisonPlottingDf = comparisonDf.stack().to_frame('Metric').reset_index()
            self.comparisonPlottingDf = comparisonPlottingDf.copy()
            #featureDfWithClusters['Cluster'] = clusterLabelList
            #Get unique cluster labels for hue order and pairwise significance comparisons
            clusterLabelListNoZero = list(filter(lambda a: a != '0', clusterLabelList))
            uniqueClusterLabelListNoZero = list(pd.unique(clusterLabelListNoZero))
            orderedClusterLabelListNoZero = []
            for uniqueClusterLabel in uniqueClusterLabelListNoZero:
                intval = int(uniqueClusterLabel)
                orderedClusterLabelListNoZero.append(intval)
            orderedClusterLabelListNoZero = sorted(orderedClusterLabelListNoZero)
            for i,orderedClusterLabel in enumerate(orderedClusterLabelListNoZero):
                orderedClusterLabelListNoZero[i] = str(orderedClusterLabel)
            #Get all pairwise combinations of clusters
            pairwiseClusterCombinations = list(itertools.combinations(orderedClusterLabelListNoZero,2))
            #Conduct significance testing to get features that define cluster differences
            comparisonKwargs = {'confidence':sliderList[0].get(),'foldchange':sliderList[1].get(),'responseCutoff':sliderList[2].get(),'errorCorrection':rbVarList['error correction method'].get()}
            self.comparisonKwargs = comparisonKwargs.copy()
            featureDfWithClusters.columns.name = 'Feature'
            significanceArray = []
            if len(clusterComparisonList) > 1:
                dataMatrix,significanceArray = cpl.significanceTesting(featureDfWithClusters,pairwiseClusterCombinations,**comparisonKwargs)
            else:
                significanceArray = list(scaledData.columns)
                print(significanceArray)
            if len(significanceArray) != 0:
                comparisonPlottingDf = comparisonPlottingDf[comparisonPlottingDf['Feature'].isin(significanceArray)]
                plotType = rbVarList2['comparison plot type'].get()
                self.comparisonKwargs['plotType'] = plotType
                comparisonPlottingDfTemp = comparisonPlottingDf.copy()
                newcols = []
                for col in comparisonPlottingDf['Feature']:
                    newcols.append(col.replace(',','\n'))
                comparisonPlottingDfTemp['Feature'] = newcols
                comparisonPlottingDfTemp['Metric'] = comparisonPlottingDfTemp['Metric'].astype(float)
                if plotType == 'violin':
                    if len(clusterComparisonList) == 1:
                        g2 = sns.violinplot(data=comparisonPlottingDfTemp,x='Feature',y='Metric',ax=clusterComparisonAxis,scale='width',inner='quartile',legend=False)
                    elif len(clusterComparisonList) == 2:
                        g2 = sns.violinplot(data=comparisonPlottingDfTemp,hue='Cluster',hue_order=orderedClusterLabelListNoZero,x='Feature',y='Metric',ax=clusterComparisonAxis,split=True,scale='width',inner='quartile',legend=False)
                    else:
                        g2 = sns.violinplot(data=comparisonPlottingDfTemp,hue='Cluster',hue_order=orderedClusterLabelListNoZero,x='Feature',y='Metric',ax=clusterComparisonAxis,dodge=True,scale='width',inner='quartile',legend=False)
                elif plotType == 'box':
                    g2 = sns.boxplot(data=comparisonPlottingDfTemp,hue='Cluster',hue_order=orderedClusterLabelListNoZero,x='Feature',y='Metric',ax=clusterComparisonAxis,showfliers=False)
                elif plotType == 'bar':
                    g2 = sns.barplot(data=comparisonPlottingDfTemp,hue='Cluster',hue_order=orderedClusterLabelListNoZero,x='Feature',y='Metric',ax=clusterComparisonAxis,ci='sd',errwidth=1,capsize=0.05,edgecolor='k')
                plt.setp(clusterComparisonAxis.xaxis.get_majorticklabels(), rotation=45)
                if len(clusterComparisonList) > 1:
                    clusterComparisonAxis.legend_.remove()
                if max(comparisonPlottingDfTemp['Metric']) > 100:
                    yticksToUse = [-1000,100,1000,10000,100000]
                    ytickValues,ytickLabels = returnTicks(yticksToUse)
                    #clusterComparisonAxis.set_ylim([0,1000])
                    clusterComparisonAxis.set_yticks(ytickValues)
                    clusterComparisonAxis.set_yticklabels(ytickLabels)
                    #clusterComparisonAxis.set_ylim([0,1000])
            else:
                clusterComparisonAxis.text(0.5, 0.5,'No significant differences',horizontalalignment='center',verticalalignment='center',transform = clusterComparisonAxis.transAxes)
            clusterComparisonAxis.set_title('Group Comparison')
            self.canvasComparison.draw()
        #Widgets
        #Frame
        clusterComparisonParameterWindow = tk.Frame(self)
        clusterComparisonParameterWindow.grid(row=1,column=2)
        sliderWindow = tk.Frame(clusterComparisonParameterWindow)
        sliderWindow.grid(row=0,column=0)
        sliderWindow.root = master.root
        #Sliders
        sliderList = ipe.createParameterAdjustmentSliders(sliderWindow,ods.clusterComparisonParameterList,ods.clusterComparisonParameterBoundsDict)
        #sliderList = ipe.createParameterAdjustmentSliders(clusterComparisonParameterWindow,ods.clusterComparisonParameterList,ods.clusterComparisonParameterBoundsDict)
        #Radio buttons (for plot type)
        radioWindow = tk.Frame(clusterComparisonParameterWindow)
        radioWindow.grid(row=0,column=1)
        radioWindow.root = master.root
        radiobuttonList2,radiobuttonVars2 = ipe.createParameterSelectionRadiobuttons(radioWindow,ods.clusterComparisonParameterList3,ods.clusterComparisonParameterValueDict3)
        
        #Radio buttons (for error correction)
        radioWindow2 = tk.Frame(clusterComparisonParameterWindow)
        radioWindow2.grid(row=0,column=2)
        radioWindow2.root = master.root
        radiobuttonList,radiobuttonVars = ipe.createParameterSelectionRadiobuttons(radioWindow2,ods.clusterComparisonParameterList2,ods.clusterComparisonParameterValueDict2)
        #Buttons
        tk.Button(clusterComparisonParameterWindow, text="Update comparison plot",command=lambda: updateComparisonPlot(sliderList,radiobuttonVars,radiobuttonVars2)).grid(row=1,column=0,columnspan=3)
        tk.Button(clusterComparisonParameterWindow, text="Save comparison plot",command=lambda: exportFigure('comparison')).grid(row=2,column=0,columnspan=3)
        
        #Group Composition
        plotFrameComposition = tk.Frame(self,borderwidth=1,relief='groove')
        plotFrameComposition.grid(row=0,column=3,sticky=tk.W+tk.E)
        figComposition = plt.figure(figsize=(figwidth*widthscale, figheight*heightscale))
        figComposition.subplots_adjust(bottom=heightscale-1,right=2-widthscale)
        gsComposition = figComposition.add_gridspec(1, 1)
        self.canvasComposition = FigureCanvasTkAgg(figComposition,master=plotFrameComposition)
        self.canvasComposition.draw()
        self.canvasComposition.get_tk_widget().pack()
        #Widgets
        groupCompositionAxis = figComposition.add_subplot(gsComposition[0])
        groupCompositionAxis.set_title('Group Composition')
        #Frame
        groupCompositionWindow = tk.Frame(self)
        groupCompositionWindow.grid(row=1,column=3)
        #Dropdowns
        groupCompParameterList = ['x','y','hue']
        groupCompParameterValueDict = {}
        #levelList2 = ['Cluster']+list(scaledData.index.names)+['None']
        levelList2 = ['Group']+list(scaledData.index.names)+['None']
        for level in groupCompParameterList:
            if level == 'x':
                groupCompParameterValueDict[level] = levelList2.copy()+list(scaledData.columns)
            elif level == 'y':
                groupCompParameterValueDict[level] = ['frequency','log-frequency','percent']+list(scaledData.columns)+['None']
            else:
                groupCompParameterValueDict[level] = levelList2.copy()+list(scaledData.columns)
        compositionDropdownWindow = tk.Frame(groupCompositionWindow)
        compositionDropdownWindow.root = master.root
        compositionDropdownWindow.grid(row=0,column=0)
        dropdownListComposition,dropdownVarsDictComposition = ipe.createParameterSelectionDropdowns(compositionDropdownWindow,groupCompParameterList,groupCompParameterValueDict,{'x':'Cluster','y':'frequency','hue':list(scaledData.index.names)[0]})
        
        def updateComposition():
            if isinstance(self.comparisonPlottingDf,list):
                featureDfList = []
                featureDfWithClusters = scaledData.copy()
                featureDfWithClusters['Cluster'] = ['0']*scaledData.shape[0]
                for i,clusterComparison in enumerate(clusterComparisonList):
                    featureDfList.append(scaledData.iloc[clusterComparison,:])
                    featureDfWithClusters.loc[:,'Cluster'].iloc[clusterComparison] = str(i+1)
                clusterLabelList = featureDfWithClusters['Cluster'] 
                comparisonDf = pd.concat(featureDfList,keys=list(map(str,list(range(1,len(clusterComparisonList)+1)))),names=['Cluster'])
                comparisonDf.columns.name = 'Feature'
                comparisonPlottingDf = comparisonDf.stack().to_frame('Metric').reset_index()
                self.comparisonPlottingDf = comparisonPlottingDf.copy()
            #compositionParameter = self.compositionRbs['Cluster composition y axis'].get()
            #ipe.updatedropdowncontrolledcompositionplot(self.canvascomposition,groupcompositionaxis,self.comparisonplottingdf,truelabeldict,dropdownvarsdictcomposition,compositionparameter)
            ipe.updateDropdownControlledCompositionPlot(self.canvasComposition,groupCompositionAxis,self.comparisonPlottingDf,trueLabelDict,dropdownVarsDictComposition)
            print(ipe.getDropdownValues(dropdownVarsDictComposition))
            print(clusterCentroidDict2)
            groupCompositionAxis.set_title('Group Composition')
            self.canvasComposition.draw()
        
        #Radio buttons (for composition y axis)
        #compositionRadioButtonWindow = tk.Frame(groupCompositionWindow)
        #compositionRadioButtonWindow.root = master.root
        #compositionRadioButtonWindow.grid(row=0,column=1)
        #compositionParameters = ['Cluster composition y axis'] 
        #compositionParameterValues = {'Cluster composition y axis':['frequency','percent']}
        #radiobuttonListComp,self.compositionRbs = ipe.createParameterSelectionRadiobuttons(compositionRadioButtonWindow,compositionParameters,compositionParameterValues)
        #Plot
        tk.Button(groupCompositionWindow, text="Update composition plot",command=lambda: updateComposition()).grid(row=1,column=0)
        tk.Button(groupCompositionWindow, text="Save composition plot",command=lambda: exportFigure('composition')).grid(row=2,column=0)

        #Figure exporting frame
        titleFrame = tk.Frame(self)
        titleFrame.grid(row=3,column=0,columnspan=4)
        titleEntryFrame = tk.Frame(titleFrame)
        titleEntryFrame.grid(row=0,column=0)
        titleEntryFrame.root = master.root
        tk.Label(titleEntryFrame,text='Title:').grid(row=0,column=0,sticky=tk.W)
        titleEntry = tk.Entry(titleEntryFrame)
        titleEntry.grid(row=0,column=1,sticky=tk.W)
        titleEntry.insert(tk.END,'group1vs2')
        
        def createDescriptiveTitle(figureName):
            #Group title segment
            groupList = []
            for group in clusterCentroidDict2:
                memberlist = []
                centroids = clusterCentroidDict2[group]
                for centroid in centroids:
                    memberlist.append(centroid[0])
                groupList.append(','.join(memberlist))
            #Figure parameter title segment
            if figureName == 'visualization':
                parameters1 = ipe.getDropdownValues(dropdownVarsDict)
                if levelValueDropdown.get() == 'All':
                    parameters2 = {'subset':levelValueDropdown.get()} 
                else:
                    parameters2 = {'subset':levelDropdown.get()+'-'+levelValueDropdown.get()} 
                parameters = {**parameters1,**parameters2}
            elif figureName == 'comparison':
                parameters = self.comparisonKwargs.copy()
            elif figureName == 'composition':
                parameters = ipe.getDropdownValues(dropdownVarsDictComposition)
            else:
                parameters = {}
            groupTitle = 'vs'.join(groupList)
            parameterTitle = ods.returnParameterString(parameters)
            return groupTitle,parameterTitle

        def exportFigure(figureName):
            figureDict = {'visualization':figVisual,'selection':figSelection,'comparison':figComparison,'composition':figComposition}
            customTitle = titleEntry.get()
            groupTitle,parameterTitle = createDescriptiveTitle(figureName)
            if figureName != 'all':
                fullFigureTitle = 'plots/'+'-'.join([customTitle,groupTitle,figureName,parameterTitle])+'.'+self.plotFormatRbs['Figure Format'].get()
                figureDict[figureName].savefig(fullFigureTitle,bbox_inches='tight')
                print(figureName+' Figure Saved')
            else:
                for figureNm in list(figureDict.keys()):
                    exportFigure(figureNm)
        
        plotFormatRadioButtonWindow = tk.Frame(titleFrame)
        plotFormatRadioButtonWindow.root = master.root
        plotFormatRadioButtonWindow.grid(row=0,column=1)
        plotFormatParameters = ['Figure Format'] 
        plotFormatParameterValues = {'Figure Format':['png','pdf']}
        radiobuttonListPlotFormat,self.plotFormatRbs = ipe.createParameterSelectionRadiobuttons(plotFormatRadioButtonWindow,plotFormatParameters,plotFormatParameterValues)
        tk.Button(titleFrame, text="Export all figures",command=lambda: exportFigure('all')).grid(row=1,column=0,columnspan=2)
        
        #Default save and quit buttons
        buttonWindow = tk.Frame(self)
        buttonWindow.grid(row=4,column=0,columnspan=4)
        tk.Button(buttonWindow, text="OK",command=lambda: master.switch_frame(backpage,folderName,secondaryhomepage)).grid(row=0,column=0)
        tk.Button(buttonWindow, text="Back",command=lambda: master.switch_frame(ClusterComparisonHomePage,folderName,backpage,secondaryhomepage)).grid(row=0,column=1)
        tk.Button(buttonWindow, text="Quit",command=lambda: quit()).grid(row=0,column=2)
Beispiel #3
0
    def __init__(self, master, scaledData, dataSubsetTitle, dimRedType,
                 plottingReduction):
        tk.Frame.__init__(self, master)

        #Initialize 1x1 canvas for interactive plots
        plotFrame = tk.Frame(self)
        plotFrame.grid(row=0, column=0, columnspan=3)
        fig = plt.figure(figsize=(10, 7))
        gs = fig.add_gridspec(1, 1)
        fig.subplots_adjust(left=0.25)
        offset = -0.1
        levelPlotAxis = fig.add_subplot(gs[0])
        self.canvas = FigureCanvasTkAgg(fig, master=plotFrame)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack()

        #Dimensional reduction plot (can be colored/resized/restyled by different level values in dropdowns)
        #Level parameter controls
        levelPlotWindow = tk.Frame(self)
        levelPlotWindow.grid(row=1, column=0, sticky=tk.N)
        levelParameterList = ['hue', 'style', 'size']
        levelParameterValueDict = {}
        #Dimensional reduction parameter controls
        dimRedNumericParameterWindow = tk.Frame(self)
        dimRedNumericParameterWindow.grid(row=1, column=1, sticky=tk.N)
        sliderList = ipe.createParameterAdjustmentSliders(
            dimRedNumericParameterWindow,
            ods.dimReductionNumericParameterDict[dimRedType],
            ods.dimReductionNumericParameterBounds)
        dimRedQualitativeParameterWindow = tk.Frame(self)
        dimRedQualitativeParameterWindow.grid(row=1, column=2, sticky=tk.N)
        radiobuttonList, radiobuttonVars = ipe.createParameterSelectionRadiobuttons(
            dimRedQualitativeParameterWindow,
            ods.dimReductionQualitativeParameterDict[dimRedType],
            ods.dimReductionQualitativeParameterValues)
        #Plot
        numericParametersForDimensionReduction = ipe.getSliderValues(
            sliderList, ods.dimReductionNumericParameterDict[dimRedType])
        qualitativeParametersForDimensionReduction = ipe.getRadiobuttonValues(
            radiobuttonVars)
        self.currentReductionParameters = numericParametersForDimensionReduction.copy(
        )
        self.currentReductionParameters.update(
            qualitativeParametersForDimensionReduction.copy())
        if len(plottingReduction) == 0:
            self.reducedData = ods.reduceDimensions(
                scaledData, dimRedType, [], self.currentReductionParameters)
        else:
            self.reducedData = plottingReduction.copy()
        self.reducedDataWithFeatures = pd.concat(
            [self.reducedData, scaledData], axis=1)
        levelList = list(self.reducedData.index.names) + ['None']
        featureList = list(scaledData.columns)
        for level in levelParameterList:
            if level == 'hue' or level == 'size':
                levelParameterValueDict[level] = levelList.copy(
                ) + featureList.copy()
            else:
                levelParameterValueDict[level] = levelList.copy()
        plottingDfReduced = self.reducedData.reset_index()
        plottingDfReducedWithFeatures = self.reducedDataWithFeatures.reset_index(
        )
        kwargs, defaultDict = ipe.getDefaultKwargs(plottingDfReduced)
        dropdownList, dropdownVarsDict = ipe.createParameterSelectionDropdowns(
            levelPlotWindow, levelParameterList, levelParameterValueDict,
            defaultDict)
        ipe.updateDropdownControlledPlot(self.canvas,
                                         levelPlotAxis,
                                         plottingDfReducedWithFeatures,
                                         dropdownVarsDict,
                                         'Dimension 1',
                                         'Dimension 2',
                                         legendoffset=offset)

        self.originalxlims = levelPlotAxis.get_xlim()
        self.originalylims = levelPlotAxis.get_ylim()
        self.currentxlims = levelPlotAxis.get_xlim()
        self.currentylims = levelPlotAxis.get_ylim()

        def updateDimRedPlot(sliderList, radiobuttonVars):
            levelPlotAxis.clear()
            numericParametersForDimensionReduction = ipe.getSliderValues(
                sliderList, ods.dimReductionNumericParameterDict[dimRedType])
            qualitativeParametersForDimensionReduction = ipe.getRadiobuttonValues(
                radiobuttonVars)
            self.currentReductionParameters = numericParametersForDimensionReduction.copy(
            )
            self.currentReductionParameters.update(
                qualitativeParametersForDimensionReduction.copy())
            self.reducedData = ods.reduceDimensions(
                scaledData, dimRedType, [], self.currentReductionParameters)
            plottingDfReduced = self.reducedData.reset_index()
            self.reducedDataWithFeatures = pd.concat(
                [self.reducedData, scaledData], axis=1)
            plottingDfReducedWithFeatures = self.reducedDataWithFeatures.reset_index(
            )
            ipe.updateDropdownControlledPlot(self.canvas,
                                             levelPlotAxis,
                                             plottingDfReducedWithFeatures,
                                             dropdownVarsDict,
                                             'Dimension 1',
                                             'Dimension 2',
                                             legendoffset=offset)
            levelPlotAxis.set_xlim(self.currentxlims)
            levelPlotAxis.set_ylim(self.currentylims)
            self.canvas.draw()

        #Click and drag widget
        def line_select_callback(eclick, erelease):
            'eclick and erelease are the press and release events'
            x1, y1 = eclick.xdata, eclick.ydata
            x2, y2 = erelease.xdata, erelease.ydata

        def toggle_selector(event):
            print(' Key pressed.')
            if event.key in ['Q', 'q'] and toggle_selector.RS.active:
                print(' RectangleSelector deactivated.')
                toggle_selector.RS.set_active(False)
            if event.key in ['A', 'a'] and not toggle_selector.RS.active:
                print(' RectangleSelector activated.')
                toggle_selector.RS.set_active(True)

        rectpropsdict = {
            'facecolor': 'grey',
            'alpha': 0.2,
            'edgecolor': 'grey'
        }
        toggle_selector.RS = RectangleSelector(levelPlotAxis,
                                               line_select_callback,
                                               drawtype='box',
                                               useblit=True,
                                               button=[1, 3],
                                               minspanx=5,
                                               minspany=5,
                                               spancoords='pixels',
                                               interactive=True,
                                               rectprops=rectpropsdict)
        self.ts = toggle_selector.RS
        self.canvas.mpl_connect('key_press_event', toggle_selector)

        def zoomIn():
            clusterSelectionBox = toggle_selector.RS.corners
            ll = np.array(
                [clusterSelectionBox[0][0],
                 clusterSelectionBox[1][0]])  # lower-left
            ur = np.array(
                [clusterSelectionBox[0][2],
                 clusterSelectionBox[1][2]])  # upper-right

            inidx = np.all(np.logical_and(ll <= self.reducedData.values,
                                          self.reducedData.values <= ur),
                           axis=1)
            inbox = self.reducedData.loc[inidx]
            bufferval = 0.1
            xlims = [
                min(inbox['Dimension 1']) - bufferval,
                max(inbox['Dimension 1']) + bufferval
            ]
            ylims = [
                min(inbox['Dimension 2']) - bufferval,
                max(inbox['Dimension 2']) + bufferval
            ]
            self.currentxlims = xlims
            self.currentylims = ylims
            levelPlotAxis.set_xlim(xlims)
            levelPlotAxis.set_ylim(ylims)
            self.canvas.draw()

        def zoomOut():
            levelPlotAxis.set_xlim(self.originalxlims)
            levelPlotAxis.set_ylim(self.originalylims)
            self.currentxlims = self.originalxlims
            self.currentylims = self.originalylims
            self.canvas.draw()

        def update():
            ipe.updateDropdownControlledPlot(
                self.canvas, levelPlotAxis,
                pd.concat([self.reducedData, scaledData],
                          axis=1).reset_index(), dropdownVarsDict,
                'Dimension 1', 'Dimension 2')
            levelPlotAxis.set_xlim(self.currentxlims)
            levelPlotAxis.set_ylim(self.currentylims)
            self.canvas.draw()

        def exportDimRed():
            ods.savePostProcessedFile(self.reducedData, dataSubsetTitle,
                                      'reduce', dimRedType,
                                      self.currentReductionParameters)
            print('Dimensional Reduction Saved!')
            if plotAllDimReds.get():
                if 'Event' in plottingDfReducedWithFeatures.columns or 'event' in plottingDfReducedWithFeatures.columns:
                    sizeParam = {'s': 5}
                else:
                    sizeParam = {}
                for feature in pd.unique(scaledData.columns):
                    g = sns.relplot(data=plottingDfReducedWithFeatures,
                                    x='Dimension 1',
                                    y='Dimension 2',
                                    hue=feature,
                                    palette='coolwarm',
                                    alpha=0.7,
                                    **sizeParam)
                    leg = g._legend
                    if max(plottingDfReducedWithFeatures[feature]
                           ) > 100 and len(sizeParam) > 0:
                        a, b = returnTicks([-1000, 100, 10000, 100000])
                        for t, l in zip(leg.texts[1:], (b)):
                            t.set_text(l)
                    else:
                        for t in leg.texts:
                            # truncate label text to 4 characters
                            if t.get_text() == '1.2000000000000002':
                                t.set_text('1.0')
                            else:
                                if '.' in t.get_text():
                                    if t.get_text().replace('.', '',
                                                            1).isdigit():
                                        decimalIndex = t.get_text().find('.')
                                        t.set_text(
                                            round(float(t.get_text()), 2))
                    reducedName = ods.getFileName(
                        dataSubsetTitle,
                        'reduce',
                        dimRedType,
                        self.currentReductionParameters,
                        fileExtension='.png')[0]
                    subprocess.run([
                        'mkdir',
                        'plots/' + reducedName[:-4] + '-featureColoredPlots'
                    ])
                    plt.savefig('plots/' + reducedName[:-4] +
                                '-featureColoredPlots/' + str(feature) +
                                '.png',
                                bbox_inches='tight')
                    plt.clf()
                    print(feature + ' plot saved')

        tk.Button(self, text="Update plot styling",
                  command=lambda: update()).grid(row=2, column=0)
        tk.Button(self, text="Zoom in",
                  command=lambda: zoomIn()).grid(row=4, column=0)
        tk.Button(self, text="Zoom out",
                  command=lambda: zoomOut()).grid(row=5, column=0)
        tk.Button(self,
                  text="Update hyperparameters",
                  command=lambda: updateDimRedPlot(sliderList, radiobuttonVars)
                  ).grid(row=2, column=1, columnspan=2)

        tk.Button(
            self,
            text='Save plot',
            command=lambda: fig.savefig('plots/' + ods.getFileName(
                dataSubsetTitle,
                'reduce',
                dimRedType,
                self.currentReductionParameters,
                plotParameterDict=ipe.getDropdownValues(dropdownVarsDict),
                fileExtension='.png')[0],
                                        bbox_inches='tight')).grid(row=3,
                                                                   column=0)
        tk.Button(self,
                  text='Save dimensional reduction',
                  command=lambda: exportDimRed(),
                  font='Helvetica 14 bold').grid(row=3, column=1, columnspan=2)
        plotAllDimReds = tk.BooleanVar()
        plotAllDimRedsButton = tk.Checkbutton(
            self,
            text='Save all feature-colored dimension reduction plots?',
            variable=plotAllDimReds)
        plotAllDimRedsButton.select()
        plotAllDimRedsButton.grid(row=4, column=1, columnspan=2)

        def okCommand():
            exportDimRed()
            master.switch_frame(backpage, folderName, secondaryhomepage)

        #Default save and quit buttons
        buttonWindow = tk.Frame(self)
        buttonWindow.grid(row=6, column=0, columnspan=2)
        try:
            k = backpage
        except NameError:
            backpage, folderName, secondaryhomepage = pickle.load(
                open('misc/dimRedPlottingParamList.pkl', 'rb'))

        tk.Button(buttonWindow,
                  text="OK",
                  command=lambda: master.switch_frame(
                      backpage, folderName, secondaryhomepage)).grid(row=0,
                                                                     column=0)
        tk.Button(buttonWindow,
                  text="Back",
                  command=lambda: master.switch_frame(
                      DimensionReductionHomePage, folderName, backpage,
                      secondaryhomepage)).grid(row=0, column=1)
        tk.Button(buttonWindow, text="Quit",
                  command=lambda: quit()).grid(row=0, column=2)
    def __init__(self, master,scaledData,reducedData,dataSubsetTitle,clusteringMethod):
        tk.Frame.__init__(self, master)
        
        loff = -0.2

        #Initialize 2x1 canvas for interactive plots
        plotFrame = tk.Frame(self)
        plotFrame.grid(row=0,column=0,columnspan=2)
        fig = plt.figure(figsize=(15, 6))
        gs = fig.add_gridspec(1, 2)
        gs.update(wspace=0.3)
        fig.subplots_adjust(left=0.2)
        levelPlotAxis = fig.add_subplot(gs[0])
        clusterPlotAxis = fig.add_subplot(gs[1])
        self.canvas = FigureCanvasTkAgg(fig,master=plotFrame)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack()
        
        #Dimensional reduction plot (can be colored/resized/restyled by different level values in dropdowns)
        levelPlotWindow = tk.Frame(self)
        levelPlotWindow.grid(row=1,column=0,sticky=tk.N)
        levelParameterList = ['hue','style','size']
        levelParameterValueDict = {}
        levelList = list(scaledData.index.names)+['None']
        featureList = list(scaledData.columns)
        for level in levelParameterList:
            if level == 'hue' or level == 'size':
                levelParameterValueDict[level] = levelList.copy()+featureList.copy()
            else:
                levelParameterValueDict[level] = levelList.copy()
        plottingDfReducedForLegend = reducedData.reset_index()
        kwargs,defaultDict = ipe.getDefaultKwargs(plottingDfReducedForLegend)
        plottingDfReduced = pd.concat([reducedData,scaledData],axis=1).reset_index()
        dropdownList,dropdownVarsDict = ipe.createParameterSelectionDropdowns(levelPlotWindow,levelParameterList,levelParameterValueDict,defaultDict)
        ipe.updateDropdownControlledPlot(self.canvas,levelPlotAxis,plottingDfReduced,dropdownVarsDict,'Dimension 1','Dimension 2',legendoffset=loff)
        
        self.originalxlims = levelPlotAxis.get_xlim()
        self.originalylims = levelPlotAxis.get_ylim()
        self.currentxlims = levelPlotAxis.get_xlim()
        self.currentylims = levelPlotAxis.get_ylim()
        
        #Click and drag widget
        def line_select_callback(eclick, erelease):
            'eclick and erelease are the press and release events'
            x1, y1 = eclick.xdata, eclick.ydata
            x2, y2 = erelease.xdata, erelease.ydata

        def toggle_selector(event):
            print(' Key pressed.')
            if event.key in ['Q', 'q'] and toggle_selector.RS.active:
                print(' RectangleSelector deactivated.')
                toggle_selector.RS.set_active(False)
            if event.key in ['A', 'a'] and not toggle_selector.RS.active:
                print(' RectangleSelector activated.')
                toggle_selector.RS.set_active(True)
        rectpropsdict = {'facecolor':'grey','alpha':0.2,'edgecolor':'grey'}
        toggle_selector.RS = RectangleSelector(levelPlotAxis, line_select_callback,drawtype='box', useblit=True,button=[1, 3], minspanx=5, minspany=5,spancoords='pixels',interactive=True,rectprops=rectpropsdict)
        self.ts = toggle_selector.RS
        self.canvas.mpl_connect('key_press_event', toggle_selector)

        def zoomIn():
            clusterSelectionBox = toggle_selector.RS.corners
            ll = np.array([clusterSelectionBox[0][0], clusterSelectionBox[1][0]])  # lower-left
            ur = np.array([clusterSelectionBox[0][2], clusterSelectionBox[1][2]])  # upper-right
            
            inidx = np.all(np.logical_and(ll <= reducedData.values, reducedData.values <= ur), axis=1)
            inbox = reducedData.loc[inidx]
            bufferval = 0.1
            xlims = [min(inbox['Dimension 1'])-bufferval,max(inbox['Dimension 1'])+bufferval]
            ylims = [min(inbox['Dimension 2'])-bufferval,max(inbox['Dimension 2'])+bufferval]
            self.currentxlims = xlims
            self.currentylims = ylims
            levelPlotAxis.set_xlim(xlims)
            levelPlotAxis.set_ylim(ylims)
            clusterPlotAxis.set_xlim(self.currentxlims)
            clusterPlotAxis.set_ylim(self.currentylims)
            self.canvas.draw()
        
        def zoomOut():
            levelPlotAxis.set_xlim(self.originalxlims)
            levelPlotAxis.set_ylim(self.originalylims)
            clusterPlotAxis.set_xlim(self.originalxlims)
            clusterPlotAxis.set_ylim(self.originalylims)
            self.currentxlims = self.originalxlims 
            self.currentylims = self.originalylims
            self.canvas.draw()
        
        def update():
            ipe.updateDropdownControlledPlot(self.canvas,levelPlotAxis,plottingDfReduced,dropdownVarsDict,'Dimension 1','Dimension 2',legendoffset=loff)
            levelPlotAxis.set_xlim(self.currentxlims)
            levelPlotAxis.set_ylim(self.currentylims)
            clusterPlotAxis.set_xlim(self.currentxlims)
            clusterPlotAxis.set_ylim(self.currentylims)
            self.canvas.draw()

        tk.Button(levelPlotWindow, text="Update level plot",command=lambda: update()).grid(row=3,column=0,columnspan = 2)
        tk.Button(levelPlotWindow, text="Zoom in",command=lambda: zoomIn()).grid(row=4,column=0,columnspan = 2)
        tk.Button(levelPlotWindow, text="Zoom out",command=lambda: zoomOut()).grid(row=5,column=0,columnspan = 2)
        
        #Clustering plot (dimensional reduction is recolored based on clustering parameters selected from sliders)
        clusterParameterWindow = tk.Frame(self)
        clusterParameterWindow.grid(row=1,column=1,sticky=tk.N)
        sliderList = ipe.createParameterAdjustmentSliders(clusterParameterWindow,ods.clusterParameterDict[clusteringMethod],ods.clusterParameterBoundsDict)
        def updateClusterPlot(sliders):
            clusterPlotAxis.clear()
            parametersForClusteringFunction = ipe.getSliderValues(sliderList,ods.clusterParameterDict[clusteringMethod])
            self.currentClusteringParameters = parametersForClusteringFunction.copy()
            self.clusterdf = ods.clusterData(scaledData,clusteringMethod,parametersForClusteringFunction) 
            self.clusterdf.columns.name = 'Feature'
            reducedDataWithClusters = reducedData.copy()
            reducedDataWithClusters['Cluster'] = list(self.clusterdf.index.get_level_values('Cluster'))
            plottingDfClustered = reducedDataWithClusters.reset_index()
            clusterPalette = sns.color_palette(sns.color_palette(),len(pd.unique(reducedDataWithClusters['Cluster'])))
            g1 = sns.scatterplot(data=plottingDfClustered,x='Dimension 1',y='Dimension 2',s=3,ax=clusterPlotAxis,alpha=0.7,hue='Cluster',palette=clusterPalette)
            clusterPlotAxis.legend_.remove()
            clusterPlotAxis.set_xlim(self.currentxlims)
            clusterPlotAxis.set_ylim(self.currentylims)
            self.canvas.draw()
        updateClusterPlot(sliderList)
        tk.Button(clusterParameterWindow, text="Update cluster plot",command=lambda: updateClusterPlot(sliderList)).grid(row=2,column=0)
        def exportDataFrames():
            ods.savePostProcessedFile(self.clusterdf,dataSubsetTitle,'cluster',clusteringMethod,self.currentClusteringParameters)
            df2 = self.clusterdf.copy() 
            df3 = df2.groupby(list(df2.index.names)[-1]).mean()
            print(df2)
            if self.clusterdf.copy().values.max() > 100:
                mfiTicks = [-1000,100,1000,10000,100000]
                mfiTickValues,mfiTickLabels = returnTicks(mfiTicks)
                cg = sns.clustermap(df3.T,cbar_kws={'label':'MFI','ticks':mfiTickValues})
                cg.cax.set_yticklabels(mfiTickLabels)
            else:
                cg = sns.clustermap(df3.T,cbar_kws={'label':'Metric'})
            plt.setp(cg.ax_heatmap.xaxis.get_majorticklabels(), rotation=0)
            plt.setp(cg.ax_heatmap.yaxis.get_majorticklabels(), rotation=0)
            clustermapName = ods.getFileName(dataSubsetTitle,'cluster',clusteringMethod,self.currentClusteringParameters,fileExtension = '.png')[0]
            plt.savefig('plots/clustermap-'+clustermapName,bbox_inches='tight')
            plt.clf()
            print('Clustered Data Frame And Phenotype Plot Saved')
        tk.Button(clusterParameterWindow, text="Save Cluster",command=lambda: exportDataFrames(),font='Helvetica 14 bold').grid(row=2,column=1)

        def okCommand():
            exportDataFrames()
            master.switch_frame(backpage,folderName,secondaryhomepage)

        #Default save and quit buttons
        buttonWindow = tk.Frame(self)
        buttonWindow.grid(row=2,column=0,columnspan=2)
        tk.Button(buttonWindow, text="OK",command=lambda: master.switch_frame(backpage,folderName,secondaryhomepage)).grid(row=0,column=0)
        tk.Button(buttonWindow, text="Back",command=lambda: master.switch_frame(ClusteringHomePage,folderName,backpage,secondaryhomepage)).grid(row=0,column=1)
        tk.Button(buttonWindow, text="Quit",command=lambda: quit()).grid(row=0,column=2)
Beispiel #5
0
    def __init__(self, master):
        if 'experimentParameters-' + folderName + '-' + expParamDict[
                dataType] + '.json' in os.listdir('misc'):
            experimentParameters = json.load(
                open(
                    'misc/experimentParameters-' + folderName + '-' +
                    expParamDict[dataType] + '.json', 'r'))
        else:
            tempDict = {}
            stackedDf = experimentDf.stack()
            for level in stackedDf.index.names:
                levelValues = list(
                    pd.unique(stackedDf.index.get_level_values(level)))
                tempDict[level] = levelValues
            experimentParameters = {}
            experimentParameters['levelLabelDict'] = tempDict
        """ 
        global dataType
        if 'cell' in pickleFileName: 
            dataType = 'cell'
        elif 'cyt' in pickleFileName:
            dataType = 'cyt'
        elif 'prolif' in pickleFileName:
            dataType = 'prolif'
        else:
            dataType = ''
        """
        print('TLD 1')
        self.tld = trueLabelDict

        axisDict = {
            'categorical': ['X', 'Y'],
            '1d': ['Y'],
            '2d': ['X', 'Y'],
            '3d': ['X', 'Y', 'Colorbar']
        }
        scalingList = ['Linear', 'Logarithmic', 'Biexponential']
        axisSharingList = ['col', 'row', '']
        axisTitleDefaults = getDefaultAxisTitles()

        tk.Frame.__init__(self, master)

        mainWindow = tk.Frame(self)
        mainWindow.pack(side=tk.TOP, padx=10, pady=10)

        tk.Label(mainWindow, text='Title: ').grid(row=1, column=0, sticky=tk.W)
        for scaling, scalingIndex in zip(scalingList, range(len(scalingList))):
            tk.Label(mainWindow,
                     text=scaling + ' Scaling: ').grid(row=scalingIndex + 2,
                                                       column=0,
                                                       sticky=tk.W)
        tk.Label(mainWindow,
                 text='Linear Range (Biexponential Scaling): ').grid(
                     row=len(scalingList) + 2, column=0, sticky=tk.W)
        tk.Label(mainWindow,
                 text='Convert to numeric: ').grid(row=len(scalingList) + 3,
                                                   column=0,
                                                   sticky=tk.W)
        tk.Label(mainWindow,
                 text='Share axis across: ').grid(row=len(scalingList) + 4,
                                                  column=0,
                                                  sticky=tk.W)
        tk.Label(mainWindow,
                 text='Axis limits: ').grid(row=len(scalingList) + 5,
                                            column=0,
                                            sticky=tk.W)

        entryList = []
        scalingVariableList = []
        radioButtonList = []
        checkButtonList = []
        checkButtonVarList = []
        radioButtonList2 = []
        radioButtonVarList2 = []
        linearRangeScalingList = []
        limitEntryList = []
        for axis, axisIndex in zip(axisDict[plotType],
                                   range(len(axisDict[plotType]))):
            tk.Label(mainWindow,
                     text=axis + ' Axis').grid(row=0, column=axisIndex + 1)

            e1 = tk.Entry(mainWindow)
            e1.grid(row=1, column=axisIndex + 1)
            e1.insert(0, axisTitleDefaults[axisIndex])
            entryList.append(e1)

            axisRadioButtonList = []
            v = tk.StringVar(value='Linear')
            for scaling, scalingIndex in zip(scalingList,
                                             range(len(scalingList))):
                rb = tk.Radiobutton(mainWindow, variable=v, value=scaling)
                rb.grid(row=scalingIndex + 2, column=axisIndex + 1)
                axisRadioButtonList.append(rb)
            radioButtonList.append(axisRadioButtonList)
            scalingVariableList.append(v)

            e2 = tk.Entry(mainWindow)
            e2.grid(row=len(scalingList) + 2, column=axisIndex + 1)
            linearRangeScalingList.append(e2)

            b = tk.BooleanVar(value=False)
            cb = tk.Checkbutton(mainWindow, variable=b)
            cb.grid(row=len(scalingList) + 3, column=axisIndex + 1)
            checkButtonList.append(cb)
            checkButtonVarList.append(b)

            shareWindow = tk.Frame(mainWindow)
            shareWindow.grid(row=len(scalingList) + 4, column=axisIndex + 1)
            shareString = tk.StringVar(value='None')
            rb2a = tk.Radiobutton(shareWindow,
                                  variable=shareString,
                                  text='All',
                                  value='all')
            rb2b = tk.Radiobutton(shareWindow,
                                  variable=shareString,
                                  text='Row',
                                  value='row')
            rb2c = tk.Radiobutton(shareWindow,
                                  variable=shareString,
                                  text='Col',
                                  value='col')
            rb2d = tk.Radiobutton(shareWindow,
                                  variable=shareString,
                                  text='None',
                                  value='none')
            shareString.set('all')
            rb2a.grid(row=0, column=1)
            rb2b.grid(row=0, column=2)
            rb2c.grid(row=0, column=3)
            rb2d.grid(row=0, column=4)
            radioButtonList2.append([rb2a, rb2b])
            radioButtonVarList2.append(shareString)

            limitWindow = tk.Frame(mainWindow)
            limitWindow.grid(row=len(scalingList) + 5, column=axisIndex + 1)
            #ll = tk.Label(limitWindow,text='Lower:').grid(row=0,column=0)
            e3 = tk.Entry(limitWindow, width=5)
            e3.grid(row=0, column=1)
            #ul = tk.Label(limitWindow,text='Upper:').grid(row=0,column=2)
            e4 = tk.Entry(limitWindow, width=5)
            e4.grid(row=0, column=3)
            limitEntryList.append([e3, e4])

        def collectInputs(plotAllVar):
            plotOptions = {}
            for axis, axisIndex in zip(axisDict[plotType],
                                       range(len(axisDict[plotType]))):
                share = radioButtonVarList2[axisIndex].get()
                if share == 'none':
                    share = False
                plotOptions[axis] = {
                    'axisTitle':
                    entryList[axisIndex].get(),
                    'axisScaling':
                    scalingVariableList[axisIndex].get(),
                    'linThreshold':
                    linearRangeScalingList[axisIndex].get(),
                    'numeric':
                    checkButtonVarList[axisIndex].get(),
                    'share':
                    share,
                    'limit': [
                        limitEntryList[axisIndex][0].get(),
                        limitEntryList[axisIndex][1].get()
                    ]
                }

            plotSpecificDict = {}
            if subPlotType == 'kde':
                scaleBool = ipe.getRadiobuttonValues(
                    modeScaleRadiobuttonVarsDict)['scale to mode']
                if scaleBool == 'yes':
                    plotSpecificDict['scaleToMode'] = True
                else:
                    plotSpecificDict['scaleToMode'] = False
                plotSpecificDict['smoothing'] = int(
                    ipe.getSliderValues(smoothingSliderList,
                                        ['smoothing'])['smoothing'])

            useModifiedDf = False
            sName = titleEntry.get()
            subsettedDfList, subsettedDfListTitles, figureLevels, levelValuesPlottedIndividually = fpl.produceSubsettedDataFrames(
                experimentDf.stack().to_frame('temp'),
                fullFigureLevelBooleanList, includeLevelValueList, self.tld)
            fpl.plotFacetedFigures(
                folderName,
                plotType,
                subPlotType,
                dataType,
                subsettedDfList,
                subsettedDfListTitles,
                figureLevels,
                levelValuesPlottedIndividually,
                useModifiedDf,
                experimentDf,
                plotOptions,
                parametersSelected,
                addDistributionPoints,
                originalLevelValueOrders=experimentParameters[
                    'levelLabelDict'],
                subfolderName=sName,
                context=ipe.getRadiobuttonValues(
                    contextRadiobuttonVarsDict)['context'],
                height=float(heightEntry.get()),
                aspect=float(widthEntry.get()),
                titleBool=ipe.getRadiobuttonValues(
                    plotTitleRadiobuttonVarsDict)['plotTitle'],
                colwrap=int(colWrapEntry.get()),
                legendBool=ipe.getRadiobuttonValues(
                    legendRadiobuttonVarsDict)['legend'],
                outlierBool=ipe.getRadiobuttonValues(
                    outlierRadiobuttonVarsDict)['remove outliers'],
                plotAllVar=plotAllVar,
                titleAdjust=titleAdjustEntry.get(),
                plotSpecificDict=plotSpecificDict)

        titleWindow = tk.Frame(self)
        titleWindow.pack(side=tk.TOP, pady=10)
        tk.Label(titleWindow,
                 text='Enter subfolder for these plots (optional):').grid(
                     row=0, column=0)
        titleEntry = tk.Entry(titleWindow, width=15)
        titleEntry.grid(row=0, column=1)

        miscOptionsWindow = tk.Frame(self)
        miscOptionsWindow.pack(side=tk.TOP, pady=10)

        contextWindow = tk.Frame(miscOptionsWindow)
        contextWindow.grid(row=0, column=0, sticky=tk.N)
        contextRadiobuttonList, contextRadiobuttonVarsDict = ipe.createParameterSelectionRadiobuttons(
            contextWindow, ['context'],
            {'context': ['notebook', 'talk', 'poster']})

        figureDimensionWindow = tk.Frame(miscOptionsWindow)
        figureDimensionWindow.grid(row=0, column=1, sticky=tk.N)
        tk.Label(figureDimensionWindow,
                 text='figure dimensions').grid(row=0, column=0)
        tk.Label(figureDimensionWindow, text='height:').grid(row=1, column=0)
        tk.Label(figureDimensionWindow, text='width:').grid(row=2, column=0)
        heightEntry = tk.Entry(figureDimensionWindow, width=3)
        if plotType != '1d':
            heightEntry.insert(0, '5')
        else:
            heightEntry.insert(0, '3')
        widthEntry = tk.Entry(figureDimensionWindow, width=3)
        widthEntry.insert(0, '1')
        heightEntry.grid(row=1, column=1)
        widthEntry.grid(row=2, column=1)

        plotTitleWindow = tk.Frame(miscOptionsWindow)
        plotTitleWindow.grid(row=0, column=2, sticky=tk.N)
        plotTitleRadiobuttonList, plotTitleRadiobuttonVarsDict = ipe.createParameterSelectionRadiobuttons(
            plotTitleWindow, ['plotTitle'], {'plotTitle': ['yes', 'no']})

        legendWindow = tk.Frame(miscOptionsWindow)
        legendWindow.grid(row=0, column=3, sticky=tk.N)
        legendRadiobuttonList, legendRadiobuttonVarsDict = ipe.createParameterSelectionRadiobuttons(
            legendWindow, ['legend'], {'legend': ['yes', 'no']})

        colWrapWindow = tk.Frame(miscOptionsWindow)
        colWrapWindow.grid(row=0, column=4, sticky=tk.N)
        tk.Label(colWrapWindow, text='column wrap:').grid(row=0, column=0)
        colWrapEntry = tk.Entry(colWrapWindow, width=5)
        colWrapEntry.insert(0, '5')
        colWrapEntry.grid(row=1, column=0)

        titleAdjustWindow = tk.Frame(miscOptionsWindow)
        titleAdjustWindow.grid(row=0, column=5, sticky=tk.N)
        tk.Label(titleAdjustWindow,
                 text='title location (% of window):').grid(row=0, column=0)
        titleAdjustEntry = tk.Entry(titleAdjustWindow, width=5)
        titleAdjustEntry.insert(0, '')
        titleAdjustEntry.grid(row=1, column=0)

        outlierWindow = tk.Frame(miscOptionsWindow)
        outlierWindow.grid(row=0, column=6, sticky=tk.N)
        outlierRadiobuttonList, outlierRadiobuttonVarsDict = ipe.createParameterSelectionRadiobuttons(
            outlierWindow, ['remove outliers'],
            {'remove outliers': ['yes', 'no']})
        outlierRadiobuttonVarsDict['remove outliers'].set('no')

        if subPlotType == 'kde':
            #Scale to mode button
            subPlotSpecificWindow = tk.Frame(self)
            subPlotSpecificWindow.pack(side=tk.TOP, pady=10)
            modeScaleWindow = tk.Frame(subPlotSpecificWindow)
            modeScaleWindow.grid(row=0, column=0, sticky=tk.N)
            modeScaleRadiobuttonList, modeScaleRadiobuttonVarsDict = ipe.createParameterSelectionRadiobuttons(
                modeScaleWindow, ['scale to mode'],
                {'scale to mode': ['yes', 'no']})
            modeScaleRadiobuttonVarsDict['scale to mode'].set('no')
            #Smoothness (or bandwidth) slider
            smoothnessWindow = tk.Frame(subPlotSpecificWindow)
            smoothnessWindow.grid(row=0, column=1, sticky=tk.N)
            smoothingSliderList = ipe.createParameterAdjustmentSliders(
                smoothnessWindow, ['smoothing'], {'smoothing': [1, 99, 2, 27]})

        plotButtonWindow = tk.Frame(self)
        plotButtonWindow.pack(side=tk.TOP, pady=10)
        tk.Button(plotButtonWindow,
                  text="Generate First Plot",
                  command=lambda: collectInputs(False)).grid(row=0, column=0)
        tk.Button(plotButtonWindow,
                  text="Generate All Plots",
                  command=lambda: collectInputs(True)).grid(row=0, column=1)

        buttonWindow = tk.Frame(self)
        buttonWindow.pack(side=tk.TOP, pady=10)

        def okCommand():
            master.switch_frame(PlotTypePage)

        tk.Button(buttonWindow, text="OK",
                  command=lambda: okCommand()).grid(row=len(scalingList) + 4,
                                                    column=0)
        tk.Button(
            buttonWindow,
            text="Back",
            command=lambda: master.switch_frame(assignLevelsToParametersPage,
                                                includeLevelValueList)).grid(
                                                    row=len(scalingList) + 4,
                                                    column=1)
        tk.Button(buttonWindow, text="Quit",
                  command=lambda: quit()).grid(row=len(scalingList) + 4,
                                               column=2)