Ejemplo n.º 1
0
    def save_pipeline(self, workspace, outf=None):
        """Save the pipeline in Batch_data.mat

        Save the pickled image_set_list state in a setting and put this
        module in batch mode.

        if outf is not None, it is used as a file object destination.
        """
        if outf is None:
            if self.wants_default_output_directory.value:
                path = cpprefs.get_default_output_directory()
            else:
                path = cpprefs.get_absolute_path(
                    self.custom_output_directory.value)
            h5_path = os.path.join(path, F_BATCH_DATA_H5)
        else:
            h5_path = outf

        image_set_list = workspace.image_set_list
        pipeline = workspace.pipeline
        m = cpmeas.Measurements(copy=workspace.measurements, filename=h5_path)
        try:
            assert isinstance(pipeline, cpp.Pipeline)
            assert isinstance(m, cpmeas.Measurements)

            orig_pipeline = pipeline
            pipeline = pipeline.copy()
            # this use of workspace.frame is okay, since we're called from
            # prepare_run which happens in the main wx thread.
            target_workspace = cpw.Workspace(pipeline, None, None, None, m,
                                             image_set_list, workspace.frame)
            pipeline.prepare_to_create_batch(target_workspace, self.alter_path)
            bizarro_self = pipeline.module(self.module_num)
            bizarro_self.revision.value = int(
                re.sub(r"\.|rc\d{1}", "", cellprofiler.__version__))
            if self.wants_default_output_directory:
                bizarro_self.custom_output_directory.value = self.alter_path(
                    cpprefs.get_default_output_directory())
            bizarro_self.default_image_directory.value = self.alter_path(
                cpprefs.get_default_image_directory())
            bizarro_self.batch_mode.value = True
            pipeline.write_pipeline_measurement(m)
            orig_pipeline.write_pipeline_measurement(m, user_pipeline=True)
            #
            # Write the path mappings to the batch measurements
            #
            m.write_path_mappings([(mapping.local_directory.value,
                                    mapping.remote_directory.value)
                                   for mapping in self.mappings])
            return h5_path
        finally:
            m.close()
Ejemplo n.º 2
0
    def create_settings(self):
        """Create the module settings and name the module"""
        self.wants_default_output_directory = cps.Binary(
            "Store batch files in default output folder?",
            True,
            doc="""\
Select "*Yes*" to store batch files in the Default Output folder.
Select "*No*" to enter the path to the folder that will be used to
store these files. The Default Output folder can be set by clicking the "View output settings" button in the main CP window, or in CellProfiler Preferences. """
            % globals(),
        )

        self.custom_output_directory = cps.Text(
            "Output folder path",
            cpprefs.get_default_output_directory(),
            doc=
            "Enter the path to the output folder. (Used only if not using the default output folder)",
        )

        # Worded this way not because I am windows-centric but because it's
        # easier than listing every other OS in the universe except for VMS
        self.remote_host_is_windows = cps.Binary(
            "Are the cluster computers running Windows?",
            False,
            doc="""\
Select "*Yes*" if the cluster computers are running one of the
Microsoft Windows operating systems. In this case, **CreateBatchFiles**
will modify all paths to use the Windows file separator (backslash \\\\ ).
Select "*No*" for **CreateBatchFiles** to modify all paths to use the
Unix or Macintosh file separator (slash / ).""" % globals(),
        )

        self.batch_mode = cps.Binary("Hidden: in batch mode", False)
        self.distributed_mode = cps.Binary("Hidden: in distributed mode",
                                           False)
        self.default_image_directory = cps.Setting(
            "Hidden: default input folder at time of save",
            cpprefs.get_default_image_directory(),
        )
        self.revision = cps.Integer("Hidden: revision number", 0)
        self.from_old_matlab = cps.Binary("Hidden: from old matlab", False)
        self.acknowledge_old_matlab = cps.DoSomething(
            "Could not update CP1.0 pipeline to be compatible with CP2.0.  See module notes.",
            "OK",
            self.clear_old_matlab,
        )
        self.mappings = []
        self.add_mapping()
        self.add_mapping_button = cps.DoSomething(
            "",
            "Add another path mapping",
            self.add_mapping,
            doc="""\
Use this option if another path must be mapped because there is a difference
between how the local computer sees a folder location vs. how the cluster
computer sees the folder location.""",
        )
Ejemplo n.º 3
0
 def __init__(self, parent_sizer, panel, progress_panel, status_panel):
     self.__panel = panel
     self.__parent_sizer = parent_sizer
     panel.AutoLayout = True
     panel.SetSizer(wx.BoxSizer(wx.VERTICAL))
     static_box_sizer = wx.BoxSizer(wx.VERTICAL)
     panel.Sizer.Add(static_box_sizer, 1, wx.EXPAND)
     self.__sizer = static_box_sizer
     self.__image_folder_panel = wx.Panel(panel)
     self.__image_folder_panel.SetAutoLayout(True)
     self.__image_edit_box = self.__make_folder_panel(
         self.__image_folder_panel,
         get_default_image_directory(),
         lambda: get_recent_files(DEFAULT_IMAGE_DIRECTORY),
         "Default Input Folder",
         DEFAULT_IMAGE_FOLDER_HELP,
         [
             set_default_image_directory,
             self.__notify_pipeline_list_view_directory_change,
         ],
         refresh_action=self.refresh_input_directory,
     )
     self.__output_folder_panel = wx.Panel(panel)
     self.__output_folder_panel.SetAutoLayout(True)
     self.__output_edit_box = self.__make_folder_panel(
         self.__output_folder_panel,
         get_default_output_directory(),
         lambda: get_recent_files(DEFAULT_OUTPUT_DIRECTORY),
         "Default Output Folder",
         DEFAULT_OUTPUT_FOLDER_HELP,
         [
             set_default_output_directory,
             self.__notify_pipeline_list_view_directory_change,
         ],
     )
     self.__odds_and_ends_panel = wx.Panel(panel)
     self.__odds_and_ends_panel.SetAutoLayout(True)
     self.__make_odds_and_ends_panel()
     self.__status_panel = status_panel
     status_panel.Sizer = wx.BoxSizer()
     self.__status_text = wx.StaticText(status_panel,
                                        style=wx.SUNKEN_BORDER,
                                        label=WELCOME_MESSAGE)
     status_panel.Sizer.Add(self.__status_text, 1, wx.EXPAND)
     self.__progress_panel = progress_panel
     self.__progress_panel.AutoLayout = True
     self.__make_progress_panel()
     self.__sizer.AddMany([
         (self.__image_folder_panel, 0, wx.EXPAND | wx.ALL, 1),
         (self.__output_folder_panel, 0, wx.EXPAND | wx.ALL, 1),
         (self.__odds_and_ends_panel, 0, wx.EXPAND | wx.ALL, 1),
     ])
     self.show_status_text()
     self.__errors = set()
     self.__pipeline_list_view = None
     self.__progress_watcher = None
Ejemplo n.º 4
0
    def save_default_folders_to_measurements(self):
        from ..constants.pipeline import M_DEFAULT_INPUT_FOLDER
        from ..constants.pipeline import M_DEFAULT_OUTPUT_FOLDER
        from cellprofiler_core.preferences import get_default_image_directory
        from cellprofiler_core.preferences import get_default_output_directory

        self.measurements.add_experiment_measurement(
            M_DEFAULT_INPUT_FOLDER, get_default_image_directory())
        self.measurements.add_experiment_measurement(
            M_DEFAULT_OUTPUT_FOLDER, get_default_output_directory())
Ejemplo n.º 5
0
 def __on_preferences_output_directory_event(self, event):
     old_selection = self.__output_edit_box.GetSelection()
     if self.__output_edit_box.GetValue() != get_default_output_directory():
         self.__output_edit_box.SetValue(get_default_output_directory())
Ejemplo n.º 6
0
    def run(self, workspace):
        default_output_directory = get_default_output_directory()
        tag = "runimagejmacro_" + str(random.randint(100000, 999999))
        tempdir = os.path.join(default_output_directory, tag)
        os.makedirs(tempdir, exist_ok=True)
        try:
            for image_group in self.image_groups_in:
                image = workspace.image_set.get_image(
                    image_group.image_name.value)
                image_pixels = image.pixel_data
                skimage.io.imsave(
                    os.path.join(tempdir, image_group.output_filename.value),
                    image_pixels)

            if self.executable_file.value[-4:] == ".app":
                executable = os.path.join(
                    default_output_directory,
                    self.executable_directory.value.split("|")[1],
                    self.executable_file.value, "Contents/MacOS/ImageJ-macosx")
            else:
                executable = os.path.join(
                    default_output_directory,
                    self.executable_directory.value.split("|")[1],
                    self.executable_file.value)
            cmd = [
                executable, "--headless", "console", "--run",
                os.path.join(default_output_directory,
                             self.macro_directory.value.split("|")[1],
                             self.macro_file.value)
            ]

            cmd += [self.stringify_metadata(tempdir)]

            subprocess.call(cmd,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)

            for image_group in self.image_groups_out:
                if not os.path.exists(
                        os.path.join(tempdir,
                                     image_group.input_filename.value)):
                    msg = f"CellProfiler couldn't find the output expected from the ImageJ Macro," \
                          f"\n File {image_group.input_filename.value} was missing"
                    raise FileNotFoundError("Missing file", msg)
                image_pixels = skimage.io.imread(
                    os.path.join(tempdir, image_group.input_filename.value))
                workspace.image_set.add(image_group.image_name.value,
                                        Image(image_pixels, convert=False))
        finally:
            # Clean up temp directory regardless of macro success
            for subdir, dirs, files in os.walk(tempdir):
                for file in files:
                    os.remove(os.path.join(tempdir, file))
            os.removedirs(tempdir)

        pixel_data = []
        image_names = []

        if self.show_window:
            for x in itertools.chain(self.image_groups_in,
                                     self.image_groups_out):
                pixel_data.append(
                    workspace.image_set.get_image(
                        x.image_name.value).pixel_data)
                image_names.append(x.image_name.value)

        workspace.display_data.pixel_data = pixel_data
        workspace.display_data.display_names = image_names
        workspace.display_data.dimensions = workspace.image_set.get_image(
            self.image_groups_out[0].image_name.value).dimensions
Ejemplo n.º 7
0
    def run(self, workspace):
        default_output_directory = get_default_output_directory()
        tag = "runimagejmacro_" + str(random.randint(100000, 999999))
        tempdir = os.path.join(default_output_directory, tag)
        os.makedirs(tempdir, exist_ok=True)
        try:
            for image_group in self.image_groups_in:
                image = workspace.image_set.get_image(
                    image_group.image_name.value)
                image_pixels = image.pixel_data
                skimage.io.imsave(
                    os.path.join(tempdir, image_group.output_filename.value),
                    image_pixels)

            if self.executable_file.value[-4:] == ".app":
                executable = os.path.join(
                    default_output_directory,
                    self.executable_directory.value.split("|")[1],
                    self.executable_file.value, "Contents/MacOS/ImageJ-macosx")
            else:
                executable = os.path.join(
                    default_output_directory,
                    self.executable_directory.value.split("|")[1],
                    self.executable_file.value)
            cmd = [
                executable, "--headless", "console", "--run",
                os.path.join(default_output_directory,
                             self.macro_directory.value.split("|")[1],
                             self.macro_file.value)
            ]

            cmd += [self.stringify_metadata(tempdir)]

            result = subprocess.run(cmd,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT,
                                    text=True)
            for image_group in self.image_groups_out:
                if not os.path.exists(
                        os.path.join(tempdir,
                                     image_group.input_filename.value)):
                    # Cleanup the error logs for display, we want to remove less-useful lines to keep it succinct.
                    reject = ('console:', 'Java Hot', 'at org', 'at java',
                              '[WARNING]', '\t')
                    # ImageJ tends to report the same few lines over and over, so we'll use a dict as an ordered set.
                    err = {}
                    for line in result.stdout.splitlines():
                        if len(line.strip()) > 0 and not line.startswith(
                                reject):
                            err[line] = None
                    if len(err) > 1:
                        # Error appears when file loading fails, but can also show up if the macro failed to generate
                        # an output image. We remove this if it wasn't the only error, as it can be confusing.
                        err.pop('Unsupported format or not found', None)
                    err = "\n".join(err.keys())
                    msg = f"CellProfiler couldn't find the output expected from the ImageJ Macro," \
                          f"\n File {image_group.input_filename.value} was missing."
                    if err:
                        msg += f"\n\nImageJ logs contained the following: \n{err}"
                    raise FileNotFoundError("Missing file", msg)
                image_pixels = skimage.io.imread(
                    os.path.join(tempdir, image_group.input_filename.value))
                workspace.image_set.add(image_group.image_name.value,
                                        Image(image_pixels, convert=False))
        finally:
            want_delete = True
            # Optionally clean up temp directory regardless of macro success
            if workspace.pipeline.test_mode and self.debug_mode:
                want_delete = False
                if not get_headless():
                    import wx
                    message = f"Debugging was enabled.\nTemporary folder was not deleted automatically" \
                              f"\n\nTemporary subfolder is {os.path.split(tempdir)[-1]} in your Default Output Folder\n\nDo you want to delete it now?"
                    with wx.Dialog(None,
                                   title="RunImageJMacro Debug Mode") as dlg:
                        text_sizer = dlg.CreateTextSizer(message)
                        sizer = wx.BoxSizer(wx.VERTICAL)
                        dlg.SetSizer(sizer)
                        button_sizer = dlg.CreateStdDialogButtonSizer(
                            flags=wx.YES | wx.NO)
                        open_temp_folder_button = wx.Button(
                            dlg, -1, "Open temporary folder")
                        button_sizer.Insert(0, open_temp_folder_button)

                        def on_open_temp_folder(event):
                            import sys
                            if sys.platform == "win32":
                                os.startfile(tempdir)
                            else:
                                import subprocess
                                subprocess.call([
                                    "open",
                                    tempdir,
                                ])

                        open_temp_folder_button.Bind(wx.EVT_BUTTON,
                                                     on_open_temp_folder)
                        sizer.Add(text_sizer, 0, wx.EXPAND | wx.ALL, 10)
                        sizer.Add(button_sizer, 0, wx.EXPAND | wx.ALL, 10)
                        dlg.SetEscapeId(wx.ID_NO)
                        dlg.SetAffirmativeId(wx.ID_YES)
                        dlg.Fit()
                        dlg.CenterOnParent()
                        if dlg.ShowModal() == wx.ID_YES:
                            want_delete = True
            if want_delete:
                try:
                    for subdir, dirs, files in os.walk(tempdir):
                        for file in files:
                            os.remove(os.path.join(tempdir, file))
                    os.removedirs(tempdir)
                except:
                    logging.error(
                        "Unable to delete temporary directory, files may be in use by another program."
                    )
                    logging.error(
                        "Temp folder is subfolder {tempdir} in your Default Output Folder.\nYou may need to remove it manually."
                    )
            else:
                logging.error(
                    f"Debugging was enabled.\nDid not remove temporary folder at {tempdir}"
                )

        pixel_data = []
        image_names = []

        if self.show_window:
            for x in itertools.chain(self.image_groups_in,
                                     self.image_groups_out):
                pixel_data.append(
                    workspace.image_set.get_image(
                        x.image_name.value).pixel_data)
                image_names.append(x.image_name.value)

        workspace.display_data.pixel_data = pixel_data
        workspace.display_data.display_names = image_names
        workspace.display_data.dimensions = workspace.image_set.get_image(
            self.image_groups_out[0].image_name.value).dimensions