Search in sources :

Example 66 with TiffParser

use of loci.formats.tiff.TiffParser in project bioformats by openmicroscopy.

the class TCSReader method initFile.

// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
    Location l = new Location(id).getAbsoluteFile();
    Location parent = l.getParentFile();
    String[] list = parent.list();
    Arrays.sort(list);
    boolean isXML = checkSuffix(id, XML_SUFFIX);
    if (list != null) {
        for (String file : list) {
            if (checkSuffix(file, XML_SUFFIX) && !isXML && isGroupFiles()) {
                xmlFile = new Location(parent, file).getAbsolutePath();
                break;
            } else if (checkSuffix(file, TiffReader.TIFF_SUFFIXES) && isXML) {
                initFile(new Location(parent, file).getAbsolutePath());
                return;
            }
        }
    }
    if (isXML)
        xmlFile = l.getAbsolutePath();
    super.initFile(id);
    MetadataStore store = makeFilterMetadata();
    in = new RandomAccessInputStream(id, 16);
    tiffParser = new TiffParser(in);
    tiffs = new ArrayList<String>();
    IFDList ifds = tiffParser.getIFDs();
    String date = ifds.get(0).getIFDStringValue(IFD.DATE_TIME);
    if (date != null) {
        datestamp = DateTools.getTime(date, "yyyy:MM:dd HH:mm:ss");
    }
    groupFiles();
    addGlobalMeta("Number of image files", tiffs.size());
    tiffReaders = new TiffReader[tiffs.size()];
    for (int i = 0; i < tiffReaders.length; i++) {
        tiffReaders[i] = new TiffReader();
    }
    tiffReaders[0].setId(tiffs.get(0));
    int[] ch = new int[ifds.size()];
    int[] idx = new int[ifds.size()];
    long[] stamp = new long[ifds.size()];
    int channelCount = 0;
    CoreMetadata ms0 = core.get(0);
    ms0.sizeZ = 1;
    ms0.sizeC = tiffReaders[0].getSizeC();
    ms0.dimensionOrder = isRGB() ? "XYC" : "XY";
    if (isGroupFiles()) {
        try {
            FilePattern fp = new FilePattern(new Location(currentId).getAbsoluteFile());
            AxisGuesser guesser = new AxisGuesser(fp, "XYTZC", 1, ifds.size(), 1, true);
            int[] axisTypes = guesser.getAxisTypes();
            int[] count = fp.getCount();
            for (int i = axisTypes.length - 1; i >= 0; i--) {
                if (axisTypes[i] == AxisGuesser.Z_AXIS) {
                    if (getDimensionOrder().indexOf('Z') == -1) {
                        ms0.dimensionOrder += 'Z';
                    }
                    ms0.sizeZ *= count[i];
                } else if (axisTypes[i] == AxisGuesser.C_AXIS) {
                    if (getDimensionOrder().indexOf('C') == -1) {
                        ms0.dimensionOrder += 'C';
                    }
                    ms0.sizeC *= count[i];
                }
            }
        } catch (NullPointerException e) {
        }
    }
    for (int i = 0; i < ifds.size(); i++) {
        String document = ifds.get(i).getIFDStringValue(IFD.DOCUMENT_NAME);
        if (document == null)
            continue;
        int index = document.indexOf("INDEX");
        String s = document.substring(8, index).trim();
        ch[i] = Integer.parseInt(s);
        if (ch[i] > channelCount)
            channelCount = ch[i];
        int space = document.indexOf(" ", index + 6);
        if (space < 0)
            continue;
        String n = document.substring(index + 6, space).trim();
        idx[i] = Integer.parseInt(n);
        date = document.substring(space, document.indexOf("FORMAT")).trim();
        stamp[i] = DateTools.getTime(date, DATE_FORMAT, ".");
        addGlobalMetaList("Timestamp for plane", stamp[i]);
    }
    ms0.sizeT = 0;
    // determine the axis sizes and ordering
    boolean unique = true;
    for (int i = 0; i < stamp.length; i++) {
        for (int j = i + 1; j < stamp.length; j++) {
            if (stamp[j] == stamp[i]) {
                unique = false;
                break;
            }
        }
        if (unique) {
            ms0.sizeT++;
            if (getDimensionOrder().indexOf('T') < 0) {
                ms0.dimensionOrder += 'T';
            }
        } else if (i > 0) {
            if ((ch[i] != ch[i - 1]) && getDimensionOrder().indexOf('C') < 0) {
                ms0.dimensionOrder += 'C';
            } else if (getDimensionOrder().indexOf('Z') < 0) {
                ms0.dimensionOrder += 'Z';
            }
        }
        unique = true;
    }
    if (getDimensionOrder().indexOf('Z') < 0)
        ms0.dimensionOrder += 'Z';
    if (getDimensionOrder().indexOf('C') < 0)
        ms0.dimensionOrder += 'C';
    if (getDimensionOrder().indexOf('T') < 0)
        ms0.dimensionOrder += 'T';
    if (getSizeC() == 0)
        ms0.sizeC = 1;
    if (getSizeT() == 0)
        ms0.sizeT = 1;
    if (channelCount == 0)
        channelCount = 1;
    if (getSizeZ() <= 1) {
        ms0.sizeZ = ifds.size() / (getSizeT() * channelCount);
    }
    ms0.sizeC *= channelCount;
    ms0.imageCount = getSizeZ() * getSizeT() * getSizeC();
    // cut up comment
    String comment = ifds.get(0).getComment();
    if (comment != null && comment.startsWith("[") && getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        String[] lines = comment.split("\n");
        for (String line : lines) {
            if (!line.startsWith("[")) {
                int eq = line.indexOf('=');
                if (eq < 0)
                    continue;
                String key = line.substring(0, eq).trim();
                String value = line.substring(eq + 1).trim();
                if (key.equals("VoxelSizeX")) {
                    try {
                        voxelX = Double.parseDouble(value);
                    } catch (NumberFormatException e) {
                    }
                } else if (key.equals("VoxelSizeY")) {
                    try {
                        voxelY = Double.parseDouble(value);
                    } catch (NumberFormatException e) {
                    }
                } else if (key.equals("VoxelSizeZ")) {
                    try {
                        voxelZ = Double.parseDouble(value);
                    } catch (NumberFormatException e) {
                    }
                }
                addGlobalMeta(key, value);
            }
        }
        metadata.remove("Comment");
    }
    ms0.sizeX = tiffReaders[0].getSizeX();
    ms0.sizeY = tiffReaders[0].getSizeY();
    ms0.rgb = tiffReaders[0].isRGB();
    ms0.pixelType = tiffReaders[0].getPixelType();
    ms0.littleEndian = tiffReaders[0].isLittleEndian();
    ms0.interleaved = tiffReaders[0].isInterleaved();
    ms0.falseColor = true;
    ms0.indexed = tiffReaders[0].isIndexed();
    if (isRGB())
        ms0.imageCount /= (getSizeC() / channelCount);
    if (getSizeZ() * getSizeT() * getEffectiveSizeC() != (ifds.size() * tiffReaders.length)) {
        int c = getEffectiveSizeC();
        if (c == 0)
            c = 1;
        ms0.sizeT = (ifds.size() * tiffReaders.length) / (c * getSizeZ());
        ms0.imageCount = getSizeT() * c * getSizeZ();
        if (getSizeT() == 0) {
            ms0.sizeT = 1;
            ms0.imageCount = ifds.size() * tiffReaders.length;
        }
    }
    if (getImageCount() == ifds.size() * getSizeZ() * getSizeT() && ifds.size() > 1) {
        if (getSizeZ() == 1) {
            ms0.sizeZ = ifds.size();
        } else if (getSizeT() == 1) {
            ms0.sizeT = ifds.size();
        } else
            ms0.sizeZ *= ifds.size();
    }
    if (xmlFile != null) {
        // parse XML metadata
        String xml = DataTools.readFile(xmlFile);
        xml = XMLTools.sanitizeXML(PREFIX + xml + SUFFIX);
        LeicaHandler handler = new LeicaHandler(store, getMetadataOptions().getMetadataLevel());
        XMLTools.parseXML(xml, handler);
        metadata = handler.getGlobalMetadata();
        MetadataTools.merge(handler.getGlobalMetadata(), metadata, "");
        core = handler.getCoreMetadataList();
        for (int i = 0; i < getSeriesCount(); i++) {
            CoreMetadata ms = core.get(i);
            if (tiffs.size() < ms.imageCount) {
                int div = ms.imageCount / ms.sizeC;
                ms.imageCount = tiffs.size();
                if (div >= ms.sizeZ)
                    ms.sizeZ /= div;
                else if (div >= ms.sizeT)
                    ms.sizeT /= div;
            }
            ms.dimensionOrder = getSizeZ() > getSizeT() ? "XYCZT" : "XYCTZ";
            ms.rgb = false;
            ms.interleaved = false;
            ms.indexed = tiffReaders[0].isIndexed();
        }
    }
    MetadataTools.populatePixels(store, this, true);
    Length sizeX = FormatTools.getPhysicalSizeX(voxelX);
    Length sizeY = FormatTools.getPhysicalSizeY(voxelY);
    Length sizeZ = FormatTools.getPhysicalSizeZ(voxelZ);
    if (sizeX != null) {
        store.setPixelsPhysicalSizeX(sizeX, 0);
    }
    if (sizeY != null) {
        store.setPixelsPhysicalSizeY(sizeY, 0);
    }
    if (sizeZ != null) {
        store.setPixelsPhysicalSizeZ(sizeZ, 0);
    }
}
Also used : CoreMetadata(loci.formats.CoreMetadata) MetadataStore(loci.formats.meta.MetadataStore) Length(ome.units.quantity.Length) IFDList(loci.formats.tiff.IFDList) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream) FilePattern(loci.formats.FilePattern) AxisGuesser(loci.formats.AxisGuesser) Location(loci.common.Location)

Example 67 with TiffParser

use of loci.formats.tiff.TiffParser in project bioformats by openmicroscopy.

the class TCSReader method groupFiles.

// -- Helper methods --
private void groupFiles() throws FormatException, IOException {
    // look for associated TIFF files
    // we assume that two files are grouped if all of the following are true:
    // 
    // * the files are in the same directory
    // * the file names are the same length
    // * the time stamps are less than 60 seconds apart
    // * the files have the same number of bytes
    Location current = new Location(currentId).getAbsoluteFile();
    if (!checkSuffix(currentId, XML_SUFFIX)) {
        tiffs.add(current.getAbsolutePath());
    }
    if (!isGroupFiles())
        return;
    Location parent = current.getParentFile();
    String[] list = parent.list();
    Arrays.sort(list);
    HashMap<String, Long> timestamps = new HashMap<String, Long>();
    RandomAccessInputStream s = new RandomAccessInputStream(current.getAbsolutePath(), 16);
    TiffParser p = new TiffParser(s);
    IFD ifd = p.getIFDs().get(0);
    s.close();
    int expectedIFDCount = p.getIFDs().size();
    long width = ifd.getImageWidth();
    long height = ifd.getImageLength();
    int samples = ifd.getSamplesPerPixel();
    for (String file : list) {
        file = new Location(parent, file).getAbsolutePath();
        if (file.length() != current.getAbsolutePath().length())
            continue;
        RandomAccessInputStream rais = new RandomAccessInputStream(file, 16);
        TiffParser tp = new TiffParser(rais);
        if (!tp.isValidHeader()) {
            continue;
        }
        ifd = tp.getIFDs().get(0);
        if (tp.getIFDs().size() != expectedIFDCount || ifd.getImageWidth() != width || ifd.getImageLength() != height || ifd.getSamplesPerPixel() != samples) {
            continue;
        }
        String date = ifd.getIFDStringValue(IFD.DATE_TIME);
        if (date != null) {
            long stamp = DateTools.getTime(date, "yyyy:MM:dd HH:mm:ss");
            String software = ifd.getIFDStringValue(IFD.SOFTWARE);
            if (software != null && software.trim().startsWith("TCS")) {
                timestamps.put(file, new Long(stamp));
            }
        }
        rais.close();
    }
    String[] files = timestamps.keySet().toArray(new String[timestamps.size()]);
    Arrays.sort(files);
    for (String file : files) {
        long thisStamp = timestamps.get(file).longValue();
        boolean match = false;
        for (String tiff : tiffs) {
            s = new RandomAccessInputStream(tiff, 16);
            TiffParser parser = new TiffParser(s);
            ifd = parser.getIFDs().get(0);
            s.close();
            String date = ifd.getIFDStringValue(IFD.DATE_TIME);
            long nextStamp = DateTools.getTime(date, "yyyy:MM:dd HH:mm:ss");
            if (Math.abs(thisStamp - nextStamp) < 600000) {
                match = true;
                break;
            }
        }
        if (match && !tiffs.contains(file))
            tiffs.add(file);
    }
}
Also used : HashMap(java.util.HashMap) IFD(loci.formats.tiff.IFD) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream) Location(loci.common.Location)

Example 68 with TiffParser

use of loci.formats.tiff.TiffParser in project bioformats by openmicroscopy.

the class CommentSurgery method main.

public static void main(String[] args) throws Exception {
    // the -test flag will print proposed changes to stdout
    // rather than actually changing the comment
    boolean test = args[0].equals("-test");
    for (int i = 0; i < args.length; i++) {
        String id = args[i];
        if (!test)
            System.out.println(id + ": ");
        String xml = new TiffParser(id).getComment();
        if (xml == null) {
            System.out.println("ERROR: No OME-XML comment.");
            return;
        }
        int len = xml.length();
        if (test)
            System.out.println(xml);
        else {
            System.out.println(len + " -> " + xml.length());
            TiffSaver saver = new TiffSaver(id);
            RandomAccessInputStream in = new RandomAccessInputStream(id);
            saver.overwriteComment(in, xml);
            in.close();
            saver.close();
        }
    }
}
Also used : TiffSaver(loci.formats.tiff.TiffSaver) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream)

Example 69 with TiffParser

use of loci.formats.tiff.TiffParser in project bioformats by openmicroscopy.

the class OMETiffReader method initFile.

// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
    // normalize file name
    super.initFile(normalizeFilename(null, id));
    id = currentId;
    String dir = new File(id).getParent();
    // parse and populate OME-XML metadata
    String fileName = new Location(id).getAbsoluteFile().getAbsolutePath();
    if (!new File(fileName).exists()) {
        fileName = currentId;
    }
    String xml;
    IFD firstIFD = null;
    boolean companion = false;
    if (checkSuffix(fileName, "companion.ome")) {
        xml = DataTools.readFile(fileName);
        companion = true;
    } else {
        RandomAccessInputStream ras = new RandomAccessInputStream(fileName, 16);
        try {
            TiffParser tp = new TiffParser(ras);
            firstIFD = tp.getFirstIFD();
            xml = firstIFD.getComment();
        } finally {
            ras.close();
        }
    }
    if (service == null)
        setupService();
    try {
        if (meta == null || !metaFile.equals(currentId)) {
            meta = service.createOMEXMLMetadata(xml);
            metaFile = currentId;
        }
        if (companion) {
            String firstTIFF = meta.getUUIDFileName(0, 0);
            initFile(new Location(dir, firstTIFF).getAbsolutePath());
            return;
        }
    } catch (ServiceException se) {
        throw new FormatException(se);
    }
    String metadataPath = null;
    try {
        metadataPath = meta.getBinaryOnlyMetadataFile();
    } catch (NullPointerException e) {
    }
    if (metadataPath != null) {
        // this is a binary-only file
        // overwrite XML with what is in the companion OME-XML file
        Location path = new Location(dir, metadataPath);
        if (path.exists()) {
            metadataFile = path.getAbsolutePath();
            xml = readMetadataFile();
            try {
                meta = service.createOMEXMLMetadata(xml);
            } catch (ServiceException se) {
                throw new FormatException(se);
            } catch (NullPointerException e) {
                metadataFile = null;
                metadataPath = null;
            }
        }
    }
    hasSPW = meta.getPlateCount() > 0;
    for (int i = 0; i < meta.getImageCount(); i++) {
        int sizeC = meta.getPixelsSizeC(i).getValue().intValue();
        service.removeChannels(meta, i, sizeC);
    }
    Hashtable originalMetadata = service.getOriginalMetadata(meta);
    if (originalMetadata != null)
        metadata = originalMetadata;
    LOGGER.trace(xml);
    if (meta.getRoot() == null) {
        throw new FormatException("Could not parse OME-XML from TIFF comment");
    }
    String[] acquiredDates = new String[meta.getImageCount()];
    for (int i = 0; i < acquiredDates.length; i++) {
        Timestamp acquisitionDate = meta.getImageAcquisitionDate(i);
        if (acquisitionDate != null) {
            acquiredDates[i] = acquisitionDate.getValue();
        }
    }
    String currentUUID = meta.getUUID();
    if (!isGroupFiles() && !isSingleFile(currentId)) {
        IFormatReader reader = new MinimalTiffReader();
        reader.setId(currentId);
        core.set(0, reader.getCoreMetadataList().get(0));
        int ifdCount = reader.getImageCount();
        reader.close();
        int maxSeries = 0;
        info = new OMETiffPlane[meta.getImageCount()][];
        ArrayList<Integer> imagesToRemove = new ArrayList<Integer>();
        ArrayList<int[]> cBounds = new ArrayList<int[]>();
        for (int i = 0; i < meta.getImageCount(); i++) {
            int maxZ = 0;
            int maxC = 0;
            int maxT = 0;
            int minZ = Integer.MAX_VALUE;
            int minC = Integer.MAX_VALUE;
            int minT = Integer.MAX_VALUE;
            int sizeZ = meta.getPixelsSizeZ(i).getValue();
            int sizeC = meta.getChannelCount(i);
            int sizeT = meta.getPixelsSizeT(i).getValue();
            String order = meta.getPixelsDimensionOrder(i).getValue();
            int num = sizeZ * sizeC * sizeT;
            CoreMetadata m = i < core.size() ? core.get(i) : new CoreMetadata(core.get(0));
            m.dimensionOrder = order;
            info[i] = new OMETiffPlane[meta.getTiffDataCount(i)];
            int next = 0;
            for (int td = 0; td < meta.getTiffDataCount(i); td++) {
                String uuid = null;
                try {
                    uuid = meta.getUUIDValue(i, td);
                } catch (NullPointerException e) {
                }
                String filename = null;
                try {
                    filename = meta.getUUIDFileName(i, td);
                } catch (NullPointerException e) {
                }
                if ((uuid == null || !uuid.equals(currentUUID)) && (filename == null || !currentId.endsWith(filename))) {
                    // this plane doesn't appear to be in the current file
                    continue;
                }
                if (i > maxSeries) {
                    maxSeries = i;
                }
                NonNegativeInteger ifd = meta.getTiffDataIFD(i, td);
                NonNegativeInteger count = meta.getTiffDataPlaneCount(i, td);
                NonNegativeInteger firstZ = meta.getTiffDataFirstZ(i, td);
                NonNegativeInteger firstC = meta.getTiffDataFirstC(i, td);
                NonNegativeInteger firstT = meta.getTiffDataFirstT(i, td);
                int realCount = count == null ? 1 : count.getValue();
                if (ifd == null && count == null) {
                    realCount = ifdCount;
                }
                for (int q = 0; q < realCount; q++) {
                    OMETiffPlane p = new OMETiffPlane();
                    p.id = currentId;
                    p.ifd = q;
                    if (ifd != null) {
                        p.ifd += ifd.getValue();
                    }
                    p.reader = reader;
                    info[i][next++] = p;
                    int z = firstZ == null ? 0 : firstZ.getValue();
                    int c = firstC == null ? 0 : firstC.getValue();
                    int t = firstT == null ? 0 : firstT.getValue();
                    if (q > 0) {
                        int index = FormatTools.getIndex(order, sizeZ, sizeC, sizeT, num, z, c, t);
                        int[] add = FormatTools.getZCTCoords(order, sizeZ, sizeC, sizeT, num, q);
                        z += add[0];
                        c += add[1];
                        t += add[2];
                    }
                    if (z > maxZ) {
                        maxZ = z;
                    }
                    if (c > maxC) {
                        maxC = c;
                    }
                    if (t > maxT) {
                        maxT = t;
                    }
                    if (z < minZ) {
                        minZ = z;
                    }
                    if (c < minC) {
                        minC = c;
                    }
                    if (t < minT) {
                        minT = t;
                    }
                }
            }
            if (i <= maxSeries) {
                m.sizeZ = (maxZ - minZ) + 1;
                m.sizeC = (maxC - minC) + 1;
                m.sizeT = (maxT - minT) + 1;
                m.imageCount = m.sizeZ * m.sizeC * m.sizeT;
                m.sizeC *= meta.getChannelSamplesPerPixel(i, 0).getValue();
                if (i >= core.size()) {
                    core.add(m);
                }
                cBounds.add(new int[] { minC, maxC });
            } else {
                imagesToRemove.add(i);
            }
        }
        // remove extra Images, Channels, and Planes
        meta.resolveReferences();
        OMEXMLMetadataRoot root = (OMEXMLMetadataRoot) meta.getRoot();
        List<Image> images = root.copyImageList();
        for (int i = imagesToRemove.size() - 1; i >= 0; i--) {
            images.remove(imagesToRemove.get(i));
        }
        for (int i = 0; i < images.size(); i++) {
            Image img = images.get(i);
            Pixels pix = img.getPixels();
            List<Plane> planes = pix.copyPlaneList();
            for (int p = 0; p < planes.size(); p++) {
                Plane plane = planes.get(p);
                if (plane.getTheZ().getValue() >= core.get(i).sizeZ || plane.getTheC().getValue() >= core.get(i).sizeC || plane.getTheT().getValue() >= core.get(i).sizeT) {
                    pix.removePlane(planes.get(p));
                }
            }
            pix.setMetadataOnly(null);
            List<Channel> channels = pix.copyChannelList();
            for (int c = 0; c < channels.size(); c++) {
                if (c < cBounds.get(i)[0] || c > cBounds.get(i)[1]) {
                    pix.removeChannel(channels.get(c));
                }
            }
        }
        meta.setRoot(root);
        service.convertMetadata(meta, metadataStore);
        MetadataTools.populatePixels(metadataStore, this);
        return;
    }
    service.convertMetadata(meta, metadataStore);
    // determine series count from Image and Pixels elements
    int seriesCount = meta.getImageCount();
    core.clear();
    for (int i = 0; i < seriesCount; i++) {
        core.add(new CoreMetadata());
    }
    info = new OMETiffPlane[seriesCount][];
    tileWidth = new int[seriesCount];
    tileHeight = new int[seriesCount];
    // compile list of file/UUID mappings
    Hashtable<String, String> files = new Hashtable<String, String>();
    boolean needSearch = false;
    for (int i = 0; i < seriesCount; i++) {
        int tiffDataCount = meta.getTiffDataCount(i);
        for (int td = 0; td < tiffDataCount; td++) {
            String uuid = null;
            try {
                uuid = meta.getUUIDValue(i, td);
            } catch (NullPointerException e) {
            }
            String filename = null;
            if (uuid == null) {
                // no UUID means that TiffData element refers to this file
                uuid = "";
                filename = id;
            } else {
                filename = meta.getUUIDFileName(i, td);
                if (!new Location(dir, filename).exists())
                    filename = null;
                if (filename == null) {
                    if (uuid.equals(currentUUID) || currentUUID == null) {
                        // UUID references this file
                        filename = id;
                    } else {
                        // will need to search for this UUID
                        filename = "";
                        needSearch = true;
                    }
                } else
                    filename = normalizeFilename(dir, filename);
            }
            String existing = files.get(uuid);
            if (existing == null)
                files.put(uuid, filename);
            else if (!existing.equals(filename)) {
                throw new FormatException("Inconsistent UUID filenames");
            }
        }
    }
    // search for missing filenames
    if (needSearch) {
        Enumeration en = files.keys();
        while (en.hasMoreElements()) {
            String uuid = (String) en.nextElement();
            String filename = files.get(uuid);
            if (filename.equals("")) {
                // to make this work with OME server may be a little tricky?
                throw new FormatException("Unmatched UUID: " + uuid);
            }
        }
    }
    // build list of used files
    Enumeration en = files.keys();
    int numUUIDs = files.size();
    // ensure no duplicate filenames
    HashSet fileSet = new HashSet();
    for (int i = 0; i < numUUIDs; i++) {
        String uuid = (String) en.nextElement();
        String filename = files.get(uuid);
        fileSet.add(filename);
    }
    used = new String[fileSet.size()];
    Iterator iter = fileSet.iterator();
    for (int i = 0; i < used.length; i++) used[i] = (String) iter.next();
    // process TiffData elements
    Hashtable<String, IFormatReader> readers = new Hashtable<String, IFormatReader>();
    boolean adjustedSamples = false;
    for (int i = 0; i < seriesCount; i++) {
        int s = i;
        LOGGER.debug("Image[{}] {", i);
        LOGGER.debug("  id = {}", meta.getImageID(i));
        String order = meta.getPixelsDimensionOrder(i).toString();
        PositiveInteger samplesPerPixel = null;
        if (meta.getChannelCount(i) > 0) {
            samplesPerPixel = meta.getChannelSamplesPerPixel(i, 0);
        }
        int samples = samplesPerPixel == null ? -1 : samplesPerPixel.getValue();
        int tiffSamples = firstIFD.getSamplesPerPixel();
        if (adjustedSamples || (samples != tiffSamples && (i == 0 || samples < 0))) {
            LOGGER.warn("SamplesPerPixel mismatch: OME={}, TIFF={}", samples, tiffSamples);
            samples = tiffSamples;
            adjustedSamples = true;
        } else {
            adjustedSamples = false;
        }
        if (adjustedSamples && meta.getChannelCount(i) <= 1) {
            adjustedSamples = false;
        }
        int effSizeC = meta.getPixelsSizeC(i).getValue().intValue();
        if (!adjustedSamples) {
            effSizeC /= samples;
        }
        if (effSizeC == 0)
            effSizeC = 1;
        if (effSizeC * samples != meta.getPixelsSizeC(i).getValue().intValue()) {
            effSizeC = meta.getPixelsSizeC(i).getValue().intValue();
        }
        int sizeT = meta.getPixelsSizeT(i).getValue().intValue();
        int sizeZ = meta.getPixelsSizeZ(i).getValue().intValue();
        int num = effSizeC * sizeT * sizeZ;
        OMETiffPlane[] planes = new OMETiffPlane[num];
        for (int no = 0; no < num; no++) planes[no] = new OMETiffPlane();
        int tiffDataCount = meta.getTiffDataCount(i);
        Boolean zOneIndexed = null;
        Boolean cOneIndexed = null;
        Boolean tOneIndexed = null;
        for (int td = 0; td < tiffDataCount; td++) {
            NonNegativeInteger firstC = meta.getTiffDataFirstC(i, td);
            NonNegativeInteger firstT = meta.getTiffDataFirstT(i, td);
            NonNegativeInteger firstZ = meta.getTiffDataFirstZ(i, td);
            int c = firstC == null ? 0 : firstC.getValue();
            int t = firstT == null ? 0 : firstT.getValue();
            int z = firstZ == null ? 0 : firstZ.getValue();
            if (c >= effSizeC && cOneIndexed == null) {
                cOneIndexed = true;
            } else if (c == 0) {
                cOneIndexed = false;
            }
            if (z >= sizeZ && zOneIndexed == null) {
                zOneIndexed = true;
            } else if (z == 0) {
                zOneIndexed = false;
            }
            if (t >= sizeT && tOneIndexed == null) {
                tOneIndexed = true;
            } else if (t == 0) {
                tOneIndexed = false;
            }
        }
        for (int td = 0; td < tiffDataCount; td++) {
            LOGGER.debug("    TiffData[{}] {", td);
            // extract TiffData parameters
            String filename = null;
            String uuid = null;
            try {
                filename = meta.getUUIDFileName(i, td);
            } catch (NullPointerException e) {
                LOGGER.debug("Ignoring null UUID object when retrieving filename.");
            }
            try {
                uuid = meta.getUUIDValue(i, td);
            } catch (NullPointerException e) {
                LOGGER.debug("Ignoring null UUID object when retrieving value.");
            }
            NonNegativeInteger tdIFD = meta.getTiffDataIFD(i, td);
            int ifd = tdIFD == null ? 0 : tdIFD.getValue();
            NonNegativeInteger numPlanes = meta.getTiffDataPlaneCount(i, td);
            NonNegativeInteger firstC = meta.getTiffDataFirstC(i, td);
            NonNegativeInteger firstT = meta.getTiffDataFirstT(i, td);
            NonNegativeInteger firstZ = meta.getTiffDataFirstZ(i, td);
            int c = firstC == null ? 0 : firstC.getValue();
            int t = firstT == null ? 0 : firstT.getValue();
            int z = firstZ == null ? 0 : firstZ.getValue();
            // NB: some writers index FirstC, FirstZ and FirstT from 1
            if (cOneIndexed != null && cOneIndexed)
                c--;
            if (zOneIndexed != null && zOneIndexed)
                z--;
            if (tOneIndexed != null && tOneIndexed)
                t--;
            if (z >= sizeZ || c >= effSizeC || t >= sizeT) {
                LOGGER.warn("Found invalid TiffData: Z={}, C={}, T={}", new Object[] { z, c, t });
                break;
            }
            int index = FormatTools.getIndex(order, sizeZ, effSizeC, sizeT, num, z, c, t);
            int count = numPlanes == null ? 1 : numPlanes.getValue();
            if (count == 0) {
                core.set(s, null);
                break;
            }
            // get reader object for this filename
            if (filename == null) {
                if (uuid == null)
                    filename = id;
                else
                    filename = files.get(uuid);
            } else
                filename = normalizeFilename(dir, filename);
            IFormatReader r = readers.get(filename);
            if (r == null) {
                r = new MinimalTiffReader();
                readers.put(filename, r);
            }
            Location file = new Location(filename);
            boolean exists = true;
            if (!file.exists()) {
                // if this is an absolute file name, try using a relative name
                // old versions of OMETiffWriter wrote an absolute path to
                // UUID.FileName, which causes problems if the file is moved to
                // a different directory
                filename = filename.substring(filename.lastIndexOf(File.separator) + 1);
                filename = dir + File.separator + filename;
                if (!new Location(filename).exists()) {
                    filename = currentId;
                    // if only one file is defined, we have to assume that it
                    // corresponds to the current file
                    exists = fileSet.size() == 1;
                }
            }
            // populate plane index -> IFD mapping
            for (int q = 0; q < count; q++) {
                int no = index + q;
                planes[no].reader = r;
                planes[no].id = filename;
                planes[no].ifd = ifd + q;
                planes[no].certain = true;
                planes[no].exists = exists;
                LOGGER.debug("      Plane[{}]: file={}, IFD={}", new Object[] { no, planes[no].id, planes[no].ifd });
            }
            if (numPlanes == null) {
                // unknown number of planes; fill down
                for (int no = index + 1; no < num; no++) {
                    if (planes[no].certain)
                        break;
                    planes[no].reader = r;
                    planes[no].id = filename;
                    planes[no].ifd = planes[no - 1].ifd + 1;
                    planes[no].exists = exists;
                    LOGGER.debug("      Plane[{}]: FILLED", no);
                }
            } else {
                // known number of planes; clear anything subsequently filled
                for (int no = index + count; no < num; no++) {
                    if (planes[no].certain)
                        break;
                    planes[no].reader = null;
                    planes[no].id = null;
                    planes[no].ifd = -1;
                    LOGGER.debug("      Plane[{}]: CLEARED", no);
                }
            }
            LOGGER.debug("    }");
        }
        if (core.get(s) == null)
            continue;
        // verify that all planes are available
        LOGGER.debug("    --------------------------------");
        for (int no = 0; no < num; no++) {
            LOGGER.debug("    Plane[{}]: file={}, IFD={}", new Object[] { no, planes[no].id, planes[no].ifd });
            if (planes[no].reader == null) {
                LOGGER.warn("Image ID '{}': missing plane #{}.  " + "Using TiffReader to determine the number of planes.", meta.getImageID(i), no);
                TiffReader r = new TiffReader();
                r.setId(currentId);
                try {
                    planes = new OMETiffPlane[r.getImageCount()];
                    for (int plane = 0; plane < planes.length; plane++) {
                        planes[plane] = new OMETiffPlane();
                        planes[plane].id = currentId;
                        planes[plane].reader = r;
                        planes[plane].ifd = plane;
                    }
                    num = planes.length;
                } finally {
                    r.close();
                }
            }
        }
        LOGGER.debug("  }");
        // populate core metadata
        CoreMetadata m = core.get(s);
        info[s] = planes;
        try {
            RandomAccessInputStream testFile = new RandomAccessInputStream(info[s][0].id, 16);
            String firstFile = info[s][0].id;
            if (!info[s][0].reader.isThisType(testFile)) {
                LOGGER.warn("{} is not a valid OME-TIFF", info[s][0].id);
                info[s][0].id = currentId;
                info[s][0].exists = false;
            }
            testFile.close();
            for (int plane = 1; plane < info[s].length; plane++) {
                if (info[s][plane].id.equals(firstFile)) {
                    // don't repeat slow type checking if the files are the same
                    if (!info[s][0].exists) {
                        info[s][plane].id = info[s][0].id;
                        info[s][plane].exists = false;
                    }
                    continue;
                }
                testFile = new RandomAccessInputStream(info[s][plane].id, 16);
                if (!info[s][plane].reader.isThisType(testFile)) {
                    LOGGER.warn("{} is not a valid OME-TIFF", info[s][plane].id);
                    info[s][plane].id = info[s][0].id;
                    info[s][plane].exists = false;
                }
                testFile.close();
            }
            info[s][0].reader.setId(info[s][0].id);
            tileWidth[s] = info[s][0].reader.getOptimalTileWidth();
            tileHeight[s] = info[s][0].reader.getOptimalTileHeight();
            m.sizeX = meta.getPixelsSizeX(i).getValue().intValue();
            int tiffWidth = (int) firstIFD.getImageWidth();
            if (m.sizeX != tiffWidth && s == 0) {
                LOGGER.warn("SizeX mismatch: OME={}, TIFF={}", m.sizeX, tiffWidth);
            }
            m.sizeY = meta.getPixelsSizeY(i).getValue().intValue();
            int tiffHeight = (int) firstIFD.getImageLength();
            if (m.sizeY != tiffHeight && s == 0) {
                LOGGER.warn("SizeY mismatch: OME={}, TIFF={}", m.sizeY, tiffHeight);
            }
            m.sizeZ = meta.getPixelsSizeZ(i).getValue().intValue();
            m.sizeC = meta.getPixelsSizeC(i).getValue().intValue();
            m.sizeT = meta.getPixelsSizeT(i).getValue().intValue();
            m.pixelType = FormatTools.pixelTypeFromString(meta.getPixelsType(i).toString());
            int tiffPixelType = firstIFD.getPixelType();
            if (m.pixelType != tiffPixelType && (s == 0 || adjustedSamples)) {
                LOGGER.warn("PixelType mismatch: OME={}, TIFF={}", m.pixelType, tiffPixelType);
                m.pixelType = tiffPixelType;
            }
            m.imageCount = num;
            m.dimensionOrder = meta.getPixelsDimensionOrder(i).toString();
            // hackish workaround for files exported by OMERO that have an
            // incorrect dimension order
            String uuidFileName = "";
            try {
                if (meta.getTiffDataCount(i) > 0) {
                    uuidFileName = meta.getUUIDFileName(i, 0);
                }
            } catch (NullPointerException e) {
            }
            if (meta.getChannelCount(i) > 0 && meta.getChannelName(i, 0) == null && meta.getTiffDataCount(i) > 0 && uuidFileName.indexOf("__omero_export") != -1) {
                m.dimensionOrder = "XYZCT";
            }
            m.orderCertain = true;
            PhotoInterp photo = firstIFD.getPhotometricInterpretation();
            m.rgb = samples > 1 || photo == PhotoInterp.RGB;
            if ((samples != m.sizeC && (samples % m.sizeC) != 0 && (m.sizeC % samples) != 0) || m.sizeC == 1 || adjustedSamples) {
                m.sizeC *= samples;
            }
            if (m.sizeZ * m.sizeT * m.sizeC > m.imageCount && !m.rgb) {
                if (m.sizeZ == m.imageCount) {
                    m.sizeT = 1;
                    m.sizeC = 1;
                } else if (m.sizeT == m.imageCount) {
                    m.sizeZ = 1;
                    m.sizeC = 1;
                } else if (m.sizeC == m.imageCount) {
                    m.sizeT = 1;
                    m.sizeZ = 1;
                }
            }
            if (meta.getPixelsBinDataCount(i) > 1) {
                LOGGER.warn("OME-TIFF Pixels element contains BinData elements! " + "Ignoring.");
            }
            m.littleEndian = firstIFD.isLittleEndian();
            m.interleaved = false;
            m.indexed = photo == PhotoInterp.RGB_PALETTE && firstIFD.getIFDValue(IFD.COLOR_MAP) != null;
            if (m.indexed) {
                m.rgb = false;
            }
            m.falseColor = true;
            m.metadataComplete = true;
            if (meta.getPixelsSignificantBits(i) != null) {
                m.bitsPerPixel = meta.getPixelsSignificantBits(i).getValue();
            }
        } catch (NullPointerException exc) {
            throw new FormatException("Incomplete Pixels metadata", exc);
        }
    }
    // remove null CoreMetadata entries
    ArrayList<CoreMetadata> series = new ArrayList<CoreMetadata>();
    final List<OMETiffPlane[]> planeInfo = new ArrayList<OMETiffPlane[]>();
    for (int i = 0; i < core.size(); i++) {
        if (core.get(i) != null) {
            series.add(core.get(i));
            planeInfo.add(info[i]);
        }
    }
    core = series;
    info = planeInfo.toArray(new OMETiffPlane[0][0]);
    if (getImageCount() == 1) {
        CoreMetadata ms0 = core.get(0);
        ms0.sizeZ = 1;
        if (!ms0.rgb) {
            ms0.sizeC = 1;
        }
        ms0.sizeT = 1;
    }
    for (int i = 0; i < core.size(); i++) {
        CoreMetadata m = core.get(i);
        Modulo z = service.getModuloAlongZ(meta, i);
        if (z != null) {
            m.moduloZ = z;
        }
        Modulo c = service.getModuloAlongC(meta, i);
        if (c != null) {
            m.moduloC = c;
        }
        Modulo t = service.getModuloAlongT(meta, i);
        if (t != null) {
            m.moduloT = t;
        }
    }
    MetadataTools.populatePixels(metadataStore, this, false, false);
    for (int i = 0; i < meta.getImageCount(); i++) {
        // TheT values are not changed
        for (int p = 0; p < meta.getPlaneCount(i); p++) {
            NonNegativeInteger z = meta.getPlaneTheZ(i, p);
            NonNegativeInteger c = meta.getPlaneTheC(i, p);
            NonNegativeInteger t = meta.getPlaneTheT(i, p);
            if (z == null) {
                z = new NonNegativeInteger(0);
                metadataStore.setPlaneTheZ(z, i, p);
            }
            if (c == null) {
                c = new NonNegativeInteger(0);
                metadataStore.setPlaneTheC(c, i, p);
            }
            if (t == null) {
                t = new NonNegativeInteger(0);
                metadataStore.setPlaneTheT(t, i, p);
            }
        }
    }
    for (int i = 0; i < acquiredDates.length; i++) {
        if (acquiredDates[i] != null) {
            metadataStore.setImageAcquisitionDate(new Timestamp(acquiredDates[i]), i);
        }
    }
}
Also used : IFormatReader(loci.formats.IFormatReader) IFD(loci.formats.tiff.IFD) ArrayList(java.util.ArrayList) Image(ome.xml.model.Image) Timestamp(ome.xml.model.primitives.Timestamp) Pixels(ome.xml.model.Pixels) Iterator(java.util.Iterator) HashSet(java.util.HashSet) PositiveInteger(ome.xml.model.primitives.PositiveInteger) Enumeration(java.util.Enumeration) Plane(ome.xml.model.Plane) Hashtable(java.util.Hashtable) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) Modulo(loci.formats.Modulo) Channel(ome.xml.model.Channel) PhotoInterp(loci.formats.tiff.PhotoInterp) CoreMetadata(loci.formats.CoreMetadata) FormatException(loci.formats.FormatException) PositiveInteger(ome.xml.model.primitives.PositiveInteger) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) ServiceException(loci.common.services.ServiceException) OMEXMLMetadataRoot(ome.xml.meta.OMEXMLMetadataRoot) TiffParser(loci.formats.tiff.TiffParser) RandomAccessInputStream(loci.common.RandomAccessInputStream) File(java.io.File) Location(loci.common.Location)

Example 70 with TiffParser

use of loci.formats.tiff.TiffParser in project bioformats by openmicroscopy.

the class OMETiffReader method isThisType.

/* @see loci.formats.IFormatReader#isThisType(RandomAccessInputStream) */
@Override
public boolean isThisType(RandomAccessInputStream stream) throws IOException {
    TiffParser tp = new TiffParser(stream);
    tp.setDoCaching(false);
    boolean validHeader = tp.isValidHeader();
    if (!validHeader)
        return false;
    // look for OME-XML in first IFD's comment
    IFD ifd = tp.getFirstIFD();
    if (ifd == null)
        return false;
    Object description = ifd.get(IFD.IMAGE_DESCRIPTION);
    if (description == null) {
        return false;
    }
    String comment = null;
    if (description instanceof TiffIFDEntry) {
        Object value = tp.getIFDValue((TiffIFDEntry) description);
        if (value != null) {
            comment = value.toString();
        }
    } else if (description instanceof String) {
        comment = (String) description;
    }
    if (comment == null || comment.trim().length() == 0)
        return false;
    comment = comment.trim();
    // we are reasonably sure that the comment contains XML
    if (!comment.startsWith("<") || !comment.endsWith(">")) {
        return false;
    }
    try {
        if (service == null)
            setupService();
        meta = service.createOMEXMLMetadata(comment);
        try {
            metadataFile = meta.getBinaryOnlyMetadataFile();
            // referencing the current OME-TIFF
            if (metadataFile != null) {
                return true;
            }
        } catch (NullPointerException e) {
        }
        for (int i = 0; i < meta.getImageCount(); i++) {
            meta.setPixelsBigEndian(Boolean.TRUE, i);
            if (meta.getPixelsBinDataCount(i) > 0) {
                for (int j = 0; j < meta.getPixelsBinDataCount(i); j++) {
                    meta.setPixelsBinDataBigEndian(Boolean.TRUE, i, j);
                }
            }
            MetadataTools.verifyMinimumPopulated(meta, i);
        }
        return meta.getImageCount() > 0;
    } catch (ServiceException se) {
        LOGGER.debug("OME-XML parsing failed", se);
    } catch (NullPointerException e) {
        LOGGER.debug("OME-XML parsing failed", e);
    } catch (FormatException e) {
        LOGGER.debug("OME-XML parsing failed", e);
    } catch (IndexOutOfBoundsException e) {
        LOGGER.debug("OME-XML parsing failed", e);
    }
    return false;
}
Also used : TiffIFDEntry(loci.formats.tiff.TiffIFDEntry) ServiceException(loci.common.services.ServiceException) IFD(loci.formats.tiff.IFD) TiffParser(loci.formats.tiff.TiffParser) FormatException(loci.formats.FormatException)

Aggregations

TiffParser (loci.formats.tiff.TiffParser)96 IFD (loci.formats.tiff.IFD)74 RandomAccessInputStream (loci.common.RandomAccessInputStream)56 FormatException (loci.formats.FormatException)26 CoreMetadata (loci.formats.CoreMetadata)19 IOException (java.io.IOException)18 IFDList (loci.formats.tiff.IFDList)16 Location (loci.common.Location)15 MetadataStore (loci.formats.meta.MetadataStore)15 ArrayList (java.util.ArrayList)12 Timestamp (ome.xml.model.primitives.Timestamp)9 Length (ome.units.quantity.Length)8 PhotoInterp (loci.formats.tiff.PhotoInterp)6 File (java.io.File)5 HashMap (java.util.HashMap)5 ServiceException (loci.common.services.ServiceException)4 Time (ome.units.quantity.Time)4 NonNegativeInteger (ome.xml.model.primitives.NonNegativeInteger)4 List (java.util.List)3 ByteArrayHandle (loci.common.ByteArrayHandle)3