From eb3b72d5575ad44b3229686068fcf6ceac626b6b Mon Sep 17 00:00:00 2001 From: Laurent Guerard <laurent.guerard@unibas.ch> Date: Tue, 14 Jan 2025 11:22:52 +0100 Subject: [PATCH] Docstring formatting and refactoring --- 2c_fibertyping.py | 342 +++++++++++++++++++++++++++++----------------- 1 file changed, 219 insertions(+), 123 deletions(-) diff --git a/2c_fibertyping.py b/2c_fibertyping.py index bb58eab..e10c3a2 100755 --- a/2c_fibertyping.py +++ b/2c_fibertyping.py @@ -1,4 +1,4 @@ -# this is a python rewrite of the original ijm published at +# this is a python rewrite of the original ijm published at # https://github.com/Hyojung-Choo/Myosoft/blob/Myosoft-hub/Scripts/central%20nuclei%20counter.ijm # IJ imports @@ -33,37 +33,47 @@ import os def fix_ij_options(): - """put IJ into a defined state + """Configure ImageJ (IJ) to a predefined state. + + This function sets various options in ImageJ to ensure a consistent + environment for image processing tasks. It includes settings for appearance, + color management, binary image options, and file output format. """ - # disable inverting LUT + # Disable inverting LUT (Look-Up Table) for images IJ.run("Appearance...", " menu=0 16-bit=Automatic") - # set foreground color to be white, background black + + # Set foreground color to be white and background color to be black, with red for selections IJ.run("Colors...", "foreground=white background=black selection=red") - # black BG for binary images and pad edges when eroding + + # Enable black background for binary images and pad edges when eroding IJ.run("Options...", "black pad") - # set saving format to .txt files + + # Set saving format to .txt files, saving both columns and rows IJ.run("Input/Output...", "file=.txt save_column save_row") - # ============= DON’T MOVE UPWARDS ============= - # set "Black Background" in "Binary Options" + + # Set "Black Background" option for binary operations IJ.run("Options...", "black") - # scale when converting = checked + + # Enable scaling when converting images between types IJ.run("Conversions...", "scale") def fix_ij_dirs(path): - """use forward slashes in directory paths + """Replace backslashes with forward slashes in directory paths. + + This function takes a directory path obtained from a dialogue or script + parameter and returns a more robust path with forward slashes as separators. Parameters ---------- - path : string - a directory path obtained from dialogue or script parameter + path : str + A directory path Returns ------- - string - a more robust path with forward slashes as separators + str + A directory path with forward slashes as separators """ - fixed_path = str(path).replace("\\", "/") # fixed_path = fixed_path + "/" @@ -71,169 +81,238 @@ def fix_ij_dirs(path): def open_image_with_BF(path_to_file): - """ use Bio-Formats to opens the first image from an image file path + """Open the first image from a file using Bio-Formats. + + This function utilizes Bio-Formats to open an image file and returns + the first image contained within the file. The image is opened in + grayscale mode with autoscaling enabled. Parameters ---------- - path_to_file : string - path to the image file + path_to_file : str + The file path to the image file to be opened. Returns ------- ImagePlus - the first imp stored in a give file + The first image contained in the specified file. """ + # Create an ImporterOptions object for configuring the import process options = ImporterOptions() + # Set the color mode to grayscale options.setColorMode(ImporterOptions.COLOR_MODE_GRAYSCALE) + # Enable autoscaling for the image options.setAutoscale(True) + # Set the file path for the image to be opened options.setId(path_to_file) - imps = BF.openImagePlus(options) # is an array of ImagePlus + # Open the image(s) using Bio-Formats and store them in an array + imps = BF.openImagePlus(options) + # Return the first image in the array return imps[0] def fix_BF_czi_imagetitle(imp): - image_title = os.path.basename( imp.getShortTitle() ) + """ + Fix the title of an image read using the bio-formats importer. + + The title is modified to remove the ".czi" extension and replace + spaces with underscores. + + Parameters + ---------- + imp : ij.ImagePlus + The image to be processed. + + Returns + ------- + str + The modified title of the image. + """ + # Get the short title of the image (without path) + image_title = os.path.basename(imp.getShortTitle()) + # Remove the ".czi" extension image_title = image_title.replace(".czi", "") + # Replace spaces with underscores image_title = image_title.replace(" ", "_") + # Remove any double underscores image_title = image_title.replace("_-_", "") + # Remove any double underscores image_title = image_title.replace("__", "_") + # Remove any "#" characters image_title = image_title.replace("#", "Series") return image_title def clear_ij_roi_manager(rm): - """delete all ROIs from the RoiManager + """ + Clear all ROIs from the RoiManager. Parameters ---------- - rm : RoiManager + rm : ij.plugin.frame.RoiManager a reference of the IJ-RoiManager """ + # Run the "reset" command in the RoiManager to clear all ROIs rm.runCommand('reset') def get_threshold_from_method(imp, channel, method): - """returns the threshold value of chosen IJ AutoThreshold method in desired channel + """Get the threshold value of chosen IJ AutoThreshold method in desired channel. Parameters ---------- imp : ImagePlus - the imp from which to get the threshold value - channel : integer - the channel in which to get the treshold - method : string - the AutoThreshold method to use + The imp from which to get the threshold value. + channel : int + The channel in which to get the threshold. + method : str + The AutoThreshold method to use. Returns ------- list - the upper and the lower threshold (integer values) + A list containing the upper and the lower threshold (integer values). """ + # Set the channel of the imp to the desired channel imp.setC(channel) # starts at 1 + # Get the processor of the imp ip = imp.getProcessor() + # Set the AutoThreshold method to the desired method ip.setAutoThreshold(method + " dark") + # Get the minimum and maximum threshold values lower_thr = ip.getMinThreshold() upper_thr = ip.getMaxThreshold() + # Reset the threshold so that the imp is not affected by this function ip.resetThreshold() - return lower_thr, upper_thr + return [lower_thr, upper_thr] def measure_in_all_rois( imp, channel, rm ): - """measures in all ROIS on a given channel of imp all parameters that are set in IJ "Set Measurements" + """Measures in all ROIs on a given channel of imp all parameters that are set in IJ "Set Measurements". + + This function takes an ImagePlus (imp), a channel (integer, starts at 1), and a RoiManager (rm) as + parameters. It then sets the channel of the imp to the desired channel, deselects all ROIs in the + RoiManager, and measures in all ROIs of the RoiManager on the channel of the imp. The parameters + that are measured are the ones that are set in IJ "Set Measurements". Parameters ---------- - imp : ImagePlus + imp : ij.ImagePlus the imp to measure on - channel : integer + channel : int the channel to measure in. starts at 1. - rm : RoiManager + rm : ij.plugin.frame.RoiManager a reference of the IJ-RoiManager """ + # Set the channel of the imp to the desired channel imp.setC(channel) + # Deselect all ROIs in the RoiManager rm.runCommand(imp,"Deselect") + # Measure in all ROIs of the RoiManager on the channel of the imp rm.runCommand(imp,"Measure") -def change_all_roi_color( rm, color ): - """change the color of all ROIs in the RoiManager +def change_all_roi_color(rm, color): + """ + Change the color of all ROIs in the RoiManager. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - color : string - the desired color. e.g. "green", "red", "yellow", "magenta" ... + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + color : str + The desired color, e.g., "green", "red", "yellow", "magenta". + + Returns + ------- + None """ - number_of_rois = rm.getCount() - for roi in range( number_of_rois ): - rm.select(roi) - rm.runCommand("Set Color", color) + # Select all ROIs in the RoiManager + rm.setSelectedIndexes(range(rm.getCount())) + # Change the color of all ROIs to the desired color + rm.runCommand("Set Color", color) + # Deselect all ROIs again to finalize changes + rm.runCommand("Deselect") -def change_subset_roi_color( rm, selected_rois, color ): - """change the color of selected ROIs in the RoiManager + +def change_subset_roi_color(rm, selected_rois, color): + """ + Change the color of selected ROIs in the RoiManager. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - selected_rois : array - ROIs in the RoiManager to change - color : string - the desired color. e.g. "green", "red", "yellow", "magenta" ... + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + selected_rois : list of int + Indices of ROIs in the RoiManager to change. + color : str + The desired color, e.g., "green", "red", "yellow", "magenta", etc. """ + # Deselect all currently selected ROIs in the RoiManager rm.runCommand("Deselect") + # Select the specified ROIs by their indices rm.setSelectedIndexes(selected_rois) + # Change the color of the selected ROIs to the specified color rm.runCommand("Set Color", color) + # Deselect all ROIs again to finalize changes rm.runCommand("Deselect") def show_all_rois_on_image(rm, imp): - """shows all ROIs in the ROiManager on imp + """ + Display all ROIs on the given image using the ROI Manager. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - imp : ImagePlus - the imp on which to show the ROIs + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + imp : ij.ImagePlus + The image on which to display the ROIs. """ + # Show the image in the ImageJ window imp.show() - rm.runCommand(imp,"Show All") + # Use the ROI Manager to show all ROIs on the image + rm.runCommand(imp, "Show All") def save_all_rois(rm, target): - """save all ROIs in the RoiManager as zip to target path + """Save all ROIs in the RoiManager as a zip file to the given target path. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - target : string - the path in to store the ROIs. e.g. /my-images/resulting_rois.zip + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + target : str + The file path in which to save the ROIs, e.g., /my-images/resulting_rois.zip """ + # Save all ROIs in the RoiManager to the given target path rm.runCommand("Save", target) -def save_selected_rois( rm, selected_rois, target ): - """save selected ROIs in the RoiManager as zip to target path +def save_selected_rois(rm, selected_rois, target): + """ + Save selected ROIs in the RoiManager as a zip file to the given target path. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - selected_rois : array - ROIs in the RoiManager to save - target : string - the path in to store the ROIs. e.g. /my-images/resulting_rois_subset.zip + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + selected_rois : list of int + Indices of ROIs in the RoiManager to save. + target : str + The file path in which to save the ROIs, e.g., /my-images/resulting_rois_subset.zip """ + # Deselect all currently selected ROIs in the RoiManager to ensure a clean start rm.runCommand("Deselect") + # Select the specified ROIs by their indices rm.setSelectedIndexes(selected_rois) + # Save the selected ROIs to the given target path as a zip file rm.runCommand("save selected", target) + # Deselect all ROIs again to finalize changes and maintain a clean state rm.runCommand("Deselect") @@ -243,19 +322,19 @@ def select_positive_fibers( imp, channel, rm, min_intensity ): Parameters ---------- - imp : ImagePlus - the imp on which to measure - channel : integer - the channel on which to measure. starts at 1 - rm : RoiManager - a reference of the IJ-RoiManager - min_intensity : integer - the selection criterion (here: intensity threshold) - + imp : ij.ImagePlus + The ImagePlus on which to measure. + channel : int + The channel on which to measure. starts at 1. + rm : ij.plugin.frame.RoiManager + A reference of the IJ-RoiManager. + min_intensity : int + The selection criterion (here: intensity threshold). + Returns ------- - array - a selection of ROIs which passed the selection criterion (are above the threshold) + list + A selection of ROIs which passed the selection criterion (are above the threshold). """ imp.setC(channel) all_rois = rm.getRoisAsArray() @@ -266,33 +345,34 @@ def select_positive_fibers( imp, channel, rm, min_intensity ): if stats.mean > min_intensity: selected_rois.append(i) - return selected_rois + return selected_rois -def open_rois_from_zip( rm, path ): - """open RoiManager ROIs from zip and adds them to the RoiManager +def open_rois_from_zip(rm, path): + """ + Open ROIs from a zip file and add them to the RoiManager. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - path : string - path to the ROI zip file + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + path : str + The file path to the ROI zip file. """ rm.runCommand("Open", path) def preset_results_column( rt, column, value): - """pre-set all rows in given column of the IJ-ResultsTable with desired value + """Pre-set all rows in given column of the IJ-ResultsTable with desired value. Parameters ---------- - rt : ResultsTable - a reference of the IJ-ResultsTable - column : string - the desired column. will be created if it does not yet exist - value : string or float or integer - the value to be set + rt : ij.measure.ResultsTable + A reference of the IJ-ResultsTable + column : str + The desired column. Will be created if it does not yet exist + value : str or float or int + The value to be set """ for i in range( rt.size() ): rt.setValue(column, i, value) @@ -300,46 +380,52 @@ def preset_results_column( rt, column, value): rt.show("Results") -def add_results( rt, column, row, value ): - """adds a value in desired rows of a given column +def add_results(rt, column, row, value): + """Add a value in specified rows of a given column. Parameters ---------- - rt : ResultsTable - a reference of the IJ-ResultsTable - column : string - the column in which to add the values - row : array - the row numbers in which too add the values. - value : string or float or integer - the value to be set + rt : ij.measure.ResultsTable + A reference to the IJ-ResultsTable. + column : str + The column in which to add the values. + row : list of int + The row numbers in which to add the values. + value : str, float, or int + The value to be set. """ - for i in range( len( row ) ): + # Iterate over each row index in the row list + for i in range(len(row)): + # Set the specified value in the given column and row rt.setValue(column, row[i], value) + # Display the updated ResultsTable rt.show("Results") -def enhance_contrast( imp ): - """use "Auto" Contrast & Brightness settings in each channel of imp +def enhance_contrast(imp): + """Use "Auto" Contrast & Brightness settings in each channel of imp. Parameters ---------- - imp : ImagePlus - the imp on which to change C&B + imp : ij.ImagePlus + The imp on which to change C&B. """ - for channel in range( imp.getDimensions()[2] ): - imp.setC(channel + 1) # IJ channels start at 1 + for channel in range(imp.getDimensions()[2]): + imp.setC(channel + 1) # IJ channels start at 1 IJ.run(imp, "Enhance Contrast", "saturated=0.35") def renumber_rois(rm): - """rename all ROIs in the RoiManager according to their number + """Rename all ROIs in the RoiManager according to their number. + + The RoiManager uses 0-based indexing, so the first ROI is at index 0. + This function renames each ROI with its index (starting from 1). Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. """ number_of_rois = rm.getCount() for roi in range( number_of_rois ): @@ -347,18 +433,28 @@ def renumber_rois(rm): def setup_defined_ij(rm, rt): - """set up a clean and defined Fiji user environment + """Set up a clean and defined Fiji user environment. + + This function configures the ImageJ environment to a predefined state by + resetting the RoiManager and ResultsTable, and clearing the IJ log. Parameters ---------- - rm : RoiManager - a reference of the IJ-RoiManager - rt : ResultsTable - a reference of the IJ-ResultsTable + rm : ij.plugin.frame.RoiManager + A reference to the IJ-RoiManager. + rt : ij.measure.ResultsTable + A reference to the IJ-ResultsTable. """ + # Configure IJ options to a predefined state fix_ij_options() + + # Reset the RoiManager to remove all existing ROIs rm.runCommand('reset') + + # Reset the ResultsTable to clear all previous results rt.reset() + + # Clear the IJ log to ensure a fresh output window IJ.log("\\Clear") @@ -412,7 +508,7 @@ for index, fiber_channel in enumerate(all_fiber_channels): preset_results_column( rt, "channel " + str(fiber_channel) + " positive (" + roi_colors[index] + ")", "NO" ) if all_min_fiber_intensities[index] == 0: all_min_fiber_intensities[index] = get_threshold_from_method(raw, fiber_channel, "Mean")[0] - IJ.log( "fiber channel " + str(fiber_channel) + " intensity threshold: " + str(all_min_fiber_intensities[index]) ) + IJ.log( "fiber channel " + str(fiber_channel) + " intensity threshold: " + str(all_min_fiber_intensities[index]) ) positive_fibers = select_positive_fibers( raw, fiber_channel, rm, all_min_fiber_intensities[index] ) all_fiber_subsets[index] = positive_fibers if len(positive_fibers) > 0: -- GitLab