Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MCD: calculate channel count based on metadata, not pixel bytes #255

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions src/main/java/com/glencoesoftware/bioformats2raw/MCDReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
}

LOGGER.debug("Reading raw acquisition #{}", getSeries() - panoramas.size());
in.seek(acquisitions.get(getSeries() - panoramas.size()).start);
Acquisition currentAcq = acquisitions.get(getSeries() - panoramas.size());
in.seek(currentAcq.start);
LOGGER.debug("File offset = {}", in.getFilePointer());

int bpp = FormatTools.getBytesPerPixel(getPixelType());
Expand All @@ -91,10 +92,20 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h)
for (int row=0; row<h; row++) {
in.skipBytes(x * (skip + bpp));
for (int col=0; col<w; col++) {
in.read(buf, ((row * w) + col) * bpp, bpp);
in.skipBytes(skip);
// don't allow reading past the defined end of the pixel data
// for this acquisition (which may be in the middle of the file)
if (in.getFilePointer() < currentAcq.end) {
in.read(buf, ((row * w) + col) * bpp, bpp);
in.skipBytes(skip);
}
else {
break;
}
}
in.skipBytes((skip + bpp) * (getSizeX() - w - x));
if (in.getFilePointer() >= currentAcq.end) {
break;
}
}

return buf;
Expand Down Expand Up @@ -219,35 +230,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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to signify anything different than null? Are we checking this value anywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will get checked in line 291/292. If null is preferable, it would be easy enough to rework that check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A ha, gotcha. No, that's fine.

}
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 +287,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 +572,7 @@ class Acquisition {
public int bpp;

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

/**
Expand Down