Skip to content

Commit 76cc54d

Browse files
authored
Merge pull request #3471 from melissalinkert/qptiff-metadata
QPTIFF: metadata fixes
2 parents 290b2cc + c0decf7 commit 76cc54d

File tree

2 files changed

+79
-15
lines changed

2 files changed

+79
-15
lines changed

components/formats-bsd/src/loci/formats/in/BaseTiffReader.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,8 @@ protected void initStandardMetadata() throws FormatException, IOException {
230230
putInt("MinSampleValue", firstIFD, IFD.MIN_SAMPLE_VALUE);
231231
putInt("MaxSampleValue", firstIFD, IFD.MAX_SAMPLE_VALUE);
232232

233-
TiffRational xResolution = firstIFD.getIFDRationalValue(IFD.X_RESOLUTION);
234-
TiffRational yResolution = firstIFD.getIFDRationalValue(IFD.Y_RESOLUTION);
235-
236-
if (xResolution != null) {
237-
put("XResolution", xResolution.doubleValue());
238-
}
239-
if (yResolution != null) {
240-
put("YResolution", yResolution.doubleValue());
241-
}
233+
putDouble("XResolution", firstIFD, IFD.X_RESOLUTION);
234+
putDouble("YResolution", firstIFD, IFD.Y_RESOLUTION);
242235

243236
int planar = firstIFD.getIFDIntValue(IFD.PLANAR_CONFIGURATION);
244237
String planarConfig = null;
@@ -252,8 +245,8 @@ protected void initStandardMetadata() throws FormatException, IOException {
252245
}
253246
put("PlanarConfiguration", planarConfig);
254247

255-
putInt("XPosition", firstIFD, IFD.X_POSITION);
256-
putInt("YPosition", firstIFD, IFD.Y_POSITION);
248+
putDouble("XPosition", firstIFD, IFD.X_POSITION);
249+
putDouble("YPosition", firstIFD, IFD.Y_POSITION);
257250
putInt("FreeOffsets", firstIFD, IFD.FREE_OFFSETS);
258251
putInt("FreeByteCounts", firstIFD, IFD.FREE_BYTE_COUNTS);
259252
putInt("GrayResponseUnit", firstIFD, IFD.GRAY_RESPONSE_UNIT);
@@ -575,6 +568,15 @@ protected void putString(String key, IFD ifd, int tag) {
575568
put(key, value);
576569
}
577570

571+
protected void putDouble(String key, IFD ifd, int tag) {
572+
if (ifd.getIFDValue(tag) instanceof Number) {
573+
Number number = (Number) ifd.getIFDValue(tag);
574+
if (number != null) {
575+
put(key, number.doubleValue());
576+
}
577+
}
578+
}
579+
578580
// -- Internal FormatReader API methods --
579581

580582
/* @see loci.formats.FormatReader#initFile(String) */

components/formats-gpl/src/loci/formats/in/VectraReader.java

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,16 @@
2626
package loci.formats.in;
2727

2828
import java.io.IOException;
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.List;
2932
import javax.xml.parsers.ParserConfigurationException;
3033

3134
import org.slf4j.Logger;
3235
import org.slf4j.LoggerFactory;
3336

3437
import loci.common.DataTools;
38+
import loci.common.Location;
3539
import loci.common.RandomAccessInputStream;
3640
import loci.common.xml.XMLTools;
3741
import loci.formats.CoreMetadata;
@@ -42,6 +46,7 @@
4246
import loci.formats.tiff.IFD;
4347
import loci.formats.tiff.PhotoInterp;
4448
import loci.formats.tiff.TiffParser;
49+
import loci.formats.tiff.TiffRational;
4550
import ome.xml.model.primitives.Color;
4651
import ome.xml.model.primitives.NonNegativeInteger;
4752

@@ -68,10 +73,17 @@ public class VectraReader extends BaseTiffReader {
6873
/** TIFF image description prefix for PerkinElmer Vectra/QPTIFF files. */
6974
private static final String SOFTWARE_CHECK = "PerkinElmer-QPI";
7075

76+
private static final String ANNOTATION_SUFFIX = "_annotations.xml";
77+
private static final List<String> EXTRA_FILES = Arrays.asList(
78+
"CoverslipMask.tif", "FocusMap.tif", "Label.tif",
79+
"OverviewBF.tif", "OverviewFL.tif", "SampleMask.tif"
80+
);
81+
7182
// -- Fields --
7283

7384
private int pyramidDepth = 1;
7485
private String profileXML;
86+
private List<String> allFiles = new ArrayList<String>();
7587

7688
// -- Constructor --
7789

@@ -82,6 +94,7 @@ public VectraReader() {
8294
noSubresolutions = true;
8395
suffixSufficient = false;
8496
canSeparateSeries = false;
97+
hasCompanionFiles = true;
8598
}
8699

87100
// -- IFormatReader API methods --
@@ -114,6 +127,19 @@ public boolean isThisType(String name, boolean open) {
114127
}
115128
}
116129

130+
/* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */
131+
@Override
132+
public String[] getSeriesUsedFiles(boolean noPixels) {
133+
if (allFiles.size() == 1) {
134+
return super.getSeriesUsedFiles(noPixels);
135+
}
136+
if (noPixels) {
137+
return allFiles.subList(
138+
1, allFiles.size()).toArray(new String[allFiles.size() - 1]);
139+
}
140+
return allFiles.toArray(new String[allFiles.size()]);
141+
}
142+
117143
/**
118144
* @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int)
119145
*/
@@ -150,6 +176,9 @@ public void close(boolean fileOnly) throws IOException {
150176
if (!fileOnly) {
151177
pyramidDepth = 1;
152178
profileXML = null;
179+
if (allFiles != null) {
180+
allFiles.clear();
181+
}
153182
}
154183
}
155184

@@ -188,6 +217,21 @@ public int getOptimalTileHeight() {
188217
protected void initStandardMetadata() throws FormatException, IOException {
189218
super.initStandardMetadata();
190219

220+
// look for companion files
221+
222+
Location currentFile = new Location(currentId).getAbsoluteFile();
223+
allFiles.add(currentFile.getAbsolutePath());
224+
Location parent = currentFile.getParentFile();
225+
String[] list = parent.list(true);
226+
Arrays.sort(list);
227+
for (String f : list) {
228+
if (f.endsWith(ANNOTATION_SUFFIX) || EXTRA_FILES.contains(f)) {
229+
allFiles.add(new Location(parent, f).getAbsolutePath());
230+
}
231+
}
232+
233+
// set up IFDs
234+
191235
ifds = tiffParser.getMainIFDs();
192236
thumbnailIFDs = null;
193237

@@ -276,6 +320,7 @@ protected void initMetadataStore() throws FormatException {
276320
MetadataStore store = makeFilterMetadata();
277321

278322
for (int i=0; i<getSeriesCount(); i++) {
323+
setSeries(i);
279324
int coreIndex = seriesToCoreIndex(i);
280325
store.setImageName(getImageName(coreIndex), i);
281326
store.setImageDescription("", i);
@@ -287,11 +332,31 @@ protected void initMetadataStore() throws FormatException {
287332

288333
store.setPixelsPhysicalSizeX(FormatTools.getPhysicalSizeX(x), i);
289334
store.setPixelsPhysicalSizeY(FormatTools.getPhysicalSizeY(y), i);
335+
336+
TiffRational xPos = ifd.getIFDRationalValue(IFD.X_POSITION);
337+
TiffRational yPos = ifd.getIFDRationalValue(IFD.Y_POSITION);
338+
int unitMultiplier = ifd.getResolutionMultiplier();
339+
340+
for (int c=0; c<getEffectiveSizeC(); c++) {
341+
store.setPlaneTheZ(new NonNegativeInteger(0), i, c);
342+
store.setPlaneTheT(new NonNegativeInteger(0), i, c);
343+
store.setPlaneTheC(new NonNegativeInteger(c), i, c);
344+
345+
if (xPos != null) {
346+
double position = xPos.doubleValue() * unitMultiplier;
347+
store.setPlanePositionX(FormatTools.getPhysicalSizeX(position), i, c);
348+
}
349+
if (yPos != null) {
350+
double position = yPos.doubleValue() * unitMultiplier;
351+
store.setPlanePositionY(FormatTools.getPhysicalSizeY(position), i, c);
352+
}
353+
}
290354
}
355+
setSeries(0);
291356

292357
// each high-resolution IFD has an XML description that needs to be parsed
293358

294-
for (int c=0; c<getSizeC(); c++) {
359+
for (int c=0; c<getEffectiveSizeC(); c++) {
295360
String xml = getIFDComment(c);
296361
try {
297362
Element root = XMLTools.parseDOM(xml).getDocumentElement();
@@ -375,9 +440,6 @@ else if (name.equals("Objective") && c == 0) {
375440
else if (name.equals("ExposureTime")) {
376441
Time exposure = new Time(DataTools.parseDouble(value), UNITS.MICROSECOND);
377442
store.setPlaneExposureTime(exposure, 0, c);
378-
store.setPlaneTheZ(new NonNegativeInteger(0), 0, c);
379-
store.setPlaneTheT(new NonNegativeInteger(0), 0, c);
380-
store.setPlaneTheC(new NonNegativeInteger(c), 0, c);
381443
}
382444
}
383445
}

0 commit comments

Comments
 (0)