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