Changeset 7568


Ignore:
Timestamp:
01/21/11 12:38:38 (9 years ago)
Author:
melissa
Message:

Initial version of Metamorph TIFF HCS support.

Location:
trunk/components/bio-formats/src/loci/formats/in
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/components/bio-formats/src/loci/formats/in/MetamorphHandler.java

    r7055 r7568  
    5858  private double positionX, positionY; 
    5959  private Vector<Double> exposures; 
     60  private String channelName; 
     61  private String stageLabel; 
    6062 
    6163  // -- Constructor -- 
     64 
     65  public MetamorphHandler() { 
     66    this(null); 
     67  } 
    6268 
    6369  public MetamorphHandler(Hashtable metadata) { 
     
    7177 
    7278  // -- MetamorphHandler API methods -- 
     79 
     80  public String getChannelName() { return channelName; } 
     81 
     82  public String getStageLabel() { return stageLabel; } 
    7383 
    7484  public Vector<String> getTimestamps() { return timestamps; } 
     
    110120    if (id != null && value != null) { 
    111121      if (id.equals("Description")) { 
    112         metadata.remove("Comment"); 
     122        if (metadata != null) metadata.remove("Comment"); 
    113123 
    114124        String k = null, v = null; 
     
    133143              k = line.substring(0, colon).trim(); 
    134144              v = line.substring(colon + 1).trim(); 
    135               metadata.put(k, v); 
     145              if (metadata != null) metadata.put(k, v); 
    136146              checkKey(k, v); 
    137147            } 
     
    145155            if (space == -1) space = value.length(); 
    146156            v = value.substring(colon + 1, space).trim(); 
    147             metadata.put(k, v); 
     157            if (metadata != null) metadata.put(k, v); 
    148158            value = value.substring(space).trim(); 
    149159            colon = value.indexOf(":"); 
     
    153163      } 
    154164      else { 
    155         metadata.put(id, value); 
     165        if (metadata != null) metadata.put(id, value); 
    156166        checkKey(id, value); 
    157167      } 
     
    194204    else if (key.equals("stage-position-x")) { 
    195205      positionX = Double.parseDouble(value); 
    196       metadata.put("X position for position #1", positionX); 
     206      if (metadata != null) { 
     207        metadata.put("X position for position #1", positionX); 
     208      } 
    197209    } 
    198210    else if (key.equals("stage-position-y")) { 
    199211      positionY = Double.parseDouble(value); 
    200       metadata.put("Y position for position #1", positionY); 
     212      if (metadata != null) { 
     213        metadata.put("Y position for position #1", positionY); 
     214      } 
    201215    } 
    202216    else if (key.equals("Speed")) { 
     
    213227      catch (NumberFormatException e) { } 
    214228    } 
     229    else if (key.equals("_IllumSetting_")) { 
     230      channelName = value; 
     231    } 
     232    else if (key.equals("stage-label")) { 
     233      stageLabel = value; 
     234    } 
    215235  } 
    216236 
  • trunk/components/bio-formats/src/loci/formats/in/MetamorphTiffReader.java

    r6881 r7568  
    2424package loci.formats.in; 
    2525 
     26import java.io.File; 
    2627import java.io.IOException; 
     28import java.util.Arrays; 
     29import java.util.Comparator; 
     30import java.util.HashMap; 
    2731import java.util.Vector; 
    2832 
    2933import loci.common.DateTools; 
     34import loci.common.Location; 
    3035import loci.common.RandomAccessInputStream; 
    3136import loci.common.xml.XMLTools; 
     37import loci.formats.CoreMetadata; 
     38import loci.formats.FilePattern; 
    3239import loci.formats.FormatException; 
    3340import loci.formats.FormatTools; 
     
    3643import loci.formats.tiff.IFD; 
    3744import loci.formats.tiff.TiffParser; 
     45 
     46import ome.xml.model.enums.NamingConvention; 
     47import ome.xml.model.primitives.NonNegativeInteger; 
    3848 
    3949/** 
     
    5464  private static final String DATE_FORMAT = "yyyyMMdd HH:mm:ss.SSS"; 
    5565 
     66  // -- Fields -- 
     67 
     68  private String[] files; 
     69  private int fieldCount = 0; 
     70  private int wellRowCount = 0; 
     71  private int wellColumnCount = 0; 
     72 
    5673  // -- Constructor -- 
    5774 
     
    6077    super("Metamorph TIFF", new String[] {"tif", "tiff"}); 
    6178    suffixSufficient = false; 
    62     domains = new String[] {FormatTools.LM_DOMAIN}; 
     79    domains = new String[] {FormatTools.LM_DOMAIN, FormatTools.HCS_DOMAIN}; 
    6380  } 
    6481 
     
    7491  } 
    7592 
     93  /* @see loci.formats.IFormatReader#getDomains() */ 
     94  public String[] getDomains() { 
     95    FormatTools.assertId(currentId, true, 1); 
     96    String[] domain = new String[1]; 
     97    domain[0] = 
     98      files.length == 1 ? FormatTools.LM_DOMAIN : FormatTools.HCS_DOMAIN; 
     99    return domain; 
     100  } 
     101 
     102  /* @see loci.formats.IFormatReader#getSeriesUsedFiles(boolean) */ 
     103  public String[] getUsedFiles(boolean noPixels) { 
     104    FormatTools.assertId(currentId, true, 1); 
     105    return noPixels ? new String[0] : files; 
     106  } 
     107 
     108  /** 
     109   * @see loci.formats.IFormatReader#openBytes(int, byte[], int, int, int, int) 
     110   */ 
     111  public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) 
     112    throws FormatException, IOException 
     113  { 
     114    if (getSeriesCount() == 1) return super.openBytes(no, buf, x, y, w, h); 
     115 
     116    int[] lengths = new int[] {getSizeZ(), getEffectiveSizeC(), fieldCount, 
     117      wellColumnCount, wellRowCount, getSizeT()}; 
     118 
     119    int[] zct = getZCTCoords(no); 
     120    Well well = getWell(getSeries()); 
     121    int[] position = new int[] {zct[0], zct[1], well.field, well.wellCol, 
     122      well.wellRow, zct[2]}; 
     123 
     124    int fileIndex = FormatTools.positionToRaster(lengths, position); 
     125    RandomAccessInputStream s = new RandomAccessInputStream(files[fileIndex]); 
     126    TiffParser parser = new TiffParser(s); 
     127    IFD ifd = parser.getFirstIFD(); 
     128    parser.getSamples(ifd, buf, x, y, w, h); 
     129    s.close(); 
     130 
     131    return buf; 
     132  } 
     133 
    76134  // -- Internal FormatReader API methods -- 
    77135 
     
    80138    super.initFile(id); 
    81139 
     140    Vector<String> uniqueChannels = new Vector<String>(); 
     141    Vector<Double> uniqueZs = new Vector<Double>(); 
     142 
     143    String filename = id.substring(id.lastIndexOf(File.separator) + 1); 
     144    filename = filename.substring(0, filename.indexOf(".")); 
     145    boolean integerFilename = true; 
     146    try { 
     147      Integer.parseInt(filename); 
     148    } 
     149    catch (NumberFormatException e) { 
     150      integerFilename = false; 
     151    } 
     152 
     153    if (integerFilename && ifds.size() == 1 && 
     154      ifds.get(0).getIFDIntValue(IFD.NEW_SUBFILE_TYPE) == 2) 
     155    { 
     156      // look for other files in the dataset 
     157 
     158      findTIFFs(); 
     159 
     160      String stageLabel = null; 
     161 
     162      for (String tiff : files) { 
     163        MetamorphHandler handler = new MetamorphHandler(); 
     164        parseFile(tiff, handler); 
     165 
     166        String label = handler.getStageLabel(); 
     167        if (stageLabel == null) { 
     168          stageLabel = label; 
     169        } 
     170        else if (!label.equals(stageLabel)) { 
     171          break; 
     172        } 
     173 
     174        if (!uniqueChannels.contains(handler.getChannelName())) { 
     175          uniqueChannels.add(handler.getChannelName()); 
     176        } 
     177 
     178        Vector<Double> zPositions = handler.getZPositions(); 
     179        Double pos = Math.rint(zPositions.get(0)); 
     180 
     181        if (!uniqueZs.contains(pos)) { 
     182          uniqueZs.add(pos); 
     183        } 
     184      } 
     185 
     186      MetamorphHandler handler = new MetamorphHandler(); 
     187      parseFile(files[files.length - 1], handler); 
     188 
     189      String lastStageLabel = handler.getStageLabel(); 
     190      int lastField = getField(lastStageLabel); 
     191      int lastWellRow = getWellRow(lastStageLabel); 
     192      int lastWellColumn = getWellColumn(lastStageLabel); 
     193 
     194      int field = getField(stageLabel); 
     195      int wellRow = getWellRow(stageLabel); 
     196      int wellColumn = getWellColumn(stageLabel); 
     197 
     198      fieldCount = lastField - field + 1; 
     199      wellRowCount = lastWellRow - wellRow + 1; 
     200      wellColumnCount = lastWellColumn - wellColumn + 1; 
     201      core[0].sizeC = uniqueChannels.size(); 
     202      core[0].sizeZ = uniqueZs.size(); 
     203    } 
     204    else { 
     205      files = new String[] {id}; 
     206      fieldCount = 1; 
     207      wellRowCount = 1; 
     208      wellColumnCount = 1; 
     209      core[0].sizeC = 0; 
     210    } 
     211 
    82212    // parse XML comment 
    83213 
     
    87217    } 
    88218 
    89     core[0].sizeC = 0; 
    90  
    91     Vector<String> timestamps = handler.getTimestamps(); 
    92219    Vector<Integer> wavelengths = handler.getWavelengths(); 
    93220    Vector<Double> zPositions = handler.getZPositions(); 
    94     Vector<Double> exposures = handler.getExposures(); 
    95221 
    96222    // calculate axis sizes 
     
    104230    int effectiveC = uniqueC.size(); 
    105231    if (effectiveC == 0) effectiveC = 1; 
    106     core[0].sizeC = effectiveC * ifds.get(0).getSamplesPerPixel(); 
     232    if (getSizeC() == 0) core[0].sizeC = 1; 
     233    int samples = ifds.get(0).getSamplesPerPixel(); 
     234    core[0].sizeC *= effectiveC * samples; 
    107235 
    108236    Vector<Double> uniqueZ = new Vector<Double>(); 
     
    110238      if (!uniqueZ.contains(z)) uniqueZ.add(z); 
    111239    } 
    112     core[0].sizeZ = uniqueZ.size(); 
    113     core[0].sizeT = ifds.size() / (getSizeZ() * effectiveC); 
     240    if (getSizeZ() == 0) core[0].sizeZ = 1; 
     241    core[0].sizeZ *= uniqueZ.size(); 
     242 
     243    int totalPlanes = files.length * ifds.size(); 
     244    effectiveC = getSizeC() / samples; 
     245    core[0].sizeT = totalPlanes / 
     246      (fieldCount * wellRowCount * wellColumnCount * getSizeZ() * effectiveC); 
     247    if (getSizeT() == 0) core[0].sizeT = 1; 
     248    core[0].imageCount = getSizeZ() * getSizeT() * effectiveC; 
     249 
     250    int seriesCount = fieldCount * wellRowCount * wellColumnCount; 
     251    if (seriesCount > 1) { 
     252      CoreMetadata oldCore = core[0]; 
     253      core = new CoreMetadata[seriesCount]; 
     254      for (int i=0; i<seriesCount; i++) { 
     255        core[i] = oldCore; 
     256      } 
     257    } 
    114258 
    115259    MetadataStore store = makeFilterMetadata(); 
    116260    MetadataTools.populatePixels(store, this, true); 
    117     store.setImageName(handler.getImageName(), 0); 
    118  
    119     String date = 
    120       DateTools.formatDate(handler.getDate(), DateTools.ISO8601_FORMAT); 
    121     store.setImageAcquiredDate(date, 0); 
    122  
    123     if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) { 
    124       for (int i=0; i<timestamps.size(); i++) { 
    125         long timestamp = DateTools.getTime(timestamps.get(i), DATE_FORMAT); 
    126         addGlobalMeta("timestamp " + i, timestamp); 
    127       } 
    128       for (int i=0; i<exposures.size(); i++) { 
    129         addGlobalMeta("exposure time " + i + " (ms)", 
    130           exposures.get(i).floatValue() * 1000); 
    131       } 
    132  
    133       long startDate = 0; 
    134       if (timestamps.size() > 0) { 
    135         startDate = DateTools.getTime(timestamps.get(0), DATE_FORMAT); 
    136       } 
    137  
    138       store.setImageDescription("", 0); 
    139  
    140       for (int i=0; i<getImageCount(); i++) { 
    141         int[] coords = getZCTCoords(i); 
    142         if (coords[2] < timestamps.size()) { 
    143           String stamp = timestamps.get(coords[2]); 
    144           long ms = DateTools.getTime(stamp, DATE_FORMAT); 
    145           store.setPlaneDeltaT((ms - startDate) / 1000.0, 0, i); 
    146         } 
    147         if (i < exposures.size()) { 
    148           store.setPlaneExposureTime(exposures.get(i), 0, i); 
    149         } 
    150       } 
    151  
    152       store.setImagingEnvironmentTemperature(handler.getTemperature(), 0); 
    153       store.setPixelsPhysicalSizeX(handler.getPixelSizeX(), 0); 
    154       store.setPixelsPhysicalSizeY(handler.getPixelSizeY(), 0); 
    155     } 
    156   } 
     261 
     262    store.setPlateID(MetadataTools.createLSID("Plate", 0), 0); 
     263    store.setPlateRowNamingConvention(NamingConvention.LETTER, 0); 
     264    store.setPlateColumnNamingConvention(NamingConvention.NUMBER, 0); 
     265 
     266    for (int row=0; row<wellRowCount; row++) { 
     267      for (int col=0; col<wellColumnCount; col++) { 
     268        int wellIndex = row * wellColumnCount + col; 
     269 
     270        store.setWellID( 
     271          MetadataTools.createLSID("Well", 0, wellIndex), 0, wellIndex); 
     272        store.setWellRow(new NonNegativeInteger(row), 0, wellIndex); 
     273        store.setWellColumn(new NonNegativeInteger(col), 0, wellIndex); 
     274 
     275        for (int field=0; field<fieldCount; field++) { 
     276          String wellSampleID = 
     277            MetadataTools.createLSID("WellSample", 0, wellIndex, field); 
     278          store.setWellSampleID(wellSampleID, 0, wellIndex, field); 
     279 
     280          int seriesIndex = getSeriesIndex(row, col, field); 
     281          String imageID = MetadataTools.createLSID("Image", seriesIndex); 
     282          store.setImageID(imageID, seriesIndex); 
     283          store.setWellSampleImageRef(imageID, 0, wellIndex, field); 
     284          store.setWellSampleIndex( 
     285            new NonNegativeInteger(seriesIndex), 0, wellIndex, field); 
     286        } 
     287      } 
     288    } 
     289 
     290    for (int s=0; s<seriesCount; s++) { 
     291      setSeries(s); 
     292      Well well = getWell(s); 
     293 
     294      String name = handler.getImageName(); 
     295      if (seriesCount > 1) { 
     296        name = "Field #" + (well.field + 1) + ", Well " + 
     297          (char) (well.wellRow + 'A') + (well.wellCol + 1) + ": " + name; 
     298      } 
     299 
     300      store.setImageName(name, s); 
     301 
     302      String date = 
     303        DateTools.formatDate(handler.getDate(), DateTools.ISO8601_FORMAT); 
     304      store.setImageAcquiredDate(date, s); 
     305 
     306      if (getMetadataOptions().getMetadataLevel() != MetadataLevel.MINIMUM) { 
     307        Vector<String> timestamps = handler.getTimestamps(); 
     308        Vector<Double> exposures = handler.getExposures(); 
     309 
     310        for (int i=0; i<timestamps.size(); i++) { 
     311          long timestamp = DateTools.getTime(timestamps.get(i), DATE_FORMAT); 
     312          addSeriesMeta("timestamp " + i, timestamp); 
     313        } 
     314        for (int i=0; i<exposures.size(); i++) { 
     315          addSeriesMeta("exposure time " + i + " (ms)", 
     316            exposures.get(i).floatValue() * 1000); 
     317        } 
     318 
     319        long startDate = 0; 
     320        if (timestamps.size() > 0) { 
     321          startDate = DateTools.getTime(timestamps.get(0), DATE_FORMAT); 
     322        } 
     323 
     324        store.setImageDescription("", s); 
     325 
     326        for (int i=0; i<getImageCount(); i++) { 
     327          int[] coords = getZCTCoords(i); 
     328          if (coords[2] < timestamps.size()) { 
     329            String stamp = timestamps.get(coords[2]); 
     330            long ms = DateTools.getTime(stamp, DATE_FORMAT); 
     331            store.setPlaneDeltaT((ms - startDate) / 1000.0, s, i); 
     332          } 
     333          if (i < exposures.size()) { 
     334            store.setPlaneExposureTime(exposures.get(i), s, i); 
     335          } 
     336        } 
     337 
     338        store.setImagingEnvironmentTemperature(handler.getTemperature(), s); 
     339        store.setPixelsPhysicalSizeX(handler.getPixelSizeX(), s); 
     340        store.setPixelsPhysicalSizeY(handler.getPixelSizeY(), s); 
     341 
     342        for (int c=0; c<getEffectiveSizeC(); c++) { 
     343          if (uniqueChannels.size() > c) { 
     344            store.setChannelName(uniqueChannels.get(c), s, c); 
     345          } 
     346          else store.setChannelName(handler.getChannelName(), s, c); 
     347        } 
     348      } 
     349    } 
     350  } 
     351 
     352  // -- Helper methods -- 
     353 
     354  private int getSeriesIndex(int wellRow, int wellColumn, int field) { 
     355    return FormatTools.positionToRaster( 
     356      new int[] {fieldCount, wellColumnCount, wellRowCount}, 
     357      new int[] {field, wellColumn, wellRow}); 
     358  } 
     359 
     360  private Well getWell(int seriesIndex) { 
     361    int[] coordinates = FormatTools.rasterToPosition( 
     362      new int[] {fieldCount, wellColumnCount, wellRowCount}, seriesIndex); 
     363    return new Well(coordinates[2], coordinates[1], coordinates[0]); 
     364  } 
     365 
     366  private int getField(String stageLabel) { 
     367    if (stageLabel.indexOf("Scan") < 0) return 0; 
     368    String index = stageLabel.substring(0, stageLabel.indexOf(":")).trim(); 
     369    return Integer.parseInt(index) - 1; 
     370  } 
     371 
     372  private int getWellRow(String stageLabel) { 
     373    int scanIndex = stageLabel.indexOf("Scan"); 
     374    if (scanIndex < 0) return 0; 
     375    scanIndex = stageLabel.indexOf(" ", scanIndex) + 1; 
     376    return (int) (stageLabel.charAt(scanIndex) - 'A'); 
     377  } 
     378 
     379  private int getWellColumn(String stageLabel) { 
     380    int scanIndex = stageLabel.indexOf("Scan"); 
     381    if (scanIndex < 0) return 0; 
     382    scanIndex = stageLabel.indexOf(" ", scanIndex) + 2; 
     383    return Integer.parseInt(stageLabel.substring(scanIndex)) - 1; 
     384  } 
     385 
     386  private void findTIFFs() throws IOException { 
     387    Location baseFile = new Location(currentId).getAbsoluteFile(); 
     388    Location parent = baseFile.getParentFile(); 
     389    FilePattern pattern = new FilePattern(baseFile); 
     390    String[] tiffs = pattern.getFiles(); 
     391    NumericComparator comparator = new NumericComparator(); 
     392    Arrays.sort(tiffs, comparator); 
     393 
     394    Vector<String> validTIFFs = new Vector<String>(); 
     395 
     396    for (String tiff : tiffs) { 
     397      if (!new Location(tiff).exists()) { 
     398        String base = tiff.substring(tiff.lastIndexOf(File.separator) + 1); 
     399        base = base.substring(0, base.indexOf(".")); 
     400        String suffix = tiff.substring(tiff.lastIndexOf(".")); 
     401        while (base.length() < 3) { 
     402          base = "0" + base; 
     403        } 
     404        Location test = new Location(parent, base + suffix); 
     405        if (test.exists()) { 
     406          tiff = test.getAbsolutePath(); 
     407        } 
     408        else continue; 
     409      } 
     410      validTIFFs.add(tiff); 
     411    } 
     412 
     413    files = validTIFFs.toArray(new String[validTIFFs.size()]); 
     414  } 
     415 
     416  private void parseFile(String tiff, MetamorphHandler handler) 
     417    throws IOException 
     418  { 
     419    RandomAccessInputStream s = new RandomAccessInputStream(tiff); 
     420    TiffParser parser = new TiffParser(s); 
     421    IFD firstIFD = parser.getFirstIFD(); 
     422    XMLTools.parseXML(firstIFD.getComment(), handler); 
     423    s.close(); 
     424  } 
     425 
     426  // -- Helper classes -- 
     427 
     428  class Well { 
     429    public int field; 
     430    public int wellRow; 
     431    public int wellCol; 
     432 
     433    public Well(int wellRow, int wellCol, int field) { 
     434      this.wellRow = wellRow; 
     435      this.wellCol = wellCol; 
     436      this.field = field; 
     437    } 
     438 
     439    public boolean equals(Object o) { 
     440      if (!(o instanceof Well)) return false; 
     441      Well w = (Well) o; 
     442 
     443      return w.field == this.field && w.wellRow == this.wellRow && 
     444        w.wellCol == this.wellCol; 
     445    } 
     446 
     447    public int hashCode() { 
     448      return (field << 16) | (wellRow << 8) | wellCol; 
     449    } 
     450  } 
     451 
     452  class NumericComparator implements Comparator<String> { 
     453    public int compare(String s1, String s2) { 
     454      if (s1.equals(s2)) return 0; 
     455 
     456      String base1 = s1.substring(s1.lastIndexOf(File.separator) + 1); 
     457      String base2 = s2.substring(s2.lastIndexOf(File.separator) + 1); 
     458 
     459      base1 = base1.substring(0, base1.indexOf(".")); 
     460      base2 = base2.substring(0, base2.indexOf(".")); 
     461 
     462      try { 
     463        int num1 = Integer.parseInt(base1); 
     464        int num2 = Integer.parseInt(base2); 
     465 
     466        if (num1 == num2) return 0; 
     467        return num1 < num2 ? -1 : 1; 
     468      } 
     469      catch (NumberFormatException e) { } 
     470      return 0; 
     471    } 
     472  } 
     473 
    157474} 
Note: See TracChangeset for help on using the changeset viewer.