/* @see loci.formats.FormatReader#initFile(String) */
  protected void initFile(String id) throws FormatException, IOException {
    super.initFile(id);

    Vector<String> uniqueChannels = new Vector<String>();
    Vector<Double> uniqueZs = new Vector<Double>();
    Vector<Double> stageX = new Vector<Double>();
    Vector<Double> stageY = new Vector<Double>();

    String filename = id.substring(id.lastIndexOf(File.separator) + 1);
    filename = filename.substring(0, filename.indexOf("."));
    boolean integerFilename = true;
    try {
      Integer.parseInt(filename);
    } catch (NumberFormatException e) {
      integerFilename = false;
    }

    if (integerFilename
        && ifds.size() == 1
        && ifds.get(0).getIFDIntValue(IFD.NEW_SUBFILE_TYPE) == 2) {
      // look for other files in the dataset

      findTIFFs();

      String stageLabel = null;

      for (String tiff : files) {
        MetamorphHandler handler = new MetamorphHandler();
        parseFile(tiff, handler);

        String label = handler.getStageLabel();
        if (stageLabel == null) {
          stageLabel = label;
        } else if (!label.equals(stageLabel)) {
          break;
        }

        if (!uniqueChannels.contains(handler.getChannelName())) {
          uniqueChannels.add(handler.getChannelName());
        }

        Vector<Double> zPositions = handler.getZPositions();
        Double pos = Math.rint(zPositions.get(0));

        if (!uniqueZs.contains(pos)) {
          uniqueZs.add(pos);
        }
      }

      MetamorphHandler handler = new MetamorphHandler();
      parseFile(files[files.length - 1], handler);

      String lastStageLabel = handler.getStageLabel();
      int lastField = getField(lastStageLabel);
      int lastWellRow = getWellRow(lastStageLabel);
      int lastWellColumn = getWellColumn(lastStageLabel);

      int field = getField(stageLabel);
      int fieldRow = getWellRow(stageLabel);
      int fieldColumn = getWellColumn(stageLabel);

      wellCount = lastField - field + 1;
      fieldRowCount = lastWellRow - fieldRow + 1;
      fieldColumnCount = lastWellColumn - fieldColumn + 1;
      core[0].sizeC = uniqueChannels.size();
      core[0].sizeZ = uniqueZs.size();
    } else {
      files = new String[] {id};
      wellCount = 1;
      fieldRowCount = 1;
      fieldColumnCount = 1;
      core[0].sizeC = 0;
    }

    // parse XML comment

    MetamorphHandler handler = new MetamorphHandler(getGlobalMetadata());
    Vector<Double> xPositions = new Vector<Double>();
    Vector<Double> yPositions = new Vector<Double>();

    for (IFD ifd : ifds) {
      String xml = XMLTools.sanitizeXML(ifd.getComment());
      XMLTools.parseXML(xml, handler);

      double x = handler.getStagePositionX();
      double y = handler.getStagePositionY();

      if (xPositions.size() == 0) {
        xPositions.add(x);
        yPositions.add(y);
      } else {
        double previousX = xPositions.get(xPositions.size() - 1);
        double previousY = yPositions.get(yPositions.size() - 1);

        if (Math.abs(previousX - x) > 0.21 || Math.abs(previousY - y) > 0.21) {
          xPositions.add(x);
          yPositions.add(y);
        }
      }
    }

    if (xPositions.size() > 1) {
      fieldRowCount = xPositions.size();
    }

    Vector<Integer> wavelengths = handler.getWavelengths();
    Vector<Double> zPositions = handler.getZPositions();

    // calculate axis sizes

    Vector<Integer> uniqueC = new Vector<Integer>();
    for (Integer c : wavelengths) {
      if (!uniqueC.contains(c)) {
        uniqueC.add(c);
      }
    }
    int effectiveC = uniqueC.size();
    if (effectiveC == 0) effectiveC = 1;
    if (getSizeC() == 0) core[0].sizeC = 1;
    int samples = ifds.get(0).getSamplesPerPixel();
    core[0].sizeC *= effectiveC * samples;

    Vector<Double> uniqueZ = new Vector<Double>();
    for (Double z : zPositions) {
      if (!uniqueZ.contains(z)) uniqueZ.add(z);
    }
    if (getSizeZ() == 0) core[0].sizeZ = 1;
    core[0].sizeZ *= uniqueZ.size();

    int totalPlanes = files.length * ifds.size();
    effectiveC = getSizeC() / samples;
    core[0].sizeT =
        totalPlanes / (wellCount * fieldRowCount * fieldColumnCount * getSizeZ() * effectiveC);
    if (getSizeT() == 0) core[0].sizeT = 1;

    int seriesCount = wellCount * fieldRowCount * fieldColumnCount;

    if (seriesCount > 1 && getSizeZ() > totalPlanes / seriesCount) {
      core[0].sizeZ = 1;
      core[0].sizeT = totalPlanes / (seriesCount * getSizeT() * effectiveC);
    }

    core[0].imageCount = getSizeZ() * getSizeT() * effectiveC;

    if (seriesCount > 1) {
      CoreMetadata oldCore = core[0];
      core = new CoreMetadata[seriesCount];
      for (int i = 0; i < seriesCount; i++) {
        core[i] = oldCore;
      }
    }

    for (int s = 0; s < wellCount * fieldRowCount * fieldColumnCount; s++) {
      if (files.length > 1) {
        int[] lengths =
            new int[] {
              getSizeZ(),
              getEffectiveSizeC(),
              fieldColumnCount,
              fieldRowCount,
              wellCount,
              getSizeT()
            };

        Well well = getWell(s);
        int[] position = new int[] {0, 0, well.fieldCol, well.fieldRow, well.well, 0};

        int fileIndex = FormatTools.positionToRaster(lengths, position);
        parseFile(files[fileIndex], handler);

        stageX.add(handler.getStagePositionX());
        stageY.add(handler.getStagePositionY());
      } else {
        stageX.add(xPositions.get(s));
        stageY.add(yPositions.get(s));
      }
    }

    MetadataStore store = makeFilterMetadata();
    MetadataTools.populatePixels(store, this);

    store.setPlateID(MetadataTools.createLSID("Plate", 0), 0);
    store.setPlateRowNamingConvention(NamingConvention.LETTER, 0);
    store.setPlateColumnNamingConvention(NamingConvention.NUMBER, 0);

    for (int well = 0; well < wellCount; well++) {
      store.setWellID(MetadataTools.createLSID("Well", 0, well), 0, well);
      store.setWellRow(new NonNegativeInteger(0), 0, well);
      store.setWellColumn(new NonNegativeInteger(well), 0, well);

      for (int row = 0; row < fieldRowCount; row++) {
        for (int col = 0; col < fieldColumnCount; col++) {
          int field = row * fieldColumnCount + col;
          String wellSampleID = MetadataTools.createLSID("WellSample", 0, well, field);
          store.setWellSampleID(wellSampleID, 0, well, field);

          int seriesIndex = getSeriesIndex(row, col, well);
          String imageID = MetadataTools.createLSID("Image", seriesIndex);
          store.setImageID(imageID, seriesIndex);
          store.setWellSampleImageRef(imageID, 0, well, field);
          store.setWellSampleIndex(new NonNegativeInteger(seriesIndex), 0, well, field);
        }
      }
    }

    for (int s = 0; s < seriesCount; s++) {
      setSeries(s);
      Well well = getWell(s);

      String name = handler.getImageName();
      if (seriesCount > 1) {
        name =
            "Field "
                + (char) (well.fieldRow + 'A')
                + (well.fieldCol + 1)
                + ", Well "
                + (well.well + 1)
                + ": "
                + name;
      }

      store.setImageName(name, s);

      String date = DateTools.formatDate(handler.getDate(), DateTools.ISO8601_FORMAT);
      store.setImageAcquiredDate(date, s);

      if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) {
        Vector<String> timestamps = handler.getTimestamps();
        Vector<Double> exposures = handler.getExposures();

        for (int i = 0; i < timestamps.size(); i++) {
          long timestamp = DateTools.getTime(timestamps.get(i), DATE_FORMAT);
          addSeriesMeta("timestamp " + i, timestamp);
        }
        for (int i = 0; i < exposures.size(); i++) {
          addSeriesMeta("exposure time " + i + " (ms)", exposures.get(i).floatValue() * 1000);
        }

        long startDate = 0;
        if (timestamps.size() > 0) {
          startDate = DateTools.getTime(timestamps.get(0), DATE_FORMAT);
        }

        store.setImageDescription("", s);

        int image = 0;
        for (int c = 0; c < getEffectiveSizeC(); c++) {
          for (int t = 0; t < getSizeT(); t++) {
            store.setPlaneTheZ(new NonNegativeInteger(0), s, image);
            store.setPlaneTheC(new NonNegativeInteger(c), s, image);
            store.setPlaneTheT(new NonNegativeInteger(t), s, image);

            if (t < timestamps.size()) {
              String stamp = timestamps.get(t);
              long ms = DateTools.getTime(stamp, DATE_FORMAT);
              store.setPlaneDeltaT((ms - startDate) / 1000.0, s, image);
            }
            if (image < exposures.size()) {
              store.setPlaneExposureTime(exposures.get(image), s, image);
            }

            if (s < stageX.size()) {
              store.setPlanePositionX(stageX.get(s), s, image);
            }
            if (s < stageY.size()) {
              store.setPlanePositionY(stageY.get(s), s, image);
            }
            image++;
          }
        }

        store.setImagingEnvironmentTemperature(handler.getTemperature(), s);
        store.setPixelsPhysicalSizeX(new PositiveFloat(handler.getPixelSizeX()), s);
        store.setPixelsPhysicalSizeY(new PositiveFloat(handler.getPixelSizeY()), s);

        for (int c = 0; c < getEffectiveSizeC(); c++) {
          if (uniqueChannels.size() > c) {
            store.setChannelName(uniqueChannels.get(c), s, c);
          } else store.setChannelName(handler.getChannelName(), s, c);
        }
      }
    }
  }
Пример #2
0
  /* @see loci.formats.FormatReader#initFile(String) */
  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();

    for (String file : dir.list(true)) {
      Location f = new Location(dir, file);
      if (!f.isDirectory()) {
        if (checkSuffix(file, META_EXT)) {
          metadataFiles.add(f.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);
    }

    Vector<String> uniqueRows = new Vector<String>();
    Vector<String> uniqueColumns = new Vector<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(dir.getAbsolutePath());

    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, "txt")) {
          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));
          }
        }
      }
    }

    for (int i = 0; i < getSeriesCount(); i++) {
      core[i] = new CoreMetadata();
      core[i].sizeC = nChannels;
      core[i].sizeZ = nSlices;
      core[i].sizeT = nTimepoints;
      core[i].sizeX = sizeX / fieldCols;
      core[i].sizeY = sizeY / fieldRows;
      core[i].pixelType = pixelType;
      core[i].rgb = rgb;
      core[i].interleaved = interleaved;
      core[i].indexed = indexed;
      core[i].littleEndian = littleEndian;
      core[i].dimensionOrder = "XYZTC";
      core[i].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);
    if (fieldRows * fieldCols > 0) {
      store.setPlateAcquisitionMaximumFieldCount(new PositiveInteger(fieldRows * fieldCols), 0, 0);
    } else {
      LOGGER.warn("Expected positive value for MaximumFieldCount; got {}", fieldRows * fieldCols);
    }

    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;
          }
        }

        Integer magnification = new Integer(mag);
        if (magnification > 0) {
          store.setObjectiveNominalMagnification(new PositiveInteger(magnification), 0, 0);
        } else {
          LOGGER.warn("Expected positive value for NominalMagnification; got {}", magnification);
        }
        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);
          if (emWave[c] > 0) {
            store.setChannelEmissionWavelength(new PositiveInteger(emWave[c]), i, c);
          } else {
            LOGGER.warn("Expected positive value for EmissionWavelength; got {}", emWave[c]);
          }
          if (exWave[c] > 0) {
            store.setChannelExcitationWavelength(new PositiveInteger(exWave[c]), i, c);
          } else {
            LOGGER.warn("Expected positive value for ExcitationWavelength; got {}", exWave[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(exposure[zct[1]], 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(timestamp, 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);
      }
    }
  }