def check_overwrite(self, workspace): """Make sure it's ok to overwrite any existing files before starting run workspace - workspace with all image sets already populated returns True if ok to proceed, False if user cancels """ if self.wants_overwrite_without_warning: return True files_to_check = [] metadata_groups = self.get_metadata_groups(workspace) for metadata_group in metadata_groups: image_number = metadata_group.image_numbers[0] files_to_check.append( self.make_image_file_name(workspace, image_number)) files_to_overwrite = filter(os.path.isfile, files_to_check) if len(files_to_overwrite) > 0: if get_headless(): logger.error( "ExportToACC is configured to refrain from overwriting files and the following file(s) already exist: %s" % ", ".join(files_to_overwrite)) return False msg = "Overwrite the following file(s)?\n" +\ "\n".join(files_to_overwrite) import wx result = wx.MessageBox( msg, caption="ExportToACC: Overwrite existing files", style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) if result != wx.YES: return False return True
def show_warning(title, message, get_preference, set_preference): """Show a silenceable warning message to the user title - title for the dialog box message - message to be displayed get_preference - function that gets a user preference: do you want to show this warning? set_preference - function that sets the user preference if they choose not to see the warning again. The message is printed to the console if headless. """ from cellprofiler_core.preferences import get_headless if get_headless(): print(message) return if not get_preference(): return import wx if wx.GetApp() is None: print(message) return with wx.Dialog(None, title=title) as dlg: dlg.Sizer = sizer = wx.BoxSizer(wx.VERTICAL) subsizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(subsizer, 0, wx.EXPAND | wx.ALL, 5) subsizer.Add( wx.StaticBitmap( dlg, wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_CMN_DIALOG), ), 0, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.RIGHT, 5, ) text = wx.StaticText(dlg, wx.ID_ANY, message) subsizer.Add(text, 0, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.ALL, 5) dont_show = wx.CheckBox(dlg, label="Don't show this message again.") sizer.Add(dont_show, 0, wx.ALIGN_LEFT | wx.ALL, 5) buttons_sizer = wx.StdDialogButtonSizer() buttons_sizer.AddButton(wx.Button(dlg, wx.ID_OK)) buttons_sizer.Realize() sizer.Add(buttons_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) dlg.Fit() dlg.ShowModal() if dont_show.GetValue(): set_preference(False)
def prepare_run(self, workspace): """Invoke the image_set_list pickling mechanism and save the pipeline""" pipeline = workspace.pipeline image_set_list = workspace.image_set_list if pipeline.test_mode or self.from_old_matlab: return True if self.batch_mode.value: self.enter_batch_mode(workspace) return True else: path = self.save_pipeline(workspace) if not cpprefs.get_headless(): import wx wx.MessageBox( "CreateBatchFiles saved pipeline to %s" % path, caption="CreateBatchFiles: Batch file saved", style=wx.OK | wx.ICON_INFORMATION, ) return False
def run(self, workspace): """Run the module. Add the measurements. """ statistics_dict = {} ratio_dict = {} for channel in self.channels: provider = workspace.image_set.get_image_provider( channel.cpimage_name.value) assert isinstance(provider, OmeroImageProvider) name = provider.get_name() omero_image_name = provider.get_omero_image_name() omero_image_id = provider.get_image_id() pixels_id = provider.get_pixels_id() z = provider.get_z() c = provider.get_c() t = provider.get_t() header = [] row = [] ratio = [] m = workspace.measurements measurements = () if self.omero_object == MS_DATASET: measurements += ( (M_DATASET_NAME, self.dataset_name, 3.0), (M_DATASET_ID, self.omero_object_id.value, 1.0), ) elif self.omero_object == MS_PLATE: # CellProfiler starts counting image sets from 1 well = self.wells[workspace.measurements.image_set_number - 1] well_row = well.getRow().getValue() well_column = well.getColumn().getValue() well_id = well.getId().getValue() measurements += ( (M_PLATE_NAME, self.plate_name, 3.0), (M_PLATE_ID, self.omero_object_id.value, 1.0), (M_WELL_ROW, well_row, 1.0), (M_WELL_COLUMN, well_column, 1.0), (M_WELL_ID, well_id, 3.0), ) measurements += ( (M_IMAGE_NAME, omero_image_name, 3.0), (M_IMAGE_ID, omero_image_id, 1.0), (M_PIXELS_ID, pixels_id, 1.0), (M_Z, z, 0.5), (M_C, c, 0.5), (M_T, t, 0.5), ) for tag, value, r in measurements: m.add_image_measurement("_".join((tag, name)), value) header.append(tag) row.append(value) ratio.append(r) statistics = [header, row] ratio = [x / sum(ratio) for x in ratio] statistics_dict[channel.channel_number.value] = statistics ratio_dict[channel.channel_number.value] = ratio workspace.display_data.statistics = statistics_dict workspace.display_data.ratio = ratio_dict if cpp.get_headless(): # headless mode for channel in self.channels: image_name, channel_number = ( channel.cpimage_name.value, channel.channel_number.value, ) print("--- image name: %s\tchannel: %s" % (image_name, channel_number)) (header, row) = workspace.display_data.statistics[channel_number] for i in range(0, len(header)): print("\t%s: %s" % (header[i], row[i]))
def prepare_run(self, workspace): """Set up omero image providers inside the image_set_list""" pipeline = workspace.pipeline image_set_list = workspace.image_set_list if pipeline.in_batch_mode(): # TODO: Rewrite the OmeroImageProvider such that it can be used in batch mode # e.g., omero session keys could be used to attach to existing sessions to # keep OmeroImageProviders from creating a new session every time an image should be loaded return False if cpp.get_headless(): print( "OmeroLoadImages running in headless mode: image directory parameter will be used as omero object id" ) self.omero_object_id.set_value( int(cpp.get_default_image_directory())) print("omero object id = %d" % self.omero_object_id.value) print("omero object type = %s" % self.omero_object.value) self.create_omero_gateway() if self.omero_object == MS_IMAGE: omero_image_list = [ self.omero_gateway.getImage(self.omero_object_id.value) ] elif self.omero_object == MS_DATASET: # Get dataset without leaves(=images&pixels) dataset = self.omero_gateway.getDataset(self.omero_object_id.value, False) self.dataset_name = dataset.getName().getValue() omero_image_list = self.get_images_from_dataset( self.omero_object_id.value) elif self.omero_object == MS_PLATE: self.wells = self.get_wells_from_plate(self.omero_object_id.value) self.plate_name = self.wells[0].getPlate().getName().getValue() omero_image_list = [] for well in self.wells: for wellsample in well.iterateWellSamples(): omero_image_list.append(wellsample.getImage()) # get names and pixels from omero images pixels_list = [] for omero_image in omero_image_list: image_id = omero_image.getId().getValue() pixels_list += self.omero_gateway.getPixelsFromImage(image_id) # add images to image sets image_set_count = len(pixels_list) for i in range(0, image_set_count): image_set = image_set_list.get_image_set(i) pixels = pixels_list[i] pixels_id = pixels.getId().getValue() sizeZ = pixels.getSizeZ().getValue() sizeC = pixels.getSizeC().getValue() sizeT = pixels.getSizeT().getValue() for channel in self.channels: for z in range(0, sizeZ): for t in range(0, sizeT): c = int(channel.channel_number.value) self.save_image_set_info( image_set, channel.cpimage_name.value, P_OMERO, V_OMERO, self.omero_gateway, pixels_id, z, c, t, ) return True
def merge_files(destination, sources, force_headless=False): is_headless = force_headless or get_headless() if not is_headless: import wx if len(sources) == 0: return if not is_headless: progress = wx.ProgressDialog( "Writing " + destination, "Loading " + sources[0], maximum=len(sources) * 4 + 1, style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME, ) count = 0 try: pipeline = cpp.Pipeline() has_error = [False] def callback(caller, event): if isinstance(event, cpp.event.LoadException): has_error = True wx.MessageBox( message="Could not load %s: %s" % (sources[0], event.error), caption="Failed to load %s" % sources[0], ) has_error[0] = True pipeline.add_listener(callback) pipeline.load(sources[0]) if has_error[0]: return if destination.lower().endswith(".h5"): mdest = cpmeas.Measurements(filename=destination, multithread=False) h5_dest = True else: mdest = cpmeas.Measurements(multithread=False) h5_dest = False for source in sources: if not is_headless: count += 1 keep_going, skip = progress.Update(count, "Loading " + source) if not keep_going: return if h5py.is_hdf5(source): msource = cpmeas.Measurements(filename=source, mode="r", multithread=False) else: msource = cpmeas.load_measurements(source) dest_image_numbers = mdest.get_image_numbers() source_image_numbers = msource.get_image_numbers() if len(dest_image_numbers) == 0 or len( source_image_numbers) == 0: offset_source_image_numbers = source_image_numbers else: offset_source_image_numbers = ( np.max(dest_image_numbers) - np.min(source_image_numbers) + source_image_numbers + 1) for object_name in msource.get_object_names(): if object_name in mdest.get_object_names(): destfeatures = mdest.get_feature_names(object_name) else: destfeatures = [] for feature in msource.get_feature_names(object_name): if object_name == cpmeas.EXPERIMENT: if not mdest.has_feature(object_name, feature): src_value = msource.get_experiment_measurement( feature) mdest.add_experiment_measurement( feature, src_value) continue src_values = msource.get_measurement( object_name, feature, image_set_number=source_image_numbers) mdest[object_name, feature, offset_source_image_numbers] = src_values destset = set(destfeatures) if not is_headless: keep_going, skip = progress.Update(count + 1, "Saving to " + destination) if not keep_going: return if not h5_dest: pipeline.save_measurements(destination, mdest) finally: if not is_headless: progress.Destroy()
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