Search in sources :

Example 11 with NonNegativeInteger

use of ome.xml.model.primitives.NonNegativeInteger in project bioformats by openmicroscopy.

the class BDReader method initFile.

// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
    // make sure we have the experiment file
    id = locateExperimentFile(id);
    super.initFile(id);
    Location dir = new Location(id).getAbsoluteFile().getParentFile();
    rootList = dir.list(true);
    Arrays.sort(rootList);
    for (int i = 0; i < rootList.length; i++) {
        String file = rootList[i];
        Location f = new Location(dir, file);
        rootList[i] = f.getAbsolutePath();
        if (!f.isDirectory()) {
            if (checkSuffix(file, META_EXT) && !f.isDirectory()) {
                metadataFiles.add(f.getAbsolutePath());
            }
        } else {
            String[] wells = f.list(true);
            Arrays.sort(wells);
            wellList.add(wells);
            for (String well : wells) {
                Location wellFile = new Location(f, well);
                if (!wellFile.isDirectory()) {
                    if (checkSuffix(well, META_EXT)) {
                        metadataFiles.add(wellFile.getAbsolutePath());
                    }
                }
            }
        }
    }
    // parse Experiment metadata
    IniList experiment = readMetaData(id);
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        objective = experiment.getTable("Geometry").get("Name");
        IniTable camera = experiment.getTable("Camera");
        binning = camera.get("BinX") + "x" + camera.get("BinY");
        parseChannelData(dir);
        addGlobalMeta("Objective", objective);
        addGlobalMeta("Camera binning", binning);
    }
    final List<String> uniqueRows = new ArrayList<String>();
    final List<String> uniqueColumns = new ArrayList<String>();
    for (String well : wellLabels) {
        String row = well.substring(0, 1).trim();
        String column = well.substring(1).trim();
        if (!uniqueRows.contains(row) && row.length() > 0)
            uniqueRows.add(row);
        if (!uniqueColumns.contains(column) && column.length() > 0) {
            uniqueColumns.add(column);
        }
    }
    int nSlices = getSizeZ() == 0 ? 1 : getSizeZ();
    int nTimepoints = getSizeT();
    int nWells = wellLabels.size();
    int nChannels = getSizeC() == 0 ? channelNames.size() : getSizeC();
    if (nChannels == 0)
        nChannels = 1;
    tiffs = getTiffs();
    reader = new MinimalTiffReader();
    reader.setId(tiffs[0][0]);
    int sizeX = reader.getSizeX();
    int sizeY = reader.getSizeY();
    int pixelType = reader.getPixelType();
    boolean rgb = reader.isRGB();
    boolean interleaved = reader.isInterleaved();
    boolean indexed = reader.isIndexed();
    boolean littleEndian = reader.isLittleEndian();
    if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        IniParser parser = new IniParser();
        for (String metadataFile : metadataFiles) {
            String filename = new Location(metadataFile).getName();
            if (!checkSuffix(metadataFile, new String[] { "txt", "bmp", "adf", "roi" })) {
                String data = DataTools.readFile(metadataFile);
                IniList ini = parser.parseINI(new BufferedReader(new StringReader(data)));
                HashMap<String, String> h = ini.flattenIntoHashMap();
                for (String key : h.keySet()) {
                    addGlobalMeta(filename + " " + key, h.get(key));
                }
            }
        }
    }
    int coresize = core.size();
    core.clear();
    for (int i = 0; i < coresize; i++) {
        CoreMetadata ms = new CoreMetadata();
        core.add(ms);
        ms.sizeC = nChannels;
        ms.sizeZ = nSlices;
        ms.sizeT = nTimepoints;
        ms.sizeX = sizeX / fieldCols;
        ms.sizeY = sizeY / fieldRows;
        ms.pixelType = pixelType;
        ms.rgb = rgb;
        ms.interleaved = interleaved;
        ms.indexed = indexed;
        ms.littleEndian = littleEndian;
        ms.dimensionOrder = "XYZTC";
        ms.imageCount = nSlices * nTimepoints * nChannels;
    }
    MetadataStore store = makeFilterMetadata();
    boolean populatePlanes = getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM;
    MetadataTools.populatePixels(store, this, populatePlanes);
    String plateAcqID = MetadataTools.createLSID("PlateAcquisition", 0, 0);
    store.setPlateAcquisitionID(plateAcqID, 0, 0);
    PositiveInteger fieldCount = FormatTools.getMaxFieldCount(fieldRows * fieldCols);
    if (fieldCount != null) {
        store.setPlateAcquisitionMaximumFieldCount(fieldCount, 0, 0);
    }
    for (int row = 0; row < wellRows; row++) {
        for (int col = 0; col < wellCols; col++) {
            int index = row * wellCols + col;
            store.setWellID(MetadataTools.createLSID("Well", 0, index), 0, index);
            store.setWellRow(new NonNegativeInteger(row), 0, index);
            store.setWellColumn(new NonNegativeInteger(col), 0, index);
        }
    }
    for (int i = 0; i < getSeriesCount(); i++) {
        int well = i / (fieldRows * fieldCols);
        int field = i % (fieldRows * fieldCols);
        MetadataTools.setDefaultCreationDate(store, tiffs[well][0], i);
        String name = wellLabels.get(well);
        String row = name.substring(0, 1);
        Integer col = Integer.parseInt(name.substring(1));
        int index = (row.charAt(0) - 'A') * wellCols + col - 1;
        String wellSampleID = MetadataTools.createLSID("WellSample", 0, index, field);
        store.setWellSampleID(wellSampleID, 0, index, field);
        store.setWellSampleIndex(new NonNegativeInteger(i), 0, index, field);
        String imageID = MetadataTools.createLSID("Image", i);
        store.setWellSampleImageRef(imageID, 0, index, field);
        store.setImageID(imageID, i);
        store.setImageName(name + " Field #" + (field + 1), i);
        store.setPlateAcquisitionWellSampleRef(wellSampleID, 0, 0, i);
    }
    MetadataLevel level = getMetadataOptions().getMetadataLevel();
    if (level != MetadataLevel.MINIMUM) {
        String instrumentID = MetadataTools.createLSID("Instrument", 0);
        store.setInstrumentID(instrumentID, 0);
        String objectiveID = MetadataTools.createLSID("Objective", 0, 0);
        store.setObjectiveID(objectiveID, 0, 0);
        if (objective != null) {
            String[] tokens = objective.split(" ");
            String mag = tokens[0].replaceAll("[xX]", "");
            String na = null;
            int naIndex = 0;
            for (int i = 0; i < tokens.length; i++) {
                if (tokens[i].equals("NA")) {
                    naIndex = i + 1;
                    na = tokens[naIndex];
                    break;
                }
            }
            Double magnification = new Double(mag);
            store.setObjectiveNominalMagnification(magnification, 0, 0);
            if (na != null) {
                na = na.substring(0, 1) + "." + na.substring(1);
                store.setObjectiveLensNA(new Double(na), 0, 0);
            }
            if (naIndex + 1 < tokens.length) {
                store.setObjectiveManufacturer(tokens[naIndex + 1], 0, 0);
            }
        }
        // populate LogicalChannel data
        for (int i = 0; i < getSeriesCount(); i++) {
            store.setImageInstrumentRef(instrumentID, i);
            store.setObjectiveSettingsID(objectiveID, i);
            for (int c = 0; c < getSizeC(); c++) {
                store.setChannelName(channelNames.get(c), i, c);
                Length emission = FormatTools.getEmissionWavelength(emWave[c]);
                Length excitation = FormatTools.getExcitationWavelength(exWave[c]);
                if (emission != null) {
                    store.setChannelEmissionWavelength(emission, i, c);
                }
                if (excitation != null) {
                    store.setChannelExcitationWavelength(excitation, i, c);
                }
                String detectorID = MetadataTools.createLSID("Detector", 0, c);
                store.setDetectorID(detectorID, 0, c);
                store.setDetectorSettingsID(detectorID, i, c);
                store.setDetectorSettingsGain(gain[c], i, c);
                store.setDetectorSettingsOffset(offset[c], i, c);
                store.setDetectorSettingsBinning(getBinning(binning), i, c);
            }
            long firstPlane = 0;
            for (int p = 0; p < getImageCount(); p++) {
                int[] zct = getZCTCoords(p);
                store.setPlaneExposureTime(new Time(exposure[zct[1]], UNITS.SECOND), i, p);
                String file = getFilename(i, p);
                if (file != null) {
                    long plane = getTimestamp(file);
                    if (p == 0) {
                        firstPlane = plane;
                    }
                    double timestamp = (plane - firstPlane) / 1000.0;
                    store.setPlaneDeltaT(new Time(timestamp, UNITS.SECOND), i, p);
                }
            }
        }
        store.setPlateID(MetadataTools.createLSID("Plate", 0), 0);
        store.setPlateRowNamingConvention(getNamingConvention("Letter"), 0);
        store.setPlateColumnNamingConvention(getNamingConvention("Number"), 0);
        store.setPlateName(plateName, 0);
        store.setPlateDescription(plateDescription, 0);
        if (level != MetadataLevel.NO_OVERLAYS) {
            parseROIs(store);
        }
    }
}
Also used : IniParser(loci.common.IniParser) IniList(loci.common.IniList) ArrayList(java.util.ArrayList) Time(ome.units.quantity.Time) StringReader(java.io.StringReader) PositiveInteger(ome.xml.model.primitives.PositiveInteger) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) CoreMetadata(loci.formats.CoreMetadata) MetadataStore(loci.formats.meta.MetadataStore) PositiveInteger(ome.xml.model.primitives.PositiveInteger) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) Length(ome.units.quantity.Length) IniTable(loci.common.IniTable) BufferedReader(java.io.BufferedReader) Location(loci.common.Location)

Example 12 with NonNegativeInteger

use of ome.xml.model.primitives.NonNegativeInteger in project bioformats by openmicroscopy.

the class FileExportSPW method initializeMetadata.

/**
 * Populate the minimum amount of metadata required to export a Plate.
 *
 * @param width
 *          the width (in pixels) of the image
 * @param height
 *          the height (in pixels) of the image
 * @param pixelType
 *          the pixel type of the image; @see loci.formats.FormatTools
 */
private IMetadata initializeMetadata(int width, int height, int pixelType) {
    Exception exception = null;
    try {
        // create the OME-XML metadata storage object
        ServiceFactory factory = new ServiceFactory();
        OMEXMLService service = factory.getInstance(OMEXMLService.class);
        OMEXMLMetadata meta = service.createOMEXMLMetadata();
        meta.createRoot();
        int plateIndex = 0;
        // count of images
        int series = 0;
        int well = 0;
        // Create Minimal 2x2 Plate
        meta.setPlateID(MetadataTools.createLSID("Plate", 0), 0);
        meta.setPlateRowNamingConvention(NamingConvention.LETTER, 0);
        meta.setPlateColumnNamingConvention(NamingConvention.NUMBER, 0);
        meta.setPlateRows(new PositiveInteger(rows), 0);
        meta.setPlateColumns(new PositiveInteger(cols), 0);
        meta.setPlateName("First test Plate", 0);
        PositiveInteger pwidth = new PositiveInteger(width);
        PositiveInteger pheight = new PositiveInteger(height);
        char rowChar = 'A';
        for (int row = 0; row < rows; row++) {
            for (int column = 0; column < cols; column++) {
                // set up well
                String wellID = MetadataTools.createLSID("Well:", well);
                meta.setWellID(wellID, plateIndex, well);
                meta.setWellRow(new NonNegativeInteger(row), plateIndex, well);
                meta.setWellColumn(new NonNegativeInteger(column), plateIndex, well);
                for (int fov = 0; fov < fovPerWell; fov++) {
                    // Create Image
                    String imageName = rowChar + ":" + Integer.toString(column + 1) + ":FOV:" + Integer.toString(fov + 1);
                    String imageID = MetadataTools.createLSID("Image", well, fov);
                    meta.setImageID(imageID, series);
                    meta.setImageName(imageName, series);
                    String pixelsID = MetadataTools.createLSID("Pixels", row, well, fov);
                    meta.setPixelsID(pixelsID, series);
                    // specify that the pixel data is stored in big-endian format
                    // change 'TRUE' to 'FALSE' to specify little-endian format
                    meta.setPixelsBinDataBigEndian(Boolean.TRUE, series, 0);
                    // specify that the image is stored in ZCT order
                    meta.setPixelsDimensionOrder(DimensionOrder.XYZCT, series);
                    // specify the pixel type of the image
                    meta.setPixelsType(PixelType.fromString(FormatTools.getPixelTypeString(pixelType)), series);
                    // specify the dimensions of the image
                    meta.setPixelsSizeX(pwidth, series);
                    meta.setPixelsSizeY(pheight, series);
                    meta.setPixelsSizeZ(new PositiveInteger(1), series);
                    meta.setPixelsSizeC(new PositiveInteger(1), series);
                    meta.setPixelsSizeT(new PositiveInteger(sizeT), series);
                    // define each channel and specify the number of samples in the
                    // channel the number of samples is 3 for RGB images and 1 otherwise
                    String channelID = MetadataTools.createLSID("Channel", well, fov);
                    meta.setChannelID(channelID, series, 0);
                    meta.setChannelSamplesPerPixel(new PositiveInteger(1), series, 0);
                    // set sample
                    String wellSampleID = MetadataTools.createLSID("WellSample", well, fov);
                    meta.setWellSampleID(wellSampleID, 0, well, fov);
                    // NB sampleIndex here == series ie the image No
                    meta.setWellSampleIndex(new NonNegativeInteger(series), 0, well, fov);
                    meta.setWellSampleImageRef(imageID, 0, well, fov);
                    // add FLIM ModuloAlongT annotation if required
                    // CoreMetadata modlo = createModuloAnn();
                    // meta.addModuloAlong(meta, modlo, series);
                    series++;
                }
                // end of samples
                well++;
            }
            rowChar++;
        }
        return meta;
    } catch (DependencyException e) {
        exception = e;
    } catch (ServiceException e) {
        exception = e;
    } catch (EnumerationException e) {
        exception = e;
    }
    System.err.println("Failed to populate OME-XML metadata object.");
    exception.printStackTrace();
    return null;
}
Also used : PositiveInteger(ome.xml.model.primitives.PositiveInteger) ServiceException(loci.common.services.ServiceException) ServiceFactory(loci.common.services.ServiceFactory) OMEXMLMetadata(loci.formats.ome.OMEXMLMetadata) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) DependencyException(loci.common.services.DependencyException) EnumerationException(ome.xml.model.enums.EnumerationException) FormatException(loci.formats.FormatException) EnumerationException(ome.xml.model.enums.EnumerationException) ServiceException(loci.common.services.ServiceException) IOException(java.io.IOException) DependencyException(loci.common.services.DependencyException) OMEXMLService(loci.formats.services.OMEXMLService)

Example 13 with NonNegativeInteger

use of ome.xml.model.primitives.NonNegativeInteger in project bioformats by openmicroscopy.

the class OMETiffWriter method populateImage.

private void populateImage(OMEXMLMetadata omeMeta, int series) {
    String dimensionOrder = omeMeta.getPixelsDimensionOrder(series).toString();
    int sizeZ = omeMeta.getPixelsSizeZ(series).getValue().intValue();
    int sizeC = omeMeta.getPixelsSizeC(series).getValue().intValue();
    int sizeT = omeMeta.getPixelsSizeT(series).getValue().intValue();
    int imageCount = getPlaneCount();
    if (imageCount == 0) {
        omeMeta.setTiffDataPlaneCount(new NonNegativeInteger(0), series, 0);
        return;
    }
    PositiveInteger samplesPerPixel = new PositiveInteger((sizeZ * sizeC * sizeT) / imageCount);
    for (int c = 0; c < omeMeta.getChannelCount(series); c++) {
        omeMeta.setChannelSamplesPerPixel(samplesPerPixel, series, c);
    }
    sizeC /= samplesPerPixel.getValue();
    int nextPlane = 0;
    for (int plane = 0; plane < imageCount; plane++) {
        int[] zct = FormatTools.getZCTCoords(dimensionOrder, sizeZ, sizeC, sizeT, imageCount, plane);
        int planeIndex = plane;
        if (imageLocations[series].length < imageCount) {
            planeIndex /= (imageCount / imageLocations[series].length);
        }
        String filename = imageLocations[series][planeIndex];
        if (filename != null) {
            filename = new Location(filename).getName();
            Integer ifdIndex = ifdCounts.get(filename);
            int ifd = ifdIndex == null ? 0 : ifdIndex.intValue();
            omeMeta.setUUIDFileName(filename, series, nextPlane);
            String uuid = "urn:uuid:" + getUUID(filename);
            omeMeta.setUUIDValue(uuid, series, nextPlane);
            // fill in any non-default TiffData attributes
            populateTiffData(omeMeta, zct, ifd, series, nextPlane);
            ifdCounts.put(filename, ifd + 1);
            nextPlane++;
        }
    }
}
Also used : PositiveInteger(ome.xml.model.primitives.PositiveInteger) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) PositiveInteger(ome.xml.model.primitives.PositiveInteger) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) Location(loci.common.Location)

Example 14 with NonNegativeInteger

use of ome.xml.model.primitives.NonNegativeInteger in project bioformats by openmicroscopy.

the class MetadataTools method populatePixels.

/**
 * Populates the Pixels element of the given metadata store, using core
 * metadata from the given reader.  If the {@code doPlane} flag is set,
 * then the Plane elements will be populated as well. If the
 * {@code doImageName} flag is set, then the image name will be populated as
 * well.
 *
 * @param store       The metadata store whose Pixels should be populated
 * @param r           The format reader whose core metadata should be used
 * @param doPlane     Specifies whether Plane elements should be populated
 * @param doImageName Specifies whether the Image name should be populated
 */
public static void populatePixels(MetadataStore store, IFormatReader r, boolean doPlane, boolean doImageName) {
    if (store == null || r == null)
        return;
    int oldSeries = r.getSeries();
    for (int i = 0; i < r.getSeriesCount(); i++) {
        r.setSeries(i);
        String imageName = null;
        if (doImageName) {
            Location f = new Location(r.getCurrentFile());
            imageName = f.getName();
            if (r.getSeriesCount() > 1) {
                imageName += " #" + (i + 1);
            }
        }
        String pixelType = FormatTools.getPixelTypeString(r.getPixelType());
        populateMetadata(store, r.getCurrentFile(), i, imageName, r.isLittleEndian(), r.getDimensionOrder(), pixelType, r.getSizeX(), r.getSizeY(), r.getSizeZ(), r.getSizeC(), r.getSizeT(), r.getRGBChannelCount());
        store.setPixelsInterleaved(r.isInterleaved(), i);
        store.setPixelsSignificantBits(new PositiveInteger(r.getBitsPerPixel()), i);
        try {
            OMEXMLService service = new ServiceFactory().getInstance(OMEXMLService.class);
            if (service.isOMEXMLRoot(store.getRoot())) {
                MetadataStore baseStore = r.getMetadataStore();
                if (service.isOMEXMLMetadata(baseStore)) {
                    OMEXMLMetadata omeMeta;
                    try {
                        omeMeta = service.getOMEMetadata(service.asRetrieve(baseStore));
                        if (omeMeta.getTiffDataCount(i) == 0 && omeMeta.getPixelsBinDataCount(i) == 0) {
                            service.addMetadataOnly(omeMeta, i, i == 0);
                        }
                    } catch (ServiceException e) {
                        LOGGER.warn("Failed to add MetadataOnly", e);
                    }
                }
            }
        } catch (DependencyException exc) {
            LOGGER.warn("Failed to add MetadataOnly", exc);
        }
        if (doPlane) {
            for (int q = 0; q < r.getImageCount(); q++) {
                int[] coords = r.getZCTCoords(q);
                store.setPlaneTheZ(new NonNegativeInteger(coords[0]), i, q);
                store.setPlaneTheC(new NonNegativeInteger(coords[1]), i, q);
                store.setPlaneTheT(new NonNegativeInteger(coords[2]), i, q);
            }
        }
    }
    r.setSeries(oldSeries);
}
Also used : MetadataStore(loci.formats.meta.MetadataStore) PositiveInteger(ome.xml.model.primitives.PositiveInteger) ServiceException(loci.common.services.ServiceException) ServiceFactory(loci.common.services.ServiceFactory) OMEXMLMetadata(loci.formats.ome.OMEXMLMetadata) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) DependencyException(loci.common.services.DependencyException) OMEXMLService(loci.formats.services.OMEXMLService) Location(loci.common.Location)

Example 15 with NonNegativeInteger

use of ome.xml.model.primitives.NonNegativeInteger in project bioformats by openmicroscopy.

the class CellVoyagerReader method readInfo.

private void readInfo(final Document msDocument, final Document omeDocument) throws FormatException {
    /*
     * Magnification.
     *
     * We need it early, because the file format reports only un-magnified
     * sizes. So if we are to put proper metadata, we need to make the
     * conversion to size measured at the sample level ourselves. I feel
     * like this is fragile and most likely to change in a future version of
     * the file format.
     */
    final Element msRoot = msDocument.getDocumentElement();
    final double objectiveMagnification = Double.parseDouble(getChildText(msRoot, new String[] { "ObjectiveLens", "Magnification" }));
    // final double zoomLensMagnification = Double.parseDouble(
    // getChildText( msRoot, new String[] { "ZoomLens", "Magnification",
    // "Value" } ) );
    // *
    final double magnification = objectiveMagnification;
    // zoomLensMagnification;
    /*
     * Read the ome.xml file. Since it is malformed, we need to parse all
     * nodes, and add an "ID" attribute to those who do not have it.
     */
    final NodeList nodeList = omeDocument.getElementsByTagName("*");
    for (int i = 0; i < nodeList.getLength(); i++) {
        final Node node = nodeList.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            final NamedNodeMap atts = node.getAttributes();
            final Node namedItem = atts.getNamedItem("ID");
            if (namedItem == null) {
                final String name = node.getNodeName();
                final String id = name + ":" + i;
                if (!node.getParentNode().getNodeName().equals("LightSource")) {
                    ((Element) node).setAttribute("ID", id);
                }
            }
        }
    }
    /*
     * For single-slice image, the PhysicalSizeZ can be 0, which will make
     * the metadata read fail. Correct that.
     */
    final Element pszEl = getChild(omeDocument.getDocumentElement(), new String[] { "Image", "Pixels" });
    final double physicalSizeZ = Double.parseDouble(pszEl.getAttribute("PhysicalSizeZ"));
    if (physicalSizeZ <= 0) {
        // default to 1 whatever
        pszEl.setAttribute("PhysicalSizeZ", "" + 1);
    }
    /*
     * Now that the XML document is properly formed, we can build a metadata
     * object from it.
     */
    OMEXMLService service = null;
    String xml = null;
    try {
        xml = XMLTools.getXML(omeDocument);
    } catch (final TransformerConfigurationException e2) {
        LOGGER.debug("", e2);
    } catch (final TransformerException e2) {
        LOGGER.debug("", e2);
    }
    try {
        service = new ServiceFactory().getInstance(OMEXMLService.class);
    } catch (final DependencyException e1) {
        LOGGER.debug("", e1);
    }
    OMEXMLMetadata omeMD = null;
    try {
        omeMD = service.createOMEXMLMetadata(xml);
    } catch (final ServiceException e) {
        LOGGER.debug("", e);
    } catch (final NullPointerException npe) {
        LOGGER.debug("", npe);
        throw npe;
    }
    // Correct pixel size for magnification
    omeMD.setPixelsPhysicalSizeX(FormatTools.createLength(omeMD.getPixelsPhysicalSizeX(0).value().doubleValue() / magnification, omeMD.getPixelsPhysicalSizeX(0).unit()), 0);
    omeMD.setPixelsPhysicalSizeY(FormatTools.createLength(omeMD.getPixelsPhysicalSizeY(0).value().doubleValue() / magnification, omeMD.getPixelsPhysicalSizeY(0).unit()), 0);
    // Time interval
    if (Double.valueOf(readFrameInterval(msDocument)) != null) {
        omeMD.setPixelsTimeIncrement(new Time(Double.valueOf(readFrameInterval(msDocument)), UNITS.SECOND), 0);
    }
    /*
     * Channels
     */
    final Element channelsEl = getChild(msRoot, "Channels");
    final List<Element> channelEls = getChildren(channelsEl, "Channel");
    channelInfos = new ArrayList<ChannelInfo>();
    for (final Element channelEl : channelEls) {
        final boolean isEnabled = Boolean.parseBoolean(getChildText(channelEl, "IsEnabled"));
        if (!isEnabled) {
            continue;
        }
        final ChannelInfo ci = readChannel(channelEl);
        channelInfos.add(ci);
    }
    /*
     * Fix missing IDs.
     *
     * Some IDs are missing in the malformed OME.XML file. We must put them
     * back manually. Some are fixed here
     */
    omeMD.setProjectID(MetadataTools.createLSID("Project", 0), 0);
    omeMD.setScreenID(MetadataTools.createLSID("Screen", 0), 0);
    omeMD.setPlateID(MetadataTools.createLSID("Plate", 0), 0);
    omeMD.setInstrumentID(MetadataTools.createLSID("Instrument", 0), 0);
    // Read pixel sizes from OME metadata.
    final double pixelWidth = omeMD.getPixelsPhysicalSizeX(0).value().doubleValue();
    final double pixelHeight = omeMD.getPixelsPhysicalSizeY(0).value().doubleValue();
    /*
     * Read tile size from channel info. This is weird, but it's like that.
     * Since we build a multi-C image, we have to assume that all channels
     * have the same dimension, even if the file format allows for changing
     * the size, binning, etc. from channel to channel. Failure to load
     * datasets that have this exoticity is to be sought here.
     */
    final int tileWidth = channelInfos.get(0).tileWidth;
    final int tileHeight = channelInfos.get(0).tileHeight;
    /*
     * Handle multiple wells.
     *
     * The same kind of remark apply: We assume that a channel setting can
     * be applied to ALL wells. So this file reader will fail for dataset
     * that have one well that has a different dimension that of others.
     */
    /*
     * First remark: there can be two modes to store Areas in the xml file:
     * Either we define different areas for each well, and in that case, the
     * areas are found as a child element of the well element. Either the
     * definition of areas is common to all wells, and in that case they
     * area defined in a separate element.
     */
    final boolean sameAreaPerWell = Boolean.parseBoolean(getChildText(msRoot, "UsesSameAreaParWell"));
    List<AreaInfo> areas = null;
    if (sameAreaPerWell) {
        final Element areasEl = getChild(msRoot, new String[] { "SameAreaUsingWell", "Areas" });
        final List<Element> areaEls = getChildren(areasEl, "Area");
        int areaIndex = 0;
        areas = new ArrayList<AreaInfo>(areaEls.size());
        int fieldIndex = 1;
        for (final Element areaEl : areaEls) {
            final AreaInfo area = readArea(areaEl, fieldIndex, pixelWidth, pixelHeight, tileWidth, tileHeight);
            area.index = areaIndex++;
            areas.add(area);
            // Continue incrementing field index across areas.
            fieldIndex = area.fields.get(area.fields.size() - 1).index + 1;
        }
    }
    final Element wellsEl = getChild(msRoot, "Wells");
    final List<Element> wellEls = getChildren(wellsEl, "Well");
    wells = new ArrayList<WellInfo>();
    for (final Element wellEl : wellEls) {
        final boolean isWellEnabled = Boolean.parseBoolean(getChild(wellEl, "IsEnabled").getTextContent());
        if (isWellEnabled) {
            final WellInfo wi = readWellInfo(wellEl, pixelWidth, pixelHeight, tileWidth, tileHeight);
            if (sameAreaPerWell) {
                wi.areas = areas;
            }
            wells.add(wi);
        }
    }
    /*
     * Z range.
     *
     * In this file format, the Z range appears to be general: it applies to
     * all fields of all wells.
     */
    final int nZSlices = Integer.parseInt(getChildText(msRoot, new String[] { "ZStackConditions", "NumberOfSlices" }));
    /*
     * Time points. They are general as well. Which just makes sense.
     */
    timePoints = readTimePoints(msDocument);
    /*
     * Populate CORE metadata for each area.
     *
     * This reader takes to convention that state that 1 area = 1 series. So
     * if you have 10 wells with 2 areas in each well, and each area is made
     * of 20 fields, you will get 20 series, and each series will be
     * stitched from 20 fields.
     */
    OMEXMLMetadataRoot root = (OMEXMLMetadataRoot) omeMD.getRoot();
    Image firstImage = root.getImage(0);
    core.clear();
    for (final WellInfo well : wells) {
        for (final AreaInfo area : well.areas) {
            final CoreMetadata ms = new CoreMetadata();
            core.add(ms);
            if (core.size() > 1) {
                root.addImage(firstImage);
            }
            ms.sizeX = area.width;
            ms.sizeY = area.height;
            ms.sizeZ = nZSlices;
            ms.sizeC = channelInfos.size();
            ms.sizeT = timePoints.size();
            ms.dimensionOrder = "XYCZT";
            ms.rgb = false;
            ms.imageCount = nZSlices * channelInfos.size() * timePoints.size();
            // Bit depth.
            switch(omeMD.getPixelsType(0)) {
                case UINT8:
                    ms.pixelType = FormatTools.UINT8;
                    ms.bitsPerPixel = 8;
                    break;
                case UINT16:
                    ms.pixelType = FormatTools.UINT16;
                    ms.bitsPerPixel = 16;
                    break;
                case UINT32:
                    ms.pixelType = FormatTools.UINT32;
                    ms.bitsPerPixel = 32;
                    break;
                default:
                    throw new FormatException("Cannot read image with pixel type = " + omeMD.getPixelsType(0));
            }
            // Determined manually on sample data. Check here is the image
            // you get is weird.
            ms.littleEndian = true;
        }
    }
    omeMD.setRoot(root);
    /*
     * Populate the MetadataStore.
     */
    final MetadataStore store = makeFilterMetadata();
    MetadataConverter.convertMetadata(omeMD, store);
    MetadataTools.populatePixels(store, this, true);
    /*
     * Pinhole disk
     */
    final double pinholeSize = Double.parseDouble(getChildText(msRoot, new String[] { "PinholeDisk", "PinholeSize_um" }));
    /*
     * MicroPlate specific stuff
     */
    final Element containerEl = getChild(msRoot, new String[] { "Attachment", "HolderInfoList", "HolderInfo", "MountedSampleContainer" });
    final String type = containerEl.getAttribute("xsi:type");
    boolean plateMetadata = false;
    if (type.equals("WellPlate")) {
        plateMetadata = true;
        final int nrows = Integer.parseInt(getChildText(containerEl, "RowCount"));
        final int ncols = Integer.parseInt(getChildText(containerEl, "ColumnCount"));
        store.setPlateRows(new PositiveInteger(nrows), 0);
        store.setPlateColumns(new PositiveInteger(ncols), 0);
        final String plateAcqID = MetadataTools.createLSID("PlateAcquisition", 0, 0);
        store.setPlateAcquisitionID(plateAcqID, 0, 0);
        final Element dimInfoEl = getChild(msRoot, "DimensionsInfo");
        final int maxNFields = Integer.parseInt(getChild(dimInfoEl, "F").getAttribute("Max"));
        final PositiveInteger fieldCount = FormatTools.getMaxFieldCount(maxNFields);
        if (fieldCount != null) {
            store.setPlateAcquisitionMaximumFieldCount(fieldCount, 0, 0);
        }
        // Plate acquisition time
        final String beginTime = getChildText(msRoot, "BeginTime");
        final String endTime = getChildText(msRoot, "EndTime");
        store.setPlateAcquisitionStartTime(new Timestamp(beginTime), 0, 0);
        store.setPlateAcquisitionEndTime(new Timestamp(endTime), 0, 0);
        store.setPlateName(beginTime, 0);
    } else if (!type.equals("PreparedSlide")) {
        LOGGER.warn("Unexpected acquisition type: {}", type);
    }
    // Wells position on the plate
    int seriesIndex = -1;
    int wellIndex = -1;
    for (final WellInfo well : wells) {
        wellIndex++;
        final int wellNumber = well.number;
        if (plateMetadata) {
            store.setWellID(MetadataTools.createLSID("Well", 0, wellIndex), 0, wellIndex);
            store.setWellRow(new NonNegativeInteger(well.row), 0, wellIndex);
            store.setWellColumn(new NonNegativeInteger(well.col), 0, wellIndex);
        }
        int areaIndex = -1;
        for (final AreaInfo area : well.areas) {
            seriesIndex++;
            areaIndex++;
            String imageID = MetadataTools.createLSID("Image", seriesIndex);
            store.setImageID(imageID, seriesIndex);
            final String imageName = "Well " + wellNumber + " (UID=" + well.UID + ", r=" + well.row + ", c=" + well.col + ") - Area " + areaIndex;
            store.setImageName(imageName, seriesIndex);
            if (plateMetadata) {
                Length posX = new Length(Double.valueOf(well.centerX), UNITS.REFERENCEFRAME);
                Length posY = new Length(Double.valueOf(well.centerY), UNITS.REFERENCEFRAME);
                String wellSample = MetadataTools.createLSID("WellSample", 0, wellIndex, areaIndex);
                store.setWellSampleID(wellSample, 0, wellIndex, areaIndex);
                store.setWellSampleImageRef(imageID, 0, wellIndex, areaIndex);
                store.setWellSampleIndex(new NonNegativeInteger(area.index), 0, wellIndex, areaIndex);
                store.setWellSamplePositionX(posX, 0, wellIndex, areaIndex);
                store.setWellSamplePositionY(posY, 0, wellIndex, areaIndex);
                store.setPlateAcquisitionWellSampleRef(wellSample, 0, 0, seriesIndex);
            }
            store.setImageInstrumentRef(MetadataTools.createLSID("Instrument", 0), seriesIndex);
            for (int i = 0; i < channelInfos.size(); i++) {
                store.setChannelPinholeSize(new Length(pinholeSize, UNITS.MICROMETER), seriesIndex, i);
                store.setChannelName(channelInfos.get(i).name, seriesIndex, i);
                store.setChannelColor(channelInfos.get(i).color, seriesIndex, i);
            }
        }
    }
}
Also used : TransformerConfigurationException(javax.xml.transform.TransformerConfigurationException) ServiceFactory(loci.common.services.ServiceFactory) Element(org.w3c.dom.Element) Node(org.w3c.dom.Node) Time(ome.units.quantity.Time) Image(ome.xml.model.Image) Timestamp(ome.xml.model.primitives.Timestamp) OMEXMLService(loci.formats.services.OMEXMLService) TransformerException(javax.xml.transform.TransformerException) PositiveInteger(ome.xml.model.primitives.PositiveInteger) NamedNodeMap(org.w3c.dom.NamedNodeMap) NonNegativeInteger(ome.xml.model.primitives.NonNegativeInteger) NodeList(org.w3c.dom.NodeList) DependencyException(loci.common.services.DependencyException) CoreMetadata(loci.formats.CoreMetadata) FormatException(loci.formats.FormatException) MetadataStore(loci.formats.meta.MetadataStore) ServiceException(loci.common.services.ServiceException) Length(ome.units.quantity.Length) OMEXMLMetadata(loci.formats.ome.OMEXMLMetadata) OMEXMLMetadataRoot(ome.xml.meta.OMEXMLMetadataRoot)

Aggregations

NonNegativeInteger (ome.xml.model.primitives.NonNegativeInteger)28 PositiveInteger (ome.xml.model.primitives.PositiveInteger)17 CoreMetadata (loci.formats.CoreMetadata)15 FormatException (loci.formats.FormatException)14 MetadataStore (loci.formats.meta.MetadataStore)14 Location (loci.common.Location)13 ArrayList (java.util.ArrayList)12 Length (ome.units.quantity.Length)11 Time (ome.units.quantity.Time)11 Timestamp (ome.xml.model.primitives.Timestamp)9 IOException (java.io.IOException)6 ServiceException (loci.common.services.ServiceException)6 RandomAccessInputStream (loci.common.RandomAccessInputStream)5 DependencyException (loci.common.services.DependencyException)5 ServiceFactory (loci.common.services.ServiceFactory)5 OMEXMLMetadata (loci.formats.ome.OMEXMLMetadata)5 OMEXMLService (loci.formats.services.OMEXMLService)5 IFD (loci.formats.tiff.IFD)5 HashMap (java.util.HashMap)3 Map (java.util.Map)3