From 8f3a24508af3adb7c81ed893f1ec4ab1577d2094 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 19 May 2023 11:29:45 -0500 Subject: [PATCH 01/27] Switch to dev.jzarr:jzarr 0.3.7 This is the latest release based on https://github.com/zarr-developers/jzarr. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 31934b7e..b70d77a2 100644 --- a/build.gradle +++ b/build.gradle @@ -49,7 +49,7 @@ dependencies { implementation 'ome:formats-gpl:6.13.0' implementation 'info.picocli:picocli:4.6.1' implementation 'com.univocity:univocity-parsers:2.8.4' - implementation 'com.bc.zarr:jzarr:0.3.5' + implementation 'dev.zarr:jzarr:0.3.7' // implementation 'org.carlspring.cloud.aws:s3fs-nio:1.0-SNAPSHOT' // implementation 'io.nextflow:nxf-s3fs:1.1.0' implementation 'org.lasersonlab:s3fs:2.2.3' From 1737ceafec9a28e06095565c63dc0a0a13363a05 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 19 May 2023 11:31:09 -0500 Subject: [PATCH 02/27] Remove GS jzarr repos dev.jzarr:jzarr is in Maven central. --- build.gradle | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build.gradle b/build.gradle index b70d77a2..2067c5cf 100644 --- a/build.gradle +++ b/build.gradle @@ -21,18 +21,12 @@ repositories { maven { url 'https://repo.glencoesoftware.com/repository/n5-zarr-snapshots/' } - maven { - url 'https://repo.glencoesoftware.com/repository/jzarr-snapshots' - } maven { url 'https://artifacts.glencoesoftware.com/artifactory/ome.external' } maven { url 'https://artifacts.glencoesoftware.com/artifactory/scijava-thirdparty' } - maven { - url 'https://artifacts.glencoesoftware.com/artifactory/jzarr-releases' - } maven { name 'Unidata' url 'https://artifacts.glencoesoftware.com/artifactory/unidata-releases' From 08d28f9f11e9357fb63f6aed9aa46ad2b934f1c6 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 19 May 2023 11:44:41 -0500 Subject: [PATCH 03/27] Remove one more unneeded repository --- build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.gradle b/build.gradle index 2067c5cf..c2914076 100644 --- a/build.gradle +++ b/build.gradle @@ -18,9 +18,6 @@ repositories { maven { url 'https://artifacts.glencoesoftware.com/artifactory/ome.releases' } - maven { - url 'https://repo.glencoesoftware.com/repository/n5-zarr-snapshots/' - } maven { url 'https://artifacts.glencoesoftware.com/artifactory/ome.external' } From 94c8ead04eef217a98d7956e65cabb59c657f7a3 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 28 Jun 2023 11:02:15 -0500 Subject: [PATCH 04/27] Update to dev.jzarr:jzarr 0.4.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c2914076..52d809f0 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'ome:formats-gpl:6.13.0' implementation 'info.picocli:picocli:4.6.1' implementation 'com.univocity:univocity-parsers:2.8.4' - implementation 'dev.zarr:jzarr:0.3.7' + implementation 'dev.zarr:jzarr:0.4.0' // implementation 'org.carlspring.cloud.aws:s3fs-nio:1.0-SNAPSHOT' // implementation 'io.nextflow:nxf-s3fs:1.1.0' implementation 'org.lasersonlab:s3fs:2.2.3' From 415caf4a9ceabee2c0391b5da76a4718d5bd65ca Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 2 Aug 2023 11:57:22 -0500 Subject: [PATCH 05/27] Update opencv to 4.7.0-0 Fixes #210, see https://github.com/openpnp/opencv/compare/v3.4.2-0...v4.7.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 40e014e1..519bd138 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ dependencies { implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.4' - implementation 'org.openpnp:opencv:3.4.2-1' + implementation 'org.openpnp:opencv:4.7.0-0' implementation 'me.tongfei:progressbar:0.9.0' // https://github.com/junit-team/junit5-samples/blob/master/junit5-migration-gradle/build.gradle From be2ae920100ae547d78c0ad04c6cecfc5406ff81 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 13 Sep 2023 10:59:56 -0500 Subject: [PATCH 06/27] Add a separate README section describing each of the additional readers Fixes #214 --- README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dfaf92fe..250cb123 100644 --- a/README.md +++ b/README.md @@ -104,8 +104,9 @@ If the input file has multiple series, a subset of the series can be converted b bioformats2raw /path/to/file.scn /path/to/zarr-pyramid --series 0,2,3,4 -By default, four additional readers (MiraxReader, PyramidTiffReader, BioTekReader, and ND2PlateReader) are added to the beginning of Bio-Formats' list of reader classes. +By default, several additional readers are added to the beginning of Bio-Formats' list of reader classes. These readers are considered to be experimental and as a result only a limited range of input data is supported. +See the [Additional readers](#additional-readers) section below for more information. Any of these readers can be excluded with the `--extra-readers` option: @@ -308,6 +309,77 @@ This is particularly helpful if you do not have write permissions in the input d As of version 0.5.0, `.*.bfmemo` files are deleted at the end of conversion by default. We do not recommend keeping these files for normal conversions, but if they are needed for troubleshooting then the `--keep-memo-files` option can be used. +Additional readers +================== + +Readers are listed here in the order in which they appear on the reader list. + +PyramidTiffReader +----------------- + +Supports TIFF files that contain a pyramid, with one pyramid resolution per IFD. While this is different from standard pyramid OME-TIFF files, +any OME-XML stored in the first IFD's `ImageDescription` tag will be used to set the number of channels, timepoints, and Z sections. +If no OME-XML is present, each IFD is assumed to represent one channel at a particular resolution; multiple IFDs at the same resolution +therefore indicates multiple channels. + +MiraxReader +----------- + +Supports 3D HISTECH .mrxs data. Only the full-resolution image is read; bioformats2raw will generate a pyramid from +the full-resolution image, but will not read the original pyramid for this format. Datasets in this format include +a .mrxs file (which is a JPEG thumbnail), along with a similarly-named directory containing a `Slidedat.ini`, `Index.dat`, +and many `Data*.dat` files. The .mrxs file alone contains does not contain anything apart from the thumbnail; +it is very important to include the entire corresponding directory when transferring these datasets. + +The `mirax.use_metadata_dimensions` reader option can be used change how XY dimensions are calculated. +By default, this option is `true`, but setting it to `false` may be helpful if the image size appears incorrect. + +BioTekReader +------------ + +Supports BioTek Cytation 5 plates. Plates in this format consist of .tif files that follow a specific naming scheme; +unlike most other plate formats, there are no metadata files that describe the whole plate. All files for a plate must be in +the same folder as the selected bioformats2raw input file. File names must match one of a limited set of regular expressions: + +* `([A-Z]{1,2})(\\d{1,2})_(-?\\d+)_(\\d+)_(\\d+)_([A-Za-z0-9 ,\\[\\]]+)_(\\d+).tif[f]?` + - This corresponds to: `_____` + - Examples: + - `A1_01_1_1_Phase Contrast_001.tif` (well A1, field 1, `Phase Contrast` channel) + - `P24_01_1_9_DAPI_002.tif` (well P24, field 9, `DAPI` channel) + - `A1_-2_1_1_Tsf[Stitched[Channel1 300,400]]_001.tif` (well A1, field 1, `Tsf[Stitched][Channel 1 300,400]]` channel) +* `([A-Z]{1,2})(\\d{1,2})_(-?\\d+)(Z(\\d+))?_([A-Za-z0-9 ,\\[\\]]+)_(\\d+)_(\\d+)_(\\d+)?.tif[f]?` + - This corresponds to: `_____` + - Examples: + - `A1_1Z0_DAPI_1_001_.tif` (well A1, field 1, Z slice 0, `DAPI` channel, timepoint 1) + - `A1_1Z4_DAPI_1_003_.tif` (well A1, field 1, Z slice 4, `DAPI` channel, timepoint 3) + - `B2_1_Bright Field_1_001_02.tif` (well B2, field 1, `Bright Field` channel, timepoint 1) +* `([A-Z]{1,2})(\\d{1,2})_(-?\\d+)_.+\\[(.+)_([A-Za-z0-9 ,\\[\\]]+)\\]_(\\d+)_(\\d+)_([0-9-]+)?.tif[f]?` + - This corresponds to: `__[_]___` + - Example: + - `H10_1_Stitched[AandB_Phase Contrast]_1_001_-1.tif` (well H10, field 1, `Phase Contrast` channel, timepoint 1) + +If the input file does not match the given regular expression, then the basic TIFF reader will be used to convert the +single input file without looking for other .tif files. It is especially important to check the conversion output when +working with BioTek plates for the first time or after any acquisition system updates, as there will not be an error in +the logs if the file name does not match any of the above regular expressions. + +ND2PlateReader +-------------- + +Supports grouping multiple .nd2 files into a single HCS plate. To our knowledge, .nd2 files contain no HCS metadata or +awareness that multiple files are part of the same acquisition. This reader relies entirely upon the file name structure +to group .nd2 files in the same directory into a plate. Each file is assumed to represent one well, which may contain +multiple fields. All files for a plate must be in the same folder as the selected bioformats2raw input file. + +File names must match the regular expression `(.*_?)Well([A-Z])(\\d{2})_Channel(.*)_Seq(\\d{4}).nd2`, e.g. +`Plate000_WellB02_ChannelDAPI,CY5,CY3_Seq0000.nd2`. In this case, `Plate000` is the plate name; only files with the +same plate name will be grouped together. + +If the input file does not match the given regular expression, then the base `ND2Reader` will be used to convert the +single input file without looking for other .nd2 files. It is especially important to check the conversion output when +working with ND2 plates for the first time or after any acquisition system updates, as there will not be an error in +the logs if the file name does not match `ND2PlateReader`'s expectations. + License ======= From 241d20f3b64deb58b484ded2a5eacb27e712d11f Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 21 Sep 2023 10:22:45 -0500 Subject: [PATCH 07/27] Fix typos noted in review Co-authored-by: Erin Diel <41040012+erindiel@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 250cb123..0fd6566b 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ MiraxReader Supports 3D HISTECH .mrxs data. Only the full-resolution image is read; bioformats2raw will generate a pyramid from the full-resolution image, but will not read the original pyramid for this format. Datasets in this format include a .mrxs file (which is a JPEG thumbnail), along with a similarly-named directory containing a `Slidedat.ini`, `Index.dat`, -and many `Data*.dat` files. The .mrxs file alone contains does not contain anything apart from the thumbnail; +and many `Data*.dat` files. The .mrxs file alone does not contain anything apart from the thumbnail; it is very important to include the entire corresponding directory when transferring these datasets. The `mirax.use_metadata_dimensions` reader option can be used change how XY dimensions are calculated. @@ -346,7 +346,7 @@ the same folder as the selected bioformats2raw input file. File names must match - Examples: - `A1_01_1_1_Phase Contrast_001.tif` (well A1, field 1, `Phase Contrast` channel) - `P24_01_1_9_DAPI_002.tif` (well P24, field 9, `DAPI` channel) - - `A1_-2_1_1_Tsf[Stitched[Channel1 300,400]]_001.tif` (well A1, field 1, `Tsf[Stitched][Channel 1 300,400]]` channel) + - `A1_-2_1_1_Tsf[Stitched[Channel1 300,400]]_001.tif` (well A1, field 1, `Tsf[Stitched[Channel1 300,400]]` channel) * `([A-Z]{1,2})(\\d{1,2})_(-?\\d+)(Z(\\d+))?_([A-Za-z0-9 ,\\[\\]]+)_(\\d+)_(\\d+)_(\\d+)?.tif[f]?` - This corresponds to: `_____` - Examples: From 321f268e88f887618c75e0929cb9302cc91b6a83 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 22 Sep 2023 10:34:39 -0500 Subject: [PATCH 08/27] Update test to use ZarrArray.getDimensionSeparator() --- .../java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 3acdb19a..19f7aadb 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -24,6 +24,7 @@ import java.util.stream.Stream; import com.bc.zarr.DataType; +import com.bc.zarr.DimensionSeparator; import com.bc.zarr.ZarrArray; import com.bc.zarr.ZarrGroup; import com.fasterxml.jackson.databind.JsonNode; @@ -270,7 +271,7 @@ public void testDefaultLayoutIsSetAndIsNested() throws Exception { // no getter for DimensionSeparator in ZarrArray // check that the correct separator was used by checking // that the expected first chunk file exists - assertTrue(output.resolve("0/0/0/0/0/0/0").toFile().exists()); + assertEquals(series0.getDimensionSeparator(), DimensionSeparator.SLASH); // Also ensure we're using the latest .zarray metadata ObjectMapper objectMapper = new ObjectMapper(); From 609f092c171d3275521903283452a8c63091f455 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Mon, 25 Sep 2023 09:47:30 -0500 Subject: [PATCH 09/27] Update test comment to reflect changes in jzarr 0.4.0 --- .../com/glencoesoftware/bioformats2raw/test/ZarrTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 19f7aadb..b5b076a0 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -268,9 +268,7 @@ public void testDefaultLayoutIsSetAndIsNested() throws Exception { ZarrArray series0 = ZarrGroup.open(output.resolve("0")).openArray("0"); - // no getter for DimensionSeparator in ZarrArray - // check that the correct separator was used by checking - // that the expected first chunk file exists + // check that the correct separator was used assertEquals(series0.getDimensionSeparator(), DimensionSeparator.SLASH); // Also ensure we're using the latest .zarray metadata From 5a99e2b528d5989f8c156cc9574862c1496bf6e0 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 5 Oct 2023 16:23:41 -0500 Subject: [PATCH 10/27] Add reset methods for each option --- .../bioformats2raw/Converter.java | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index d3fb5e16..c760bacd 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -799,6 +799,249 @@ public void setDimensionOrder(DimensionOrder order) { dimensionOrder = order; } + // Option resetters - reset to defaults + + /** + * Reset all options to their default values. + */ + public void resetOptions() { + resetInputPath(); + resetOutputPath(); + resetOutputOptions(); + resetResolutions(); + resetSeriesList(); + resetTileWidth(); + resetTileHeight(); + resetChunkDepth(); + resetLogLevel(); + resetProgressBars(); + resetPrintVersionOnly(); + resetMaxWorkers(); + resetMaxCachedTiles(); + resetCompression(); + resetCompressionProperties(); + resetExtraReaders(); + resetCalculateOMEROMetadata(); + resetNested(); + resetPyramidName(); + resetScaleFormat(); + resetAdditionalScaleFormatCSV(); + resetMemoDirectory(); + resetKeepMemoFiles(); + resetDownsampling(); + resetOverwrite(); + resetFillValue(); + resetReaderOptions(); + resetNoHCS(); + resetNoOMEMeta(); + resetNoRootGroup(); + resetReuseExistingResolutions(); + resetMinImageSize(); + resetDimensionOrder(); + } + + /** + */ + public void resetInputPath() { + inputPath = null; + } + + /** + */ + public void resetOutputPath() { + outputLocation = null; + } + + /** + */ + public void resetOutputOptions() { + outputOptions = null; + } + + /** + */ + public void resetResolutions() { + pyramidResolutions = null; + } + + /** + */ + public void resetSeriesList() { + seriesList.clear(); + } + + /** + */ + public void resetTileWidth() { + tileWidth = 1024; + } + + /** + */ + public void resetTileHeight() { + tileHeight = 1024; + } + + /** + */ + public void resetChunkDepth() { + chunkDepth = 1; + } + + /** + */ + public void resetLogLevel() { + logLevel = "WARN"; + } + + /** + */ + public void resetProgressBars() { + progressBars = false; + } + + /** + */ + public void resetPrintVersionOnly() { + printVersion = false; + } + + /** + */ + public void resetMaxWorkers() { + maxWorkers = (int) Math.min(4, Runtime.getRuntime().availableProcessors()); + } + + /** + */ + public void resetMaxCachedTiles() { + maxCachedTiles = 64; + } + + /** + */ + public void resetCompression() { + compressionType = ZarrCompression.blosc; + } + + /** + */ + public void resetCompressionProperties() { + compressionProperties.clear(); + } + + /** + */ + public void resetExtraReaders() { + extraReaders = new Class[] { + PyramidTiffReader.class, MiraxReader.class, + BioTekReader.class, ND2PlateReader.class + }; + } + + /** + */ + public void resetCalculateOMEROMetadata() { + omeroMetadata = true; + } + + /** + */ + public void resetNested() { + nested = true; + } + + /** + */ + public void resetPyramidName() { + pyramidName = null; + } + + /** + */ + public void resetScaleFormat() { + scaleFormatString = "%d/%d"; + } + + /** + */ + public void resetAdditionalScaleFormatCSV() { + additionalScaleFormatStringArgsCsv = null; + additionalScaleFormatStringArgs = null; + } + + /** + */ + public void resetMemoDirectory() { + memoDirectory = null; + } + + /** + */ + public void resetKeepMemoFiles() { + keepMemoFiles = false; + } + + /** + */ + public void resetDownsampling() { + downsampling = Downsampling.SIMPLE; + } + + /** + */ + public void resetOverwrite() { + overwrite = false; + } + + /** + */ + public void resetFillValue() { + fillValue = null; + } + + /** + */ + public void resetReaderOptions() { + readerOptions.clear(); + } + + /** + */ + public void resetNoHCS() { + noHCS = false; + } + + /** + */ + public void resetNoOMEMeta() { + noOMEMeta = false; + } + + /** + */ + public void resetNoRootGroup() { + noRootGroup = false; + } + + /** + */ + public void resetReuseExistingResolutions() { + reuseExistingResolutions = false; + } + + /** + */ + public void resetMinImageSize() { + minSize = MIN_SIZE; + } + + /** + */ + public void resetDimensionOrder() { + dimensionOrder = DimensionOrder.XYZCT; + } + // Option getters /** From dce2075193c86fb7e4403b4d863a9a8b246c769c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besson?= Date: Wed, 11 Oct 2023 09:23:47 +0100 Subject: [PATCH 11/27] Add variant for all options with underscores using dash separator --- .../com/glencoesoftware/bioformats2raw/Converter.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index d3fb5e16..d7b55d1f 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -307,7 +307,7 @@ public void setSeriesList(List seriesToConvert) { * @param width tile width */ @Option( - names = {"-w", "--tile_width"}, + names = {"-w", "--tile-width", "--tile_width"}, description = "Maximum tile width (default: ${DEFAULT-VALUE}). " + "This is both the chunk size (in X) when writing Zarr and the tile " + "size used for reading from the original data. Changing the tile " + @@ -329,7 +329,7 @@ public void setTileWidth(int width) { * @param height tile height */ @Option( - names = {"-h", "--tile_height"}, + names = {"-h", "--tile-height", "--tile_height"}, description = "Maximum tile height (default: ${DEFAULT-VALUE}). " + "This is both the chunk size (in Y) when writing Zarr and the tile " + "size used for reading from the original data. Changing the tile " + @@ -351,7 +351,7 @@ public void setTileHeight(int height) { * @param depth Z chunk size */ @Option( - names = {"-z", "--chunk_depth"}, + names = {"-z", "--chunk-depth", "--chunk_depth"}, description = "Maximum chunk depth to read (default: ${DEFAULT-VALUE}) ", defaultValue = "1" ) @@ -421,7 +421,7 @@ public void setPrintVersionOnly(boolean versionOnly) { * @param workers maximum worker count */ @Option( - names = "--max_workers", + names = {"--max-workers", "--max_workers"}, description = "Maximum number of workers (default: ${DEFAULT-VALUE})" ) public void setMaxWorkers(int workers) { @@ -441,7 +441,7 @@ public void setMaxWorkers(int workers) { * @param maxTiles maximum number of cached tiles */ @Option( - names = "--max_cached_tiles", + names = {"--max-cached-tiles", "--max_cached_tiles"}, description = "Maximum number of tiles that will be cached across all " + "workers (default: ${DEFAULT-VALUE})", From 0b48816b603a64ed5ce05a303c276ab89b0316e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besson?= Date: Wed, 11 Oct 2023 10:01:39 +0100 Subject: [PATCH 12/27] Update README to use dash separated option names --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0fd6566b..f1ec12c2 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ Alternatively, the `--resolutions` options can be passed to specify the exact nu bioformats2raw /path/to/file.svs /path/to/zarr-pyramid --resolutions 6 -Maximum tile dimensions can be configured with the `--tile_width` and `--tile_height` options. Defaults can be viewed with +Maximum tile dimensions can be configured with the `--tile-width` and `--tile-height` options. Defaults can be viewed with `bioformats2raw --help`. Be mindful of the downstream workflow when selecting a tile size other than the default. A smaller than default tile size is rarely recommended. @@ -276,9 +276,9 @@ Performance This package is __highly__ sensitive to underlying hardware as well as the following configuration options: - * `--max_workers` - * `--tile_width` - * `--tile_height` + * `--max-workers` + * `--tile-width` + * `--tile-height` On systems with significant I/O bandwidth, particularly SATA or NVMe based storage, you may find sharply diminishing returns with high From b890e1cabb72057fd7260de179f1610bf2e43c7c Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Mon, 16 Oct 2023 16:43:09 -0500 Subject: [PATCH 13/27] Update progress listener API to provide tile counts at each start notification This should make it easier for a listener implementation to use a single progress bar for the whole conversion, instead of one progress bar per resolution. Updating the notifications in Converter requires pre-calculating tile and resolution counts before starting to write tiles, but that also means failing faster if the pixel type and downsampling (or other options) are incompatible. --- .../bioformats2raw/Converter.java | 158 +++++++++++++----- .../bioformats2raw/IProgressListener.java | 12 +- .../bioformats2raw/NoOpProgressListener.java | 8 +- .../bioformats2raw/ProgressBarListener.java | 9 +- .../test/TestProgressListener.java | 24 ++- .../bioformats2raw/test/ZarrTest.java | 6 + 6 files changed, 175 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index d7b55d1f..3bab4917 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -209,6 +209,7 @@ public class Converter implements Callable { private volatile Path outputPath; private IProgressListener progressListener; + private Map tileCounts = new HashMap(); // Option setters @@ -1337,6 +1338,17 @@ public void convert() root.writeAttributes(attributes); } + // pre-calculate resolution and tile counts + long totalTiles = 0; + for (Integer index : seriesList) { + int[] counts = calculateTileCounts(index); + tileCounts.put(index, counts); + for (int count : counts) { + totalTiles += count; + } + } + getProgressListener().notifyTotalTileCount(totalTiles); + for (Integer index : seriesList) { try { write(index); @@ -1375,6 +1387,105 @@ public void convert() } } + /** + * Pre-calculate the number of resolutions and tiles for the + * given series index. This is useful for accurate progress reporting + * and failing faster for incompatible pixel/downsampling combinations. + * + * @param series series index + * @return array of tile counts; the array length is the number of resolutions + */ + private int[] calculateTileCounts(int series) + throws FormatException, IOException, InterruptedException, + EnumerationException + { + readers.forEach((reader) -> { + reader.setSeries(series); + }); + + IFormatReader workingReader = readers.take(); + int resolutions = 1; + int sizeX; + int sizeY; + int sizeZ; + int imageCount; + try { + // calculate a reasonable pyramid depth if not specified as an argument + sizeX = workingReader.getSizeX(); + sizeY = workingReader.getSizeY(); + if (pyramidResolutions == null) { + if (workingReader.getResolutionCount() > 1 + && reuseExistingResolutions) + { + resolutions = workingReader.getResolutionCount(); + } + else { + resolutions = calculateResolutions(sizeX, sizeY); + } + } + else { + resolutions = pyramidResolutions; + + // check to make sure too many resolutions aren't being used + if ((int) (sizeX / Math.pow(PYRAMID_SCALE, resolutions)) == 0 || + (int) (sizeY / Math.pow(PYRAMID_SCALE, resolutions)) == 0) + { + resolutions = calculateResolutions(sizeX, sizeY); + LOGGER.warn("Too many resolutions specified; reducing to {}", + resolutions); + } + } + LOGGER.info("Using {} pyramid resolutions", resolutions); + sizeZ = workingReader.getSizeZ(); + imageCount = workingReader.getImageCount(); + pixelType = workingReader.getPixelType(); + } + finally { + readers.put(workingReader); + } + + int[] resTileCounts = new int[resolutions]; + + if ((pixelType == FormatTools.INT8 || pixelType == FormatTools.INT32) && + getDownsampling() != Downsampling.SIMPLE && resolutions > 0) + { + String type = FormatTools.getPixelTypeString(pixelType); + throw new UnsupportedOperationException( + "OpenCV does not support downsampling " + type + " data. " + + "See https://github.com/opencv/opencv/issues/7862"); + } + + for (int resCounter=0; resCounter 1 + && reuseExistingResolutions) + { + workingReader.setResolution(resCounter); + scaledWidth = workingReader.getSizeX(); + scaledHeight = workingReader.getSizeY(); + scaledDepth = workingReader.getSizeZ(); + } + } + finally { + readers.put(workingReader); + } + + resTileCounts[resCounter] = + (int) Math.ceil((double) scaledWidth / tileWidth) + * (int) Math.ceil((double) scaledHeight / tileHeight) + * (int) Math.ceil((double) scaledDepth / chunkDepth) + * (imageCount / sizeZ); + } + return resTileCounts; + } + /** * Convert the data specified by the given initialized reader to * an intermediate form. @@ -1835,9 +1946,15 @@ public void saveResolutions(int series) throws FormatException, IOException, InterruptedException, EnumerationException { - getProgressListener().notifySeriesStart(series); + int[] resTileCounts = tileCounts.get(series); + int resolutions = resTileCounts.length; + int seriesTiles = 0; + for (int t : resTileCounts) { + seriesTiles += t; + } + getProgressListener().notifySeriesStart(series, resolutions, seriesTiles); + IFormatReader workingReader = readers.take(); - int resolutions = 1; int sizeX; int sizeY; int sizeZ; @@ -1849,29 +1966,6 @@ public void saveResolutions(int series) // calculate a reasonable pyramid depth if not specified as an argument sizeX = workingReader.getSizeX(); sizeY = workingReader.getSizeY(); - if (pyramidResolutions == null) { - if (workingReader.getResolutionCount() > 1 - && reuseExistingResolutions) - { - resolutions = workingReader.getResolutionCount(); - } - else { - resolutions = calculateResolutions(sizeX, sizeY); - } - } - else { - resolutions = pyramidResolutions; - - // check to make sure too many resolutions aren't being used - if ((int) (sizeX / Math.pow(PYRAMID_SCALE, resolutions)) == 0 || - (int) (sizeY / Math.pow(PYRAMID_SCALE, resolutions)) == 0) - { - resolutions = calculateResolutions(sizeX, sizeY); - LOGGER.warn("Too many resolutions specified; reducing to {}", - resolutions); - } - } - LOGGER.info("Using {} pyramid resolutions", resolutions); sizeZ = workingReader.getSizeZ(); sizeT = workingReader.getSizeT(); sizeC = workingReader.getSizeC(); @@ -1883,15 +1977,6 @@ public void saveResolutions(int series) readers.put(workingReader); } - if ((pixelType == FormatTools.INT8 || pixelType == FormatTools.INT32) && - getDownsampling() != Downsampling.SIMPLE && resolutions > 0) - { - String type = FormatTools.getPixelTypeString(pixelType); - throw new UnsupportedOperationException( - "OpenCV does not support downsampling " + type + " data. " + - "See https://github.com/opencv/opencv/issues/7862"); - } - LOGGER.info( "Preparing to write pyramid sizeX {} (tileWidth: {}) " + "sizeY {} (tileWidth: {}) sizeZ {} (tileDepth: {}) imageCount {}", @@ -1958,10 +2043,7 @@ public void saveResolutions(int series) ZarrArray.create(getRootPath().resolve(resolutionString), arrayParams); nTile = new AtomicInteger(0); - tileCount = (int) Math.ceil((double) scaledWidth / tileWidth) - * (int) Math.ceil((double) scaledHeight / tileHeight) - * (int) Math.ceil((double) scaledDepth / chunkDepth) - * (imageCount / sizeZ); + tileCount = resTileCounts[resolution]; List> futures = new ArrayList>(); diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java index bda2e7e4..8917a7d1 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java @@ -11,12 +11,22 @@ public interface IProgressListener extends EventListener { + /** + * Indicates the total number of tiles in this conversion operation. + * Includes all resolutions in all series. + * + * @param tileCount total number of tiles + */ + void notifyTotalTileCount(long tileCount); + /** * Indicates the beginning of processing a particular series. * * @param series the series index being processed + * @param resolutionCount total number of resolutions in this series + * @param tileCount total number of tiles for all resolutions in this series */ - void notifySeriesStart(int series); + void notifySeriesStart(int series, int resolutionCount, int tileCount); /** * Indicates the end of processing a particular series. diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java index 914f5373..ec952ede 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java @@ -10,7 +10,13 @@ public class NoOpProgressListener implements IProgressListener { @Override - public void notifySeriesStart(int series) { + public void notifyTotalTileCount(long tileCount) { + } + + @Override + public void notifySeriesStart(int series, int resolutionCount, + int tileCount) + { } @Override diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java index fc61e36d..e08e972f 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java @@ -32,14 +32,21 @@ public ProgressBarListener(String level) { logLevel = level; } + @Override + public void notifyTotalTileCount(long tileCount) { + // intentional no-op + } @Override - public void notifySeriesStart(int series) { + public void notifySeriesStart(int series, int resolutionCount, + int tileCount) + { currentSeries = series; } @Override public void notifySeriesEnd(int series) { + // intentional no-op } @Override diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java index 46d8179c..3160400f 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java @@ -18,9 +18,17 @@ public class TestProgressListener implements IProgressListener { private int startedTiles = 0; private int completedTiles = 0; private int expectedTileCount = 0; + private int seriesTiles = 0; + private long totalTiles = 0; @Override - public void notifySeriesStart(int series) { + public void notifyTotalTileCount(long tileCount) { + totalTiles = tileCount; + } + + @Override + public void notifySeriesStart(int series, int res, int tiles) { + seriesTiles = tiles; } @Override @@ -64,4 +72,18 @@ public Integer[] getTileCounts() { return finishedResolutions.toArray(new Integer[finishedResolutions.size()]); } + /** + * @return the reported number of tiles for the most recent series + */ + public int getSeriesTileCount() { + return seriesTiles; + } + + /** + * @return the reported number of total tiles for the conversion + */ + public long getTotalTileCount() { + return totalTiles; + } + } diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 3acdb19a..61abf598 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -711,6 +711,12 @@ public void testProgressListener() throws Exception { Integer[] expectedTileCounts = new Integer[] {320, 80, 20, 5, 5, 5}; Integer[] tileCounts = listener.getTileCounts(); assertArrayEquals(expectedTileCounts, tileCounts); + long totalTileCount = 0; + for (Integer t : expectedTileCounts) { + totalTileCount += t; + } + assertEquals(totalTileCount, listener.getTotalTileCount()); + assertEquals(totalTileCount, listener.getSeriesTileCount()); } private int bytesPerPixel(DataType dataType) { From db851370cceca12dde2f3afeebcb3791b503979b Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 19 Oct 2023 09:59:47 -0500 Subject: [PATCH 14/27] Update progress listener terminology to standardize on chunk (not tile) --- .../bioformats2raw/Converter.java | 2 +- .../bioformats2raw/IProgressListener.java | 15 ++++++++------- .../bioformats2raw/NoOpProgressListener.java | 6 +++--- .../bioformats2raw/ProgressBarListener.java | 8 ++++---- .../test/TestProgressListener.java | 8 ++++---- .../bioformats2raw/test/ZarrTest.java | 16 ++++++++-------- 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index 3bab4917..58d2a391 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -1347,7 +1347,7 @@ public void convert() totalTiles += count; } } - getProgressListener().notifyTotalTileCount(totalTiles); + getProgressListener().notifyTotalCounts(seriesList.size(), totalTiles); for (Integer index : seriesList) { try { diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java index 8917a7d1..d90a3359 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java @@ -12,21 +12,22 @@ public interface IProgressListener extends EventListener { /** - * Indicates the total number of tiles in this conversion operation. + * Indicates the total number of chunks in this conversion operation. * Includes all resolutions in all series. * - * @param tileCount total number of tiles + * @param seriesCount total number of series + * @param chunkCount total number of chunks */ - void notifyTotalTileCount(long tileCount); + void notifyTotalCounts(int seriesCount, long chunkCount); /** * Indicates the beginning of processing a particular series. * * @param series the series index being processed * @param resolutionCount total number of resolutions in this series - * @param tileCount total number of tiles for all resolutions in this series + * @param chunkCount total number of chunks for all resolutions in this series */ - void notifySeriesStart(int series, int resolutionCount, int tileCount); + void notifySeriesStart(int series, int resolutionCount, int chunkCount); /** * Indicates the end of processing a particular series. @@ -39,9 +40,9 @@ public interface IProgressListener extends EventListener { * Indicates the beginning of processing a particular resolution. * * @param resolution the resolution index being processed - * @param tileCount the total number of tiles in this resolution + * @param chunkCount the total number of chunks in this resolution */ - void notifyResolutionStart(int resolution, int tileCount); + void notifyResolutionStart(int resolution, int chunkCount); /** * Indicates the end of processing a particular resolution. diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java index ec952ede..4c0a04a4 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java @@ -10,12 +10,12 @@ public class NoOpProgressListener implements IProgressListener { @Override - public void notifyTotalTileCount(long tileCount) { + public void notifyTotalCounts(int seriesCount, long chunkCount) { } @Override public void notifySeriesStart(int series, int resolutionCount, - int tileCount) + int chunkCount) { } @@ -24,7 +24,7 @@ public void notifySeriesEnd(int series) { } @Override - public void notifyResolutionStart(int resolution, int tileCount) { + public void notifyResolutionStart(int resolution, int chunkCount) { } @Override diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java index e08e972f..2d3e00da 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java @@ -33,13 +33,13 @@ public ProgressBarListener(String level) { } @Override - public void notifyTotalTileCount(long tileCount) { + public void notifyTotalCounts(int seriesCount, long chunkCount) { // intentional no-op } @Override public void notifySeriesStart(int series, int resolutionCount, - int tileCount) + int chunkCount) { currentSeries = series; } @@ -50,9 +50,9 @@ public void notifySeriesEnd(int series) { } @Override - public void notifyResolutionStart(int resolution, int tileCount) { + public void notifyResolutionStart(int resolution, int chunkCount) { ProgressBarBuilder builder = new ProgressBarBuilder() - .setInitialMax(tileCount) + .setInitialMax(chunkCount) .setTaskName(String.format("[%d/%d]", currentSeries, resolution)); if (!(logLevel.equals("OFF") || diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java index 3160400f..59cbd49c 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java @@ -22,7 +22,7 @@ public class TestProgressListener implements IProgressListener { private long totalTiles = 0; @Override - public void notifyTotalTileCount(long tileCount) { + public void notifyTotalCounts(int seriesCount, long tileCount) { totalTiles = tileCount; } @@ -68,21 +68,21 @@ public void notifyResolutionEnd(int resolution) { * * @return an array with one element per resolution */ - public Integer[] getTileCounts() { + public Integer[] getChunkCounts() { return finishedResolutions.toArray(new Integer[finishedResolutions.size()]); } /** * @return the reported number of tiles for the most recent series */ - public int getSeriesTileCount() { + public int getSeriesChunkCount() { return seriesTiles; } /** * @return the reported number of total tiles for the conversion */ - public long getTotalTileCount() { + public long getTotalChunkCount() { return totalTiles; } diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 61abf598..59a125a2 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -708,15 +708,15 @@ public void testProgressListener() throws Exception { throw new RuntimeException(t); } - Integer[] expectedTileCounts = new Integer[] {320, 80, 20, 5, 5, 5}; - Integer[] tileCounts = listener.getTileCounts(); - assertArrayEquals(expectedTileCounts, tileCounts); - long totalTileCount = 0; - for (Integer t : expectedTileCounts) { - totalTileCount += t; + Integer[] expectedChunkCounts = new Integer[] {320, 80, 20, 5, 5, 5}; + Integer[] chunkCounts = listener.getChunkCounts(); + assertArrayEquals(expectedChunkCounts, chunkCounts); + long totalChunkCount = 0; + for (Integer t : expectedChunkCounts) { + totalChunkCount += t; } - assertEquals(totalTileCount, listener.getTotalTileCount()); - assertEquals(totalTileCount, listener.getSeriesTileCount()); + assertEquals(totalChunkCount, listener.getTotalChunkCount()); + assertEquals(totalChunkCount, listener.getSeriesChunkCount()); } private int bytesPerPixel(DataType dataType) { From b532b7721366a37546f31d286aabdf29f29a879f Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 20 Oct 2023 11:39:16 -0500 Subject: [PATCH 15/27] Add test for options resetting --- .../bioformats2raw/Converter.java | 8 ++--- .../bioformats2raw/test/ZarrTest.java | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index c760bacd..7a7fcd2a 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -867,7 +867,7 @@ public void resetResolutions() { /** */ public void resetSeriesList() { - seriesList.clear(); + seriesList = new ArrayList(); } /** @@ -927,7 +927,7 @@ public void resetCompression() { /** */ public void resetCompressionProperties() { - compressionProperties.clear(); + compressionProperties = new HashMap(); } /** @@ -1003,7 +1003,7 @@ public void resetFillValue() { /** */ public void resetReaderOptions() { - readerOptions.clear(); + readerOptions = new ArrayList(); } /** @@ -1048,7 +1048,7 @@ public void resetDimensionOrder() { * @return path to input data */ public String getInputPath() { - return inputPath.toString(); + return inputPath == null ? null : inputPath.toString(); } /** diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 3acdb19a..426bd62b 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -1983,6 +1983,40 @@ public void testOptionsAPI() throws Exception { } } + /** + * Check that setting and resetting options via API will reset options to + * their default values. + */ + @Test + public void testResetOptions() throws Exception { + input = fake("series", "2", "sizeX", "4096", "sizeY", "4096"); + + Converter apiConverter = new Converter(); + apiConverter.setInputPath(input.toString()); + apiConverter.setOutputPath(output.toString()); + apiConverter.setSeriesList(Collections.singletonList(1)); + apiConverter.setTileWidth(128); + apiConverter.setTileHeight(128); + + assertEquals(apiConverter.getInputPath(), input.toString()); + assertEquals(apiConverter.getOutputPath(), output.toString()); + assertEquals(apiConverter.getSeriesList(), Collections.singletonList(1)); + assertEquals(apiConverter.getTileWidth(), 128); + assertEquals(apiConverter.getTileHeight(), 128); + + apiConverter.resetInputPath(); + assertEquals(apiConverter.getInputPath(), null); + + apiConverter.setInputPath(input.toString()); + + apiConverter.resetOptions(); + assertEquals(apiConverter.getInputPath(), null); + assertEquals(apiConverter.getOutputPath(), null); + assertEquals(apiConverter.getSeriesList().size(), 0); + assertEquals(apiConverter.getTileWidth(), 1024); + assertEquals(apiConverter.getTileHeight(), 1024); + } + /** * @param root dataset root path * @param rowCount total rows the plate could contain From b060386f4788695fb83a9ba24446794ce5077980 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Fri, 20 Oct 2023 13:29:10 -0500 Subject: [PATCH 16/27] Allow resetting to defaults via picocli --- build.gradle | 2 +- .../bioformats2raw/Converter.java | 391 +++++------------- .../bioformats2raw/test/ZarrTest.java | 17 +- 3 files changed, 108 insertions(+), 302 deletions(-) diff --git a/build.gradle b/build.gradle index e929d2ee..43ced16e 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ configurations.all { dependencies { implementation 'net.java.dev.jna:jna:5.10.0' implementation 'ome:formats-gpl:7.0.0' - implementation 'info.picocli:picocli:4.6.1' + implementation 'info.picocli:picocli:4.7.5' implementation 'com.univocity:univocity-parsers:2.8.4' implementation 'com.bc.zarr:jzarr:0.3.5' // implementation 'org.carlspring.cloud.aws:s3fs-nio:1.0-SNAPSHOT' diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index 7a7fcd2a..7afd739a 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -130,49 +130,41 @@ public class Converter implements Callable { private Map outputOptions; private volatile Integer pyramidResolutions; - private volatile List seriesList = new ArrayList(); + private volatile List seriesList; - private volatile int tileWidth = 1024; - private volatile int tileHeight = 1024; - private volatile int chunkDepth = 1; - private volatile String logLevel = "WARN"; + private volatile int tileWidth; + private volatile int tileHeight; + private volatile int chunkDepth; + private volatile String logLevel; private volatile boolean progressBars = false; private volatile boolean printVersion = false; - // cap the default worker count at 4, to prevent problems with - // large images that are not tiled - private volatile int maxWorkers = - (int) Math.min(4, Runtime.getRuntime().availableProcessors()); - - private volatile int maxCachedTiles = 64; - private volatile ZarrCompression compressionType = ZarrCompression.blosc; - private volatile Map compressionProperties = - new HashMap();; - private volatile Class[] extraReaders = new Class[] { - PyramidTiffReader.class, MiraxReader.class, - BioTekReader.class, ND2PlateReader.class - }; + private volatile int maxWorkers; + private volatile int maxCachedTiles; + private volatile ZarrCompression compressionType; + private volatile Map compressionProperties; + private volatile Class[] extraReaders; private volatile boolean omeroMetadata = true; private volatile boolean nested = true; private volatile String pyramidName = null; - private volatile String scaleFormatString = "%d/%d"; + private volatile String scaleFormatString; private volatile Path additionalScaleFormatStringArgsCsv; /** Additional scale format string arguments after parsing. */ private volatile List additionalScaleFormatStringArgs; - private volatile DimensionOrder dimensionOrder = DimensionOrder.XYZCT; + private volatile DimensionOrder dimensionOrder; private volatile File memoDirectory; private volatile boolean keepMemoFiles = false; - private volatile Downsampling downsampling = Downsampling.SIMPLE; + private volatile Downsampling downsampling; private volatile boolean overwrite = false; private volatile Short fillValue = null; - private volatile List readerOptions = new ArrayList(); + private volatile List readerOptions; private volatile boolean noHCS = false; private volatile boolean noOMEMeta = false; private volatile boolean noRootGroup = false; private volatile boolean reuseExistingResolutions = false; - private volatile int minSize = MIN_SIZE; + private volatile int minSize; /** Scaling implementation that will be used during downsampling. */ private volatile IImageScaler scaler = new SimpleImageScaler(); @@ -218,11 +210,17 @@ public class Converter implements Callable { @Parameters( index = "0", arity = "1", - description = "file to convert" + description = "file to convert", + defaultValue = Option.NULL_VALUE ) public void setInputPath(String input) { - // this could be expanded later to support files not on disk - inputPath = Paths.get(input); + if (input != null) { + // this could be expanded later to support files not on disk + inputPath = Paths.get(input); + } + else { + inputPath = null; + } } /** @@ -237,7 +235,8 @@ public void setInputPath(String input) { "Filesystems. For example, if the output path given " + "is 's3://my-bucket/some-path' *and* you have an "+ "S3FileSystem implementation in your classpath, then " + - "all files will be written to S3." + "all files will be written to S3.", + defaultValue = Option.NULL_VALUE ) public void setOutputPath(String output) { outputLocation = output; @@ -255,7 +254,8 @@ public void setOutputPath(String output) { "to be used as an additional argument to Filesystem " + "implementations if used. For example, " + "--output-options=s3fs_path_style_access=true|... " + - "might be useful for connecting to minio." + "might be useful for connecting to minio.", + defaultValue = Option.NULL_VALUE ) public void setOutputOptions(Map options) { outputOptions = options; @@ -265,16 +265,19 @@ public void setOutputOptions(Map options) { * Define the number of resolutions in the generated pyramid. * By default, the resolution count is calculated based upon * the input image size. The resolution count includes the - * full-resolution image, so must be greater than 0. + * full-resolution image. If the resolution count is null, + * then the number of resolutions will be calculated automatically. + * If not null, it must be greater than 0. * * @param resolutions pyramid resolution count */ @Option( names = {"-r", "--resolutions"}, - description = "Number of pyramid resolutions to generate" + description = "Number of pyramid resolutions to generate", + defaultValue = Option.NULL_VALUE ) - public void setResolutions(int resolutions) { - if (resolutions > 0) { + public void setResolutions(Integer resolutions) { + if (resolutions == null || resolutions > 0) { pyramidResolutions = resolutions; } else { @@ -293,12 +296,16 @@ public void setResolutions(int resolutions) { names = {"-s", "--series"}, arity = "0..1", split = ",", - description = "Comma-separated list of series indexes to convert" + description = "Comma-separated list of series indexes to convert", + defaultValue = Option.NULL_VALUE ) public void setSeriesList(List seriesToConvert) { if (seriesToConvert != null) { seriesList = seriesToConvert; } + else { + seriesList = new ArrayList(); + } } /** @@ -393,7 +400,8 @@ public void setLogLevel(String level) { @Option( names = {"-p", "--progress"}, description = "Print progress bars during conversion", - help = true + help = true, + defaultValue = "false" ) public void setProgressBars(boolean useProgressBars) { progressBars = useProgressBars; @@ -408,7 +416,8 @@ public void setProgressBars(boolean useProgressBars) { @Option( names = "--version", description = "Print version information and exit", - help = true + help = true, + defaultValue = "false" ) public void setPrintVersionOnly(boolean versionOnly) { printVersion = versionOnly; @@ -422,10 +431,15 @@ public void setPrintVersionOnly(boolean versionOnly) { */ @Option( names = "--max_workers", - description = "Maximum number of workers (default: ${DEFAULT-VALUE})" + description = "Maximum number of workers (default: ${DEFAULT-VALUE})", + defaultValue = "4" ) public void setMaxWorkers(int workers) { - if (workers > 0) { + int availableProcessors = Runtime.getRuntime().availableProcessors(); + if (workers > availableProcessors) { + maxWorkers = availableProcessors; + } + else if (workers > 0) { maxWorkers = workers; } else { @@ -477,12 +491,16 @@ public void setCompression(ZarrCompression compression) { names = {"--compression-properties"}, description = "Properties for the chosen compression (see " + "https://jzarr.readthedocs.io/en/latest/tutorial.html#compressors" + - " )" + " )", + defaultValue = Option.NULL_VALUE ) public void setCompressionProperties(Map properties) { if (properties != null) { compressionProperties = properties; } + else { + compressionProperties = new HashMap(); + } } /** @@ -497,7 +515,12 @@ public void setCompressionProperties(Map properties) { arity = "0..1", split = ",", description = "Separate set of readers to include; " + - "(default: ${DEFAULT-VALUE})" + "(default: ${DEFAULT-VALUE})", + defaultValue = + "com.glencoesoftware.bioformats2raw.PyramidTiffReader," + + "com.glencoesoftware.bioformats2raw.MiraxReader," + + "com.glencoesoftware.bioformats2raw.BioTekReader," + + "com.glencoesoftware.bioformats2raw.ND2PlateReader" ) public void setExtraReaders(Class[] extraReaderList) { if (extraReaderList != null) { @@ -517,7 +540,8 @@ public void setExtraReaders(Class[] extraReaderList) { description = "Whether to calculate minimum and maximum pixel " + "values. Min/max calculation can result in slower " + "conversions. If true, min/max values are saved as " + - "OMERO rendering metadata (true by default)" + "OMERO rendering metadata (true by default)", + defaultValue = "false" ) public void setCalculateOMEROMetadata(boolean noMinMax) { omeroMetadata = !noMinMax; @@ -532,7 +556,8 @@ public void setCalculateOMEROMetadata(boolean noMinMax) { @Option( names = "--no-nested", negatable=true, description = "Whether to use '/' as the chunk path separator " + - "(true by default)" + "(true by default)", + defaultValue = "false" ) public void setUnnested(boolean unnested) { nested = !unnested; @@ -549,7 +574,8 @@ public void setUnnested(boolean unnested) { @Option( names = "--pyramid-name", description = "Name of pyramid (default: ${DEFAULT-VALUE}) " + - "[Can break compatibility with raw2ometiff]" + "[Can break compatibility with raw2ometiff]", + defaultValue = Option.NULL_VALUE ) public void setPyramidName(String pyramid) { pyramidName = pyramid; @@ -567,7 +593,8 @@ public void setPyramidName(String pyramid) { "by any additional arguments brought in from " + "`--additional-scale-format-string-args` " + "[Can break compatibility with raw2ometiff] " + - "(default: ${DEFAULT-VALUE})" + "(default: ${DEFAULT-VALUE})", + defaultValue = "%d/%d" ) public void setScaleFormat(String formatString) { if (formatString != null) { @@ -587,7 +614,8 @@ public void setScaleFormat(String formatString) { "scale format string mapping the at the corresponding CSV " + "row index. It is expected that the CSV file contain " + "exactly the same number of rows as the input file has " + - "series" + "series", + defaultValue = Option.NULL_VALUE ) public void setAdditionalScaleFormatCSV(Path scaleFormatCSV) { additionalScaleFormatStringArgsCsv = scaleFormatCSV; @@ -600,7 +628,8 @@ public void setAdditionalScaleFormatCSV(Path scaleFormatCSV) { */ @Option( names = "--memo-directory", - description = "Directory used to store .bfmemo cache files" + description = "Directory used to store .bfmemo cache files", + defaultValue = Option.NULL_VALUE ) public void setMemoDirectory(File memoDir) { memoDirectory = memoDir; @@ -614,7 +643,8 @@ public void setMemoDirectory(File memoDir) { */ @Option( names = "--keep-memo-files", - description = "Do not delete .bfmemo files created during conversion" + description = "Do not delete .bfmemo files created during conversion", + defaultValue = "false" ) public void setKeepMemoFiles(boolean keepMemos) { keepMemoFiles = keepMemos; @@ -644,7 +674,8 @@ public void setDownsampling(Downsampling downsampleType) { */ @Option( names = "--overwrite", - description = "Overwrite the output directory if it exists" + description = "Overwrite the output directory if it exists", + defaultValue = "false" ) public void setOverwrite(boolean canOverwrite) { overwrite = canOverwrite; @@ -659,7 +690,8 @@ public void setOverwrite(boolean canOverwrite) { @Option( names = "--fill-value", description = "Default value to fill in for missing tiles (0-255)" + - " (currently .mrxs only)" + " (currently .mrxs only)", + defaultValue = Option.NULL_VALUE ) public void setFillValue(Short tileFill) { if (tileFill == null || (tileFill >= 0 && tileFill <= 255)) { @@ -681,12 +713,16 @@ public void setFillValue(Short tileFill) { names = "--options", split = ",", description = - "Reader-specific options, in format key=value[,key2=value2]" + "Reader-specific options, in format key=value[,key2=value2]", + defaultValue = Option.NULL_VALUE ) public void setReaderOptions(List readerOpts) { if (readerOpts != null) { readerOptions = readerOpts; } + else { + readerOptions = new ArrayList(); + } } /** @@ -699,7 +735,8 @@ public void setReaderOptions(List readerOpts) { */ @Option( names = "--no-hcs", - description = "Turn off HCS writing" + description = "Turn off HCS writing", + defaultValue = "false" ) public void setNoHCS(boolean noHCSWriting) { noHCS = noHCSWriting; @@ -715,7 +752,8 @@ public void setNoHCS(boolean noHCSWriting) { @Option( names = "--no-ome-meta-export", description = "Turn off OME metadata exporting " + - "[Will break compatibility with raw2ometiff]" + "[Will break compatibility with raw2ometiff]", + defaultValue = "false" ) public void setNoOMEMeta(boolean noOMEMetaWriting) { noOMEMeta = noOMEMetaWriting; @@ -730,8 +768,8 @@ public void setNoOMEMeta(boolean noOMEMetaWriting) { @Option( names = "--no-root-group", description = "Turn off creation of root group and corresponding " + - "metadata [Will break compatibility with raw2ometiff]" - + "metadata [Will break compatibility with raw2ometiff]", + defaultValue = "false" ) public void setNoRootGroup(boolean noRootGroupWriting) { noRootGroup = noRootGroupWriting; @@ -748,8 +786,8 @@ public void setNoRootGroup(boolean noRootGroupWriting) { @Option( names = "--use-existing-resolutions", description = "Use existing sub resolutions from original input format" + - "[Will break compatibility with raw2ometiff]" - + "[Will break compatibility with raw2ometiff]", + defaultValue = "false" ) public void setReuseExistingResolutions(boolean reuse) { reuseExistingResolutions = reuse; @@ -799,249 +837,6 @@ public void setDimensionOrder(DimensionOrder order) { dimensionOrder = order; } - // Option resetters - reset to defaults - - /** - * Reset all options to their default values. - */ - public void resetOptions() { - resetInputPath(); - resetOutputPath(); - resetOutputOptions(); - resetResolutions(); - resetSeriesList(); - resetTileWidth(); - resetTileHeight(); - resetChunkDepth(); - resetLogLevel(); - resetProgressBars(); - resetPrintVersionOnly(); - resetMaxWorkers(); - resetMaxCachedTiles(); - resetCompression(); - resetCompressionProperties(); - resetExtraReaders(); - resetCalculateOMEROMetadata(); - resetNested(); - resetPyramidName(); - resetScaleFormat(); - resetAdditionalScaleFormatCSV(); - resetMemoDirectory(); - resetKeepMemoFiles(); - resetDownsampling(); - resetOverwrite(); - resetFillValue(); - resetReaderOptions(); - resetNoHCS(); - resetNoOMEMeta(); - resetNoRootGroup(); - resetReuseExistingResolutions(); - resetMinImageSize(); - resetDimensionOrder(); - } - - /** - */ - public void resetInputPath() { - inputPath = null; - } - - /** - */ - public void resetOutputPath() { - outputLocation = null; - } - - /** - */ - public void resetOutputOptions() { - outputOptions = null; - } - - /** - */ - public void resetResolutions() { - pyramidResolutions = null; - } - - /** - */ - public void resetSeriesList() { - seriesList = new ArrayList(); - } - - /** - */ - public void resetTileWidth() { - tileWidth = 1024; - } - - /** - */ - public void resetTileHeight() { - tileHeight = 1024; - } - - /** - */ - public void resetChunkDepth() { - chunkDepth = 1; - } - - /** - */ - public void resetLogLevel() { - logLevel = "WARN"; - } - - /** - */ - public void resetProgressBars() { - progressBars = false; - } - - /** - */ - public void resetPrintVersionOnly() { - printVersion = false; - } - - /** - */ - public void resetMaxWorkers() { - maxWorkers = (int) Math.min(4, Runtime.getRuntime().availableProcessors()); - } - - /** - */ - public void resetMaxCachedTiles() { - maxCachedTiles = 64; - } - - /** - */ - public void resetCompression() { - compressionType = ZarrCompression.blosc; - } - - /** - */ - public void resetCompressionProperties() { - compressionProperties = new HashMap(); - } - - /** - */ - public void resetExtraReaders() { - extraReaders = new Class[] { - PyramidTiffReader.class, MiraxReader.class, - BioTekReader.class, ND2PlateReader.class - }; - } - - /** - */ - public void resetCalculateOMEROMetadata() { - omeroMetadata = true; - } - - /** - */ - public void resetNested() { - nested = true; - } - - /** - */ - public void resetPyramidName() { - pyramidName = null; - } - - /** - */ - public void resetScaleFormat() { - scaleFormatString = "%d/%d"; - } - - /** - */ - public void resetAdditionalScaleFormatCSV() { - additionalScaleFormatStringArgsCsv = null; - additionalScaleFormatStringArgs = null; - } - - /** - */ - public void resetMemoDirectory() { - memoDirectory = null; - } - - /** - */ - public void resetKeepMemoFiles() { - keepMemoFiles = false; - } - - /** - */ - public void resetDownsampling() { - downsampling = Downsampling.SIMPLE; - } - - /** - */ - public void resetOverwrite() { - overwrite = false; - } - - /** - */ - public void resetFillValue() { - fillValue = null; - } - - /** - */ - public void resetReaderOptions() { - readerOptions = new ArrayList(); - } - - /** - */ - public void resetNoHCS() { - noHCS = false; - } - - /** - */ - public void resetNoOMEMeta() { - noOMEMeta = false; - } - - /** - */ - public void resetNoRootGroup() { - noRootGroup = false; - } - - /** - */ - public void resetReuseExistingResolutions() { - reuseExistingResolutions = false; - } - - /** - */ - public void resetMinImageSize() { - minSize = MIN_SIZE; - } - - /** - */ - public void resetDimensionOrder() { - dimensionOrder = DimensionOrder.XYZCT; - } - // Option getters /** diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java index 426bd62b..5a95b65a 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/ZarrTest.java @@ -995,6 +995,9 @@ public void testUnsupportedOpenCVType() throws Exception { public void testUnsupportedOpenCVTypeAPI() throws Exception { input = fake("pixelType", "int32"); Converter apiConverter = new Converter(); + CommandLine cmd = new CommandLine(apiConverter); + cmd.parseArgs(); // this sets default values for all options + apiConverter.setInputPath(input.toString()); apiConverter.setOutputPath(output.toString()); apiConverter.setDownsampling(Downsampling.AREA); @@ -1938,6 +1941,9 @@ public void testOptionsAPI() throws Exception { input = fake("series", "2", "sizeX", "4096", "sizeY", "4096"); Converter apiConverter = new Converter(); + CommandLine cmd = new CommandLine(apiConverter); + cmd.parseArgs(); // this sets default values for all options + apiConverter.setInputPath(input.toString()); apiConverter.setOutputPath(output.toString()); apiConverter.setSeriesList(Collections.singletonList(1)); @@ -1992,6 +1998,9 @@ public void testResetOptions() throws Exception { input = fake("series", "2", "sizeX", "4096", "sizeY", "4096"); Converter apiConverter = new Converter(); + CommandLine cmd = new CommandLine(apiConverter); + cmd.parseArgs(); // this sets default values for all options + apiConverter.setInputPath(input.toString()); apiConverter.setOutputPath(output.toString()); apiConverter.setSeriesList(Collections.singletonList(1)); @@ -2004,13 +2013,15 @@ public void testResetOptions() throws Exception { assertEquals(apiConverter.getTileWidth(), 128); assertEquals(apiConverter.getTileHeight(), 128); - apiConverter.resetInputPath(); + apiConverter.call(); // do a conversion + + cmd.parseArgs(); // this should reset default values for all options + assertEquals(apiConverter.getInputPath(), null); apiConverter.setInputPath(input.toString()); - apiConverter.resetOptions(); - assertEquals(apiConverter.getInputPath(), null); + assertEquals(apiConverter.getInputPath(), input.toString()); assertEquals(apiConverter.getOutputPath(), null); assertEquals(apiConverter.getSeriesList().size(), 0); assertEquals(apiConverter.getTileWidth(), 1024); From a4bb062637271e13fdaed70ddc2b7ee61c6e6b9a Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Tue, 31 Oct 2023 09:42:34 -0500 Subject: [PATCH 17/27] Update to jzarr 0.4.2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 52d809f0..2bcad87c 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'ome:formats-gpl:6.13.0' implementation 'info.picocli:picocli:4.6.1' implementation 'com.univocity:univocity-parsers:2.8.4' - implementation 'dev.zarr:jzarr:0.4.0' + implementation 'dev.zarr:jzarr:0.4.2' // implementation 'org.carlspring.cloud.aws:s3fs-nio:1.0-SNAPSHOT' // implementation 'io.nextflow:nxf-s3fs:1.1.0' implementation 'org.lasersonlab:s3fs:2.2.3' From e095dfc2aa24f4975f77f07de5a0e866653c070d Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Mon, 6 Nov 2023 12:30:16 -0600 Subject: [PATCH 18/27] Rename notifyTotalCounts to notifyStart in progress API --- src/main/java/com/glencoesoftware/bioformats2raw/Converter.java | 2 +- .../com/glencoesoftware/bioformats2raw/IProgressListener.java | 2 +- .../glencoesoftware/bioformats2raw/NoOpProgressListener.java | 2 +- .../com/glencoesoftware/bioformats2raw/ProgressBarListener.java | 2 +- .../bioformats2raw/test/TestProgressListener.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java index 58d2a391..7be611d0 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/Converter.java @@ -1347,7 +1347,7 @@ public void convert() totalTiles += count; } } - getProgressListener().notifyTotalCounts(seriesList.size(), totalTiles); + getProgressListener().notifyStart(seriesList.size(), totalTiles); for (Integer index : seriesList) { try { diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java index d90a3359..f69821d1 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/IProgressListener.java @@ -18,7 +18,7 @@ public interface IProgressListener extends EventListener { * @param seriesCount total number of series * @param chunkCount total number of chunks */ - void notifyTotalCounts(int seriesCount, long chunkCount); + void notifyStart(int seriesCount, long chunkCount); /** * Indicates the beginning of processing a particular series. diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java index 4c0a04a4..f0de1467 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/NoOpProgressListener.java @@ -10,7 +10,7 @@ public class NoOpProgressListener implements IProgressListener { @Override - public void notifyTotalCounts(int seriesCount, long chunkCount) { + public void notifyStart(int seriesCount, long chunkCount) { } @Override diff --git a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java index 2d3e00da..c9dc5fe7 100644 --- a/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java +++ b/src/main/java/com/glencoesoftware/bioformats2raw/ProgressBarListener.java @@ -33,7 +33,7 @@ public ProgressBarListener(String level) { } @Override - public void notifyTotalCounts(int seriesCount, long chunkCount) { + public void notifyStart(int seriesCount, long chunkCount) { // intentional no-op } diff --git a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java index 59cbd49c..41a4b1cd 100644 --- a/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java +++ b/src/test/java/com/glencoesoftware/bioformats2raw/test/TestProgressListener.java @@ -22,7 +22,7 @@ public class TestProgressListener implements IProgressListener { private long totalTiles = 0; @Override - public void notifyTotalCounts(int seriesCount, long tileCount) { + public void notifyStart(int seriesCount, long tileCount) { totalTiles = tileCount; } From 752067a1cd304f93e9da6013e2853bb2c1dab987 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 15 Nov 2023 14:13:25 -0600 Subject: [PATCH 19/27] Release version 0.8.0-rc1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2d6736eb..03e27982 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.glencoesoftware' -version = '0.7.1-SNAPSHOT' +version = '0.8.0-rc1' mainClassName = 'com.glencoesoftware.bioformats2raw.Converter' sourceCompatibility = 1.8 From 7648b1659330b31b50646f7c561e95d67512062b Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 15 Nov 2023 14:14:19 -0600 Subject: [PATCH 20/27] Bump version to 0.8.0-SNAPSHOT --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 03e27982..2e38be51 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.glencoesoftware' -version = '0.8.0-rc1' +version = '0.8.0-SNAPSHOT' mainClassName = 'com.glencoesoftware.bioformats2raw.Converter' sourceCompatibility = 1.8 From 8c4296ebad2de0ac641407f6c02fc4601f8024c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besson?= Date: Tue, 28 Nov 2023 12:20:17 +0000 Subject: [PATCH 21/27] Add GPL license metadata to published POM --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 2e38be51..d7ed27bc 100644 --- a/build.gradle +++ b/build.gradle @@ -115,6 +115,14 @@ publishing { publications { bioformats2raw(MavenPublication) { from components.java + pom { + licenses { + license { + name = 'GNU General Public License version 2' + url = 'http://www.gnu.org/licenses/gpl-2.0.txt' + } + } + } } } From e6a4f3d94f5ec4913eebbd4cd12506cde0bef272 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Tue, 28 Nov 2023 09:59:45 -0600 Subject: [PATCH 22/27] Update to Bio-Formats 7.0.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d7ed27bc..0d498935 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ configurations.all { dependencies { implementation 'net.java.dev.jna:jna:5.10.0' - implementation 'ome:formats-gpl:7.0.0' + implementation 'ome:formats-gpl:7.0.1' implementation 'info.picocli:picocli:4.6.1' implementation 'com.univocity:univocity-parsers:2.8.4' implementation 'dev.zarr:jzarr:0.4.2' From 7d1e483eb21847706376df69ff7cf1f155bbab0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besson?= Date: Thu, 30 Nov 2023 12:13:31 +0000 Subject: [PATCH 23/27] Bump logback to version 1.3.13 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 03278d4a..a7221734 100644 --- a/build.gradle +++ b/build.gradle @@ -45,8 +45,8 @@ dependencies { // implementation 'io.nextflow:nxf-s3fs:1.1.0' implementation 'org.lasersonlab:s3fs:2.2.3' implementation 'javax.xml.bind:jaxb-api:2.3.0' - implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.4' - implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.4' + implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.13' + implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.13' implementation 'org.openpnp:opencv:4.7.0-0' From 8066afd54b770de1ac6f459e1f89fccea69461b8 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Wed, 6 Dec 2023 10:43:23 -0600 Subject: [PATCH 24/27] Bump logback to 1.3.14 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a7221734..f2a6dece 100644 --- a/build.gradle +++ b/build.gradle @@ -45,8 +45,8 @@ dependencies { // implementation 'io.nextflow:nxf-s3fs:1.1.0' implementation 'org.lasersonlab:s3fs:2.2.3' implementation 'javax.xml.bind:jaxb-api:2.3.0' - implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.13' - implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.13' + implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.14' + implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.14' implementation 'org.openpnp:opencv:4.7.0-0' From 639ab793386358b740d0f18b78033828ba0ec04d Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 7 Dec 2023 08:19:22 -0600 Subject: [PATCH 25/27] Release 0.8.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f2a6dece..53188746 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.glencoesoftware' -version = '0.8.0-SNAPSHOT' +version = '0.8.0' mainClassName = 'com.glencoesoftware.bioformats2raw.Converter' sourceCompatibility = 1.8 From 49eeb848e1b40116511b40d4ee5677ec04248d65 Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Thu, 7 Dec 2023 08:20:13 -0600 Subject: [PATCH 26/27] Bump version to 0.9.0-SNAPSHOT --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 53188746..affaaad8 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.glencoesoftware' -version = '0.8.0' +version = '0.9.0-SNAPSHOT' mainClassName = 'com.glencoesoftware.bioformats2raw.Converter' sourceCompatibility = 1.8 From 162e20982aaba3e54fda6cf050b3e42a931e750f Mon Sep 17 00:00:00 2001 From: Melissa Linkert Date: Mon, 11 Dec 2023 16:48:56 -0600 Subject: [PATCH 27/27] Update to Bio-Formats 7.1.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index affaaad8..4176526a 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ configurations.all { dependencies { implementation 'net.java.dev.jna:jna:5.10.0' - implementation 'ome:formats-gpl:7.0.1' + implementation 'ome:formats-gpl:7.1.0' implementation 'info.picocli:picocli:4.7.5' implementation 'com.univocity:univocity-parsers:2.8.4' implementation 'dev.zarr:jzarr:0.4.2'