Skip to content

About

A collection of Groovy scripts I use in QuPath for daily analysis tasks

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

QuPath Daily Scripts

A collection of QuPath Groovy scripts used for daily image analysis tasks, including measurement extraction, cell detection, annotation export, and spatial analysis.


Folder Overview

basic_measurements/

Scripts for calculating or cleaning object measurements.

  • add_circularity_and_solidity.groovy
  • add_imagej_shape_measurements.groovy
  • add_intensity_measurements.groovy
  • add_shape_measurements.groovy
  • clean_measurement_list.groovy

benchmarking/

Scripts for comparing segmentation results or evaluating model performance.

  • segmentation_metrics.groovy

cell_analysis/

Scripts for generating and analyzing cell objects.

  • create_cells_from_annotation_hierarchy.groovy

classification/

Scripts for classifying objects based on morphology or other measurements.

  • classify_detections_shape_vs_round.groovy

cpsam_training/

Python toolkit for fine-tuning CellPose-SAM on custom annotated data. Unlike the Groovy scripts, this is used outside QuPath in a terminal or Jupyter notebook.

Copy the training_template/ folder to your experiment project directory, then follow the workflow in the notebook, or see training_template/README.md for a step-by-step CLI-only walkthrough (no notebook required):

  1. Export annotated pairs from QuPath using export_annotations/cellpose_training/
  2. Place exported _img.tif / _mask.tif pairs in data/ (flat or one subfolder per dataset)
  3. Split the data using the Split data cell in the notebook, or run python split_data.py data/ from a terminal
  4. Train via notebook (train_cpsam.ipynb) or CLI (python train_cpsam.py --model_name <name>)
  5. The trained model is saved to models/<model_name> inside your copied folder

Requires the cellpose-sam conda environment.

instanseg_training/

Python helper for training InstanSeg on data exported from QuPath, used outside QuPath like cpsam_training/.

  • pack_instanseg_dataset.py: packs the pairs from export_annotations/instanseg_training/ into InstanSeg's <name>_dataset.pth.

    • It reads the channel names and pixel size from each OME-TIFF and relabels the masks.
    • It splits Train/Validation/Test by source image. Use --split-csv for your own split, e.g. by patient.
    • Train with -d_p <export folder> -data <name> -source "[<name>]".
  • training_template/split_data.py — creates reproducible train/test/eval splits; auto-detects flat or multi-dataset layout

  • training_template/train_cpsam.ipynb — step-by-step notebook with inline loss plot

  • training_template/train_cpsam.py — CLI equivalent; saves loss curve as PNG and CSV

detection_extensions/

Scripts for cell detection using external models and extensions (e.g., StarDist, Cellpose, ImageJ).

  • cpsam_detection_live_cell_imaging.groovy — Requires QuPath 0.5.0 + qupath-extension-cellpose 0.9.3. In QuPath 0.7.0, the extension does not correctly use the timepoint from the annotation ROI when exporting image tiles, causing all frames to be detected using frame 0 data. This is a known regression; do not run this script in QuPath 0.7.0 until a fix is confirmed.
  • instanseg_detection.groovy: InstanSeg detection with a custom or downloaded model folder (rdf.yaml + instanseg.pt).
    • Input channels are given by name or index, and the output channel is selectable (e.g. cells only from a nuclei+cells model).
    • It runs in the region annotations of a class, or in the selected annotations, or on the whole image.
    • Requires qupath-extension-instanseg 0.1.6 (tested in QuPath 0.7.0).
  • imagej_threshold_detection_on_annotations.groovy — creates threshold-based annotation objects using an ImageJ threshold method, keeping only regions overlapping with target annotations
  • stardist_fluorescence_cell_detection.groovy
  • stardist_fluorescence_cell_detection_with_preprocessing.groovy
  • stardist_fluorescence_cell_detection_zstack.groovy
  • stardist_fluorescence_detection_on_annotations.groovy

export_annotations/

Scripts for exporting annotations, masks, or training labels.

  • cellpose_training/
    • export_labels_for_cellpose.groovy
    • export_labels_for_cellpose_all_zslices_and_timepoints.groovy
    • export_labels_for_cellpose_current_zslice_and_timepoint.groovy
    • export_labels_for_cellpose_training_regions.groovy — exports one image/mask pair per "Training"-classified region annotation, instance-labeling only the objects inside each region (2D only)
  • instanseg_training/
    • export_labels_for_instanseg_training_regions.groovy: the InstanSeg version of the Cellpose training-regions export.
      • Writes the image as OME-TIFF, so the channel names and pixel size are kept.
      • Channels are chosen by name.
      • Labels can come from annotations or detections of one or more classes.
      • Large regions can be cut into tiles that lie fully inside them.
      • Pack the output with instanseg_training/pack_instanseg_dataset.py.
  • geojson/
    • export_geojson.groovy
  • individualized_annotations/
    • export_binary_mask_bounding_boxes.groovy
    • export_binary_mask_multichannel.groovy
  • semantic_training/
    • export_semantic_labels_regions.groovy — multi-class label export per unclassified-annotation region, single plane
    • export_semantic_labels_zstack.groovy — single-class label export across the whole image (all z-slices/timepoints), with an optional border/boundary label to separate touching instances downstream

import_annotations/

Scripts for importing external data (e.g. model predictions) as annotations.

  • import_predicted_labels_as_annotations.groovy — imports a prediction/label image as annotations for curation; per-class threshold-based ROI extraction via ImageJ, auto-detects XY downsample mismatches, and skips images that already have curated annotations of the target class(es)

name_and_format_utilities/

Scripts for renaming or reformatting project entries.

  • rename_project_images.groovy — renames project entries by combining the parent folder name and filename, stripping the file extension and a configurable suffix

object_filtering/

Scripts for removing objects that fail a measurement-based or spatial criterion.

  • filter_detections_by_measurement.groovy — removes detections whose value for a given measurement (e.g. Circularity) falls outside a configurable threshold
  • remove_annotations_at_image_boundaries.groovy — removes objects whose ROIs touch or are within a set distance of an annotation boundary
  • remove_detections_at_image_boundaries.groovy — detection-native counterpart to the above; removes detections touching or within a set distance of the image border, without needing an annotation<->detection conversion

skeleton_analysis/

Scripts for analyzing skeletonized structures via ImageJ.

  • analyze_skeleton.groovy

spatial_relationships/

Scripts for computing distances, relationships, or reference-based measurements.

  • add_centroid_relative_to_parent_rectangle.groovy — adds each detection's centroid (calibrated) using its rectangle parent's top-left corner as the origin; detections with a non-rectangle parent or no parent are skipped
  • add_reference_centroid_xy.groovy
  • distance_to_nearest_objects.groovy
  • is_in_object.groovy
  • peripheral_overlap_with_class.groovy — for each detection, measures the % of a band along its boundary (configurable inner/outer width, core excluded) covered by objects of a given class, e.g. objects created from a thresholder

utilities/

General-purpose helper scripts for managing channels, annotations, or calibration.

  • annotations_to_detections.groovy
  • change_channel_names.groovy
  • change_channel_names_nchannel_variable.groovy — sets channel names for images with either 3 or 4 channels
  • detections_to_annotations.groovy
  • expand_or_erode_annotations.groovy — replaces annotations with a dilated (positive) or eroded (negative) version, keeping the original classification and parent nesting; by default respects the parent annotation's boundary (or image bounds, if none) so erosion doesn't recede from it and dilation doesn't cross it
  • fill_annotations.groovy
  • prepend_folder_to_entry_name.groovy — prepends the parent folder name to each project entry name
  • remove_annotations.groovy
  • remove_detections.groovy
  • set_pixel_calibration.groovy
  • set_project_classes.groovy — sets the available classification classes for the project
  • square_annotation_from_point.groovy — converts point annotations into square annotations centered on each point, keeping the original classification (size in pixels, unaffected by calibration)

Usage

These scripts can be run directly within QuPath's Script Editor:

  1. Open QuPath → Automate → Show script editor
  2. Load the desired .groovy file.
  3. Adjust the parameters in the configuration block at the top of the script.
  4. Run (Ctrl/Cmd + R) or Run for project.

Configuration convention

All scripts expose their parameters in a clearly marked block at the top:

// ── Configuration ────────────────────────────────────────────────────────────
def targetClassName = "YOUR_CLASS_NAME"  // class name, null (all), or "" (unclassified)
// ─────────────────────────────────────────────────────────────────────────────

For scripts that filter by annotation class, targetClassName accepts three forms:

Value Behaviour
"ClassName" objects of that class only
null all objects, regardless of class
"" unclassified objects only

Detection scripts (StarDist, Cellpose) follow their own parameter convention and are not covered by this pattern.


Acknowledgments

These scripts build upon the QuPath scripting API and community examples.

About

A collection of Groovy scripts I use in QuPath for daily analysis tasks

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages