metadata-qupath

A QuPath extension for extracting cohort-wide slide metadata whose scanner-metadata block fails on 100% of images because of a single Groovy type error — the most-starred repository in this cluster, publicly readable, and two characters away from also having a valid licence.

Purpose

Walk a QuPath project and write one CSV row per slide: pixel size, dimensions, pyramid structure, scanner, magnification, scan date. This is the tool Known gap 1 has been asking for, which is why it is status: active despite the defects below — the need is real and the fix is small.

Public repository, 5 stars, last pushed 2025-06-02. Read the whole of Slide Metadata Extraction before running it; that page carries the analysis and this one carries the repository facts.

Data used

A 107-row internal H&E control series (kontrol*.svs, from an E:/KONTROLHE_2025/ staining control set) is committed as project.qpproj plus data/1..107/. Those are QC slides, not patient cases — the .qpproj convention on QuPath Tooling is not breached. They do carry the institution’s drive layout and scan-batch folder names, which is a reason not to quote example paths from this repository onto a published page.

Methods

Groovy scripts pasted into QuPath’s Script Editor, plus R/Python/SQL “integration examples”.

What works: pixel_width_um/pixel_height_um from getPixelCalibration(), image dimensions, pyramid levels and factor, file size, server type, and — usefully for De-identificationhas_label_image and has_macro_image.

What fails, on every image: the entire scanner block. server.getMetadata() returns an ImageServerMetadata object, and the script iterates it as if it were a map with a two-argument closure, which is a type error. scanner, scanner_type, scanscope_id, apparent_magnification, mpp, scan_date, icc_profile and the compression fields are therefore absent from the committed output entirely. The error is logged 107 times and the summary still reports Successfully processed: 107 / Failed: 107 / Success rate: 100%, because the success counter increments unconditionally.

The substitute is worse than the gap. Unable to read AppMag, it computes estimated_magnification = round(0.25 / pixel_width_um * 40), producing 38× for 55 slides. No scanner has a 38× objective; the same slides read through OpenSlide declare 40×. That derived number has since propagated into four pages of this wiki via PinkKidney — see Slide Metadata Extraction for the full trace, which is the most useful thing this reading produced.

Duplication and drift. QuPath_v03_Compatible.groovy and SimpleMetadataExtractor.groovy are byte-identical apart from line endings; QuPathExtensions/CohortWorkflow/CohortMetadataExtractor.groovy is a copy of the flat v06 script despite its name. scripts/MenuSetup.groovy is a zero-byte file, and the README tells users to copy MenuSetup.groovy from the repository.

Documented features that do not exist. JSON export is declared in config.json, the menu dialog and qupath_menu_integration.md, and the R and Python helpers both expect a cohort_metadata.json — no script writes one; the CHANGELOG records that the JSON libraries were removed and the docs were not updated. config.json itself is never read by anything. Execution-time reporting prints System.currentTimeMillis() - 0, i.e. epoch seconds.

The licence is two characters from valid. LICENSE is a canonical MIT text whose copyright line reads Copyright (c) 2025 [Serdar Balcı] — the template placeholder brackets were never removed, which is why GitHub reports no licence on a public repository. The file is byte-identical to sectra-qupath/LICENSE, so this is a template, not a one-off. The README also points its clone path, citation block and issue links at sbalci/qupath-cohort-extractor, a repository name that does not match this one, and the citation’s author field is still [Your Name/Institution].

Current state / open questions

Active as the intended solution to Known gap 1, blocked on a small fix. In order: repair the ImageServerMetadata iteration so the scanner fields populate; delete estimated_magnification or rename it so nothing downstream mistakes it for a reading; make the summary’s failure count mean something; remove the brackets from the licence.

Until then the working route is the Python one — helpers/svs_info_extraction/ in Digital Pathology Drafts — which already returns every field this tool is missing.

  • Does anything besides PinkKidney consume estimated_magnification? [unverified]
  • Is the 5-star audience running this and getting empty scanner columns? Public and unlicensed, so there is no way to tell and no licence permitting them to fix it.

Related: Slide Metadata Extraction — the method page this repository is the worked example for, including the derived-versus-measured trap. Related: PinkKidney — inherited the computed magnification and built a vendor column on it. Related: QuPath Tooling — the index this belongs in. Related: Digital Pathology Drafts — the umbrella repository this sits in as a submodule, and where the Python extractor that actually works lives.

Derived from: repository source read 2026-07-26 — scripts/QuPath_v06_Compatible.groovy, scripts/QuPath_v04_Compatible.groovy, scripts/QuPath_v03_Compatible.groovy, scripts/SimpleMetadataExtractor.groovy, scripts/MenuSetup.groovy, QuPathExtensions/CohortWorkflow/, cohort_metadata/cohort_metadata_v06.csv, cohort_metadata/detailed_summary_v06.txt, cohort_metadata/processing_log.txt, LICENSE, README.md, CHANGELOG.md, config.json, qupath_menu_integration.md; GitHub API for visibility, stars and licence state, read 2026-07-26.