Created
April 16, 2024 01:53
-
-
Save bogovicj/f8e4ffd7ce5b1d377565649a35d597d5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#@ File(styles="both") root | |
#@ String(value="/") datasetPath | |
/* | |
* If you used Fiji to export a multi-scale OME-Zarr image using average downsampling | |
* between approximately March 13 and April 15 2024, the translation metadata may be incorrect. | |
* | |
* Running this script will correct the metadata. | |
* | |
* John Bogovic | |
*/ | |
String normDatasetPath = N5URI.normalizeGroupPath(datasetPath); | |
N5Writer n5 = new N5Factory() | |
.gsonBuilder(OmeNgffMetadataParser.gsonBuilder()) | |
.openWriter(root.getAbsolutePath()); | |
N5TreeNode treeRoot = N5DatasetDiscoverer.discover(n5, | |
Collections.singletonList(new N5GenericSingleScaleMetadataParser()), | |
Collections.singletonList(new OmeNgffMetadataParser())); | |
Optional<N5TreeNode> node = treeRoot.getDescendant(datasetPath == "/" ? "" : datasetPath); | |
if (node.isPresent()) { | |
N5Metadata metadata = node.get().getMetadata(); | |
if (!(metadata instanceof OmeNgffMetadata)) { | |
System.err.println("Could not find NGFF metadata at: " + datasetPath); | |
return; | |
} | |
final OmeNgffMetadata ngffMeta = (OmeNgffMetadata)metadata; | |
ScaleCoordinateTransformation baseScale = null; | |
for( OmeNgffDataset dataset : ngffMeta.multiscales[0].datasets ) { | |
ValuePair<ScaleCoordinateTransformation, TranslationCoordinateTransformation> tforms = getTransformsMulti(dataset); | |
if( baseScale == null ) | |
{ | |
baseScale = tforms.getA(); | |
continue; | |
} | |
correct(baseScale, tforms); | |
Optional<N5TreeNode> childNode = treeRoot.getDescendant(normDatasetPath + "/" + dataset.path); | |
if(childNode.isPresent()) | |
{ | |
N5Metadata childMetadata = childNode.get().getMetadata(); | |
if( childMetadata instanceof NgffSingleScaleAxesMetadata ) | |
{ | |
NgffSingleScaleAxesMetadata ngffChildMetadata = (NgffSingleScaleAxesMetadata)childMetadata; | |
final ValuePair<ScaleCoordinateTransformation, TranslationCoordinateTransformation> tformsArray = getTransformsArray(ngffChildMetadata); | |
correct(baseScale, tformsArray); | |
n5.setAttribute( | |
N5URI.normalizeGroupPath(normDatasetPath + "/" + dataset.path), | |
"coordinateTransformations", ngffChildMetadata.getCoordinateTransformations()); | |
} | |
} | |
} | |
// write the new metadata out | |
n5.setAttribute(normDatasetPath, "multiscales", ngffMeta.multiscales); | |
} | |
else { | |
System.err.println("could not find : " + datasetPath); | |
} | |
def correct(ScaleCoordinateTransformation baseScale, ValuePair tforms) { | |
EPS = 1e-3; | |
ScaleCoordinateTransformation scale = tforms.getA(); | |
TranslationCoordinateTransformation translation = tforms.getB(); | |
res = baseScale.getScale(); | |
s = scale.getScale(); | |
t = translation.getTranslation(); | |
if( t[0] < 0.1 * EPS * s[0] ) | |
return; | |
int nd = scale.getScale().length; | |
if( translation.getTranslation().length != nd ) | |
{ | |
System.err.println("scale and translation different lengths"); | |
return; | |
} | |
for( int i = 0; i < nd; i++ ) | |
{ | |
double factor = s[i] / res[i]; | |
t[i] = res[i] * (0.5 * factor - 0.5); | |
} | |
} | |
def ValuePair validateTransforms(String path, CoordinateTransformation[] coordinateTransformations ) { | |
numTforms = coordinateTransformations.length; | |
if (numTforms != 2) { | |
System.err.println("Nothing to do, need 2 transforms. There are " + numTforms + " transforms at " + path); | |
return null; | |
} | |
CoordinateTransformation<?> fst = coordinateTransformations[0]; | |
CoordinateTransformation<?> snd = coordinateTransformations[1]; | |
if (!(fst instanceof ScaleCoordinateTransformation)) { | |
System.err.println("First transform not a scale transformation"); | |
return null; | |
} | |
if (!(snd instanceof TranslationCoordinateTransformation)) { | |
System.err.println("Second transform not a translation transformation"); | |
return null; | |
} | |
ScaleCoordinateTransformation scale = (ScaleCoordinateTransformation)fst; | |
TranslationCoordinateTransformation translation = (TranslationCoordinateTransformation)snd; | |
return new ValuePair(scale, translation); | |
} | |
def ValuePair getTransformsMulti(OmeNgffDataset dataset) { | |
return validateTransforms(dataset.path, dataset.coordinateTransformations) | |
} | |
def ValuePair getTransformsArray(NgffSingleScaleAxesMetadata meta) { | |
return validateTransforms(meta.getPath(), meta.getCoordinateTransformations()); | |
} | |
import java.io.File; | |
import java.util.Collections; | |
import java.util.Optional; | |
import org.janelia.saalfeldlab.n5.N5URI; | |
import org.janelia.saalfeldlab.n5.N5Writer; | |
import org.janelia.saalfeldlab.n5.universe.N5DatasetDiscoverer; | |
import org.janelia.saalfeldlab.n5.universe.N5Factory; | |
import org.janelia.saalfeldlab.n5.universe.N5TreeNode; | |
import org.janelia.saalfeldlab.n5.universe.metadata.N5GenericSingleScaleMetadataParser; | |
import org.janelia.saalfeldlab.n5.universe.metadata.N5Metadata; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.NgffSingleScaleAxesMetadata; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.OmeNgffMetadata; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.OmeNgffMultiScaleMetadata.OmeNgffDataset; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.CoordinateTransformation; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.ScaleCoordinateTransformation; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.coordinateTransformations.TranslationCoordinateTransformation; | |
import net.imglib2.util.ValuePair; | |
import org.janelia.saalfeldlab.n5.universe.metadata.ome.ngff.v04.OmeNgffMetadataParser; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment