Commit 347325b9 authored by danyfel80's avatar danyfel80
Browse files

well plate reader im merge

parent 966aa0ac
package plugins.adufour.hcs.io;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import danyfel80.wells.data.IField;
import danyfel80.wells.data.IPlate;
import danyfel80.wells.data.IWell;
import danyfel80.wells.data.columbus.ColumbusField;
import danyfel80.wells.data.im.ImChannel;
import danyfel80.wells.data.im.ImField;
import danyfel80.wells.data.im.ImPlane;
import danyfel80.wells.data.im.ImPlate;
import danyfel80.wells.data.im.ImTimepoint;
import danyfel80.wells.util.MessageProgressListener;
import danyfel80.wells.util.stream.StreamUtils;
import icy.image.IcyBufferedImage;
import icy.image.colormap.IcyColorMap;
import icy.image.colormap.LinearColorMap;
import icy.sequence.Sequence;
import icy.type.dimension.Dimension2D;
import icy.type.dimension.Dimension2D.Double;
import ome.xml.meta.OMEXMLMetadata;
import ome.xml.model.primitives.PositiveInteger;
/**
* Well plate reader for plates exported by the Image Mining software.
*
* @author Daniel Felipe Gonzalez Obando
*/
public class WellPlateReader_Im extends AbstractWellPlateReader
{
@Override
public String getSystemName()
{
return "IM";
}
@Override
public boolean isValidPlate(File file)
{
if (!file.exists() || !file.isDirectory())
return false;
Path folderPath = file.toPath();
Path xmlFile = Paths.get("" + folderPath.getParent(), folderPath.getFileName() + ".xml");
// Check if an XML descriptor exists next to this directory
return Files.exists(xmlFile);
}
@Override
public Future<ImPlate> loadPlateFromFolder(File folder, MessageProgressListener progressListener)
{
ExecutorService executor = Executors.newSingleThreadExecutor((Runnable r) -> {
return new Thread(r, "ImWellPlateReader");
});
Future<ImPlate> future = executor.submit(() -> {
return loadPlateFromFolder_internal(folder, progressListener);
});
executor.shutdown();
return future;
}
private ImPlate loadPlateFromFolder_internal(File folder, MessageProgressListener progressListener)
throws IOException
{
Path xmlFilePath;
{
Path folderPath = folder.toPath();
xmlFilePath = Paths.get("" + folderPath.getParent(), folderPath.getFileName() + ".xml");
}
if (progressListener != null)
{
progressListener.notifyProgress(-1, "Loading well plate: " + xmlFilePath);
}
ImPlate plate = new ImPlate.Builder(xmlFilePath.toString(), folder.toString())
.progressListener(progressListener).build();
if (progressListener != null)
{
progressListener.notifyProgress(1, "Well plate loaded: " + xmlFilePath);
}
return plate;
}
@Override
public Future<? extends Sequence> loadField(IPlate plate, IWell well, IField field, Sequence sequence,
MessageProgressListener progressListener)
{
CompletableFuture<Sequence> future = new CompletableFuture<Sequence>();
if (!(field instanceof ImField))
{
future.completeExceptionally(
new ClassCastException("Provided field is not of type " + ColumbusField.class.getName()));
return future;
}
if (!(plate instanceof ImPlate))
{
future.completeExceptionally(
new ClassCastException("Provided field is not of type " + ColumbusField.class.getName()));
return future;
}
if (sequence == null)
{
sequence = new Sequence();
}
sequence.beginUpdate();
ImPlate imPlate = (ImPlate) plate;
OMEXMLMetadata metadata = sequence.getOMEXMLMetadata();
metadata.setPlateName(imPlate.getName(), 0);
metadata.setPlateID(imPlate.getId(), 0);
metadata.setPlateRows(new PositiveInteger(imPlate.getDimension().height), 0);
metadata.setPlateColumns(new PositiveInteger(imPlate.getDimension().width), 0);
sequence.setPositionX(field.getPosition().getX());
sequence.setPositionY(field.getPosition().getY());
Dimension2D.Double pixelSize = new Dimension2D.Double();
Map<Integer, String> channelNames = new HashMap<>();
Map<Integer, IcyColorMap> channelColors = new HashMap<>();
try
{
loadPlanes(imPlate, (ImField) field, sequence, pixelSize, channelNames, channelColors);
sequence.setPixelSizeX(pixelSize.getSizeX());
sequence.setPixelSizeY(pixelSize.getSizeY());
for (Entry<Integer, String> entry : channelNames.entrySet())
{
sequence.setChannelName(entry.getKey(), entry.getValue());
}
for (Entry<Integer, IcyColorMap> entry : channelColors.entrySet())
{
sequence.setColormap(entry.getKey(), entry.getValue(), true);
}
}
finally
{
sequence.endUpdate();
}
future.complete(sequence);
return future;
}
private void loadPlanes(ImPlate plate, ImField field, Sequence sequence, Double pixelSize,
Map<Integer, String> channelNames, Map<Integer, IcyColorMap> channelColors)
{
List<List<IcyBufferedImage>> planes = field.getPlanes().values().stream()
.sorted(Comparator.comparingDouble(ImPlane::getPositionZ))
.map(StreamUtils.wrapFunction(
plane -> loadPlane(sequence, pixelSize, channelNames, channelColors, plate, field, plane)))
.collect(Collectors.toList());
int z = 0, t;
for (Iterator<List<IcyBufferedImage>> itZ = planes.iterator(); itZ.hasNext();)
{
List<IcyBufferedImage> planeImages = (List<IcyBufferedImage>) itZ.next();
t = 0;
for (Iterator<IcyBufferedImage> itT = planeImages.iterator(); itT.hasNext();)
{
IcyBufferedImage image = (IcyBufferedImage) itT.next();
sequence.setImage(t, z, image);
t++;
}
z++;
}
}
private List<IcyBufferedImage> loadPlane(Sequence sequence, Dimension2D.Double pixelSize,
Map<Integer, String> channelNames, Map<Integer, IcyColorMap> channelColors, ImPlate plate, ImField field,
ImPlane plane)
{
List<IcyBufferedImage> timeImages = plane.getTimepoints().values().stream()
.sorted(Comparator.comparingLong(ImTimepoint::getId))
.map(StreamUtils.wrapFunction(
t -> loadTimePoint(sequence, pixelSize, channelNames, channelColors, plate, field, plane, t)))
.collect(Collectors.toList());
return timeImages;
}
private IcyBufferedImage loadTimePoint(Sequence sequence, Dimension2D.Double pixelSize,
Map<Integer, String> channelNames, Map<Integer, IcyColorMap> channelColors, ImPlate plate, ImField field,
ImPlane plane, ImTimepoint t) throws IOException
{
ImChannel firstChannel = t.getChannels().values().stream().findFirst().get();
pixelSize.setSize(firstChannel.getImage().getResolution());
String imageFile = firstChannel.getImage().getUrl();
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
try
{
reader.setInput(new FileInputStream(imageFile));
int nChannels = t.getChannels().size();
List<BufferedImage> channels = new ArrayList<>(nChannels);
List<IcyColorMap> colorMaps = LinearColorMap.getLinearColorMaps(false, false);
for (int ch = 0; ch < nChannels; ch++)
{
ImageReadParam p = new ImageReadParam();
p.setDestination(
new BufferedImage(reader.getWidth(ch), reader.getHeight(ch), BufferedImage.TYPE_USHORT_GRAY));
channels.add(reader.read(ch, p));
channelNames.put(ch, "ch" + ch);
channelColors.put(ch, colorMaps.get((1 + ch) % colorMaps.size()));
}
return IcyBufferedImage.createFrom(channels);
}
finally
{
reader.dispose();
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment