Skip to content

Commit

Permalink
MCD: calculate channel count based on metadata, not pixel bytes
Browse files Browse the repository at this point in the history
In some cases, the number of pixel bytes stored for a particular acquisition
may not match the expected number of bytes, so calculating the channel count
based on the stored number of pixel bytes will cause problems.

Instead of throwing an exception, this sets the channel count to the
number of channels linked to the acquisition, and logs that
some image data may be blank. This more closely matches the behavior
of MCDViewer (the vendor software).
  • Loading branch information
melissalinkert committed Aug 6, 2024
1 parent 67d9edd commit bc5ec8f
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions src/main/java/com/glencoesoftware/bioformats2raw/MCDReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,35 +219,48 @@ protected void initFile(String id) throws FormatException, IOException {
m.sizeZ = 1;
m.sizeT = 1;

LOGGER.debug("Acquisition size: {} x {}, {} bytes per pixel",
acq.sizeX, acq.sizeY, acq.bpp);

int plane = acq.sizeX * acq.sizeY * acq.bpp;
long totalBytes = acq.end - acq.start;
LOGGER.debug("Total pixel bytes: {}", totalBytes);
if (totalBytes <= 0) {
LOGGER.debug(
"Skipping acquistiion {} with 0 pixel bytes", acq.description);
"Skipping acquisition {} with 0 pixel bytes", acq.description);
acquisitions.remove(acq);
a--;
continue;
}
long totalPlanes = totalBytes / plane;
LOGGER.debug("Detected {} planes in acquisition", totalPlanes);
if (totalPlanes > Integer.MAX_VALUE) {
throw new FormatException(
"Too many channels (" + totalPlanes + ") for series " + core.size());
}
m.sizeC = (int) totalPlanes;
m.imageCount = m.sizeC * m.sizeZ * m.sizeT;
m.dimensionOrder = "XYCZT";
m.littleEndian = true;
core.add(m);

// the XML defines a big list of all channels across all acquisitions
// map each channel to the correct location in the correct acquisition
acq.channelIndexes = new int[m.sizeC];
acq.channelIndexes = new ArrayList<Integer>();
for (int c=0; c<channels.size(); c++) {
Channel channel = channels.get(c);
if (channel.acqID == acq.id) {
acq.channelIndexes[channel.index] = c;
while (channel.index >= acq.channelIndexes.size()) {
acq.channelIndexes.add(-1);
}
acq.channelIndexes.set(channel.index, c);
m.sizeC++;
}
}

m.imageCount = m.sizeC * m.sizeZ * m.sizeT;
if (totalPlanes < m.imageCount) {
LOGGER.warn("Not enough pixel bytes in file; images may be blank");
}

m.dimensionOrder = "XYCZT";
m.littleEndian = true;
core.add(m);
}

MetadataStore store = makeFilterMetadata();
Expand All @@ -263,8 +276,14 @@ protected void initFile(String id) throws FormatException, IOException {
Acquisition acq = acquisitions.get(a);
store.setImageName(acq.description, imageIndex);

for (int c=0; c<acq.channelIndexes.length; c++) {
Channel channel = channels.get(acq.channelIndexes[c]);
for (int c=0; c<acq.channelIndexes.size(); c++) {
int index = acq.channelIndexes.get(c);
if (index < 0) {
LOGGER.warn("Missing channel definition, channel #{}, image #{}",
c, imageIndex);
continue;
}
Channel channel = channels.get(index);

// this is kind of wrong, but the reference viewer
// exposes both the name and label (which are often slightly different)
Expand Down Expand Up @@ -542,7 +561,7 @@ class Acquisition {
public int bpp;

/** Indexes into list of channels; length matches SizeC. */
public int[] channelIndexes;
public List<Integer> channelIndexes;
}

/**
Expand Down

0 comments on commit bc5ec8f

Please sign in to comment.