//
// MetadataTools.java
//
/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan,
Eric Kjellman and Brian Loranger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.formats;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
/**
* A utility class for working with metadata objects,
* including {@link MetadataStore}, {@link MetadataRetrieve},
* and OME-XML strings.
* Most of the methods require the optional {@link loci.formats.ome}
* package, and optional ome-java.jar library, to be present at runtime.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/MetadataTools.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/MetadataTools.java">SVN</a></dd></dl>
*/
public final class MetadataTools {
// -- Constructor --
private MetadataTools() { }
// -- Utility methods - OME-XML --
/**
* Creates an OME-XML metadata object using reflection, to avoid
* direct dependencies on the optional {@link loci.formats.ome} package.
* @return A new instance of {@link loci.formats.ome.OMEXMLMetadata},
* or null if the class is not available.
*/
public static MetadataStore createOMEXMLMetadata() {
return createOMEXMLMetadata(null);
}
/**
* Creates an OME-XML metadata object using reflection, to avoid
* direct dependencies on the optional {@link loci.formats.ome} package,
* wrapping a DOM representation of the given OME-XML string.
* @return A new instance of {@link loci.formats.ome.OMEXMLMetadata},
* or null if the class is not available.
*/
public static MetadataStore createOMEXMLMetadata(String xml) {
MetadataStore store = null;
ReflectedUniverse r = new ReflectedUniverse();
try {
r.exec("import loci.formats.ome.OMEXMLMetadata");
r.setVar("xml", xml);
store = (MetadataStore) r.exec("new OMEXMLMetadata(xml)");
}
catch (ReflectException exc) { }
return store;
}
/**
* Checks whether the given object is an OME-XML metadata object.
* @return True iff the object is an instance of
* {@link loci.formats.ome.OMEXMLMetadata}.
*/
public static boolean isOMEXMLMetadata(Object o) {
ReflectedUniverse r = new ReflectedUniverse();
try {
r.exec("import loci.formats.ome.OMEXMLMetadata");
Class c = (Class) r.getVar("OMEXMLMetadata");
return c.isInstance(o);
}
catch (ReflectException exc) { }
return false;
}
/**
* Adds the specified key/value pair as a new OriginalMetadata node
* to the given OME-XML metadata object.
* Does nothing unless the given object is an OME-XML metadata object.
* @param o An object of type {@link loci.formats.ome.OMEXMLMetadata}.
* @param key Metadata key to populate.
* @param value Metadata value corresponding to the specified key.
*/
public static void populateOriginalMetadata(Object o,
String key, String value)
{
ReflectedUniverse r = new ReflectedUniverse();
r.setVar("omexmlMeta", o);
r.setVar("key", key);
r.setVar("value", value);
try {
r.exec("omexmlMeta.populateOriginalMetadata(key, value)");
}
catch (ReflectException exc) { }
}
/**
* Extracts an OME-XML metadata string from the given metadata object,
* by converting to an OME-XML metadata object if necessary.
*/
public static String getOMEXML(MetadataRetrieve src) {
MetadataStore omexmlMeta;
if (isOMEXMLMetadata(src)) {
// the metadata is already an OME-XML metadata object
omexmlMeta = (MetadataStore) src;
}
else {
// populate a new OME-XML metadata object with metadata
// converted from the non-OME-XML metadata object
omexmlMeta = createOMEXMLMetadata();
MetadataTools.convertMetadata(src, omexmlMeta);
}
ReflectedUniverse r = new ReflectedUniverse();
r.setVar("omexmlMeta", omexmlMeta);
try {
return (String) r.exec("omexmlMeta.dumpXML()");
}
catch (ReflectException exc) { }
return null;
}
/**
* Attempts to validate the given OME-XML string using
* Java's XML validation facility. Requires Java 1.5+.
*/
public static void validateOMEXML(String xml) {
XMLTools.validateXML(xml, "OME-XML");
}
// -- Utility methods -- metadata conversion --
/**
* Converts information from an OME-XML string (source)
* into a metadata store (destination).
*/
public static void convertMetadata(String xml, MetadataStore dest) {
if (isOMEXMLMetadata(dest)) {
// metadata store is already an OME-XML metadata object;
// populate OME-XML string directly
ReflectedUniverse r = new ReflectedUniverse();
try {
r.setVar("xml", xml);
r.setVar("omexmlMeta", dest);
r.exec("omexmlMeta.createRoot(xml)");
}
catch (ReflectException exc) { }
}
else {
// metadata store is foreign; create an OME-XML
// metadata object and copy it into the destination
MetadataRetrieve src = (MetadataRetrieve) createOMEXMLMetadata(xml);
convertMetadata(src, dest);
}
}
/**
* Copies information from a metadata retrieval object
* (source) into a metadata store (destination).
*/
public static void convertMetadata(MetadataRetrieve src, MetadataStore dest) {
Integer ii = null;
int globalPixCount = 0;
for (int i=0; i<src.getImageCount(); i++) {
ii = new Integer(i);
dest.setImage(src.getImageName(ii), src.getCreationDate(ii),
src.getDescription(ii), ii);
dest.setDimensions(src.getPixelSizeX(ii),
src.getPixelSizeY(ii), src.getPixelSizeZ(ii),
src.getPixelSizeC(ii), src.getPixelSizeT(ii), ii);
for (int j=0; j<src.getPixelsCount(ii); j++) {
Integer p = new Integer(j);
dest.setPixels(src.getSizeX(ii), src.getSizeY(ii),
src.getSizeZ(ii), src.getSizeC(ii),
src.getSizeT(ii),
new Integer(FormatTools.pixelTypeFromString(src.getPixelType(ii))),
src.getBigEndian(ii), src.getDimensionOrder(ii), ii, p);
dest.setDisplayOptions(src.getZoom(ii),
src.isRedChannelOn(ii), src.isGreenChannelOn(ii),
src.isBlueChannelOn(ii), src.isDisplayRGB(ii),
src.getColorMap(ii), src.getZStart(ii),
src.getZStop(ii), src.getTStart(ii),
src.getTStop(ii), ii, p, new Integer(0), new Integer(1),
new Integer(2), new Integer(0));
Integer globalPix = new Integer(globalPixCount);
for (int ch=0; ch<src.getChannelCount(globalPix); ch++) {
Integer c = new Integer(ch);
dest.setLogicalChannel(ch, src.getChannelName(globalPix, c),
null, null, null, null, null, null, null, null, null, null, null,
src.getPhotometricInterpretation(globalPix, c),
src.getMode(globalPix, c), null, null, null, null, null,
src.getEmWave(globalPix, c), src.getExWave(globalPix, c),
null, src.getChannelNDFilter(globalPix, c), globalPix);
dest.setChannelGlobalMinMax(ch, src.getGlobalMin(globalPix, c),
src.getGlobalMax(globalPix, c), globalPix);
dest.setDisplayChannel(c, src.getBlackLevel(globalPix, c),
src.getWhiteLevel(globalPix, c), src.getGamma(globalPix, c),
globalPix);
}
globalPixCount++;
}
dest.setImagingEnvironment(src.getTemperature(ii),
src.getAirPressure(ii), src.getHumidity(ii),
src.getCO2Percent(ii), ii);
}
for (int i=0; i<src.getExperimenterCount(); i++) {
ii = new Integer(i);
dest.setExperimenter(src.getFirstName(ii),
src.getLastName(ii), src.getEmail(ii),
src.getInstitution(ii), src.getDataDirectory(ii),
src.getGroup(ii), ii);
}
for (int i=0; i<src.getGroupCount(); i++) {
ii = new Integer(i);
dest.setGroup(src.getGroupName(ii), src.getLeader(ii),
src.getContact(ii), ii);
}
for (int i=0; i<src.getInstrumentCount(); i++) {
ii = new Integer(i);
dest.setInstrument(src.getManufacturer(ii),
src.getModel(ii), src.getSerialNumber(ii),
src.getType(ii), ii);
}
for (int i=0; i<src.getDisplayROICount(); i++) {
ii = new Integer(i);
dest.setDisplayROI(src.getX0(ii), src.getY0(ii),
src.getZ0(ii), src.getX1(ii), src.getY1(ii),
src.getZ1(ii), src.getT0(ii), src.getT1(ii),
src.getDisplayOptions(ii), ii);
}
for (int i=0; i<src.getStageLabelCount(); i++) {
ii = new Integer(i);
dest.setStageLabel(src.getStageName(ii), src.getStageX(ii),
src.getStageY(ii), src.getStageZ(ii), ii);
}
ii = null;
dest.setPlaneInfo(0, 0, 0, src.getTimestamp(ii, ii, ii, ii),
src.getExposureTime(ii, ii, ii, ii), ii);
dest.setLightSource(src.getLightManufacturer(ii),
src.getLightModel(ii), src.getLightSerial(ii), ii, ii);
dest.setLaser(src.getLaserType(ii), src.getLaserMedium(ii),
src.getLaserWavelength(ii), src.isFrequencyDoubled(ii),
src.isTunable(ii), src.getPulse(ii),
src.getPower(ii), ii, ii, ii, ii);
dest.setFilament(src.getFilamentType(ii),
src.getFilamentPower(ii), ii, ii);
dest.setArc(src.getArcType(ii), src.getArcPower(ii), ii, ii);
dest.setDetector(src.getDetectorManufacturer(ii),
src.getDetectorModel(ii), src.getDetectorSerial(ii),
src.getDetectorType(ii), src.getDetectorGain(ii),
src.getDetectorVoltage(ii),
src.getDetectorOffset(ii), ii, ii);
dest.setObjective(src.getObjectiveManufacturer(ii),
src.getObjectiveModel(ii), src.getObjectiveSerial(ii),
src.getLensNA(ii),
src.getObjectiveMagnification(ii), ii, ii);
dest.setExcitationFilter(src.getExcitationManufacturer(ii),
src.getExcitationModel(ii), src.getExcitationLotNumber(ii),
src.getExcitationType(ii), ii);
dest.setDichroic(src.getDichroicManufacturer(ii),
src.getDichroicModel(ii), src.getDichroicLotNumber(ii), ii);
dest.setEmissionFilter(src.getEmissionManufacturer(ii),
src.getEmissionModel(ii), src.getEmissionLotNumber(ii),
src.getEmissionType(ii), ii);
dest.setFilterSet(src.getFilterSetManufacturer(ii),
src.getFilterSetModel(ii),
src.getFilterSetLotNumber(ii), ii, ii);
dest.setOTF(src.getOTFSizeX(ii), src.getOTFSizeY(ii),
src.getOTFPixelType(ii), src.getOTFPath(ii),
src.getOTFOpticalAxisAverage(ii), ii, ii, ii, ii);
}
// -- Helper classes --
/** Used by testRead to handle XML validation errors. */
private static class ValidationHandler implements ErrorHandler {
private boolean ok = true;
public boolean ok() { return ok; }
public void error(SAXParseException e) {
LogTools.println("error: " + e.getMessage());
ok = false;
}
public void fatalError(SAXParseException e) {
LogTools.println("fatal error: " + e.getMessage());
ok = false;
}
public void warning(SAXParseException e) {
LogTools.println("warning: " + e.getMessage());
ok = false;
}
}
}