19
19
import java .nio .file .Path ;
20
20
import java .nio .file .Paths ;
21
21
import java .util .ArrayList ;
22
- import java .util .Collections ;
23
22
import java .util .Comparator ;
24
23
import java .util .HashMap ;
25
24
import java .util .List ;
56
55
import loci .formats .ome .OMEXMLMetadata ;
57
56
import loci .formats .services .OMEXMLService ;
58
57
import loci .formats .services .OMEXMLServiceImpl ;
58
+ import ome .units .quantity .Quantity ;
59
59
import ome .xml .meta .OMEXMLMetadataRoot ;
60
60
import ome .xml .model .enums .DimensionOrder ;
61
61
import ome .xml .model .enums .EnumerationException ;
@@ -239,7 +239,8 @@ public class Converter implements Callable<Void> {
239
239
"(default: ${DEFAULT-VALUE})"
240
240
)
241
241
private volatile Class <?>[] extraReaders = new Class [] {
242
- PyramidTiffReader .class , MiraxReader .class , BioTekReader .class
242
+ PyramidTiffReader .class , MiraxReader .class ,
243
+ BioTekReader .class , ND2PlateReader .class
243
244
};
244
245
245
246
@ Option (
@@ -562,6 +563,12 @@ public void convert()
562
563
563
564
if (!noHCS ) {
564
565
noHCS = !hasValidPlate (meta );
566
+ int plateCount = meta .getPlateCount ();
567
+ if (!noHCS && plateCount > 1 ) {
568
+ throw new IllegalArgumentException (
569
+ "Found " + plateCount + " plates; only one can be converted. " +
570
+ "Use --no-hcs to as a work-around." );
571
+ }
565
572
}
566
573
else {
567
574
((OMEXMLMetadata ) meta ).resolveReferences ();
@@ -1522,35 +1529,84 @@ private void setSeriesLevelMetadata(int series, int resolutions)
1522
1529
multiscale .put ("type" , downsampling .getName ());
1523
1530
}
1524
1531
multiscale .put ("metadata" , metadata );
1525
- multiscale .put ("version" , nested ? "0.2 " : "0.1" );
1532
+ multiscale .put ("version" , nested ? "0.4 " : "0.1" );
1526
1533
multiscales .add (multiscale );
1527
- List <Map <String , String >> datasets = new ArrayList <Map <String , String >>();
1534
+
1535
+ IFormatReader v = null ;
1536
+ IMetadata meta = null ;
1537
+ String axisOrder = null ;
1538
+ try {
1539
+ v = readers .take ();
1540
+ meta = (IMetadata ) v .getMetadataStore ();
1541
+
1542
+ if (dimensionOrder != null ) {
1543
+ axisOrder = dimensionOrder .toString ();
1544
+ }
1545
+ else {
1546
+ axisOrder = v .getDimensionOrder ();
1547
+ }
1548
+ }
1549
+ finally {
1550
+ readers .put (v );
1551
+ }
1552
+
1553
+ List <Map <String , Object >> datasets = new ArrayList <Map <String , Object >>();
1528
1554
for (int r = 0 ; r < resolutions ; r ++) {
1529
1555
resolutionString = String .format (
1530
1556
scaleFormatString , getScaleFormatStringArgs (series , r ));
1531
1557
String lastPath = resolutionString .substring (
1532
1558
resolutionString .lastIndexOf ('/' ) + 1 );
1533
- datasets .add (Collections .singletonMap ("path" , lastPath ));
1534
- }
1535
- multiscale .put ("datasets" , datasets );
1536
1559
1537
- String axisOrder = null ;
1538
- if (dimensionOrder != null ) {
1539
- axisOrder = dimensionOrder .toString ();
1540
- }
1541
- else {
1542
- IFormatReader reader = readers .take ();
1543
- try {
1544
- axisOrder = reader .getDimensionOrder ();
1545
- }
1546
- finally {
1547
- readers .put (reader );
1560
+ List <Map <String , Object >> transforms =
1561
+ new ArrayList <Map <String , Object >>();
1562
+ Map <String , Object > scale = new HashMap <String , Object >();
1563
+ scale .put ("type" , "scale" );
1564
+ List <Double > axisValues = new ArrayList <Double >();
1565
+ double resolutionScale = Math .pow (PYRAMID_SCALE , r );
1566
+ for (int i =axisOrder .length ()-1 ; i >=0 ; i --) {
1567
+ Quantity axisScale = getScale (meta , series , axisOrder , i );
1568
+ String axisChar = axisOrder .substring (i , i + 1 ).toLowerCase ();
1569
+
1570
+ if (axisScale != null ) {
1571
+ // if physical dimension information is defined,
1572
+ // use it directly for dimensions that aren't scaled (Z and T)
1573
+ // increase it according to the resolution number for dimensions that
1574
+ // are scaled (X and Y)
1575
+ if (axisChar .equals ("x" ) || axisChar .equals ("y" )) {
1576
+ axisValues .add (axisScale .value ().doubleValue () * resolutionScale );
1577
+ }
1578
+ else {
1579
+ axisValues .add (axisScale .value ().doubleValue ());
1580
+ }
1581
+ }
1582
+ else {
1583
+ // if physical dimension information is not defined,
1584
+ // store the scale factor for the dimension in the current resolution,
1585
+ // i.e. 1.0 for everything other than X and Y
1586
+ if (axisChar .equals ("x" ) || axisChar .equals ("y" )) {
1587
+ axisValues .add (resolutionScale );
1588
+ }
1589
+ else {
1590
+ axisValues .add (1.0 );
1591
+ }
1592
+ }
1548
1593
}
1594
+ scale .put ("scale" , axisValues );
1595
+
1596
+ transforms .add (scale );
1597
+
1598
+ Map <String , Object > dataset = new HashMap <String , Object >();
1599
+ dataset .put ("path" , lastPath );
1600
+ dataset .put ("coordinateTransformations" , transforms );
1601
+ datasets .add (dataset );
1549
1602
}
1603
+ multiscale .put ("datasets" , datasets );
1604
+
1550
1605
List <Map <String , String >> axes = new ArrayList <Map <String , String >>();
1551
1606
for (int i =axisOrder .length ()-1 ; i >=0 ; i --) {
1552
1607
String axis = axisOrder .substring (i , i + 1 ).toLowerCase ();
1553
1608
String type = "space" ;
1609
+ Quantity scale = getScale (meta , series , axisOrder , i );
1554
1610
if (axis .equals ("t" )) {
1555
1611
type = "time" ;
1556
1612
}
@@ -1560,6 +1616,9 @@ else if (axis.equals("c")) {
1560
1616
Map <String , String > thisAxis = new HashMap <String , String >();
1561
1617
thisAxis .put ("name" , axis );
1562
1618
thisAxis .put ("type" , type );
1619
+ if (scale != null ) {
1620
+ thisAxis .put ("unit" , scale .unit ().getSymbol ());
1621
+ }
1563
1622
axes .add (thisAxis );
1564
1623
}
1565
1624
multiscale .put ("axes" , axes );
@@ -1573,6 +1632,33 @@ else if (axis.equals("c")) {
1573
1632
LOGGER .debug (" finished writing subgroup attributes" );
1574
1633
}
1575
1634
1635
+ private Quantity getScale (
1636
+ IMetadata meta , int series , String axisOrder , int axis )
1637
+ {
1638
+ if (meta == null ) {
1639
+ return null ;
1640
+ }
1641
+ int seriesIndex = seriesList .indexOf (series );
1642
+
1643
+ if (seriesIndex < 0 || seriesIndex >= meta .getImageCount ()) {
1644
+ return null ;
1645
+ }
1646
+
1647
+ String axisChar = axisOrder .substring (axis , axis + 1 ).toLowerCase ();
1648
+ switch (axisChar .charAt (0 )) {
1649
+ case 'x' :
1650
+ return meta .getPixelsPhysicalSizeX (seriesIndex );
1651
+ case 'y' :
1652
+ return meta .getPixelsPhysicalSizeY (seriesIndex );
1653
+ case 'z' :
1654
+ return meta .getPixelsPhysicalSizeZ (seriesIndex );
1655
+ case 't' :
1656
+ return meta .getPixelsTimeIncrement (seriesIndex );
1657
+ default :
1658
+ return null ;
1659
+ }
1660
+ }
1661
+
1576
1662
/**
1577
1663
* Takes exception from asynchronous execution and re-throw known exception
1578
1664
* types. If the end is reached with no known exception detected, either the
0 commit comments