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)
Esempio n. 3
0
    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 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)