def __init__(self, parent, size=(600, 600), **kwargs):
        wx.Frame.__init__(self,
                          parent,
                          -1,
                          size=size,
                          title='Histogram',
                          **kwargs)
        CPATool.__init__(self)
        self.SetName(self.tool_name)
        self.SetBackgroundColour("white")
        points = []
        figpanel = HistogramPanel(self, points)
        configpanel = DataSourcePanel(self, figpanel)
        figpanel.set_configpanel(configpanel)

        self.SetToolBar(figpanel.get_toolbar())

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(figpanel, 1, wx.EXPAND)
        sizer.Add(configpanel, 0, wx.EXPAND | wx.ALL, 5)
        self.SetSizer(sizer)

        #
        # Forward save and load settings functionality to the configpanel
        #
        self.save_settings = configpanel.save_settings
        self.load_settings = configpanel.load_settings
        self.fig = figpanel
    def __init__(self, parent, size=(600,600), **kwargs):
        wx.Frame.__init__(self, parent, -1, size=size, title='Time Visual', **kwargs)
        CPATool.__init__(self)
        self.SetName(self.tool_name)

        # Check for required properties fields.
        #fail = False
        #missing_fields = [field for field in required_fields if not props.field_defined(field)]
        #if missing_fields:
            #fail = True
            #message = 'The following missing fields are required for TimeVisual: %s.'%(",".join(missing_fields))
            #wx.MessageBox(message,'Required field(s) missing')
            #logging.error(message)
        #if fail:    
            #self.Destroy()
            #return

        self.configpanel = DataSourcePanel(self)
        self.selected_dataset = self.configpanel.dataset_choice.GetStringSelection()
        self.selected_colormap  = self.configpanel.colormap_choice.GetStringSelection()
        self.plot_updated = False
        self.trajectory_selected = False
        self.mayavi_view = MayaviView()
        
        self.trajectory_info = None
        self.selected_trajectories = None
        self.selected_node = None 
        
        self.figpanel = self.mayavi_view.edit_traits(
                            parent=self,
                            kind='subpanel').control
        
           
        self.generate_graph(True)
        self.plot_trajectories(True)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.figpanel, 1, wx.EXPAND)
        sizer.Add(self.configpanel, 0, wx.EXPAND|wx.ALL, 5)
        self.SetSizer(sizer)
        
        self.figpanel.Bind(wx.EVT_CONTEXT_MENU, self.on_show_popup_menu)
        
        # Define events
        wx.EVT_COMBOBOX(self.configpanel.dataset_choice, -1, self.on_dataset_selected)
        wx.EVT_COMBOBOX(self.configpanel.feature_choice, -1, self.on_feature_selected)
        wx.EVT_BUTTON(self.configpanel.trajectory_selection_button, -1, self.update_trajectory_selection)
        wx.EVT_BUTTON(self.configpanel.colormap_choice, -1, self.on_colormap_selected)
        wx.EVT_BUTTON(self.configpanel.update_plot_button, -1, self.update_plot)
Example #3
0
 def __init__(self, parent, size=(600,600), **kwargs):
     wx.Frame.__init__(self, parent, -1, size=size, title='Density Plot', **kwargs)
     CPATool.__init__(self)
     self.SetName(self.tool_name)
     self.SetBackgroundColour("white")
     figpanel = DensityPanel(self)
     configpanel = DataSourcePanel(self, figpanel)
     figpanel.set_configpanel(configpanel)
     self.SetToolBar(figpanel.get_toolbar())
     sizer = wx.BoxSizer(wx.VERTICAL)
     sizer.Add(figpanel, 1, wx.EXPAND)
     sizer.Add(configpanel, 0, wx.EXPAND|wx.ALL, 5)
     self.SetSizer(sizer)
     
     #
     # Forward save and load settings functionality to the configpanel
     #
     self.save_settings = configpanel.save_settings
     self.load_settings = configpanel.load_settings
Example #4
0
    def __init__(self, parent, size=(800,-1), **kwargs):
        wx.Frame.__init__(self, parent, -1, size=size, title='Plate Viewer', **kwargs)
        CPATool.__init__(self)
        self.SetName(self.tool_name)
        self.SetBackgroundColour("white") # Fixing the color

        # Check for required properties fields.
        fail = False
        for field in required_fields:
            if not p.field_defined(field):
                fail = True
                raise Exception('Properties field "%s" is required for PlateViewer.'%(field))
        if fail:    
            self.Destroy()
            return

        self.chMap = p.image_channel_colors[:]

        self.menuBar = wx.MenuBar()
        self.SetMenuBar(self.menuBar)
        self.fileMenu = wx.Menu()
        self.exitMenuItem = self.fileMenu.Append(id=wx.ID_EXIT, text='Exit\tCtrl+Q', help='Close Plate Viewer')
        self.GetMenuBar().Append(self.fileMenu, 'File')
        self.menuBar.Append(cpa.helpmenu.make_help_menu(self), 'Help')
        save_csv_menu_item = self.fileMenu.Append(-1, 'Save table to CSV\tCtrl+S')
        self.Bind(wx.EVT_MENU, self.on_save_csv, save_csv_menu_item)
        
        wx.EVT_MENU(self, wx.ID_EXIT, lambda _:self.Close())

        dataSourceSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Source:'), wx.VERTICAL)
        dataSourceSizer.Add(wx.StaticText(self, label='Data source:'))
        self.sourceChoice = TableComboBox(self, -1, size=fixed_width)
        dataSourceSizer.Add(self.sourceChoice)
        dataSourceSizer.AddSpacer((-1,3))
        dataSourceSizer.Add(wx.StaticText(self, label='Measurement:'))
        measurements = get_non_blob_types_from_table(p.image_table)
        self.measurementsChoice = ComboBox(self, choices=measurements, size=fixed_width)
        self.measurementsChoice.Select(0)
        dataSourceSizer.Add(self.measurementsChoice)
        dataSourceSizer.Add(wx.StaticText(self, label='Filter:'))
        self.filterChoice = FilterComboBox(self, size=fixed_width)
        dataSourceSizer.Add(self.filterChoice)
        
        groupingSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Data aggregation:'), wx.VERTICAL)
        groupingSizer.Add(wx.StaticText(self, label='Aggregation method:'))
        aggregation = ['mean', 'sum', 'median', 'stdev', 'cv%', 'min', 'max']
        self.aggregationMethodsChoice = ComboBox(self, choices=aggregation, size=fixed_width)
        self.aggregationMethodsChoice.Select(0)
        groupingSizer.Add(self.aggregationMethodsChoice)

        viewSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='View options:'), wx.VERTICAL)
        viewSizer.Add(wx.StaticText(self, label='Color map:'))
        maps = [m for m in matplotlib.cm.datad.keys() if not m.endswith("_r")]
        maps.sort()
        self.colorMapsChoice = ComboBox(self, choices=maps, size=fixed_width)
        self.colorMapsChoice.SetSelection(maps.index('jet'))
        viewSizer.Add(self.colorMapsChoice)

        viewSizer.AddSpacer((-1,3))
        viewSizer.Add(wx.StaticText(self, label='Well display:'))
        if p.image_thumbnail_cols:
            choices = pmp.all_well_shapes
        else:
            choices = list(pmp.all_well_shapes)
            choices.remove(pmp.THUMBNAIL)
        self.wellDisplayChoice = ComboBox(self, choices=choices, size=fixed_width)
        self.wellDisplayChoice.Select(0)
        viewSizer.Add(self.wellDisplayChoice)

        viewSizer.AddSpacer((-1,3))
        viewSizer.Add(wx.StaticText(self, label='Number of plates:'))
        self.numberOfPlatesTE = wx.TextCtrl(self, -1, '1', style=wx.TE_PROCESS_ENTER)
        viewSizer.Add(self.numberOfPlatesTE)
        if not p.plate_id:
            self.numberOfPlatesTE.Disable()

        annotationSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Annotation:'), wx.VERTICAL)
        annotationSizer.Add(wx.StaticText(self, label='Annotation column:'))
        annotationColSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.annotation_cols = dict([(col, db.GetColumnType(p.image_table, col)) 
                                     for col in db.GetUserColumnNames(p.image_table)])
        self.annotationCol = ComboBox(self, choices=self.annotation_cols.keys(), size=(120,-1))
        if len(self.annotation_cols) > 0:
            self.annotationCol.SetSelection(0)
        annotationColSizer.Add(self.annotationCol, flag=wx.ALIGN_CENTER_VERTICAL)
        annotationColSizer.AddSpacer((3,-1))
        self.addAnnotationColBtn = wx.Button(self, -1, 'Add', size=(44,-1))
        annotationColSizer.Add(self.addAnnotationColBtn, flag=wx.ALIGN_CENTER_VERTICAL)
        annotationSizer.Add(annotationColSizer)
        annotationSizer.AddSpacer((-1,3))
        annotationSizer.Add(wx.StaticText(self, label='Label:'))
        self.annotationLabel = wx.TextCtrl(self, -1, 'Select wells')#, style=wx.TE_PROCESS_ENTER)
        self.annotationLabel.Disable()
        self.annotationLabel.SetForegroundColour(wx.Colour(80,80,80))
        self.annotationLabel.SetBackgroundColour(wx.LIGHT_GREY)
        annotationSizer.Add(self.annotationLabel)
        annotationSizer.AddSpacer((-1,3))
        self.outlineMarked = wx.CheckBox(self, -1, label='Outline annotated wells')
        annotationSizer.Add(self.outlineMarked)
        annotationSizer.AddSpacer((-1,3))
        self.annotationShowVals = wx.CheckBox(self, -1, label='Show values on plate')
        annotationSizer.Add(self.annotationShowVals)
        if len(db.GetUserColumnNames(p.image_table)) == 0:
            self.outlineMarked.Disable()
            self.annotationShowVals.Disable()
            
        controlSizer = wx.BoxSizer(wx.VERTICAL)
        controlSizer.Add(dataSourceSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1,3))
        controlSizer.Add(groupingSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1,3))
        controlSizer.Add(viewSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1,3))
        controlSizer.Add(annotationSizer, 0 , wx.EXPAND)

        self.plateMapSizer = wx.GridSizer(1,1,5,5)
        self.plateMaps = []
        self.plateMapChoices = []

        self.rightSizer = wx.BoxSizer(wx.VERTICAL)
        self.rightSizer.Add(self.plateMapSizer, 1, wx.EXPAND|wx.BOTTOM, 10)
        self.colorBar = ColorBarPanel(self, 'jet', size=(-1,25))
        self.rightSizer.Add(self.colorBar, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)

        mainSizer = wx.BoxSizer(wx.HORIZONTAL)
        mainSizer.Add(controlSizer, 0, wx.LEFT|wx.TOP|wx.BOTTOM, 10)
        mainSizer.Add(self.rightSizer, 1, wx.EXPAND|wx.ALL, 10)

        self.SetSizer(mainSizer)
        self.SetClientSize((self.Size[0],self.Sizer.CalcMin()[1]))

        self.sourceChoice.Bind(wx.EVT_COMBOBOX, self.UpdateMeasurementChoice)
        self.measurementsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectMeasurement)
        self.measurementsChoice.Select(0)
        self.aggregationMethodsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectAggregationMethod)
        self.colorMapsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectColorMap)
        self.numberOfPlatesTE.Bind(wx.EVT_TEXT_ENTER, self.OnEnterNumberOfPlates)
        self.wellDisplayChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectWellDisplay)
        self.annotationCol.Bind(wx.EVT_COMBOBOX, self.OnSelectAnnotationCol)
        self.addAnnotationColBtn.Bind(wx.EVT_BUTTON, self.OnAddAnnotationCol)
        self.annotationLabel.Bind(wx.EVT_KEY_UP, self.OnEnterAnnotation)
        self.outlineMarked.Bind(wx.EVT_CHECKBOX, self.OnOutlineMarked)
        self.annotationShowVals.Bind(wx.EVT_CHECKBOX, self.OnShowAnnotationValues)
        self.filterChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectFilter)

        self.AddPlateMap()
        self.OnSelectMeasurement()
    def __init__(self, parent, size=(800, -1), **kwargs):
        wx.Frame.__init__(self, parent, -1, size=size, title="Plate Viewer", **kwargs)
        CPATool.__init__(self)
        self.SetName(self.tool_name)
        self.SetBackgroundColour(wx.NullColor)

        # Check for required properties fields.
        fail = False
        for field in required_fields:
            if not p.field_defined(field):
                fail = True
                raise Exception('Properties field "%s" is required for PlateViewer.' % (field))
        if fail:
            self.Destroy()
            return

        self.chMap = p.image_channel_colors[:]

        self.menuBar = wx.MenuBar()
        self.SetMenuBar(self.menuBar)
        self.fileMenu = wx.Menu()
        self.exitMenuItem = self.fileMenu.Append(id=wx.ID_EXIT, text="Exit\tCtrl+Q", help="Close Plate Viewer")
        self.GetMenuBar().Append(self.fileMenu, "File")

        wx.EVT_MENU(self, wx.ID_EXIT, lambda (_): self.Close())

        dataSourceSizer = wx.StaticBoxSizer(wx.StaticBox(self, label="Source:"), wx.VERTICAL)
        dataSourceSizer.Add(wx.StaticText(self, label="Data source:"))
        self.sourceChoice = TableComboBox(self, -1, style=wx.CB_READONLY)
        dataSourceSizer.Add(self.sourceChoice)
        dataSourceSizer.AddSpacer((-1, 3))
        dataSourceSizer.Add(wx.StaticText(self, label="Measurement:"))
        measurements = get_non_blob_types_from_table(p.image_table)
        self.measurementsChoice = ComboBox(self, choices=measurements, style=wx.CB_READONLY)
        self.measurementsChoice.Select(0)
        dataSourceSizer.Add(self.measurementsChoice)
        dataSourceSizer.Add(wx.StaticText(self, label="Filter:"))
        self.filterChoice = FilterComboBox(self)
        dataSourceSizer.Add(self.filterChoice)

        groupingSizer = wx.StaticBoxSizer(wx.StaticBox(self, label="Data aggregation:"), wx.VERTICAL)
        groupingSizer.Add(wx.StaticText(self, label="Aggregation method:"))
        aggregation = ["mean", "sum", "median", "stdev", "cv%", "min", "max"]
        self.aggregationMethodsChoice = ComboBox(self, choices=aggregation, style=wx.CB_READONLY)
        self.aggregationMethodsChoice.Select(0)
        groupingSizer.Add(self.aggregationMethodsChoice)

        viewSizer = wx.StaticBoxSizer(wx.StaticBox(self, label="View options:"), wx.VERTICAL)
        viewSizer.Add(wx.StaticText(self, label="Color map:"))
        maps = [m for m in matplotlib.cm.datad.keys() if not m.endswith("_r")]
        maps.sort()
        self.colorMapsChoice = ComboBox(self, choices=maps, style=wx.CB_READONLY)
        self.colorMapsChoice.SetSelection(maps.index("jet"))
        viewSizer.Add(self.colorMapsChoice)

        viewSizer.AddSpacer((-1, 3))
        viewSizer.Add(wx.StaticText(self, label="Well display:"))
        if p.image_thumbnail_cols:
            choices = pmp.all_well_shapes
        else:
            choices = list(pmp.all_well_shapes)
            choices.remove(pmp.THUMBNAIL)
        self.wellDisplayChoice = ComboBox(self, choices=choices, style=wx.CB_READONLY)
        self.wellDisplayChoice.Select(0)
        viewSizer.Add(self.wellDisplayChoice)

        viewSizer.AddSpacer((-1, 3))
        viewSizer.Add(wx.StaticText(self, label="Number of plates:"))
        self.numberOfPlatesTE = wx.TextCtrl(self, -1, "1", style=wx.TE_PROCESS_ENTER)
        viewSizer.Add(self.numberOfPlatesTE)
        if not p.plate_id:
            self.numberOfPlatesTE.Disable()

        annotationSizer = wx.StaticBoxSizer(wx.StaticBox(self, label="Annotation:"), wx.VERTICAL)
        annotationSizer.Add(wx.StaticText(self, label="Annotation column:"))
        annotationColSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.annotation_cols = dict(
            [(col, db.GetColumnType(p.image_table, col)) for col in db.GetUserColumnNames(p.image_table)]
        )
        self.annotationCol = ComboBox(self, choices=self.annotation_cols.keys(), size=(120, -1), style=wx.CB_READONLY)
        if len(self.annotation_cols) > 0:
            self.annotationCol.SetSelection(0)
        annotationColSizer.Add(self.annotationCol)
        annotationColSizer.AddSpacer((3, -1))
        self.addAnnotationColBtn = wx.Button(self, -1, "Add", size=(44, -1))
        annotationColSizer.Add(self.addAnnotationColBtn, 0, wx.TOP, 3)
        annotationSizer.Add(annotationColSizer)
        annotationSizer.AddSpacer((-1, 3))
        annotationSizer.Add(wx.StaticText(self, label="Label:"))
        self.annotationLabel = wx.TextCtrl(self, -1, "Select wells")  # , style=wx.TE_PROCESS_ENTER)
        self.annotationLabel.Disable()
        self.annotationLabel.SetForegroundColour(wx.Colour(80, 80, 80))
        self.annotationLabel.SetBackgroundColour(wx.LIGHT_GREY)
        annotationSizer.Add(self.annotationLabel)
        annotationSizer.AddSpacer((-1, 3))
        self.outlineMarked = wx.CheckBox(self, -1, label="Outline annotated wells")
        annotationSizer.Add(self.outlineMarked)
        annotationSizer.AddSpacer((-1, 3))
        self.annotationShowVals = wx.CheckBox(self, -1, label="Show values on plate")
        annotationSizer.Add(self.annotationShowVals)
        if len(db.GetUserColumnNames(p.image_table)) == 0:
            self.outlineMarked.Disable()
            self.annotationShowVals.Disable()

        controlSizer = wx.BoxSizer(wx.VERTICAL)
        controlSizer.Add(dataSourceSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1, 3))
        controlSizer.Add(groupingSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1, 3))
        controlSizer.Add(viewSizer, 0, wx.EXPAND)
        controlSizer.AddSpacer((-1, 3))
        controlSizer.Add(annotationSizer, 0, wx.EXPAND)

        self.plateMapSizer = wx.GridSizer(1, 1, 5, 5)
        self.plateMaps = []
        self.plateMapChoices = []

        self.rightSizer = wx.BoxSizer(wx.VERTICAL)
        self.rightSizer.Add(self.plateMapSizer, 1, wx.EXPAND | wx.BOTTOM, 10)
        self.colorBar = ColorBarPanel(self, "jet", size=(-1, 25))
        self.rightSizer.Add(self.colorBar, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL)

        mainSizer = wx.BoxSizer(wx.HORIZONTAL)
        mainSizer.Add(controlSizer, 0, wx.LEFT | wx.TOP | wx.BOTTOM, 10)
        mainSizer.Add(self.rightSizer, 1, wx.EXPAND | wx.ALL, 10)

        self.SetSizer(mainSizer)
        self.SetClientSize((self.Size[0], self.Sizer.CalcMin()[1]))

        self.sourceChoice.Bind(wx.EVT_COMBOBOX, self.UpdateMeasurementChoice)
        self.measurementsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectMeasurement)
        self.aggregationMethodsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectAggregationMethod)
        self.colorMapsChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectColorMap)
        self.numberOfPlatesTE.Bind(wx.EVT_TEXT_ENTER, self.OnEnterNumberOfPlates)
        self.wellDisplayChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectWellDisplay)
        self.annotationCol.Bind(wx.EVT_COMBOBOX, self.OnSelectAnnotationCol)
        self.addAnnotationColBtn.Bind(wx.EVT_BUTTON, self.OnAddAnnotationCol)
        self.annotationLabel.Bind(wx.EVT_KEY_UP, self.OnEnterAnnotation)
        self.outlineMarked.Bind(wx.EVT_CHECKBOX, self.OnOutlineMarked)
        self.annotationShowVals.Bind(wx.EVT_CHECKBOX, self.OnShowAnotationValues)
        self.filterChoice.Bind(wx.EVT_COMBOBOX, self.OnSelectFilter)

        self.AddPlateMap()
        self.OnSelectMeasurement()
    def __init__(self,
                 parent,
                 id=-1,
                 title='Normalization Settings',
                 **kwargs):
        kwargs['size'] = kwargs.get('size', (500, 500))
        wx.Frame.__init__(self, parent, id, title=title, **kwargs)
        CPATool.__init__(self)
        wx.HelpProvider_Set(wx.SimpleHelpProvider())

        self.n_steps = 1

        self.SetBackgroundColour("white")

        #
        # Define the controls
        #
        tables = ([p.image_table]
                  or []) + ([p.object_table] if p.object_table else [])
        self.table_choice = wx.Choice(self, -1, choices=tables)
        select_all_btn = wx.Button(self, -1, 'Select all columns')
        select_all_btn.SetHelpText("Click this button to check all columns.")

        self.table_choice.Select(0)
        self.table_choice.SetHelpText(
            "Select the table containing the measurement columns to normalize."
        )
        self.col_choices = wx.CheckListBox(self,
                                           -1,
                                           choices=[],
                                           size=(-1, 100))
        self.col_choices.SetHelpText(
            "Select the measurement columns to normalize. More than one column may be selected. "
            "The normalization steps below will be performed on all columns.")
        add_norm_step_btn = wx.Button(self, -1, 'Add normalization step')
        add_norm_step_btn.SetHelpText(
            "Click this button to add another normalization to perform. "
            "The normalizations are performed from top to bottom, with the "
            "results from one step being used as input into the following step."
        )
        self.norm_meas_checkbox = wx.CheckBox(self, -1,
                                              'Normalized measurements')
        self.norm_meas_checkbox.Set3StateValue(True)
        self.norm_meas_checkbox.SetHelpText(
            "Write a column of normalized measurements to the output table. "
            "This column ihas the same name as the input, with the suffix '_NmV'"
        )
        self.norm_factor_checkbox = wx.CheckBox(self, -1,
                                                'Normalization factors')
        self.norm_factor_checkbox.SetHelpText(
            "Write a column of normalization factors to the output table. "
            "This column ihas the same name as the input, with the suffix '_NmF' added."
        )
        self.output_table = wx.TextCtrl(self,
                                        -1,
                                        'normalized_measurements',
                                        size=(200, -1))
        self.output_table.SetHelpText(
            "Enter the name of the output table which will contain "
            "your normalized measurements and/or the normalization factors.\n "
            "The text will appear orange if the table already exists "
            "in the database. The output table will be linked to the existing "
            "tables so it is usable immediately.")
        self.help_btn = wx.ContextHelpButton(self)
        self.do_norm_btn = wx.Button(self, wx.ID_OK, 'Perform Normalization')
        self.do_norm_btn.SetHelpText(
            "Once you have adjusted the settings, click this button to start normalization "
            "and write the results to the output table. A progress bar will inform you "
            "of the normalization status.")

        self.boxes = []

        self.SetSizer(wx.BoxSizer(wx.VERTICAL))
        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.Add(wx.StaticText(self, -1, 'Select a table:'), 0,
               wx.EXPAND | wx.RIGHT, 5)
        sz.Add(self.table_choice, 0)
        sz.Add(select_all_btn, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 15)
        self.col_choices_desc = wx.StaticText(
            self, -1, 'Select measurements to normalize:')
        self.Sizer.Add(self.col_choices_desc, 0,
                       wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 15)
        self.Sizer.AddSpacer((-1, 5))
        self.Sizer.Add(self.col_choices, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 15)

        #
        # Lay out the first normalization step inside a scrolled window
        # and a static box sizer.
        #
        self.Sizer.Add(
            wx.StaticText(
                self, -1,
                'Specify the normalization steps you want to perform:'), 0,
            wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 15)
        self.sw = wx.ScrolledWindow(self)
        sbs = wx.StaticBoxSizer(wx.StaticBox(self.sw, label=''), wx.VERTICAL)
        nsp = NormalizationStepPanel(self.sw, allow_delete=False)
        self.norm_steps = [nsp]
        self.boxes = [sbs]
        sbs.Add(nsp, 0, wx.EXPAND)
        self.sw.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.sw.Sizer.Add(sbs, 0, wx.EXPAND)
        (w, h) = self.sw.Sizer.GetSize()
        self.sw.SetScrollbars(20, 20, w / 20, h / 20, 0, 0)
        self.Sizer.Add(self.sw, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.AddStretchSpacer()
        sz.Add(add_norm_step_btn, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND | wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        self.output_table_desc = wx.StaticText(self, -1,
                                               'Name your output table:')
        sz.Add(self.output_table_desc, 0, wx.EXPAND | wx.RIGHT, 5)
        sz.Add(self.output_table, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        self.output_format_desc = wx.StaticText(self, -1, 'Output columns:')
        sz.Add(self.output_format_desc, 0, wx.EXPAND | wx.RIGHT, 5)
        sz.Add(self.norm_meas_checkbox, 0, wx.EXPAND | wx.RIGHT, 5)
        sz.Add(self.norm_factor_checkbox, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.Add(self.help_btn)
        sz.AddStretchSpacer()
        sz.Add(self.do_norm_btn)
        self.Sizer.Add(sz, 0, wx.EXPAND | wx.ALL, 15)

        self.table_choice.Bind(wx.EVT_CHOICE, self.on_select_table)
        select_all_btn.Bind(wx.EVT_BUTTON, self.on_select_all_columns)
        add_norm_step_btn.Bind(wx.EVT_BUTTON, self.on_add_norm_step)
        self.col_choices.Bind(wx.EVT_CHECKLISTBOX, lambda e: self.validate())
        self.norm_meas_checkbox.Bind(wx.EVT_CHECKBOX,
                                     lambda e: self.validate())
        self.norm_factor_checkbox.Bind(wx.EVT_CHECKBOX,
                                       lambda e: self.validate())
        self.output_table.Bind(wx.EVT_TEXT, lambda e: self.validate())
        self.do_norm_btn.Bind(wx.EVT_BUTTON, self.on_do_normalization)

        self.update_measurement_choices()
        self.validate()
    def __init__(self, parent, id=-1, title='Normalization Settings', **kwargs):
        kwargs['size'] = kwargs.get('size', (500,500))
        wx.Frame.__init__(self, parent, id, title=title, **kwargs)
        CPATool.__init__(self)
        wx.HelpProvider_Set(wx.SimpleHelpProvider())

        self.n_steps = 1

        self.SetBackgroundColour("white")

        
        #
        # Define the controls
        #
        tables = ([p.image_table] or []) + ([p.object_table] if p.object_table else [])
        self.table_choice = wx.Choice(self, -1, choices=tables)
        select_all_btn = wx.Button(self, -1, 'Select all columns')
        select_all_btn.SetHelpText("Click this button to check all columns.")

        self.table_choice.Select(0)
        self.table_choice.SetHelpText("Select the table containing the measurement columns to normalize.")
        self.col_choices = wx.CheckListBox(self, -1, choices=[], size=(-1, 100))
        self.col_choices.SetHelpText("Select the measurement columns to normalize. More than one column may be selected. "
                                     "The normalization steps below will be performed on all columns.")
        add_norm_step_btn = wx.Button(self, -1, 'Add normalization step')
        add_norm_step_btn.SetHelpText("Click this button to add another normalization to perform. "
                                      "The normalizations are performed from top to bottom, with the "
                                      "results from one step being used as input into the following step.")
        self.norm_meas_checkbox = wx.CheckBox(self, -1, 'Normalized measurements')
        self.norm_meas_checkbox.Set3StateValue(True)
        self.norm_meas_checkbox.SetHelpText("Write a column of normalized measurements to the output table. "
                                            "This column ihas the same name as the input, with the suffix '_NmV'")
        self.norm_factor_checkbox = wx.CheckBox(self, -1, 'Normalization factors')
        self.norm_factor_checkbox.SetHelpText("Write a column of normalization factors to the output table. "
                                            "This column ihas the same name as the input, with the suffix '_NmF' added.")
        self.output_table = wx.TextCtrl(self, -1, 'normalized_measurements', size=(200,-1))
        self.output_table.SetHelpText("Enter the name of the output table which will contain "
                                      "your normalized measurements and/or the normalization factors.\n "
                                      "The text will appear orange if the table already exists "
                                      "in the database. The output table will be linked to the existing "
                                      "tables so it is usable immediately.")
        self.help_btn = wx.ContextHelpButton(self)
        self.do_norm_btn = wx.Button(self, wx.ID_OK, 'Perform Normalization')
        self.do_norm_btn.SetHelpText("Once you have adjusted the settings, click this button to start normalization "
                                     "and write the results to the output table. A progress bar will inform you "
                                     "of the normalization status.")
                
        self.boxes = [ ]
        
        self.SetSizer(wx.BoxSizer(wx.VERTICAL))
        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.Add(wx.StaticText(self, -1, 'Select a table:'), 0, wx.EXPAND|wx.RIGHT, 5)
        sz.Add(self.table_choice, 0)
        sz.Add(select_all_btn, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 15)
        self.col_choices_desc = wx.StaticText(self, -1, 'Select measurements to normalize:')
        self.Sizer.Add(self.col_choices_desc, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 15)
        self.Sizer.AddSpacer((-1,5))
        self.Sizer.Add(self.col_choices, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
        
        #
        # Lay out the first normalization step inside a scrolled window
        # and a static box sizer.
        #
        self.Sizer.Add(wx.StaticText(self, -1, 'Specify the normalization steps you want to perform:'), 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 15)
        self.sw = wx.ScrolledWindow(self)
        sbs = wx.StaticBoxSizer(wx.StaticBox(self.sw, label=''), wx.VERTICAL)
        nsp = NormalizationStepPanel(self.sw, allow_delete=False)
        self.norm_steps = [ nsp ]
        self.boxes = [ sbs ]
        sbs.Add(nsp, 0, wx.EXPAND)
        self.sw.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.sw.Sizer.Add(sbs, 0, wx.EXPAND)
        (w,h) = self.sw.Sizer.GetSize()
        self.sw.SetScrollbars(20,20,w/20,h/20,0,0)
        self.Sizer.Add(self.sw, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
        
        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.AddStretchSpacer()
        sz.Add(add_norm_step_btn, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND|wx.RIGHT, 15)
        
        sz = wx.BoxSizer(wx.HORIZONTAL)
        self.output_table_desc = wx.StaticText(self, -1, 'Name your output table:')
        sz.Add(self.output_table_desc, 0, wx.EXPAND|wx.RIGHT, 5)
        sz.Add(self.output_table, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        self.output_format_desc = wx.StaticText(self, -1, 'Output columns:')
        sz.Add(self.output_format_desc, 0, wx.EXPAND|wx.RIGHT, 5)
        sz.Add(self.norm_meas_checkbox, 0, wx.EXPAND|wx.RIGHT, 5)
        sz.Add(self.norm_factor_checkbox, 0, wx.EXPAND)
        self.Sizer.Add(sz, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 15)

        sz = wx.BoxSizer(wx.HORIZONTAL)
        sz.Add(self.help_btn)
        sz.AddStretchSpacer()
        sz.Add(self.do_norm_btn)
        self.Sizer.Add(sz, 0, wx.EXPAND|wx.ALL, 15)
        
        self.table_choice.Bind(wx.EVT_CHOICE, self.on_select_table)
        select_all_btn.Bind(wx.EVT_BUTTON, self.on_select_all_columns)
        add_norm_step_btn.Bind(wx.EVT_BUTTON, self.on_add_norm_step)
        self.col_choices.Bind(wx.EVT_CHECKLISTBOX, lambda e: self.validate())
        self.norm_meas_checkbox.Bind(wx.EVT_CHECKBOX, lambda e: self.validate())
        self.norm_factor_checkbox.Bind(wx.EVT_CHECKBOX, lambda e: self.validate())
        self.output_table.Bind(wx.EVT_TEXT, lambda e: self.validate())
        self.do_norm_btn.Bind(wx.EVT_BUTTON, self.on_do_normalization)
        
        self.update_measurement_choices()
        self.validate()