def save_run_output(self, sample_num, directory_path, output_file): """Save the parameter settings and images for the current run of 'self.__module'.""" for i, setting in enumerate(self.__module.visible_settings()): value_to_write = '' # Do not write settings without values, ie, buttons etc if setting.get_text() != '': value_to_write = str(setting.get_value()) if isinstance(setting, cellprofiler.setting.ImageNameProvider): # Save image image = \ self.__measurements.get_image(value_to_write) path = \ os.path.join(directory_path, value_to_write + '_' + str(sample_num)) self.save_image(image, path) value_to_write += '_' + str(sample_num) + '.jpg' # ~*~ # elif isinstance(setting, settings.ObjectNameProvider): # print 'Bingo! ' + str(value_to_write) # objects =\ # self.__workspace.get_object_set().get_objects(setting.get_value()) # value_to_write = str(len(objects.indices)) # ~^~ if i < len(self.__module.visible_settings() ) - 1 and value_to_write != '': value_to_write += '\t' if i == len(self.__module.visible_settings()) - 1: value_to_write += '\n' # Write line to 'open_file' if value_to_write != '': output_file.write(value_to_write)
def save_run_output(self, sample_num, directory_path, output_file): """Save the parameter settings and images for the current run of 'self.__module'.""" for i, setting in enumerate(self.__module.visible_settings()): value_to_write = '' # Do not write settings without values, ie, buttons etc if setting.get_text() != '': value_to_write = str(setting.get_value()) if isinstance(setting, cellprofiler.setting.ImageNameProvider): # Save image image = \ self.__measurements.get_image(value_to_write) path = \ os.path.join(directory_path, value_to_write + '_' + str(sample_num)) self.save_image(image, path) value_to_write += '_' + str(sample_num) + '.jpg' # ~*~ # elif isinstance(setting, settings.ObjectNameProvider): # print 'Bingo! ' + str(value_to_write) # objects =\ # self.__workspace.get_object_set().get_objects(setting.get_value()) # value_to_write = str(len(objects.indices)) # ~^~ if i < len(self.__module.visible_settings()) - 1 and value_to_write != '': value_to_write += '\t' if i == len(self.__module.visible_settings()) - 1: value_to_write += '\n' # Write line to 'open_file' if value_to_write != '': output_file.write(value_to_write)
def get_parameter_input_size(setting): """Get input size of 'setting'.""" size = 1 try: size = len(setting.get_value()) except: pass return size
def validate_input_ranges(self): """Validates input ranges specified by the input widgets. This method uses CellProfiler's validate methods on settings to test whether the ranges specified on the UI are acceptable. When these do not validate, the user is shown an error message that lists all violations as well as the error message received back from CellProfiler. """ # First, test whether selected parameters are valid message = '' for i, checkbox in enumerate(self.__check_box_list): if checkbox.IsChecked(): setting = self.__module.setting(self.__parameters_list[i][1]) input_size = self.get_parameter_input_size(setting) if input_size == 1: widget_idx = self.__parameters_to_widgets_list[i][0] lower_value = self.__lower_bound_spin_ctrl_list[ widget_idx].GetValue() upper_value = self.__upper_bound_spin_ctrl_list[ widget_idx].GetValue() elif input_size == 2: widget_idx = self.__parameters_to_widgets_list[i][0] lower_value = ( self.__lower_bound_spin_ctrl_list[widget_idx].GetValue( ), self.__lower_bound_spin_ctrl_list[widget_idx + 1].GetValue()) upper_value = ( self.__upper_bound_spin_ctrl_list[widget_idx].GetValue( ), self.__upper_bound_spin_ctrl_list[widget_idx + 1].GetValue()) old_value = setting.get_value() try: setting.set_value(lower_value) setting.test_valid(self.__pipeline) except cellprofiler.setting.ValidationError as instance: message += '\'' + str(setting.get_text()) + \ '\': lower bound invalid, ' + \ '\n\t' + str(instance.message) + '\n' try: setting.set_value(upper_value) setting.test_valid(self.__pipeline) except cellprofiler.setting.ValidationError as instance: message += '\'' + str(setting.get_text()) + \ '\': upper bound invalid, ' + \ '\n\t' + str(instance.message) + '\n' setting.set_value(old_value) # Second, if there are invalid parameters, tell the user if len(message) > 0: message = 'Invalid sample settings:\n\n' + message dialog = wx.MessageDialog(self, message, caption='Sample settings error', style=wx.ICON_ERROR | wx.OK) dialog.ShowModal() raise Exception(message)
def validate_input_ranges(self): """Validates input ranges specified by the input widgets. This method uses CellProfiler's validate methods on settings to test whether the ranges specified on the UI are acceptable. When these do not validate, the user is shown an error message that lists all violations as well as the error message received back from CellProfiler. """ # First, test whether selected parameters are valid message = '' for i, checkbox in enumerate(self.__check_box_list): if checkbox.IsChecked(): setting = self.__module.setting(self.__parameters_list[i][1]) input_size = self.get_parameter_input_size(setting) if input_size == 1: widget_idx = self.__parameters_to_widgets_list[i][0] lower_value = self.__lower_bound_spin_ctrl_list[widget_idx].GetValue() upper_value = self.__upper_bound_spin_ctrl_list[widget_idx].GetValue() elif input_size == 2: widget_idx = self.__parameters_to_widgets_list[i][0] lower_value = (self.__lower_bound_spin_ctrl_list[widget_idx].GetValue(), self.__lower_bound_spin_ctrl_list[widget_idx + 1].GetValue()) upper_value = (self.__upper_bound_spin_ctrl_list[widget_idx].GetValue(), self.__upper_bound_spin_ctrl_list[widget_idx + 1].GetValue()) old_value = setting.get_value() try: setting.set_value(lower_value) setting.test_valid(self.__pipeline) except cellprofiler.setting.ValidationError as instance: message += '\'' + str(setting.get_text()) + \ '\': lower bound invalid, ' + \ '\n\t' + str(instance.message) + '\n' try: setting.set_value(upper_value) setting.test_valid(self.__pipeline) except cellprofiler.setting.ValidationError as instance: message += '\'' + str(setting.get_text()) + \ '\': upper bound invalid, ' + \ '\n\t' + str(instance.message) + '\n' setting.set_value(old_value) # Second, if there are invalid parameters, tell the user if len(message) > 0: message = 'Invalid sample settings:\n\n' + message dialog = wx.MessageDialog( self, message, caption='Sample settings error', style=wx.ICON_ERROR | wx.OK) dialog.ShowModal() raise Exception(message)
def on_button(self, event): if event.GetId() == ID_SAMPLE_BUTTON: # try: self.validate_input_ranges() number = self.calc_number_samples() sample_dialog = wx.MessageDialog( self, 'Proceed with calculating ' + str(number) + ' samples?', caption='Confirm sample size', style=wx.ICON_QUESTION | wx.OK | wx.CANCEL) if sample_dialog.ShowModal() == wx.ID_OK: save_dialog = wx.FileDialog( event.GetEventObject(), message='Save sampled output', wildcard='Tab separated values (*.tsv)|*.tsv', style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if save_dialog.ShowModal() == wx.ID_OK: # 1. Copy original parameter values original_values = [] for setting in self.__module.visible_settings(): original_values.append(setting.get_value()) # 2. Sample input parameters self.__sample_list = self.generate_parameter_samples() # 3. Open output file and write headers output_file = \ open(save_dialog.GetPath(), 'w') headers = '' for i, setting in enumerate( self.__module.visible_settings()): # Do not write settings without values, ie, buttons etc if setting.get_text() != '': headers += setting.get_text() if i < len(self.__module.visible_settings()) - 1: headers += '\t' headers += '\n' output_file.write(headers) # 4. Run pipeline once for each sample # ~*~ self.Show(False) progressDialog = wx.ProgressDialog( parent=self, title='Sampling parameters', message='Run 1', maximum=len(self.__sample_list)) size = progressDialog.GetSize() size.SetWidth(2 * size.GetWidth()) progressDialog.SetSize(size) # ~^~ for i, l in enumerate(self.__sample_list): # print '\nStarting run ' + str(i+1) + '...' for j, value in enumerate(l): if value is not None: setting_nr = self.__parameters_list[j][1] setting = self.__module.setting(setting_nr) setting.set_value(value) # print str(setting.get_text()) + ' -> ' + str(setting.get_value()) # ~*~ progressDialog.Update( i + 1, newmsg='Executing run ' + str(i + 1) + \ ' of ' + str(len(self.__sample_list))) # ~^~ # It's not very efficient to run the complete pipeline # when only the last module's parameter values are # different. However, this is the only way I can get # the images to update correctly for the last module. Ie, # when I don't prepare and run the pipeline from scratch # for every different configuration of the last module, # I get the images generated by the first run for every # run. # 4.1 Prepare to run pipeline self.prepare_for_run() # 4.2 Run modules for module in self.__pipeline.modules(): if module.get_module_num( ) <= self.__module.get_module_num(): self.run_module(module) # 4.3 Save output self.save_run_output(i, save_dialog.GetDirectory(), output_file) # This is the way to run headless, if only I could get at the images... # self.stop_now = False # running_pipeline = self.__pipeline.run_with_yield( # run_in_background=False, # status_callback=self.status_callback) # while not self.stop_now: # measurements = running_pipeline.next() # print '...run completed.' # 5. Close output file output_file.close() # ~*~ progressDialog.Destroy() # ~^~ # 6. Set parameters back to original values and close window for i, setting in enumerate( self.__module.visible_settings()): setting.set_value(original_values[i]) self.Close(True)
def __init__(self, parent, module, pipeline, identifier=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name=wx.FrameNameStr): # Flag to check during event handling: widgets generate events as they # are created leading to referencing errors before all data structs # have been initialized. self.__initialized = False # Init frame self.__module = module self.__pipeline = pipeline self.__frame = parent # Data members for running pipeline self.__measurements = None self.__object_set = None self.__image_set_list = None self.__keys = None self.__groupings = None self.__grouping_index = None self.__within_group_index = None self.__outlines = None self.__grids = None frame_title = 'Sampling settings for module, ' + self.__module.module_name wx.Frame.__init__(self, self.__frame, identifier, frame_title, pos, size, style, name) self.__frame_sizer = wx.BoxSizer(wx.VERTICAL) self.SetSize(wx.Size(700, 350)) self.SetSizer(self.__frame_sizer) # Get parameters self.__parameters_list = self.get_parameters_list() if len(self.__parameters_list) == 0: dialog = wx.MessageDialog(self, self.__module.module_name + ' has no unbounded parameters.', caption='No unbounded parameters', style=wx.OK) dialog.ShowModal() self.Close(True) # Init settings panel self.__settings_panel = wx.Panel(self, -1) self.__settings_panel_sizer = wx.BoxSizer(wx.VERTICAL) self.__settings_panel.SetSizer(self.__settings_panel_sizer) self.__frame_sizer.Add(self.__settings_panel, 1, wx.EXPAND | wx.ALL, 5) # Init settings scrolled window self.__settings_scrolled_window = wx.ScrolledWindow( self.__settings_panel) self.__settings_scrolled_window.SetScrollRate(20, 20) self.__settings_scrolled_window.EnableScrolling(True, True) self.__settings_scrolled_window_sizer = wx.FlexGridSizer(rows=0, cols=5) self.__settings_scrolled_window.SetSizer( self.__settings_scrolled_window_sizer) self.__settings_scrolled_window_sizer.AddGrowableCol(0) self.__settings_panel_sizer.Add(self.__settings_scrolled_window, 1, wx.EXPAND | wx.ALL, 5) # Headings self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Parameter'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Current value'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Lower bound'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Upper bound'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Number samples'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP | wx.RIGHT, 5) # Init dynamic widgets based on parameters self.__parameters_to_widgets_list = self.get_parameters_to_widgets_list( self.__parameters_list) self.__check_box_list = [] self.__current_static_text_list = [] self.__lower_bound_spin_ctrl_list = [] self.__upper_bound_spin_ctrl_list = [] self.__number_spin_ctrl_list = [] for i in range(len(self.__parameters_to_widgets_list)): label = self.__parameters_list[i][0] setting = self.__module.setting(self.__parameters_list[i][1]) value = setting.get_value() for j in range(len(self.__parameters_to_widgets_list[i])): # Checkbox & label if j == 0: check_box = wx.CheckBox(self.__settings_scrolled_window, -1, label) check_box.Bind(wx.EVT_CHECKBOX, self.on_check_box) self.__settings_scrolled_window_sizer.Add( check_box, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__check_box_list.append(check_box) else: self.__settings_scrolled_window_sizer.Add( wx.Panel(self.__settings_scrolled_window, -1)) # Current value if self.is_parameter_int(setting): if self.get_parameter_input_size(setting) == 1: cur_value = str(value) elif self.get_parameter_input_size(setting) == 2: cur_value = str(value[j]) elif self.is_parameter_float(setting): if self.get_parameter_input_size(setting) == 1: cur_value = str(round(value, FLOAT_DIGITS_TO_ROUND_TO)) elif self.get_parameter_input_size(setting) == 2: cur_value = str( round(value[j], FLOAT_DIGITS_TO_ROUND_TO)) current_static_text = wx.StaticText( self.__settings_scrolled_window, -1, cur_value) self.__settings_scrolled_window_sizer.Add( current_static_text, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP | wx.RIGHT, 5) self.__current_static_text_list.append(current_static_text) # Lower and upper bounds if self.is_parameter_int(setting): # Integer lower_spin_ctrl = wx.SpinCtrl( self.__settings_scrolled_window, wx.NewId()) lower_spin_ctrl.SetRange(INT_LOWER_BOUND, INT_UPPER_BOUND) lower_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_lower_spin_ctrl) upper_spin_ctrl = wx.SpinCtrl( self.__settings_scrolled_window, wx.NewId()) upper_spin_ctrl.SetRange(INT_LOWER_BOUND, INT_UPPER_BOUND) upper_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_upper_spin_ctrl) interval = DEFAULT_NUMBER_SAMPLES - 1 # Used later to set upper bound elif self.is_parameter_float(setting): # Float lower_spin_ctrl = wx.lib.agw.floatspin.FloatSpin( self.__settings_scrolled_window, wx.NewId(), size=wx.DefaultSize ) # NB: if not set, spin buttons are hidden lower_spin_ctrl.SetDigits(FLOAT_DIGITS_TO_ROUND_TO) lower_spin_ctrl.SetIncrement(10**-FLOAT_DIGITS_TO_ROUND_TO) lower_spin_ctrl.SetRange(FLOAT_LOWER_BOUND, FLOAT_UPPER_BOUND) lower_spin_ctrl.Bind(wx.lib.agw.floatspin.EVT_FLOATSPIN, self.on_lower_float_spin) upper_spin_ctrl = wx.lib.agw.floatspin.FloatSpin( self.__settings_scrolled_window, wx.NewId(), size=wx.DefaultSize ) # NB: if not set, spin buttons are hidden upper_spin_ctrl.SetDigits(FLOAT_DIGITS_TO_ROUND_TO) upper_spin_ctrl.SetIncrement(10**-FLOAT_DIGITS_TO_ROUND_TO) upper_spin_ctrl.SetRange(FLOAT_LOWER_BOUND, FLOAT_UPPER_BOUND) upper_spin_ctrl.Bind(wx.lib.agw.floatspin.EVT_FLOATSPIN, self.on_upper_float_spin) interval = upper_spin_ctrl.GetIncrement( ) # Used later to set upper bound if self.get_parameter_input_size(setting) == 1: lower_spin_ctrl.SetValue( value) # Set value after range to avoid rounding upper_spin_ctrl.SetValue(value + interval) elif self.get_parameter_input_size(setting) == 2: lower_spin_ctrl.SetValue(value[j]) upper_spin_ctrl.SetValue(value[j] + interval) lower_spin_ctrl.Enable(False) self.__settings_scrolled_window_sizer.Add( lower_spin_ctrl, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.LEFT | wx.TOP, 5) self.__lower_bound_spin_ctrl_list.append(lower_spin_ctrl) upper_spin_ctrl.Enable(False) self.__settings_scrolled_window_sizer.Add( upper_spin_ctrl, 0, wx.LEFT | wx.TOP, 5) self.__upper_bound_spin_ctrl_list.append(upper_spin_ctrl) # Number samples num_spin_ctrl = wx.SpinCtrl(self.__settings_scrolled_window, wx.NewId()) num_spin_ctrl.Enable(False) num_spin_ctrl.SetRange(1, 100) num_spin_ctrl.SetValue(10) num_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_number_spin_ctrl) self.__settings_scrolled_window_sizer.Add( num_spin_ctrl, 0, wx.LEFT | wx.TOP | wx.RIGHT, 5) self.__number_spin_ctrl_list.append(num_spin_ctrl) self.__settings_scrolled_window.Layout() self.__settings_panel.Layout() # Add button self.sample_button = wx.Button(self, ID_SAMPLE_BUTTON, 'Sample') self.sample_button.Bind(wx.EVT_BUTTON, self.on_button) self.sample_button.Enable(False) self.__frame_sizer.Add(self.sample_button, 0, wx.ALIGN_RIGHT | wx.ALL, 5) self.__initialized = True
def on_button(self, event): if event.GetId() == ID_SAMPLE_BUTTON: # try: self.validate_input_ranges() number = self.calc_number_samples() sample_dialog = wx.MessageDialog( self, 'Proceed with calculating ' + str(number) + ' samples?', caption='Confirm sample size', style=wx.ICON_QUESTION | wx.OK | wx.CANCEL) if sample_dialog.ShowModal() == wx.ID_OK: save_dialog = wx.FileDialog( event.GetEventObject(), message='Save sampled output', wildcard='Tab separated values (*.tsv)|*.tsv', style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if save_dialog.ShowModal() == wx.ID_OK: # 1. Copy original parameter values original_values = [] for setting in self.__module.visible_settings(): original_values.append(setting.get_value()) # 2. Sample input parameters self.__sample_list = self.generate_parameter_samples() # 3. Open output file and write headers output_file = \ open(save_dialog.GetPath(), 'w') headers = '' for i, setting in enumerate(self.__module.visible_settings()): # Do not write settings without values, ie, buttons etc if setting.get_text() != '': headers += setting.get_text() if i < len(self.__module.visible_settings()) - 1: headers += '\t' headers += '\n' output_file.write(headers) # 4. Run pipeline once for each sample # ~*~ self.Show(False) progressDialog = wx.ProgressDialog( parent=self, title='Sampling parameters', message='Run 1', maximum=len(self.__sample_list)) size = progressDialog.GetSize() size.SetWidth(2 * size.GetWidth()) progressDialog.SetSize(size) # ~^~ for i, l in enumerate(self.__sample_list): # print '\nStarting run ' + str(i+1) + '...' for j, value in enumerate(l): if value is not None: setting_nr = self.__parameters_list[j][1] setting = self.__module.setting(setting_nr) setting.set_value(value) # print str(setting.get_text()) + ' -> ' + str(setting.get_value()) # ~*~ progressDialog.Update( i + 1, newmsg='Executing run ' + str(i + 1) + \ ' of ' + str(len(self.__sample_list))) # ~^~ # It's not very efficient to run the complete pipeline # when only the last module's parameter values are # different. However, this is the only way I can get # the images to update correctly for the last module. Ie, # when I don't prepare and run the pipeline from scratch # for every different configuration of the last module, # I get the images generated by the first run for every # run. # 4.1 Prepare to run pipeline self.prepare_for_run() # 4.2 Run modules for module in self.__pipeline.modules(): if module.get_module_num() <= self.__module.get_module_num(): self.run_module(module) # 4.3 Save output self.save_run_output(i, save_dialog.GetDirectory(), output_file) # This is the way to run headless, if only I could get at the images... # self.stop_now = False # running_pipeline = self.__pipeline.run_with_yield( # run_in_background=False, # status_callback=self.status_callback) # while not self.stop_now: # measurements = running_pipeline.next() # print '...run completed.' # 5. Close output file output_file.close() # ~*~ progressDialog.Destroy() # ~^~ # 6. Set parameters back to original values and close window for i, setting in enumerate(self.__module.visible_settings()): setting.set_value(original_values[i]) self.Close(True)
def __init__(self, parent, module, pipeline, identifier=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name=wx.FrameNameStr): # Flag to check during event handling: widgets generate events as they # are created leading to referencing errors before all data structs # have been initialized. self.__initialized = False # Init frame self.__module = module self.__pipeline = pipeline self.__frame = parent # Data members for running pipeline self.__measurements = None self.__object_set = None self.__image_set_list = None self.__keys = None self.__groupings = None self.__grouping_index = None self.__within_group_index = None self.__outlines = None self.__grids = None frame_title = 'Sampling settings for module, ' + self.__module.module_name wx.Frame.__init__(self, self.__frame, identifier, frame_title, pos, size, style, name) self.__frame_sizer = wx.BoxSizer(wx.VERTICAL) self.SetSize(wx.Size(700, 350)) self.SetSizer(self.__frame_sizer) # Get parameters self.__parameters_list = self.get_parameters_list() if len(self.__parameters_list) == 0: dialog = wx.MessageDialog( self, self.__module.module_name + ' has no unbounded parameters.', caption='No unbounded parameters', style=wx.OK) dialog.ShowModal() self.Close(True) # Init settings panel self.__settings_panel = wx.Panel(self, -1) self.__settings_panel_sizer = wx.BoxSizer(wx.VERTICAL) self.__settings_panel.SetSizer(self.__settings_panel_sizer) self.__frame_sizer.Add(self.__settings_panel, 1, wx.EXPAND | wx.ALL, 5) # Init settings scrolled window self.__settings_scrolled_window = wx.ScrolledWindow(self.__settings_panel) self.__settings_scrolled_window.SetScrollRate(20, 20) self.__settings_scrolled_window.EnableScrolling(True, True) self.__settings_scrolled_window_sizer = wx.FlexGridSizer(rows=0, cols=5) self.__settings_scrolled_window.SetSizer( self.__settings_scrolled_window_sizer) self.__settings_scrolled_window_sizer.AddGrowableCol(0) self.__settings_panel_sizer.Add( self.__settings_scrolled_window, 1, wx.EXPAND | wx.ALL, 5) # Headings self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Parameter'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Current value'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Lower bound'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Upper bound'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__settings_scrolled_window_sizer.Add( wx.StaticText(self.__settings_scrolled_window, -1, 'Number samples'), 0, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP | wx.RIGHT, 5) # Init dynamic widgets based on parameters self.__parameters_to_widgets_list = self.get_parameters_to_widgets_list( self.__parameters_list) self.__check_box_list = [] self.__current_static_text_list = [] self.__lower_bound_spin_ctrl_list = [] self.__upper_bound_spin_ctrl_list = [] self.__number_spin_ctrl_list = [] for i in range(len(self.__parameters_to_widgets_list)): label = self.__parameters_list[i][0] setting = self.__module.setting(self.__parameters_list[i][1]) value = setting.get_value() for j in range(len(self.__parameters_to_widgets_list[i])): # Checkbox & label if j == 0: check_box = wx.CheckBox(self.__settings_scrolled_window, -1, label) check_box.Bind(wx.EVT_CHECKBOX, self.on_check_box) self.__settings_scrolled_window_sizer.Add( check_box, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 5) self.__check_box_list.append(check_box) else: self.__settings_scrolled_window_sizer.Add( wx.Panel(self.__settings_scrolled_window, -1)) # Current value if self.is_parameter_int(setting): if self.get_parameter_input_size(setting) == 1: cur_value = str(value) elif self.get_parameter_input_size(setting) == 2: cur_value = str(value[j]) elif self.is_parameter_float(setting): if self.get_parameter_input_size(setting) == 1: cur_value = str(round(value, FLOAT_DIGITS_TO_ROUND_TO)) elif self.get_parameter_input_size(setting) == 2: cur_value = str(round(value[j], FLOAT_DIGITS_TO_ROUND_TO)) current_static_text = wx.StaticText( self.__settings_scrolled_window, -1, cur_value) self.__settings_scrolled_window_sizer.Add( current_static_text, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP | wx.RIGHT, 5) self.__current_static_text_list.append(current_static_text) # Lower and upper bounds if self.is_parameter_int(setting): # Integer lower_spin_ctrl = wx.SpinCtrl( self.__settings_scrolled_window, wx.NewId()) lower_spin_ctrl.SetRange(INT_LOWER_BOUND, INT_UPPER_BOUND) lower_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_lower_spin_ctrl) upper_spin_ctrl = wx.SpinCtrl( self.__settings_scrolled_window, wx.NewId()) upper_spin_ctrl.SetRange(INT_LOWER_BOUND, INT_UPPER_BOUND) upper_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_upper_spin_ctrl) interval = DEFAULT_NUMBER_SAMPLES - 1 # Used later to set upper bound elif self.is_parameter_float(setting): # Float lower_spin_ctrl = wx.lib.agw.floatspin.FloatSpin( self.__settings_scrolled_window, wx.NewId(), size=wx.DefaultSize) # NB: if not set, spin buttons are hidden lower_spin_ctrl.SetDigits(FLOAT_DIGITS_TO_ROUND_TO) lower_spin_ctrl.SetIncrement(10 ** -FLOAT_DIGITS_TO_ROUND_TO) lower_spin_ctrl.SetRange(FLOAT_LOWER_BOUND, FLOAT_UPPER_BOUND) lower_spin_ctrl.Bind(wx.lib.agw.floatspin.EVT_FLOATSPIN, self.on_lower_float_spin) upper_spin_ctrl = wx.lib.agw.floatspin.FloatSpin( self.__settings_scrolled_window, wx.NewId(), size=wx.DefaultSize) # NB: if not set, spin buttons are hidden upper_spin_ctrl.SetDigits(FLOAT_DIGITS_TO_ROUND_TO) upper_spin_ctrl.SetIncrement(10 ** -FLOAT_DIGITS_TO_ROUND_TO) upper_spin_ctrl.SetRange(FLOAT_LOWER_BOUND, FLOAT_UPPER_BOUND) upper_spin_ctrl.Bind(wx.lib.agw.floatspin.EVT_FLOATSPIN, self.on_upper_float_spin) interval = upper_spin_ctrl.GetIncrement() # Used later to set upper bound if self.get_parameter_input_size(setting) == 1: lower_spin_ctrl.SetValue(value) # Set value after range to avoid rounding upper_spin_ctrl.SetValue(value + interval) elif self.get_parameter_input_size(setting) == 2: lower_spin_ctrl.SetValue(value[j]) upper_spin_ctrl.SetValue(value[j] + interval) lower_spin_ctrl.Enable(False) self.__settings_scrolled_window_sizer.Add( lower_spin_ctrl, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.LEFT | wx.TOP, 5) self.__lower_bound_spin_ctrl_list.append(lower_spin_ctrl) upper_spin_ctrl.Enable(False) self.__settings_scrolled_window_sizer.Add( upper_spin_ctrl, 0, wx.LEFT | wx.TOP, 5) self.__upper_bound_spin_ctrl_list.append(upper_spin_ctrl) # Number samples num_spin_ctrl = wx.SpinCtrl( self.__settings_scrolled_window, wx.NewId()) num_spin_ctrl.Enable(False) num_spin_ctrl.SetRange(1, 100) num_spin_ctrl.SetValue(10) num_spin_ctrl.Bind(wx.EVT_SPINCTRL, self.on_number_spin_ctrl) self.__settings_scrolled_window_sizer.Add( num_spin_ctrl, 0, wx.LEFT | wx.TOP | wx.RIGHT, 5) self.__number_spin_ctrl_list.append(num_spin_ctrl) self.__settings_scrolled_window.Layout() self.__settings_panel.Layout() # Add button self.sample_button = wx.Button(self, ID_SAMPLE_BUTTON, 'Sample') self.sample_button.Bind(wx.EVT_BUTTON, self.on_button) self.sample_button.Enable(False) self.__frame_sizer.Add(self.sample_button, 0, wx.ALIGN_RIGHT | wx.ALL, 5) self.__initialized = True