Changeset 6071


Ignore:
Timestamp:
03/26/10 15:58:59 (10 years ago)
Author:
melissa
Message:
  • Filled in implementations of IMetadataConfigurable methods.
  • Updated Leica LEI reader to respect MetadataOptions when parsing metadata.
Location:
trunk/components/bio-formats/src/loci/formats
Files:
6 edited

Legend:

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

    r6069 r6071  
    259259   */ 
    260260  public Set<MetadataLevel> getSupportedMetadataLevels() { 
    261     throw new RuntimeException("Not implemented."); 
     261    return reader.getSupportedMetadataLevels(); 
    262262  } 
    263263 
     
    266266   */ 
    267267  public MetadataOptions getMetadataOptions() { 
    268     throw new RuntimeException("Not implemented."); 
     268    return reader.getMetadataOptions(); 
    269269  } 
    270270 
     
    273273   */ 
    274274  public void setMetadataOptions(MetadataOptions options) { 
    275     throw new RuntimeException("Not implemented."); 
     275    reader.setMetadataOptions(options); 
    276276  } 
    277277 
  • trunk/components/bio-formats/src/loci/formats/FormatReader.java

    r6069 r6071  
    2525 
    2626import java.io.IOException; 
     27import java.util.HashSet; 
    2728import java.util.Hashtable; 
    2829import java.util.Set; 
     
    3435import loci.common.services.DependencyException; 
    3536import loci.common.services.ServiceFactory; 
     37import loci.formats.in.DefaultMetadataOptions; 
    3638import loci.formats.in.MetadataLevel; 
    3739import loci.formats.in.MetadataOptions; 
     
    110112   */ 
    111113  protected MetadataStore metadataStore = new DummyMetadata(); 
     114 
     115  /** Metadata parsing options. */ 
     116  protected MetadataOptions metadataOptions; 
    112117 
    113118  // -- Constructors -- 
     
    145150    core[0] = new CoreMetadata(); 
    146151    core[0].orderCertain = true; 
     152 
     153    if (metadataOptions == null) { 
     154      metadataOptions = new DefaultMetadataOptions(); 
     155    } 
    147156 
    148157    // reinitialize the MetadataStore 
     
    404413   */ 
    405414  public Set<MetadataLevel> getSupportedMetadataLevels() { 
    406     throw new RuntimeException("Not implemented."); 
     415    Set<MetadataLevel> supportedLevels = new HashSet<MetadataLevel>(); 
     416    supportedLevels.add(MetadataLevel.ALL); 
     417    supportedLevels.add(MetadataLevel.PIXELS_ONLY); 
     418    return supportedLevels; 
    407419  } 
    408420 
     
    411423   */ 
    412424  public MetadataOptions getMetadataOptions() { 
    413     throw new RuntimeException("Not implemented."); 
     425    return metadataOptions; 
    414426  } 
    415427 
     
    418430   */ 
    419431  public void setMetadataOptions(MetadataOptions options) { 
    420     throw new RuntimeException("Not implemented."); 
     432    this.metadataOptions = options; 
    421433  } 
    422434 
  • trunk/components/bio-formats/src/loci/formats/ImageReader.java

    r6069 r6071  
    184184  // -- IMetadataConfigurable API methods -- 
    185185 
    186   /* (non-Javadoc) 
    187    * @see loci.formats.IMetadataConfigurable#getSupportedMetadataLevels() 
    188    */ 
     186  /* @see loci.formats.IMetadataConfigurable#getSupportedMetadataLevels() */ 
    189187  public Set<MetadataLevel> getSupportedMetadataLevels() { 
    190     throw new RuntimeException("Not implemented."); 
    191   } 
    192  
    193   /* (non-Javadoc) 
    194    * @see loci.formats.IMetadataConfigurable#getMetadataOptions() 
    195    */ 
     188    return getReader().getSupportedMetadataLevels(); 
     189  } 
     190 
     191  /* @see loci.formats.IMetadataConfigurable#getMetadataOptions() */ 
    196192  public MetadataOptions getMetadataOptions() { 
    197     throw new RuntimeException("Not implemented."); 
    198   } 
    199  
    200   /* (non-Javadoc) 
    201    * @see loci.formats.IMetadataConfigurable#setMetadataOptions(loci.formats.in.MetadataOptions) 
     193    return getReader().getMetadataOptions(); 
     194  } 
     195 
     196  /** 
     197   * @see loci.formats.IMetadataConfigurable#setMetadataOptions(MetadataOptions) 
    202198   */ 
    203199  public void setMetadataOptions(MetadataOptions options) { 
    204     throw new RuntimeException("Not implemented."); 
     200    for (IFormatReader reader : readers) { 
     201      reader.setMetadataOptions(options); 
     202    } 
    205203  } 
    206204 
  • trunk/components/bio-formats/src/loci/formats/MetadataTools.java

    r6053 r6071  
    223223      series); 
    224224  } 
     225 
     226  /** 
     227   * Adjusts the given dimension order as needed so that it contains exactly 
     228   * one of each of the following characters: 'X', 'Y', 'Z', 'C', 'T'. 
     229   */ 
     230  public static String makeSaneDimensionOrder(String dimensionOrder) { 
     231    String order = dimensionOrder.toUpperCase(); 
     232    order = order.replaceAll("[^XYZCT]", ""); 
     233    String[] axes = new String[] {"X", "Y", "C", "Z", "T"}; 
     234    for (String axis : axes) { 
     235      if (order.indexOf(axis) == -1) order += axis; 
     236      while (order.indexOf(axis) != order.lastIndexOf(axis)) { 
     237        order = order.replaceFirst(axis, ""); 
     238      } 
     239    } 
     240    return order; 
     241  } 
     242 
    225243  // -- Utility methods - original metadata -- 
    226244 
  • trunk/components/bio-formats/src/loci/formats/in/DeltavisionReader.java

    r6069 r6071  
    5151 * @author Melissa Linkert linkert at wisc.edu 
    5252 */ 
    53 public class DeltavisionReader extends FormatReader implements IMetadataConfigurable { 
     53public class DeltavisionReader extends FormatReader { 
    5454 
    5555  // -- Constants -- 
     
    8989  protected int numFloatsPerSection; 
    9090 
    91   private MetadataOptions metadataOptions; 
    92  
    9391  /** Initialize an array of Extended Header Field structures. */ 
    9492  protected DVExtHdrFields[][][] extHdrFields = null; 
     
    107105    suffixNecessary = false; 
    108106    domains = new String[] {FormatTools.LM_DOMAIN}; 
    109     metadataOptions = new DefaultMetadataOptions(); 
    110107  } 
    111108 
     
    12051202  } 
    12061203 
    1207   /* (non-Javadoc) 
    1208    * @see loci.formats.in.IMetadataConfigurable#getMetadataOptions() 
    1209    */ 
    1210   public MetadataOptions getMetadataOptions() { 
    1211     return metadataOptions; 
    1212   } 
    1213  
    1214   /* (non-Javadoc) 
    1215    * @see loci.formats.in.IMetadataConfigurable#getSupportedMetadataLevels() 
    1216    */ 
    1217   public Set<MetadataLevel> getSupportedMetadataLevels() { 
    1218     Set<MetadataLevel> supportedLevels = new HashSet<MetadataLevel>(); 
    1219     supportedLevels.add(MetadataLevel.ALL); 
    1220     supportedLevels.add(MetadataLevel.PIXELS_ONLY); 
    1221     return supportedLevels; 
    1222   } 
    1223  
    1224   /* (non-Javadoc) 
    1225    * @see loci.formats.in.IMetadataConfigurable#setMetadataOptions(loci.formats.in.MetadataOptions) 
    1226    */ 
    1227   public void setMetadataOptions(MetadataOptions options) { 
    1228     this.metadataOptions = options; 
    1229   } 
    1230  
    12311204} 
  • trunk/components/bio-formats/src/loci/formats/in/LeicaReader.java

    r6058 r6071  
    130130  private String leiFilename; 
    131131 
     132  /** Length of each file name. */ 
     133  private int fileLength; 
     134 
     135  private boolean[] valid; 
     136 
     137  private String[][] timestamps; 
     138 
    132139  private Vector<String> seriesNames; 
    133140  private Vector<String> seriesDescriptions; 
    134   private int lastPlane = 0; 
     141  private int lastPlane = 0, nameLength = 0; 
    135142 
    136143  private double[][] physicalSizes; 
     
    291298    close(); 
    292299 
    293     if (checkSuffix(id, TiffReader.TIFF_SUFFIXES) && isGroupFiles()) { 
    294       // need to find the associated .lei file 
    295       if (ifds == null) super.initFile(id); 
    296  
    297       in = new RandomAccessInputStream(id); 
    298       TiffParser tp = new TiffParser(in); 
    299       in.order(tp.checkHeader().booleanValue()); 
    300  
    301       in.seek(0); 
    302  
    303       LOGGER.info("Finding companion file name"); 
    304  
    305       // open the TIFF file and look for the "Image Description" field 
    306  
    307       ifds = tp.getIFDs(); 
    308       if (ifds == null) throw new FormatException("No IFDs found"); 
    309       String descr = ifds.get(0).getComment(); 
    310  
    311       // remove anything of the form "[blah]" 
    312  
    313       descr = descr.replaceAll("\\[.*.\\]\n", ""); 
    314  
    315       // each remaining line in descr is a (key, value) pair, 
    316       // where '=' separates the key from the value 
    317  
    318       String lei = id.substring(0, id.lastIndexOf(File.separator) + 1); 
    319  
    320       StringTokenizer lines = new StringTokenizer(descr, "\n"); 
    321       String line = null, key = null, value = null; 
    322       while (lines.hasMoreTokens()) { 
    323         line = lines.nextToken(); 
    324         if (line.indexOf("=") == -1) continue; 
    325         key = line.substring(0, line.indexOf("=")).trim(); 
    326         value = line.substring(line.indexOf("=") + 1).trim(); 
    327         addGlobalMeta(key, value); 
    328  
    329         if (key.startsWith("Series Name")) lei += value; 
    330       } 
    331  
    332       // now open the LEI file 
    333  
    334       Location l = new Location(lei).getAbsoluteFile(); 
    335       if (l.exists()) { 
    336         initFile(lei); 
     300    String leiFile = findLEIFile(id); 
     301    if (leiFile == null) { 
     302      if (checkSuffix(id, TiffReader.TIFF_SUFFIXES) && !isGroupFiles()) { 
     303        super.initFile(id); 
     304        TiffReader r = new TiffReader(); 
     305        r.setMetadataStore(getMetadataStore()); 
     306        r.setId(id); 
     307 
     308        core = r.getCoreMetadata(); 
     309        metadataStore = r.getMetadataStore(); 
     310 
     311        Hashtable globalMetadata = r.getGlobalMetadata(); 
     312        for (Object key : globalMetadata.keySet()) { 
     313          addGlobalMeta(key.toString(), globalMetadata.get(key)); 
     314        } 
     315 
     316        r.close(); 
     317 
     318        files = new Vector[] {new Vector()}; 
     319        files[0].add(id); 
     320        tiff = new MinimalTiffReader(); 
     321 
    337322        return; 
    338323      } 
    339324      else { 
    340         l = l.getParentFile(); 
    341         String[] list = l.list(); 
    342         for (int i=0; i<list.length; i++) { 
    343           if (checkSuffix(list[i], LEI_SUFFIX)) { 
    344             initFile( 
    345               new Location(l.getAbsolutePath(), list[i]).getAbsolutePath()); 
    346             return; 
    347           } 
    348         } 
    349       } 
    350       throw new FormatException("LEI file not found."); 
    351     } 
    352     else if (checkSuffix(id, TiffReader.TIFF_SUFFIXES) && !isGroupFiles()) { 
    353       super.initFile(id); 
    354       TiffReader r = new TiffReader(); 
    355       r.setMetadataStore(getMetadataStore()); 
    356       r.setId(id); 
    357  
    358       core = r.getCoreMetadata(); 
    359       metadataStore = r.getMetadataStore(); 
    360  
    361       Hashtable globalMetadata = r.getGlobalMetadata(); 
    362       for (Object key : globalMetadata.keySet()) { 
    363         addGlobalMeta(key.toString(), globalMetadata.get(key)); 
    364       } 
    365  
    366       r.close(); 
    367  
    368       files = new Vector[] {new Vector()}; 
    369       files[0].add(id); 
    370       tiff = new MinimalTiffReader(); 
    371  
    372       return; 
     325        throw new FormatException("LEI file not found."); 
     326      } 
    373327    } 
    374328 
    375329    // parse the LEI file 
    376330 
    377     super.initFile(id); 
    378  
    379     leiFilename = new File(id).exists() ? 
    380       new Location(id).getAbsolutePath() : id; 
    381     in = new RandomAccessInputStream(id); 
     331    super.initFile(leiFile); 
     332 
     333    in = new RandomAccessInputStream(leiFile); 
     334    MetadataLevel metadataLevel = metadataOptions.getMetadataLevel(); 
    382335 
    383336    seriesNames = new Vector<String>(); 
     
    414367 
    415368        int size = in.readInt(); 
    416         byte[] data = new byte[size]; 
    417         in.read(data); 
    418         ifd.putIFDValue(tag, data); 
     369        ifd.putIFDValue(tag, in.getFilePointer()); 
    419370        in.seek(pos); 
    420371        tag = in.readInt(); 
     
    447398    // determine the length of a filename 
    448399 
    449     int nameLength = 0; 
    450     int maxPlanes = 0; 
    451  
    452400    LOGGER.info("Parsing metadata blocks"); 
    453401 
     
    455403 
    456404    int seriesIndex = 0; 
    457     boolean[] valid = new boolean[numSeries]; 
     405    int invalidCount = 0; 
     406    valid = new boolean[numSeries]; 
     407    timestamps = new String[headerIFDs.size()][]; 
    458408    for (int i=0; i<headerIFDs.size(); i++) { 
    459409      IFD ifd = headerIFDs.get(i); 
    460410      valid[i] = true; 
    461411      if (ifd.get(SERIES) != null) { 
    462         byte[] temp = (byte[]) ifd.get(SERIES); 
    463         nameLength = DataTools.bytesToInt(temp, 8, isLittleEndian()) * 2; 
    464       } 
    465  
    466       Vector<String> f = new Vector<String>(); 
    467       byte[] tempData = (byte[]) ifd.get(IMAGES); 
    468       RandomAccessInputStream data = new RandomAccessInputStream(tempData); 
    469       data.order(isLittleEndian()); 
    470       int tempImages = data.readInt(); 
    471  
    472       if (((long) tempImages * nameLength) > data.length()) { 
    473         data.order(!isLittleEndian()); 
    474         tempImages = data.readInt(); 
    475         data.order(isLittleEndian()); 
    476       } 
    477  
    478       core[i].sizeX = data.readInt(); 
    479       core[i].sizeY = data.readInt(); 
    480       data.skipBytes(4); 
    481       int samplesPerPixel = data.readInt(); 
    482       core[i].rgb = samplesPerPixel > 1; 
    483       core[i].sizeC = samplesPerPixel; 
    484  
    485       File dirFile = new File(id).getAbsoluteFile(); 
    486       String[] listing = null; 
    487       String dirPrefix = ""; 
    488       if (dirFile.exists()) { 
    489         listing = dirFile.getParentFile().list(); 
    490         dirPrefix = dirFile.getParent(); 
    491         if (!dirPrefix.endsWith(File.separator)) dirPrefix += File.separator; 
    492       } 
    493       else { 
    494         listing = 
    495           (String[]) Location.getIdMap().keySet().toArray(new String[0]); 
    496       } 
    497  
    498       Vector<String> list = new Vector<String>(); 
    499  
    500       for (int k=0; k<listing.length; k++) { 
    501         if (checkSuffix(listing[k], TiffReader.TIFF_SUFFIXES)) { 
    502           list.add(listing[k]); 
    503         } 
    504       } 
    505  
    506       boolean tiffsExist = false; 
    507  
    508       String prefix = ""; 
    509       for (int j=0; j<tempImages; j++) { 
    510         // read in each filename 
    511         prefix = getString(data, nameLength); 
    512         f.add(dirPrefix + prefix); 
    513         // test to make sure the path is valid 
    514         Location test = new Location(f.get(f.size() - 1)); 
    515         if (test.exists()) list.remove(prefix); 
    516         if (!tiffsExist) tiffsExist = test.exists(); 
    517       } 
    518       data.close(); 
    519       tempData = null; 
    520  
    521       // all of the TIFF files were renamed 
    522  
    523       if (!tiffsExist) { 
    524         // Strategy for handling renamed files: 
    525         // 1) Assume that files for each series follow a pattern. 
    526         // 2) Assign each file group to the first series with the correct count. 
    527         LOGGER.info("Handling renamed TIFF files"); 
    528  
    529         listing = list.toArray(new String[list.size()]); 
    530  
    531         // grab the file patterns 
    532         Vector<String> filePatterns = new Vector<String>(); 
    533         for (String q : listing) { 
    534           Location l = new Location(dirPrefix, q).getAbsoluteFile(); 
    535           FilePattern pattern = new FilePattern(l); 
    536  
    537           AxisGuesser guess = new AxisGuesser(pattern, "XYZCT", 1, 1, 1, false); 
    538           String fp = pattern.getPattern(); 
    539  
    540           if (guess.getAxisCountS() >= 1) { 
    541             String pre = pattern.getPrefix(guess.getAxisCountS()); 
    542             Vector<String> fileList = new Vector<String>(); 
    543             for (int n=0; n<listing.length; n++) { 
    544               Location p = new Location(dirPrefix, listing[n]); 
    545               if (p.getAbsolutePath().startsWith(pre)) { 
    546                 fileList.add(listing[n]); 
    547               } 
    548             } 
    549             fp = FilePattern.findPattern(l.getAbsolutePath(), dirPrefix, 
    550               fileList.toArray(new String[fileList.size()])); 
    551           } 
    552  
    553           if (fp != null && !filePatterns.contains(fp)) { 
    554             filePatterns.add(fp); 
    555           } 
    556         } 
    557  
    558         for (String q : filePatterns) { 
    559           String[] pattern = new FilePattern(q).getFiles(); 
    560           if (pattern.length == tempImages) { 
    561             // make sure that this pattern hasn't already been used 
    562  
    563             boolean validPattern = true; 
    564             for (int n=0; n<i; n++) { 
    565               if (files[n] == null) continue; 
    566               if (files[n].contains(pattern[0])) { 
    567                 validPattern = false; 
    568                 break; 
    569               } 
    570             } 
    571  
    572             if (validPattern) { 
    573               files[i] = new Vector<String>(); 
    574               files[i].addAll(Arrays.asList(pattern)); 
    575             } 
    576           } 
    577         } 
    578       } 
    579       else files[i] = f; 
    580       if (files[i] == null) valid[i] = false; 
    581       else { 
    582         core[i].imageCount = files[i].size(); 
    583         if (core[i].imageCount > maxPlanes) maxPlanes = core[i].imageCount; 
    584       } 
    585     } 
    586  
    587     int invalidCount = 0; 
    588     for (int i=0; i<valid.length; i++) { 
     412        long offset = ((Long) ifd.get(SERIES)).longValue(); 
     413        in.seek(offset + 8); 
     414        nameLength = in.readInt() * 2; 
     415      } 
     416 
     417      in.seek(((Long) ifd.get(IMAGES)).longValue()); 
     418      parseFilenames(i); 
    589419      if (!valid[i]) invalidCount++; 
    590420    } 
     
    624454    if (headerIFDs == null) headerIFDs = ifds; 
    625455 
    626     int fileLength = 0; 
    627  
    628     int resolution = -1; 
    629     String[][] timestamps = new String[headerIFDs.size()][]; 
    630456    seriesDescriptions = new Vector<String>(); 
    631457 
     
    639465      core[i].littleEndian = isLittleEndian(); 
    640466      setSeries(i); 
    641       Object[] keys = ifd.keySet().toArray(); 
     467      Integer[] keys = ifd.keySet().toArray(new Integer[ifd.size()]); 
    642468      Arrays.sort(keys); 
    643469 
    644       for (int q=0; q<keys.length; q++) { 
    645         byte[] tmp = (byte[]) ifd.get(keys[q]); 
    646         if (tmp == null) continue; 
    647         RandomAccessInputStream stream = new RandomAccessInputStream(tmp); 
    648         stream.order(isLittleEndian()); 
    649  
    650         if (keys[q].equals(SERIES)) { 
    651           addSeriesMeta("Version", stream.readInt()); 
    652           addSeriesMeta("Number of Series", stream.readInt()); 
    653           fileLength = stream.readInt(); 
    654           addSeriesMeta("Length of filename", fileLength); 
    655           int extLen = stream.readInt(); 
    656           if (extLen > fileLength) { 
    657             stream.seek(8); 
    658             core[0].littleEndian = !isLittleEndian(); 
    659             stream.order(isLittleEndian()); 
    660             fileLength = stream.readInt(); 
    661             extLen = stream.readInt(); 
    662           } 
    663           addSeriesMeta("Length of file extension", extLen); 
    664           addSeriesMeta("Image file extension", getString(stream, extLen)); 
    665         } 
    666         else if (keys[q].equals(IMAGES)) { 
    667           core[i].imageCount = stream.readInt(); 
    668           core[i].sizeX = stream.readInt(); 
    669           core[i].sizeY = stream.readInt(); 
    670  
    671           addSeriesMeta("Number of images", getImageCount()); 
    672           addSeriesMeta("Image width", getSizeX()); 
    673           addSeriesMeta("Image height", getSizeY()); 
    674           addSeriesMeta("Bits per Sample", stream.readInt()); 
    675           addSeriesMeta("Samples per pixel", stream.readInt()); 
    676  
    677           String name = getString(stream, fileLength * 2); 
    678  
    679           if (name.indexOf(".") != -1) { 
    680             name = name.substring(0, name.lastIndexOf(".")); 
    681           } 
    682  
    683           String[] tokens = name.split("_"); 
    684           StringBuffer buf = new StringBuffer(); 
    685           for (int p=1; p<tokens.length; p++) { 
    686             String lcase = tokens[p].toLowerCase(); 
    687             if (!lcase.startsWith("ch0") && !lcase.startsWith("c0") && 
    688               !lcase.startsWith("z0") && !lcase.startsWith("t0")) 
    689             { 
    690               if (buf.length() > 0) buf.append("_"); 
    691               buf.append(tokens[p]); 
    692             } 
    693           } 
    694           seriesNames.add(buf.toString()); 
    695         } 
    696         else if (keys[q].equals(DIMDESCR)) { 
    697           addSeriesMeta("Voxel Version", stream.readInt()); 
    698           core[i].rgb = stream.readInt() == 20; 
    699           addSeriesMeta("VoxelType", isRGB() ? "RGB" : "gray"); 
    700  
    701           int bpp = stream.readInt(); 
    702           addSeriesMeta("Bytes per pixel", bpp); 
    703  
    704           switch (bpp) { 
    705             case 1: 
    706               core[i].pixelType = FormatTools.UINT8; 
    707               break; 
    708             case 3: 
    709               core[i].pixelType = FormatTools.UINT8; 
    710               core[i].sizeC = 3; 
    711               core[i].rgb = true; 
    712               break; 
    713             case 2: 
    714               core[i].pixelType = FormatTools.UINT16; 
    715               break; 
    716             case 6: 
    717               core[i].pixelType = FormatTools.UINT16; 
    718               core[i].sizeC = 3; 
    719               core[i].rgb = true; 
    720               break; 
    721             case 4: 
    722               core[i].pixelType = FormatTools.UINT32; 
    723               break; 
    724             default: 
    725               throw new FormatException("Unsupported bytes per pixel (" + 
    726                 bpp + ")"); 
    727           } 
    728  
    729           core[i].dimensionOrder = "XY"; 
    730  
    731           resolution = stream.readInt(); 
    732           core[i].bitsPerPixel = resolution; 
    733           addSeriesMeta("Real world resolution", resolution); 
    734           addSeriesMeta("Maximum voxel intensity", getString(stream, true)); 
    735           addSeriesMeta("Minimum voxel intensity", getString(stream, true)); 
    736           int len = stream.readInt(); 
    737           stream.skipBytes(len * 2 + 4); 
    738  
    739           len = stream.readInt(); 
    740           for (int j=0; j<len; j++) { 
    741             int dimId = stream.readInt(); 
    742             String dimType = dimensionNames.get(new Integer(dimId)); 
    743             if (dimType == null) dimType = ""; 
    744  
    745             int size = stream.readInt(); 
    746             int distance = stream.readInt(); 
    747             int strlen = stream.readInt() * 2; 
    748             String[] sizeData = getString(stream, strlen).split(" "); 
    749             String physicalSize = sizeData[0]; 
    750             String unit = ""; 
    751             if (sizeData.length > 1) unit = sizeData[1]; 
    752  
    753             double physical = Double.parseDouble(physicalSize) / size; 
    754             if (unit.equals("m")) { 
    755               physical *= 1000000; 
    756             } 
    757  
    758             if (dimType.equals("x")) { 
    759               core[i].sizeX = size; 
    760               physicalSizes[i][0] = physical; 
    761             } 
    762             else if (dimType.equals("y")) { 
    763               core[i].sizeY = size; 
    764               physicalSizes[i][1] = physical; 
    765             } 
    766             else if (dimType.equals("channel")) { 
    767               if (getSizeC() == 0) core[i].sizeC = 1; 
    768               core[i].sizeC *= size; 
    769               if (getDimensionOrder().indexOf("C") == -1) { 
    770                 core[i].dimensionOrder += "C"; 
    771               } 
    772               physicalSizes[i][3] = physical; 
    773             } 
    774             else if (dimType.equals("z")) { 
    775               core[i].sizeZ = size; 
    776             } 
    777             else { 
    778               core[i].sizeT = size; 
    779               if (getDimensionOrder().indexOf("T") == -1) { 
    780                 core[i].dimensionOrder += "T"; 
    781               } 
    782               physicalSizes[i][4] = physical; 
    783             } 
    784  
    785             String dimPrefix = "Dim" + j; 
    786  
    787             addSeriesMeta(dimPrefix + " type", dimType); 
    788             addSeriesMeta(dimPrefix + " size", size); 
    789             addSeriesMeta(dimPrefix + " distance between sub-dimensions", 
    790               distance); 
    791  
    792             addSeriesMeta(dimPrefix + " physical length", 
    793               physicalSize + " " + unit); 
    794  
    795             addSeriesMeta(dimPrefix + " physical origin", 
    796               getString(stream, true)); 
    797           } 
    798           addSeriesMeta("Series name", getString(stream, false)); 
    799  
    800           String description = getString(stream, false); 
    801           seriesDescriptions.add(description); 
    802           addSeriesMeta("Series description", description); 
    803         } 
    804         else if (keys[q].equals(TIMEINFO)) { 
    805           int nDims = stream.readInt(); 
    806           addSeriesMeta("Number of time-stamped dimensions", nDims); 
    807           addSeriesMeta("Time-stamped dimension", stream.readInt()); 
    808  
    809           for (int j=0; j<nDims; j++) { 
    810             String dimPrefix = "Dimension " + j; 
    811             addSeriesMeta(dimPrefix + " ID", stream.readInt()); 
    812             addSeriesMeta(dimPrefix + " size", stream.readInt()); 
    813             addSeriesMeta(dimPrefix + " distance", stream.readInt()); 
    814           } 
    815  
    816           int numStamps = stream.readInt(); 
    817           addSeriesMeta("Number of time-stamps", numStamps); 
    818           timestamps[i] = new String[numStamps]; 
    819           for (int j=0; j<numStamps; j++) { 
    820             timestamps[i][j] = getString(stream, 64); 
    821             addSeriesMeta("Timestamp " + j, timestamps[i][j]); 
    822           } 
    823  
    824           if (stream.getFilePointer() < stream.length()) { 
    825             int numTMs = stream.readInt(); 
    826             addSeriesMeta("Number of time-markers", numTMs); 
    827             for (int j=0; j<numTMs; j++) { 
    828               int numDims = stream.readInt(); 
    829  
    830               String time = "Time-marker " + j + " Dimension "; 
    831  
    832               for (int k=0; k<numDims; k++) { 
    833                 addSeriesMeta(time + k + " coordinate", stream.readInt()); 
    834               } 
    835               addSeriesMeta("Time-marker " + j, getString(stream, 64)); 
    836             } 
    837           } 
    838         } 
    839         else if (keys[q].equals(EXPERIMENT)) { 
    840           stream.skipBytes(8); 
    841           String description = getString(stream, true); 
    842           addSeriesMeta("Image Description", description); 
    843           addSeriesMeta("Main file extension", getString(stream, true)); 
    844           addSeriesMeta("Image format identifier", getString(stream, true)); 
    845           addSeriesMeta("Single image extension", getString(stream, true)); 
    846         } 
    847         else if (keys[q].equals(LUTDESC)) { 
    848           int nChannels = stream.readInt(); 
    849           if (nChannels > 0) core[i].indexed = true; 
    850           addSeriesMeta("Number of LUT channels", nChannels); 
    851           addSeriesMeta("ID of colored dimension", stream.readInt()); 
    852  
    853           for (int j=0; j<nChannels; j++) { 
    854             String p = "LUT Channel " + j; 
    855             addSeriesMeta(p + " version", stream.readInt()); 
    856             addSeriesMeta(p + " inverted?", stream.read() == 1); 
    857             addSeriesMeta(p + " description", getString(stream, false)); 
    858             addSeriesMeta(p + " filename", getString(stream, false)); 
    859             String lut = getString(stream, false); 
    860             addSeriesMeta(p + " name", lut); 
    861             stream.skipBytes(8); 
    862           } 
    863         } 
    864         else if (keys[q].equals(CHANDESC)) { 
    865           int nBands = stream.readInt(); 
    866           for (int band=0; band<nBands; band++) { 
    867             String p = "Band #" + (band + 1) + " "; 
    868             addSeriesMeta(p + "Lower wavelength", stream.readDouble()); 
    869             stream.skipBytes(4); 
    870             addSeriesMeta(p + "Higher wavelength", stream.readDouble()); 
    871             stream.skipBytes(4); 
    872             addSeriesMeta(p + "Gain", stream.readDouble()); 
    873             addSeriesMeta(p + "Offset", stream.readDouble()); 
    874           } 
    875         } 
    876  
    877         stream.close(); 
     470      for (Integer key : keys) { 
     471        long offset = ((Long) ifd.get(key)).longValue(); 
     472        in.seek(offset); 
     473 
     474        if (key.equals(SERIES) && metadataLevel == MetadataLevel.ALL) { 
     475          parseSeriesTag(); 
     476        } 
     477        else if (key.equals(IMAGES)) { 
     478          parseImageTag(i); 
     479        } 
     480        else if (key.equals(DIMDESCR)) { 
     481          parseDimensionTag(i); 
     482        } 
     483        else if (key.equals(TIMEINFO) && metadataLevel == MetadataLevel.ALL) { 
     484          parseTimeTag(i); 
     485        } 
     486        else if (key.equals(EXPERIMENT) && metadataLevel == MetadataLevel.ALL) { 
     487          parseExperimentTag(); 
     488        } 
     489        else if (key.equals(LUTDESC) && metadataLevel == MetadataLevel.ALL) { 
     490          parseLUT(i); 
     491        } 
     492        else if (key.equals(CHANDESC) && metadataLevel == MetadataLevel.ALL) { 
     493          parseChannelTag(); 
     494        } 
    878495      } 
    879496 
     
    908525      if (isRGB()) core[i].indexed = false; 
    909526 
    910       if (getDimensionOrder().indexOf("C") == -1) { 
    911         core[i].dimensionOrder += "C"; 
    912       } 
    913       if (getDimensionOrder().indexOf("Z") == -1) { 
    914         core[i].dimensionOrder += "Z"; 
    915       } 
    916       if (getDimensionOrder().indexOf("T") == -1) { 
    917         core[i].dimensionOrder += "T"; 
    918       } 
     527      core[i].dimensionOrder = 
     528        MetadataTools.makeSaneDimensionOrder(getDimensionOrder()); 
    919529    } 
    920530 
     
    922532      new FilterMetadata(getMetadataStore(), isMetadataFiltered()); 
    923533    MetadataTools.populatePixels(store, this, true); 
     534 
     535    if (metadataLevel == MetadataLevel.PIXELS_ONLY) return; 
    924536 
    925537    for (int i=0; i<numSeries; i++) { 
     
    952564      cutOutPopulated[i] = new boolean[core[i].sizeC]; 
    953565 
    954       Object[] keys = ifd.keySet().toArray(); 
     566      Integer[] keys = ifd.keySet().toArray(new Integer[ifd.size()]); 
    955567      Arrays.sort(keys); 
    956568      int nextInstrumentBlock = 1; 
    957569      sequential = DataTools.indexOf(keys, SEQ_SCANNERSET) != -1; 
    958       for (int q=0; q<keys.length; q++) { 
    959         if (keys[q].equals(FILTERSET) || keys[q].equals(SCANNERSET) || 
    960           keys[q].equals(SEQ_SCANNERSET) || keys[q].equals(SEQ_FILTERSET) || 
    961           (((Integer) keys[q]).intValue() > SEQ_SCANNERSET.intValue() && 
    962           ((Integer) keys[q]).intValue() < SEQ_SCANNERSET_END) || 
    963           (((Integer) keys[q]).intValue() > SEQ_FILTERSET.intValue() && 
    964           ((Integer) keys[q]).intValue() < SEQ_FILTERSET_END)) 
     570      for (Integer key : keys) { 
     571        if (key.equals(FILTERSET) || key.equals(SCANNERSET) || 
     572          key.equals(SEQ_SCANNERSET) || key.equals(SEQ_FILTERSET) || 
     573          (key > SEQ_SCANNERSET && key < SEQ_SCANNERSET_END) || 
     574          (key > SEQ_FILTERSET && key < SEQ_FILTERSET_END)) 
    965575        { 
    966           if (sequential && (keys[q].equals(FILTERSET) || 
    967             keys[q].equals(SCANNERSET))) 
    968           { 
     576          if (sequential && (key.equals(FILTERSET) || key.equals(SCANNERSET))) { 
    969577            continue; 
    970578          } 
    971           byte[] tmp = (byte[]) ifd.get(keys[q]); 
    972           if (tmp == null) continue; 
    973           RandomAccessInputStream stream = new RandomAccessInputStream(tmp); 
    974           stream.order(isLittleEndian()); 
    975           parseInstrumentData(stream, store, i, nextInstrumentBlock++); 
    976           stream.close(); 
     579          long offset = ((Long) ifd.get(key)).longValue(); 
     580          in.seek(offset); 
     581          setSeries(i); 
     582          parseInstrumentData(store, nextInstrumentBlock++); 
    977583        } 
    978584      } 
     
    1006612  // -- Helper methods -- 
    1007613 
    1008   private void parseInstrumentData(RandomAccessInputStream stream, 
    1009     MetadataStore store, int series, int blockNum) throws IOException 
     614  /** Find the .lei file that belongs to the same dataset as the given file. */ 
     615  private String findLEIFile(String baseFile) 
     616    throws FormatException, IOException 
    1010617  { 
    1011     setSeries(series); 
     618    if (checkSuffix(baseFile, LEI_SUFFIX)) { 
     619      return baseFile; 
     620    } 
     621    else if (checkSuffix(baseFile, TiffReader.TIFF_SUFFIXES) && isGroupFiles()) 
     622    { 
     623      // need to find the associated .lei file 
     624      if (ifds == null) super.initFile(baseFile); 
     625 
     626      in = new RandomAccessInputStream(baseFile); 
     627      TiffParser tp = new TiffParser(in); 
     628      in.order(tp.checkHeader().booleanValue()); 
     629 
     630      in.seek(0); 
     631 
     632      LOGGER.info("Finding companion file name"); 
     633 
     634      // open the TIFF file and look for the "Image Description" field 
     635 
     636      ifds = tp.getIFDs(); 
     637      if (ifds == null) throw new FormatException("No IFDs found"); 
     638      String descr = ifds.get(0).getComment(); 
     639 
     640      // remove anything of the form "[blah]" 
     641 
     642      descr = descr.replaceAll("\\[.*.\\]\n", ""); 
     643 
     644      // each remaining line in descr is a (key, value) pair, 
     645      // where '=' separates the key from the value 
     646 
     647      String lei = 
     648        baseFile.substring(0, baseFile.lastIndexOf(File.separator) + 1); 
     649 
     650      StringTokenizer lines = new StringTokenizer(descr, "\n"); 
     651      String line = null, key = null, value = null; 
     652      while (lines.hasMoreTokens()) { 
     653        line = lines.nextToken(); 
     654        if (line.indexOf("=") == -1) continue; 
     655        key = line.substring(0, line.indexOf("=")).trim(); 
     656        value = line.substring(line.indexOf("=") + 1).trim(); 
     657        addGlobalMeta(key, value); 
     658 
     659        if (key.startsWith("Series Name")) lei += value; 
     660      } 
     661 
     662      // now open the LEI file 
     663 
     664      Location l = new Location(lei).getAbsoluteFile(); 
     665      if (l.exists()) { 
     666        return lei; 
     667      } 
     668      else { 
     669        l = l.getParentFile(); 
     670        String[] list = l.list(); 
     671        for (int i=0; i<list.length; i++) { 
     672          if (checkSuffix(list[i], LEI_SUFFIX)) { 
     673            return new Location(l.getAbsolutePath(), list[i]).getAbsolutePath(); 
     674          } 
     675        } 
     676      } 
     677    } 
     678    return null; 
     679  } 
     680 
     681  private void parseFilenames(int seriesIndex) throws IOException { 
     682    int maxPlanes = 0; 
     683    Vector<String> f = new Vector<String>(); 
     684    int tempImages = in.readInt(); 
     685 
     686    if (((long) tempImages * nameLength) > in.length()) { 
     687      in.order(!isLittleEndian()); 
     688      tempImages = in.readInt(); 
     689      in.order(isLittleEndian()); 
     690    } 
     691 
     692    core[seriesIndex].sizeX = in.readInt(); 
     693    core[seriesIndex].sizeY = in.readInt(); 
     694    in.skipBytes(4); 
     695    int samplesPerPixel = in.readInt(); 
     696    core[seriesIndex].rgb = samplesPerPixel > 1; 
     697    core[seriesIndex].sizeC = samplesPerPixel; 
     698 
     699    File dirFile = new File(currentId).getAbsoluteFile(); 
     700    String[] listing = null; 
     701    String dirPrefix = ""; 
     702    if (dirFile.exists()) { 
     703      listing = dirFile.getParentFile().list(); 
     704      dirPrefix = dirFile.getParent(); 
     705      if (!dirPrefix.endsWith(File.separator)) dirPrefix += File.separator; 
     706    } 
     707    else { 
     708      listing = 
     709        (String[]) Location.getIdMap().keySet().toArray(new String[0]); 
     710    } 
     711 
     712    Vector<String> list = new Vector<String>(); 
     713 
     714    for (int k=0; k<listing.length; k++) { 
     715      if (checkSuffix(listing[k], TiffReader.TIFF_SUFFIXES)) { 
     716        list.add(listing[k]); 
     717      } 
     718    } 
     719 
     720    boolean tiffsExist = false; 
     721 
     722    String prefix = ""; 
     723    for (int j=0; j<tempImages; j++) { 
     724      // read in each filename 
     725      prefix = getString(nameLength); 
     726      f.add(dirPrefix + prefix); 
     727      // test to make sure the path is valid 
     728      Location test = new Location(f.get(f.size() - 1)); 
     729      if (test.exists()) list.remove(prefix); 
     730      if (!tiffsExist) tiffsExist = test.exists(); 
     731    } 
     732 
     733    // all of the TIFF files were renamed 
     734 
     735    if (!tiffsExist) { 
     736      // Strategy for handling renamed files: 
     737      // 1) Assume that files for each series follow a pattern. 
     738      // 2) Assign each file group to the first series with the correct count. 
     739      LOGGER.info("Handling renamed TIFF files"); 
     740 
     741      listing = list.toArray(new String[list.size()]); 
     742 
     743      // grab the file patterns 
     744      Vector<String> filePatterns = new Vector<String>(); 
     745      for (String q : listing) { 
     746        Location l = new Location(dirPrefix, q).getAbsoluteFile(); 
     747        FilePattern pattern = new FilePattern(l); 
     748 
     749        AxisGuesser guess = new AxisGuesser(pattern, "XYZCT", 1, 1, 1, false); 
     750        String fp = pattern.getPattern(); 
     751 
     752        if (guess.getAxisCountS() >= 1) { 
     753          String pre = pattern.getPrefix(guess.getAxisCountS()); 
     754          Vector<String> fileList = new Vector<String>(); 
     755          for (int n=0; n<listing.length; n++) { 
     756            Location p = new Location(dirPrefix, listing[n]); 
     757            if (p.getAbsolutePath().startsWith(pre)) { 
     758              fileList.add(listing[n]); 
     759            } 
     760          } 
     761          fp = FilePattern.findPattern(l.getAbsolutePath(), dirPrefix, 
     762            fileList.toArray(new String[fileList.size()])); 
     763        } 
     764 
     765        if (fp != null && !filePatterns.contains(fp)) { 
     766          filePatterns.add(fp); 
     767        } 
     768      } 
     769 
     770      for (String q : filePatterns) { 
     771        String[] pattern = new FilePattern(q).getFiles(); 
     772        if (pattern.length == tempImages) { 
     773          // make sure that this pattern hasn't already been used 
     774 
     775          boolean validPattern = true; 
     776          for (int n=0; n<seriesIndex; n++) { 
     777            if (files[n] == null) continue; 
     778            if (files[n].contains(pattern[0])) { 
     779              validPattern = false; 
     780              break; 
     781            } 
     782          } 
     783 
     784          if (validPattern) { 
     785            files[seriesIndex] = new Vector<String>(); 
     786            files[seriesIndex].addAll(Arrays.asList(pattern)); 
     787          } 
     788        } 
     789      } 
     790    } 
     791    else files[seriesIndex] = f; 
     792    if (files[seriesIndex] == null) valid[seriesIndex] = false; 
     793    else { 
     794      core[seriesIndex].imageCount = files[seriesIndex].size(); 
     795      maxPlanes = (int) Math.max(maxPlanes, core[seriesIndex].imageCount); 
     796    } 
     797  } 
     798 
     799  private void parseSeriesTag() throws IOException { 
     800    addSeriesMeta("Version", in.readInt()); 
     801    addSeriesMeta("Number of Series", in.readInt()); 
     802    fileLength = in.readInt(); 
     803    addSeriesMeta("Length of filename", fileLength); 
     804    int extLen = in.readInt(); 
     805    if (extLen > fileLength) { 
     806      in.seek(8); 
     807      core[0].littleEndian = !isLittleEndian(); 
     808      in.order(isLittleEndian()); 
     809      fileLength = in.readInt(); 
     810      extLen = in.readInt(); 
     811    } 
     812    addSeriesMeta("Length of file extension", extLen); 
     813    addSeriesMeta("Image file extension", getString(extLen)); 
     814  } 
     815 
     816  private void parseImageTag(int seriesIndex) throws IOException { 
     817    core[seriesIndex].imageCount = in.readInt(); 
     818    core[seriesIndex].sizeX = in.readInt(); 
     819    core[seriesIndex].sizeY = in.readInt(); 
     820 
     821    addSeriesMeta("Number of images", getImageCount()); 
     822    addSeriesMeta("Image width", getSizeX()); 
     823    addSeriesMeta("Image height", getSizeY()); 
     824    addSeriesMeta("Bits per Sample", in.readInt()); 
     825    addSeriesMeta("Samples per pixel", in.readInt()); 
     826 
     827    String name = getString(fileLength * 2); 
     828 
     829    if (name.indexOf(".") != -1) { 
     830      name = name.substring(0, name.lastIndexOf(".")); 
     831    } 
     832 
     833    String[] tokens = name.split("_"); 
     834    StringBuffer buf = new StringBuffer(); 
     835    for (int p=1; p<tokens.length; p++) { 
     836      String lcase = tokens[p].toLowerCase(); 
     837      if (!lcase.startsWith("ch0") && !lcase.startsWith("c0") && 
     838        !lcase.startsWith("z0") && !lcase.startsWith("t0")) 
     839      { 
     840        if (buf.length() > 0) buf.append("_"); 
     841        buf.append(tokens[p]); 
     842      } 
     843    } 
     844    seriesNames.add(buf.toString()); 
     845  } 
     846 
     847  private void parseDimensionTag(int seriesIndex) 
     848    throws FormatException, IOException 
     849  { 
     850    addSeriesMeta("Voxel Version", in.readInt()); 
     851    core[seriesIndex].rgb = in.readInt() == 20; 
     852    addSeriesMeta("VoxelType", isRGB() ? "RGB" : "gray"); 
     853 
     854    int bpp = in.readInt(); 
     855    addSeriesMeta("Bytes per pixel", bpp); 
     856 
     857    switch (bpp) { 
     858      case 1: 
     859        core[seriesIndex].pixelType = FormatTools.UINT8; 
     860        break; 
     861      case 3: 
     862        core[seriesIndex].pixelType = FormatTools.UINT8; 
     863        core[seriesIndex].sizeC = 3; 
     864        core[seriesIndex].rgb = true; 
     865        break; 
     866      case 2: 
     867        core[seriesIndex].pixelType = FormatTools.UINT16; 
     868        break; 
     869      case 6: 
     870        core[seriesIndex].pixelType = FormatTools.UINT16; 
     871        core[seriesIndex].sizeC = 3; 
     872        core[seriesIndex].rgb = true; 
     873        break; 
     874      case 4: 
     875        core[seriesIndex].pixelType = FormatTools.UINT32; 
     876        break; 
     877      default: 
     878        throw new FormatException("Unsupported bytes per pixel (" + 
     879          bpp + ")"); 
     880    } 
     881 
     882    core[seriesIndex].dimensionOrder = "XY"; 
     883 
     884    int resolution = in.readInt(); 
     885    core[seriesIndex].bitsPerPixel = resolution; 
     886    addSeriesMeta("Real world resolution", resolution); 
     887    addSeriesMeta("Maximum voxel intensity", getString(true)); 
     888    addSeriesMeta("Minimum voxel intensity", getString(true)); 
     889    int len = in.readInt(); 
     890    in.skipBytes(len * 2 + 4); 
     891 
     892    len = in.readInt(); 
     893    for (int j=0; j<len; j++) { 
     894      int dimId = in.readInt(); 
     895      String dimType = dimensionNames.get(new Integer(dimId)); 
     896      if (dimType == null) dimType = ""; 
     897 
     898      int size = in.readInt(); 
     899      int distance = in.readInt(); 
     900      int strlen = in.readInt() * 2; 
     901      String[] sizeData = getString(strlen).split(" "); 
     902      String physicalSize = sizeData[0]; 
     903      String unit = ""; 
     904      if (sizeData.length > 1) unit = sizeData[1]; 
     905 
     906      double physical = Double.parseDouble(physicalSize) / size; 
     907      if (unit.equals("m")) { 
     908        physical *= 1000000; 
     909      } 
     910 
     911      if (dimType.equals("x")) { 
     912        core[seriesIndex].sizeX = size; 
     913        physicalSizes[seriesIndex][0] = physical; 
     914      } 
     915      else if (dimType.equals("y")) { 
     916        core[seriesIndex].sizeY = size; 
     917        physicalSizes[seriesIndex][1] = physical; 
     918      } 
     919      else if (dimType.equals("channel")) { 
     920        if (getSizeC() == 0) core[seriesIndex].sizeC = 1; 
     921        core[seriesIndex].sizeC *= size; 
     922        if (getDimensionOrder().indexOf("C") == -1) { 
     923          core[seriesIndex].dimensionOrder += "C"; 
     924        } 
     925        physicalSizes[seriesIndex][3] = physical; 
     926      } 
     927      else if (dimType.equals("z")) { 
     928        core[seriesIndex].sizeZ = size; 
     929      } 
     930      else { 
     931        core[seriesIndex].sizeT = size; 
     932        if (getDimensionOrder().indexOf("T") == -1) { 
     933          core[seriesIndex].dimensionOrder += "T"; 
     934        } 
     935        physicalSizes[seriesIndex][4] = physical; 
     936      } 
     937 
     938      String dimPrefix = "Dim" + j; 
     939 
     940      addSeriesMeta(dimPrefix + " type", dimType); 
     941      addSeriesMeta(dimPrefix + " size", size); 
     942      addSeriesMeta(dimPrefix + " distance between sub-dimensions", 
     943        distance); 
     944 
     945      addSeriesMeta(dimPrefix + " physical length", 
     946        physicalSize + " " + unit); 
     947 
     948      addSeriesMeta(dimPrefix + " physical origin", getString(true)); 
     949    } 
     950    addSeriesMeta("Series name", getString(false)); 
     951 
     952    String description = getString(false); 
     953    seriesDescriptions.add(description); 
     954    addSeriesMeta("Series description", description); 
     955  } 
     956 
     957  private void parseTimeTag(int seriesIndex) throws IOException { 
     958    int nDims = in.readInt(); 
     959    addSeriesMeta("Number of time-stamped dimensions", nDims); 
     960    addSeriesMeta("Time-stamped dimension", in.readInt()); 
     961 
     962    for (int j=0; j<nDims; j++) { 
     963      String dimPrefix = "Dimension " + j; 
     964      addSeriesMeta(dimPrefix + " ID", in.readInt()); 
     965      addSeriesMeta(dimPrefix + " size", in.readInt()); 
     966      addSeriesMeta(dimPrefix + " distance", in.readInt()); 
     967    } 
     968 
     969    int numStamps = in.readInt(); 
     970    addSeriesMeta("Number of time-stamps", numStamps); 
     971    timestamps[seriesIndex] = new String[numStamps]; 
     972    for (int j=0; j<numStamps; j++) { 
     973      timestamps[seriesIndex][j] = getString(64); 
     974      addSeriesMeta("Timestamp " + j, timestamps[seriesIndex][j]); 
     975    } 
     976 
     977    if (in.getFilePointer() < in.length()) { 
     978      int numTMs = in.readInt(); 
     979      addSeriesMeta("Number of time-markers", numTMs); 
     980      for (int j=0; j<numTMs; j++) { 
     981        int numDims = in.readInt(); 
     982 
     983        String time = "Time-marker " + j + " Dimension "; 
     984 
     985        for (int k=0; k<numDims; k++) { 
     986          addSeriesMeta(time + k + " coordinate", in.readInt()); 
     987        } 
     988        addSeriesMeta("Time-marker " + j, getString(64)); 
     989      } 
     990    } 
     991  } 
     992 
     993  private void parseExperimentTag() throws IOException { 
     994    in.skipBytes(8); 
     995    String description = getString(true); 
     996    addSeriesMeta("Image Description", description); 
     997    addSeriesMeta("Main file extension", getString(true)); 
     998    addSeriesMeta("Image format identifier", getString(true)); 
     999    addSeriesMeta("Single image extension", getString(true)); 
     1000  } 
     1001 
     1002  private void parseLUT(int seriesIndex) throws IOException { 
     1003    int nChannels = in.readInt(); 
     1004    if (nChannels > 0) core[seriesIndex].indexed = true; 
     1005    addSeriesMeta("Number of LUT channels", nChannels); 
     1006    addSeriesMeta("ID of colored dimension", in.readInt()); 
     1007 
     1008    for (int j=0; j<nChannels; j++) { 
     1009      String p = "LUT Channel " + j; 
     1010      addSeriesMeta(p + " version", in.readInt()); 
     1011      addSeriesMeta(p + " inverted?", in.read() == 1); 
     1012      addSeriesMeta(p + " description", getString(false)); 
     1013      addSeriesMeta(p + " filename", getString(false)); 
     1014      String lut = getString(false); 
     1015      addSeriesMeta(p + " name", lut); 
     1016      in.skipBytes(8); 
     1017    } 
     1018  } 
     1019 
     1020  private void parseChannelTag() throws IOException { 
     1021    int nBands = in.readInt(); 
     1022    for (int band=0; band<nBands; band++) { 
     1023      String p = "Band #" + (band + 1) + " "; 
     1024      addSeriesMeta(p + "Lower wavelength", in.readDouble()); 
     1025      in.skipBytes(4); 
     1026      addSeriesMeta(p + "Higher wavelength", in.readDouble()); 
     1027      in.skipBytes(4); 
     1028      addSeriesMeta(p + "Gain", in.readDouble()); 
     1029      addSeriesMeta(p + "Offset", in.readDouble()); 
     1030    } 
     1031  } 
     1032 
     1033  private void parseInstrumentData(MetadataStore store, int blockNum) 
     1034    throws IOException 
     1035  { 
     1036    int series = getSeries(); 
    10121037 
    10131038    // read 24 byte SAFEARRAY 
    1014     stream.skipBytes(4); 
    1015     int cbElements = stream.readInt(); 
    1016     stream.skipBytes(8); 
    1017     int nElements = stream.readInt(); 
    1018     stream.skipBytes(4); 
     1039    in.skipBytes(4); 
     1040    int cbElements = in.readInt(); 
     1041    in.skipBytes(8); 
     1042    int nElements = in.readInt(); 
     1043    in.skipBytes(4); 
    10191044 
    10201045    for (int j=0; j<nElements; j++) { 
    1021       stream.seek(24 + j * cbElements); 
    1022       String contentID = getString(stream, 128); 
    1023       String description = getString(stream, 64); 
    1024       String data = getString(stream, 64); 
    1025       int dataType = stream.readShort(); 
    1026       stream.skipBytes(6); 
     1046      in.seek(24 + j * cbElements); 
     1047      String contentID = getString(128); 
     1048      String description = getString(64); 
     1049      String data = getString(64); 
     1050      int dataType = in.readShort(); 
     1051      in.skipBytes(6); 
    10271052 
    10281053      // read data 
    10291054      switch (dataType) { 
    10301055        case 2: 
    1031           data = String.valueOf(stream.readShort()); 
     1056          data = String.valueOf(in.readShort()); 
    10321057          break; 
    10331058        case 3: 
    1034           data = String.valueOf(stream.readInt()); 
     1059          data = String.valueOf(in.readInt()); 
    10351060          break; 
    10361061        case 4: 
    1037           data = String.valueOf(stream.readFloat()); 
     1062          data = String.valueOf(in.readFloat()); 
    10381063          break; 
    10391064        case 5: 
    1040           data = String.valueOf(stream.readDouble()); 
     1065          data = String.valueOf(in.readDouble()); 
    10411066          break; 
    10421067        case 7: 
    10431068        case 11: 
    1044           data = stream.read() == 0 ? "false" : "true"; 
     1069          data = in.read() == 0 ? "false" : "true"; 
    10451070          break; 
    10461071        case 17: 
    1047           data = stream.readString(1); 
     1072          data = in.readString(1); 
    10481073          break; 
    10491074      } 
     1075 
     1076      if (data.trim().length() == 0) continue; 
    10501077 
    10511078      String[] tokens = contentID.split("\\|"); 
     
    12471274      addSeriesMeta("Block " + blockNum + " " + contentID, data); 
    12481275    } 
    1249     stream.close(); 
    12501276 
    12511277    // populate saved LogicalChannel data 
     
    12901316  } 
    12911317 
    1292   private String getString(RandomAccessInputStream stream, int len) 
    1293     throws IOException 
    1294   { 
    1295     return DataTools.stripString(stream.readString(len)); 
    1296   } 
    1297  
    1298   private String getString(RandomAccessInputStream stream, boolean doubleLength) 
    1299     throws IOException 
    1300   { 
    1301     int len = stream.readInt(); 
     1318  private String getString(int len) throws IOException { 
     1319    return DataTools.stripString(in.readString(len)); 
     1320  } 
     1321 
     1322  private String getString(boolean doubleLength) throws IOException { 
     1323    int len = in.readInt(); 
    13021324    if (doubleLength) len *= 2; 
    1303     return getString(stream, len); 
     1325    return getString(len); 
    13041326  } 
    13051327 
Note: See TracChangeset for help on using the changeset viewer.