<commit_before>//
// MetadataTools.java
//

/*
OME Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.

You should have received a copy of the GNU 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 java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;

import loci.common.DateTools;
import loci.common.Location;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory;
import loci.formats.meta.IMetadata;
import loci.formats.meta.MetadataRetrieve;
import loci.formats.meta.MetadataStore;
import loci.formats.ome.OMEXMLMetadataImpl;
import loci.formats.services.OMEXMLService;

import ome.xml.model.BinData;
import ome.xml.model.OME;
import ome.xml.model.enums.DimensionOrder;
import ome.xml.model.enums.EnumerationException;
import ome.xml.model.enums.PixelType;
import ome.xml.model.primitives.NonNegativeInteger;
import ome.xml.model.primitives.NonNegativeLong;
import ome.xml.model.primitives.PositiveInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 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-xml.jar library, to be present at runtime.
 *
 * <dl><dt><b>Source code:</b></dt>
 * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/src/loci/formats/MetadataTools.java">Trac</a>,
 * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/src/loci/formats/MetadataTools.java;hb=HEAD">Gitweb</a></dd></dl>
 */
public final class MetadataTools {

  // -- Constants --

  private static final Logger LOGGER =
    LoggerFactory.getLogger(MetadataTools.class);

  // -- Static fields --

  // -- Constructor --

  private MetadataTools() { }

  // -- Utility methods - OME-XML --

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.
   */
  public static void populatePixels(MetadataStore store, IFormatReader r) {
    populatePixels(store, r, false, true);
  }

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.  If the 'doPlane' flag is set,
   * then the 'plane' elements will be populated as well.
   */
  public static void populatePixels(MetadataStore store, IFormatReader r,
    boolean doPlane)
  {
    populatePixels(store, r, doPlane, true);
  }

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.  If the 'doPlane' flag is set,
   * then the 'plane' elements will be populated as well.
   * If the 'doImageName' flag is set, then the image name will be populated
   * as well.  By default, 'doImageName' is true.
   */
  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);
      store.setImageID(createLSID("Image", i), i);
      if (doImageName) {
        Location f = new Location(r.getCurrentFile());
        store.setImageName(f.getName(), i);
      }
      String pixelsID = createLSID("Pixels", i);
      store.setPixelsID(pixelsID, i);
      store.setPixelsSizeX(new PositiveInteger(r.getSizeX()), i);
      store.setPixelsSizeY(new PositiveInteger(r.getSizeY()), i);
      store.setPixelsSizeZ(new PositiveInteger(r.getSizeZ()), i);
      store.setPixelsSizeC(new PositiveInteger(r.getSizeC()), i);
      store.setPixelsSizeT(new PositiveInteger(r.getSizeT()), i);
      store.setPixelsBinDataBigEndian(new Boolean(!r.isLittleEndian()), i, 0);

      try {
        OMEXMLService service =
          new ServiceFactory().getInstance(OMEXMLService.class);
        if (service.isOMEXMLRoot(store.getRoot())) {
          MetadataStore baseStore = r.getMetadataStore();
          if (service.isOMEXMLMetadata(baseStore)) {
            ((OMEXMLMetadataImpl) baseStore).resolveReferences();
          }

          OME root = (OME) store.getRoot();
          BinData bin = root.getImage(i).getPixels().getBinData(0);
          bin.setLength(new NonNegativeLong(0L));
          store.setRoot(root);
        }
      }
      catch (DependencyException exc) {
        LOGGER.debug("Failed to set BinData.Length", exc);
      }

      try {
        store.setPixelsType(PixelType.fromString(
          FormatTools.getPixelTypeString(r.getPixelType())), i);
        store.setPixelsDimensionOrder(
          DimensionOrder.fromString(r.getDimensionOrder()), i);
      }
      catch (EnumerationException e) {
        LOGGER.debug("Failed to create enumeration", e);
      }
      if (r.getSizeC() > 0) {
        Integer sampleCount = new Integer(r.getRGBChannelCount());
        for (int c=0; c<r.getEffectiveSizeC(); c++) {
          store.setChannelID(createLSID("Channel", i, c), i, c);
          store.setChannelSamplesPerPixel(
            new PositiveInteger(sampleCount), i, c);
        }
      }
      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);
  }

  /**
   * Constructs an LSID, given the object type and indices.
   * For example, if the arguments are "Detector", 1, and 0, the LSID will
   * be "Detector:1:0".
   */<commit_msg>Add utility method to populate minimum metadata.<commit_after>//
// MetadataTools.java
//

/*
OME Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.

You should have received a copy of the GNU 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 java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;

import loci.common.DateTools;
import loci.common.Location;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory;
import loci.formats.meta.IMetadata;
import loci.formats.meta.MetadataRetrieve;
import loci.formats.meta.MetadataStore;
import loci.formats.ome.OMEXMLMetadataImpl;
import loci.formats.services.OMEXMLService;

import ome.xml.model.BinData;
import ome.xml.model.OME;
import ome.xml.model.enums.DimensionOrder;
import ome.xml.model.enums.EnumerationException;
import ome.xml.model.enums.PixelType;
import ome.xml.model.primitives.NonNegativeInteger;
import ome.xml.model.primitives.NonNegativeLong;
import ome.xml.model.primitives.PositiveInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 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-xml.jar library, to be present at runtime.
 *
 * <dl><dt><b>Source code:</b></dt>
 * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/src/loci/formats/MetadataTools.java">Trac</a>,
 * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/src/loci/formats/MetadataTools.java;hb=HEAD">Gitweb</a></dd></dl>
 */
public final class MetadataTools {

  // -- Constants --

  private static final Logger LOGGER =
    LoggerFactory.getLogger(MetadataTools.class);

  // -- Static fields --

  // -- Constructor --

  private MetadataTools() { }

  // -- Utility methods - OME-XML --

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.
   */
  public static void populatePixels(MetadataStore store, IFormatReader r) {
    populatePixels(store, r, false, true);
  }

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.  If the 'doPlane' flag is set,
   * then the 'plane' elements will be populated as well.
   */
  public static void populatePixels(MetadataStore store, IFormatReader r,
    boolean doPlane)
  {
    populatePixels(store, r, doPlane, true);
  }

  /**
   * Populates the 'pixels' element of the given metadata store, using core
   * metadata from the given reader.  If the 'doPlane' flag is set,
   * then the 'plane' elements will be populated as well.
   * If the 'doImageName' flag is set, then the image name will be populated
   * as well.  By default, 'doImageName' is true.
   */
  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);
      store.setImageID(createLSID("Image", i), i);
      if (doImageName) {
        Location f = new Location(r.getCurrentFile());
        store.setImageName(f.getName(), i);
      }
      String pixelsID = createLSID("Pixels", i);
      store.setPixelsID(pixelsID, i);
      store.setPixelsSizeX(new PositiveInteger(r.getSizeX()), i);
      store.setPixelsSizeY(new PositiveInteger(r.getSizeY()), i);
      store.setPixelsSizeZ(new PositiveInteger(r.getSizeZ()), i);
      store.setPixelsSizeC(new PositiveInteger(r.getSizeC()), i);
      store.setPixelsSizeT(new PositiveInteger(r.getSizeT()), i);
      store.setPixelsBinDataBigEndian(new Boolean(!r.isLittleEndian()), i, 0);

      try {
        OMEXMLService service =
          new ServiceFactory().getInstance(OMEXMLService.class);
        if (service.isOMEXMLRoot(store.getRoot())) {
          MetadataStore baseStore = r.getMetadataStore();
          if (service.isOMEXMLMetadata(baseStore)) {
            ((OMEXMLMetadataImpl) baseStore).resolveReferences();
          }

          OME root = (OME) store.getRoot();
          BinData bin = root.getImage(i).getPixels().getBinData(0);
          bin.setLength(new NonNegativeLong(0L));
          store.setRoot(root);
        }
      }
      catch (DependencyException exc) {
        LOGGER.debug("Failed to set BinData.Length", exc);
      }

      try {
        store.setPixelsType(PixelType.fromString(
          FormatTools.getPixelTypeString(r.getPixelType())), i);
        store.setPixelsDimensionOrder(
          DimensionOrder.fromString(r.getDimensionOrder()), i);
      }
      catch (EnumerationException e) {
        LOGGER.debug("Failed to create enumeration", e);
      }
      if (r.getSizeC() > 0) {
        Integer sampleCount = new Integer(r.getRGBChannelCount());
        for (int c=0; c<r.getEffectiveSizeC(); c++) {
          store.setChannelID(createLSID("Channel", i, c), i, c);
          store.setChannelSamplesPerPixel(
            new PositiveInteger(sampleCount), i, c);
        }
      }
      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);
  }

  /**
   * Populates the given {@link MetadataStore}, for the specified series, using
   * the values from the provided {@link CoreMetadata}.
   * <p>
   * After calling this method, the metadata store will be sufficiently
   * populated for use with an {@link IFormatWriter} (assuming it is also a
   * {@link MetadataRetrieve}).
   * </p>
   *
   * @throws EnumerationException if the dimensionOrder string is invalid.
   */
  public static void populateMetadata(MetadataStore store, int series,
    String imageName, CoreMetadata coreMeta) throws EnumerationException
  {
    final String pixelType = FormatTools.getPixelTypeString(coreMeta.pixelType);
    final int effSizeC = coreMeta.imageCount / coreMeta.sizeZ / coreMeta.sizeT;
    final int samplesPerPixel = coreMeta.sizeC / effSizeC;
    populateMetadata(store, series, imageName, coreMeta.littleEndian,
      coreMeta.dimensionOrder, pixelType, coreMeta.sizeX, coreMeta.sizeY,
      coreMeta.sizeZ, coreMeta.sizeC, coreMeta.sizeT, samplesPerPixel);
  }

  /**
   * Populates the given {@link MetadataStore}, for the specified series, using
   * the provided values.
   * <p>
   * After calling this method, the metadata store will be sufficiently
   * populated for use with an {@link IFormatWriter} (assuming it is also a
   * {@link MetadataRetrieve}).
   * </p>
   *
   * @throws EnumerationException if the dimensionOrder or pixelType values are
   *           invalid.
   */
  public static void populateMetadata(MetadataStore store, int series,
    String imageName, boolean littleEndian, String dimensionOrder,
    String pixelType, int sizeX, int sizeY, int sizeZ, int sizeC, int sizeT,
    int samplesPerPixel) throws EnumerationException
  {
    store.setImageID(createLSID("Image", series), series);
    if (imageName != null) store.setImageName(imageName, series);
    store.setPixelsID(createLSID("Pixels", series), series);
    store.setPixelsBinDataBigEndian(!littleEndian, series, 0);
    store.setPixelsDimensionOrder(
      DimensionOrder.fromString(dimensionOrder), series);
    store.setPixelsType(PixelType.fromString(pixelType), series);
    store.setPixelsSizeX(new PositiveInteger(sizeX), series);
    store.setPixelsSizeY(new PositiveInteger(sizeY), series);
    store.setPixelsSizeZ(new PositiveInteger(sizeZ), series);
    store.setPixelsSizeC(new PositiveInteger(sizeC), series);
    store.setPixelsSizeT(new PositiveInteger(sizeT), series);
    int effSizeC = sizeC / samplesPerPixel;
    for (int i=0; i<effSizeC; i++) {
      store.setChannelID(createLSID("Channel", series, i),
        series, i);
      store.setChannelSamplesPerPixel(new PositiveInteger(samplesPerPixel),
        series, i);
    }
  }

  /**
   * Constructs an LSID, given the object type and indices.
   * For example, if the arguments are "Detector", 1, and 0, the LSID will
   * be "Detector:1:0".
   */
{'fraction_non_alphanumeric': 0.11239174732552216, 'fraction_numerical': 0.004584819154355578, 'mean_word_length': 3.5, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '12118', 'n_tokens_mistral': 4925, 'n_tokens_neox': 4738, 'n_words': 1311}