MoMA tutorial preprocessing - nimwegenLab/moma GitHub Wiki
Note
This is part 1 of the MoMA tutorial. It explains how to preprocess data for subsequent analysis with MoMA. Please refer to the tutorial introduction for a general overview of the analysis workflow.
This section assumes that you have correctly setup the preprocessing software on your system following these installation instructions.
- Overview
- Generating the template image
- Generating the template configuration
- Configuring the preprocessing bash script
- Running the preprocessing
- Overview of the preprocessed data
The preprocessing performs the following steps on the full frame images in the OME-TIFF stack that was captured with MicroManager:
- It registers the frames from each position to compensate image drift/shifting between frames.
- It normalizes image intensity of the phase contrast (PhC) images to improve predictions of the U-Net model.
- It detects the location the GLs in the image, using template matching.
- It splits the full frame TIFF stack into smaller TIFF stacks containing one growth lane each (GL). These stacks are referred to as GL ROIs in the following sections (ROI: region of interest).
To preprocess your data you have to perform the following steps:
- Setup the path to the preprocessing module in your .bashrc.
- Create a template image to detect GLs.
- Create a template configuration file for your template image. Template image and configuration are used to locate the GL ROIs in the full frame image.
- Configure the preprocessing bash script for your dataset.
- Run the bash script to preprocess your data.
We will go through these steps in the following sections.
The template image and configuration are used to locate the GL ROIs inside the full frame image. We start by creating a template image ...
-
Launch MicroManager.
-
Open the OME-TIFF stack in MicroManager as virtual stack (click on the screenshots to enlarge):
- Step 1: Open the menu "File > Open (Virtual)...".
- Step 2: Select image folder (or the first OME TIF file) to open the dataset.
- Step 3: View with opened image stack. Use the slider of in the phase contrast histogram (top) to adjust image saturation for better channel visibility.
- Use the sliders p and t under the image to select a position and time steps, which contains 3 adjacent, suitable GLs. We will use a crop of this region to create the template image. A suitable frame is one, which has good focus and similar appearance to the other positions and frames in the dataset. Ideally, the GLs in the template image crop should be empty, but template matching also works well with filled GLs (or a mix of filled/non-filled GLs). After you identified a suitable position and frame, duplicate it to a new image and save it.
- Step 1: Zoom into image for better using either '+' key or the magnifying glass of the ImageJ window.
- Step 2: Open the duplicate dialog (Ctrl+Shift+D) and enter channel 1 (the PhC channel) and the frame of interest.
- Step 3: Save the duplicated image to the template folder (we recommend using the prefix
TEMPLATE_SOURCE_
).
- Rotate the duplicated frame (referred to from here on as template source) in counter clockwise direction (i.e. negative angle) and create a crop from the image, which will be used as template image.
Note
Note down the rotation angle of the template source, which is needed when editing up the preprocessing bash-script (see below).
- Step 1: Open the image rotation dialog of ImageJ with the "Image > Transform > Rotate..." menu.
- Step 2: Enable Preview and select Bicubic interpolation. Rotate the image in negative direction so that the main channel of the mother machine is in vertical direction. You can adjust the number of Grid Lines to aid you in aligning the main channel. The rotation angle must be precise to within 0.1 degrees.

- Step 3: Activate the rectangular selection tool in the ImageJ window and drag a rectangle selection on the rotated image, to select the region for the template image.

- Step 4: Hit Ctrl+Shift+X to crop the image to the selected region and save it under a different name (we recommend using the prefix
TEMPLATE_IMAGE_
). Do not overwrite the template source image. It is still needed for measuring the distance between GLs (see below).
This section explains how create a template configuration file. The template configuration is a JSON file, which specifies where GLs are located in the template image. You can find more information about its parameters here. The reference file is located here:
<ANALYSIS_DIRECTORY>/TEMPLATE/template_config.json
To generate a template configuration file follow these steps:
-
Create a new config file in your template folder and copy the following to it:
{ "description": "", "gl_regions": [ { "first_gl_position_from_top": , "gl_spacing_vertical": , "horizontal_range": [ , ], "gl_exit_orientation": "" }, { "first_gl_position_from_top": , "gl_spacing_vertical": , "horizontal_range": [ , ], "gl_exit_orientation": "" } ], "name": "", "pixel_size_micron": 1.0, "template_image_path": "" }
-
Add the path to the template image from above in the field template_image_path:
-
Measure the distance between GLs in the template source image and enter it into the template configuration:
- Step 1: Open the template source image and activate the line selection tool in the ImageJ window.
- Step 2: Draw a line selection from the first to the last GL in the image.

- Step 3: Refine start and endpoints of the line so that they are centered on their respective GL. This requires switching in the ImageJ window between the Zoom tool (zoom in: left mouse-click; zoom out: right mouse-click) and the line selection tool for adjustments (hover over an end-point and drag it with the left mouse-button). start point:


- Step 4: Measure the line length in pixels by hitting Ctrl+Shift+M (in this case it is 1920.3).
- Step 5: Calculate average space between the GLs by dividing the previous value by the number of spaces between GLs spanned by the line. Enter the value into the field gl_spacing_vertical for both gl_regions. In this case: 1920.3/18=106.683 (keep 3 decimals for sufficient precision).
- Measure the values of first_gl_position_from_top and horizontal_range for the left gl_region and add them to the template configuration. This is done by locating the cursor at the respective position, while holding the Alt-key. By holding the Alt-key ImageJ will report the cursor position in pixels in the ImageJ window.
Warning
Leave a margin of at least 20 pixel at the closed end of the GL (i.e. beyond the last possible position of the mother cell). This is needed for the U-Net model to perform well when segmenting mother cells.
-
Repeat the previous steps for the second/right gl_region.
-
Set the orientation of the GL exits for both gl_regions in gl_exit_orientation. In the left region the GLs open towards the right so we set gl_exit_orientation to right. For the right region they open towards the left, so we set gl_exit_orientation to left.
To create the bash script, we start from this template:
#!/bin/bash
PREPROC_DIR_TPL=""
RAW_PATH=""
FLATFIELD_PATH=""
POS_NAMES=()
GL_DETECTION_TEMPLATE_PATH=""
ROTATION=
IMAGE_REGISTRATION_METHOD=1
FRAMES_TO_IGNORE=()
NORMALIZATION_CONFIG_PATH="true"
NORMALIZATION_REGION_OFFSET=120
#### DO NOT EDIT BELOW THIS LINE ####
ROI_BOUNDARY_OFFSET_AT_MOTHER_CELL=0
# generate an array of same length as position array, with every element containing the ROTATION scalar value
ROTATIONS=$ROTATION
for f in `seq ${#POS_NAMES[*]}`
do
f=`echo $f - 1 | bc`
ROTATIONS[$f]=$ROTATION
done
source mm_dispatch_preprocessing.sh
mm_dispatch_preprocessing
We adapt the template in order to process positions Pos1 and Pos7 of the experiment and save the preprocessed data to the folder:
<ANALYSIS_DIRECTORY>/preprocessed_data
This is the adapted bash-script (located at <ANALYSIS_DIRECTORY>/process_positions.sh
):
#!/bin/bash
PREPROC_DIR_TPL="<ANALYSIS_DIRECTORY>/preprocessed_data/mmpreproc_%s/"
RAW_PATH="<PATH_TO_FIRST_OME_TIF_MEASUREMENT_FILE>"
FLATFIELD_PATH="<PATH_TO_FIRST_OME_TIF_FLATFIELD_FILE>"
GL_DETECTION_TEMPLATE_PATH="<ANALYSIS_DIRECTORY>/TEMPLATE/template_config.json"
POS_NAMES=(Pos0 Pos7)
TMAX=5
ROTATION=90.0
IMAGE_REGISTRATION_METHOD=1
FRAMES_TO_IGNORE=()
NORMALIZATION_CONFIG_PATH="true"
NORMALIZATION_REGION_OFFSET=120
#### DO NOT EDIT BELOW THIS LINE ####
ROI_BOUNDARY_OFFSET_AT_MOTHER_CELL=0
# generate an array of same length as position array, with every element containing the ROTATION scalar value
ROTATIONS=$ROTATION
for f in `seq ${#POS_NAMES[*]}`
do
f=`echo $f - 1 | bc`
ROTATIONS[$f]=$ROTATION
done
source mm_dispatch_preprocessing.sh
mm_dispatch_preprocessing
The parameters that were changed/added above are:
- PREPROC_DIR_TPL: Path to the output folder where the preprocessed data will be stored.
Warning
You have to append /mmpreproc\_%s/
to the desired output folder. This is for legacy reasons.
-
RAW_PATH: Path to the first TIFF-file of the OME-TIFF stack.
-
FLATFIELD_PATH: Path to the first TIFF-file in the OME-TIFF stack containing the corresponding flat-field images.
-
GL_DETECTION_TEMPLATE_PATH: This is the path to the template configuration file, that we created earlier.
-
POS_NAMES: This array defines that names of the positions in the OME-TIFF stack that will be processed. The name of a position can be obtained from MicroManager.

-
TMAX: Setting this value to 5 preprocesses only the first 5 frames of the experiment. This is useful for testing the preprocessing script before running the actual preprocessing or if there were experimental issues at later time points that you want to ignore. Once you are confident that the configuration works as expected, comment this value out (e.g. by adding a #, so: #TMAX=5) or set it to the desired value.
-
ROTATION: This is the rotation angle of the image that was determine in the section Generating the template image.
Warning
You have to enter the negative value of the angle reported by ImageJ, because ImageJ uses a different convention for the rotation angle than the preprocessing code. Hence we enter 90.0 instead of the -90.0 that we determined before.
Note
For an explanation of the remaining parameters please see here.
Open a terminal window and navigate to the location of the bash script. If you created a new file from scratch you will have to first make it executable using the command chmod +x process_positions.sh
. Then launch it (./process_positions.sh
).

You can monitor the progress of the preprocessing of each position by running:
watch -n1 'squeue -u $USER'
Here will give an overview of the data that the preprocessing outputs. It is located here:
<ANALYSIS_DIRECTORY>/preprocessed_data
This is a screenshot of that folder:

The index images \*\_GL_index_initial.tif
and \*\_GL_index_final.tif
indicate the GL ROIs that were detected and stored. They show their bounding boxes overlaid on the first and last frames of the processed frame range:


Note
GL ROIs are only stored if they lie inside the full frame image for all time steps. GL ROIs that (partially) move outside of the full frame due to image drift/shift are discarded (this can happen in particular for GLs located at the image border).
The GL ROIs of each position are stored in the folders Pos\*
in separate GL subfolders:

Each GL folder contains three files:
- The minimum and maximum values used for normalization are stored in:
20211026_VNG1040_AB6min_2h_1\_MMStack_Pos0_GL3.csv
. - A kymograph of the GL vertical center line is stored in:
20211026_VNG1040_AB6min_2h_1\_MMStack_Pos0_GL3_kymo.tif
. - The GL ROI is contained in:
20211026_VNG1040_AB6min_2h_1\_MMStack_Pos0_GL3.tif
.
Screenshots of the first frame in the GL ROI stack | Screenshots of PhC (left) and FL (right) kymograph images |
---|---|
Each FL channel in the input image is output twice: The first duplicate is the flatfield-corrected signal; the second is the unaltered signal. ![]() ![]() ![]() |
Again the FL channel is duplicated for the flat-field correct and non-corrected signal. ![]() ![]() ![]() |
During preprocessing the input images are normalized. Information on the normalization can be found in the respective normalization log-folder of each position:

Screenshot of region_indicator_images\_\_pos_0.tif
|
Screenshots of intensity profiles |
---|---|
These images indicate the regions, which were used for the normalization of each GL region (red: start of horizontal region; green: end of horizontal region). These images can also helpful for checking if the image registration (i.e. compensating image drift) worked correctly. If so, the positions of the GLs should not change between frames. ![]() |
intensity_profile\_\_pos_0\_\_region_0.tif and intensity_profile\_\_pos_0\_\_region_1.tif show the intensity profile that was obtained from the normalization regions in region_indicator_images\_\_pos_0.tif . They help in debugging problems with the intensity normalization. ![]() ![]() |
The files in the log folder are intended for debugging. For example, the bash-script slurm_Pos0.sh
is the script was run to process Pos0
. The slurm_Pos0.log
contains the log-output from that bash script, in particular information on the preprocessing settings and the shift that was measured during image registration..