Ejemplo n.º 1
0
    def create_widgets_for_dimRed(self):
        '''
		'''
        self.dimRed_cbs_var = dict()
        vertFrame = VerticalScrolledFrame(self.contClust)
        vertFrame.pack(expand=True, fill=tk.BOTH)
        for id, props in self.dimRedModelResults.items():

            varCb = tk.BooleanVar(value=False)
            textInfo = self.dimRedModelResults[id]['data'][
                'Predictor'].get_params()
            columnsInDimRed = self.dimRedModelResults[id]['numericColumns']
            modelName = self.dimRedModelResults[id]['name']
            cb = ttk.Checkbutton(vertFrame.interior,
                                 text=modelName,
                                 variable=varCb)
            self.dimRed_cbs_var[id] = varCb

            if len(columnsInDimRed) != len(self.numericColumns):
                cb.configure(state=tk.DISABLED)
                title_ = ' == Number of selected columns/features does NOT match the\nnumber of columns/features used in model creation! == '
            else:
                title_ = 'Dimensional Reduction Model\nMethod: {}\nColumns: {}'.format(
                    self.dimRedModelResults[id]['method'],
                    get_elements_from_list_as_string(columnsInDimRed))

            CreateToolTip(cb,
                          text=str(textInfo).replace("'", ''),
                          title_=title_)
            cb.grid(sticky=tk.W, column=0, padx=3, pady=3)

        vertFrame.grid_rowconfigure(len(self.dimRedModelResults) + 1, weight=1)
Ejemplo n.º 2
0
    def create_widgets_for_clustClasses(self):
        '''
		'''
        self.clust_cbs_var = dict()
        vertFrame = VerticalScrolledFrame(self.contClust)
        vertFrame.pack(expand=True, fill=tk.BOTH)
        for clustClass in self.availableClusterClasses:

            varCb = tk.BooleanVar(value=False)
            textInfo = self.clusterCollection.clusterClasses[
                clustClass].get_params()
            infoDict = self.clusterCollection.clusterProperties[clustClass]
            columnsInClustClass = infoDict['numericColumns']

            cb = ttk.Checkbutton(vertFrame.interior,
                                 text=clustClass,
                                 variable=varCb)
            self.clust_cbs_var[clustClass] = varCb

            if 'Spectral Clustering' in clustClass:
                cb.configure(state=tk.DISABLED)
                title_ = '== Spectral Clustering does not support predictions. =='
            elif 'Agglomerative' in clustClass:
                cb.configure(state=tk.DISABLED)
                title_ = '== Agglomerative Clustering does not support predictions. =='
            elif len(columnsInClustClass) != len(self.numericColumns):
                cb.configure(state=tk.DISABLED)
                title_ = ' == Number of selected columns/features does NOT match the\nnumber of columns/features used in cluster class creation! == '
            else:
                title_ = 'Cluster settings\nColumns: {}\n\nSilhouette-Score: {}\nCalinski-Score: {}'.format(
                    get_elements_from_list_as_string(columnsInClustClass),
                    round(infoDict['silhouette-score'], 3),
                    round(infoDict['calinski-score'], 2))
            CreateToolTip(cb,
                          text=str(textInfo).replace("'", ''),
                          title_=title_)
            cb.grid(sticky=tk.W, column=0, padx=3, pady=3)

        vertFrame.grid_rowconfigure(len(self.availableClusterClasses) + 1,
                                    weight=1)
Ejemplo n.º 3
0
class settingsDialog(object):
    def __init__(self, plotter, colorHelper, dimRedCollection):

        self.plotter = plotter
        self.dimRedCollection = dimRedCollection
        self.colorPalettes = colorHelper.get_all_color_palettes()

        self.define_variables()
        self.build_toplevel()
        self.build_widgets()

    def close(self, event=None):
        '''
		Close toplevel
		'''
        self.toplevel.destroy()

    def build_toplevel(self):
        '''
		Builds the toplevel to put widgets in 
		'''

        popup = tk.Toplevel(bg=MAC_GREY)
        popup.wm_title('Settings')
        popup.bind('<Escape>', self.close)
        popup.bind('<Tab>', self.switch_settings)
        popup.protocol("WM_DELETE_WINDOW", self.close)
        w = 450
        h = 500
        self.toplevel = popup
        self.center_popup((w, h))

    def build_widgets(self):
        '''
		Defines and grids widgets on toplevel
		'''
        self.cont = tk.Frame(self.toplevel, background=MAC_GREY)
        self.cont.pack(expand=True, fill=tk.BOTH)
        labelTitle = tk.Label(self.cont,
                              text='Main settings\n',
                              **titleLabelProperties)
        labelType = tk.Label(self.cont, text='Type: ', bg=MAC_GREY)
        comboSettingType = ttk.Combobox(self.cont,
                                        textvariable=self.type,
                                        values=list(allSettings.keys()))
        comboSettingType.bind('<<ComboboxSelected>>', self.refresh_settings)

        labelTitle.grid()
        labelType.grid(row=1, column=0, padx=2)
        comboSettingType.grid(row=1, column=1, padx=2, sticky=tk.EW)
        ttk.Separator(self.cont, orient=tk.HORIZONTAL).grid(row=2,
                                                            sticky=tk.EW,
                                                            columnspan=2,
                                                            pady=5)

        self.contSettings = tk.Frame(self.cont)
        self.contSettings.grid(row=5, sticky=tk.NSEW, columnspan=2, pady=5)
        self.cont.grid_rowconfigure(5, weight=1)
        self.cont.grid_columnconfigure(1, weight=1)
        self.create_setting_options()

        applyButton = ttk.Button(self.cont,
                                 text='Save & Close',
                                 command=self.change_settings)
        closeButton = ttk.Button(self.cont,
                                 text='Discard & Close',
                                 command=self.close)

        applyButton.grid(row=6, column=0, padx=5, pady=4, sticky=tk.W)
        closeButton.grid(row=6, column=1, padx=5, pady=4, sticky=tk.E)

    def create_setting_options(self):
        '''
		'''
        type = self.type.get()
        if type not in allSettings:
            return
        self.settingFrame = VerticalScrolledFrame(self.contSettings)
        self.settingFrame.pack(expand=True, fill=tk.BOTH)
        self.build_type_specific_widgets(type)

    def build_type_specific_widgets(self, type):
        '''
		'''
        self.settingsVar = dict()
        n = 0
        for option, values in allSettings[type].items():
            valueList = self.get_values(values)
            var = tk.StringVar()
            label = tk.Label(self.settingFrame.interior,
                             text='{}: '.format(option),
                             bg=MAC_GREY)
            if option in tooltipText:
                CreateToolTip(label, text=tooltipText[option])
            combo = ttk.Combobox(self.settingFrame.interior,
                                 textvariable=var,
                                 values=valueList)
            var.set(self.set_default_value(option))
            label.grid(row=n, column=0, sticky=tk.E)
            combo.grid(row=n, column=1, padx=5, sticky=tk.EW)

            self.settingsVar[option] = var
            n += 1

        self.settingFrame.interior.grid_columnconfigure(1,
                                                        weight=1,
                                                        minsize=100)
        self.settingFrame.interior.grid_columnconfigure(0,
                                                        weight=1,
                                                        minsize=150)

    def refresh_settings(self, event=None):
        '''
		'''
        clear_frame(self.contSettings)
        self.create_setting_options()

    def get_values(self, option):
        '''
		This functions checks for strings. 
		And if there is a string (colorScheme) it will return
		the current set of palettes. We need to check this before, because 
		users can add new user defined color palettes.
		'''
        if isinstance(option, str):
            return self.colorPalettes
        else:
            return option

    def define_variables(self):
        '''
		'''
        self.type = tk.StringVar(value='Hierarchical Clustering')

    def set_default_value(self, option):
        '''
		'''
        if self.type.get() == 'Hierarchical Clustering':
            return getattr(self.plotter, attrNames[option])
        elif self.type.get() == 'Dimensional Reduction':
            if option == 'Components':
                return self.dimRedCollection.nComponents
        elif self.type.get() == 'General Settings':
            if option == 'Error bar':
                return self.plotter.errorBar
            elif option == 'Arrow Style':
                return arrow_args['connectionstyle']
            elif option == 'Aggegrate num. encoding colors':
                return self.plotter.aggMethod
        elif self.type.get() == 'Binned Scatter':
            if option == 'Number of bins':
                return self.plotter.numbBins
            elif option == 'Scale counts (1-0)':
                return str(self.plotter.scaleBinsInScatter)

    def change_settings(self):
        '''
		'''
        type = self.type.get()

        if type == 'Hierarchical Clustering':
            for key, var in self.settingsVar.items():
                setattr(self.plotter, attrNames[key], var.get())

        elif type == 'General Settings':

            self.error_bar_adjustment()
            self.adjust_agg_method()
            self.adjust_arrow_style()

        elif type == 'Dimensional Reduction':

            ncomps = self.get_number_from_string(
                self.settingsVar['Components'].get())
            if ncomps is None:
                return
            elif ncomps < 3:
                tk.messagebox.showinfo(
                    'Error..',
                    'Minimum number of calculated components is 3. Falling back to the default = 3'
                )
                ncomps = 3
            self.dimRedCollection.set_max_comps(ncomps)

        elif type == 'Binned Scatter':

            self.binned_scatter_adjustment()

        self.close()

    def get_number_from_string(self, input, type='int', addErrorString=''):
        '''
		'''
        try:
            if type == 'int':
                out = int(float(input))
            else:
                out = float(input)
            return out
        except:
            tk.messagebox.showinfo(
                'Error ..',
                'Could not convert input to float/integer.' + addErrorString,
                parent=self.toplevel)

    def binned_scatter_adjustment(self):
        '''
		'''
        for key, var in self.settingsVar.items():
            if key == 'Number of bins':
                value = int(float(var.get()))
            elif key in ['Scale counts (1-0)', 'Color encode counts']:
                value = stringBool[var.get()]

            setattr(self.plotter, attrNames[key], value)

    def adjust_agg_method(self):
        '''
		'''
        input = self.settingsVar['Aggegrate num. encoding colors'].get()
        if input not in ['mean', 'sum']:
            tk.messagebox.showinfo('Error ..',
                                   'Cannot interpret agg. method input.',
                                   parent=self.toplevel)
            return
        else:
            setattr(self.plotter, 'aggMethod', input)

    def adjust_arrow_style(self):
        global arrow_args
        input = self.settingsVar['Arrow Style'].get()
        if input not in arrowOptions:
            tk.messagebox.showinfo('Error.',
                                   'Unknwon arrow option',
                                   parent=self.toplevel)
            return
        else:
            arrow_args['connectionstyle'] = input

    def error_bar_adjustment(self):
        '''
		'''
        input = self.settingsVar['Error bar'].get()
        if input in abbrError:
            self.plotter.errorBar = abbrError[input]

        else:

            ciValue = self.get_number_from_string(
                input,
                type='int',
                addErrorString=
                'Valid inputs are (0-100] or any option from the drop-down menu.'
            )

            if ciValue is None:
                return

            if ciValue <= 100:
                self.plotter.errorBar = ciValue

    def switch_settings(self, event):
        '''
		'''
        type = self.type.get()
        if type in allSettings:
            idx = list(allSettings.keys()).index(self.type.get())
            if idx == len(allSettings) - 1:
                idx = -1
            self.type.set(list(allSettings.keys())[idx + 1])
            self.refresh_settings()

    def center_popup(self, size):
        '''
         	Casts poup and centers in screen mid
         	'''

        w_screen = self.toplevel.winfo_screenwidth()
        h_screen = self.toplevel.winfo_screenheight()
        x = w_screen / 2 - size[0] / 2
        y = h_screen / 2 - size[1] / 2
        self.toplevel.geometry('%dx%d+%d+%d' % (size + (x, y)))