Changeset 3984


Ignore:
Timestamp:
04/25/08 16:07:27 (12 years ago)
Author:
curtis
Message:

Update Dataset logic to harness Bio-Formats more effectively.

Location:
trunk/loci/visbio/data
Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/visbio/data/DataManager.java

    r3768 r3984  
    250250          pattern = FilePattern.findPattern(files[i]); 
    251251          if (pattern == null) pattern = files[i].getAbsolutePath(); 
     252          break; 
    252253        } 
    253254        if (task.isStopped()) { 
     
    261262 
    262263        FilePattern fp = new FilePattern(pattern); 
    263         int[] lengths = fp.getCount(); 
    264  
    265         // assume first dimension is Time, last is Slice, and others are Other 
    266         int len = lengths.length; 
    267         String[] dims = new String[len + 1]; 
    268         dims[0] = "Time"; 
    269         for (int i=1; i<len; i++) dims[i] = "Other"; 
    270         dims[len] = "Slice"; 
    271264 
    272265        if (task.isStopped()) { 
     
    274267          return; 
    275268        } 
    276         createDataset(dirName, pattern, fp.getFiles(), 
    277           lengths, dims, Float.NaN, Float.NaN, Float.NaN, task); 
     269        createDataset(dirName, pattern, task); 
    278270      } 
    279271    }.start(); 
     
    284276   * If no task object is given, a new one is created to use. 
    285277   */ 
    286   public void createDataset(String name, String pattern, 
    287     String[] ids, int[] lengths, String[] dims, 
    288     float width, float height, float step, BioTask bioTask) 
    289   { 
     278  public void createDataset(String name, String pattern, BioTask bioTask) { 
    290279    if (bioTask == null) { 
    291280      TaskManager tm = (TaskManager) bio.getManager(TaskManager.class); 
     
    303292      } 
    304293    }; 
    305     Dataset dataset = new Dataset(name, pattern, 
    306       ids, lengths, dims, width, height, step, sl); 
     294    Dataset dataset = new Dataset(name, pattern, sl); 
    307295    task.setCompleted(); 
    308296    addData(dataset); 
  • trunk/loci/visbio/data/Dataset.java

    r3524 r3984  
    2525 
    2626import java.awt.*; 
    27 import java.awt.datatransfer.*; 
    2827import java.awt.image.BufferedImage; 
    2928import java.io.*; 
     
    3231import java.util.Hashtable; 
    3332import javax.swing.JComponent; 
     33import javax.swing.JFileChooser; 
     34import javax.swing.JOptionPane; 
    3435import loci.formats.*; 
     36import loci.formats.gui.GUITools; 
    3537import loci.formats.meta.MetadataStore; 
    36 import loci.formats.ome.OMEXMLMetadata; 
     38import loci.visbio.VisBioFrame; 
    3739import loci.visbio.state.Dynamic; 
    3840import loci.visbio.state.SaveException; 
    3941import loci.visbio.util.*; 
    40 import org.openmicroscopy.xml.OMENode; 
    4142import org.w3c.dom.Element; 
     43import ome.xml.OMEXMLNode; 
    4244import visad.*; 
    4345 
     
    6668public class Dataset extends ImageTransform { 
    6769 
    68   // -- Static fields -- 
    69  
    70   /** Dataset import dialog. */ 
    71   protected static DatasetPane datasetImporter; 
    72  
    7370  // -- Data fields -- 
    7471 
     
    7673  protected String pattern; 
    7774 
    78   /** Source file array. */ 
    79   protected String[] ids; 
    80  
    8175  /** Optional listener for constructor progress. */ 
    8276  protected StatusListener listener; 
     
    8478  // -- Computed fields -- 
    8579 
    86   /** Data readers, one for each source file in the array. */ 
    87   protected ImageReader[] readers; 
     80  /** Data reader. */ 
     81  protected IFormatReader reader; 
    8882 
    8983  /** Controls for this dataset. */ 
    9084  protected DatasetWidget controls; 
    9185 
    92   /** Number of images per source file. */ 
    93   protected int numImages; 
    94  
    95   /** File format description of source files. */ 
    96   protected String format; 
    97  
    98   /** Metadata associated with the first source file. */ 
    99   protected Hashtable metadata; 
    100  
    101   /** OME node associated with the first source file. */ 
    102   protected OMENode ome; 
    103  
    104   /** Range component count for each image. */ 
    105   protected int numRange; 
    106  
    107   /** Width of each image. */ 
    108   protected int resX; 
    109  
    110   /** Height of each image. */ 
    111   protected int resY; 
    112  
    113   /** Computed offset coefficients into rasterized source file array. */ 
    114   protected int[] offsets; 
    115  
    11686  /** Types mapped to spatial components (X, Y). */ 
    11787  protected RealType[] spatial; 
     
    12999   * See the complete constructor for more information. 
    130100   */ 
    131   public Dataset(String name, String pattern, 
    132     String[] ids, int[] lengths, String[] dims) 
    133   { 
    134     this(name, pattern, ids, lengths, dims, 
    135       Float.NaN, Float.NaN, Float.NaN, null); 
    136   } 
    137  
    138   /** 
    139    * Constructs a multidimensional data object. 
    140    * See the complete constructor for more information. 
    141    */ 
    142   public Dataset(String name, String pattern, String[] ids, 
    143     int[] lengths, String[] dims, float width, float height, float step) 
    144   { 
    145     this(name, pattern, ids, lengths, dims, width, height, step, null); 
    146   } 
    147  
    148   /** 
    149    * Constructs a new multidimensional data object from the given list of 
    150    * source files. Any multidimensional file organization can be specified, 
    151    * rasterized, using the ids source file list coupled with the lengths 
    152    * array, which lists the length of each dimension in the structure. 
    153    * <p> 
    154    * Also, a list of what each dimension in the multidimensional structure 
    155    * means must be provided, using the dims array. Since each file can contain 
    156    * multiple images, those images implicitly define another dimension whose 
    157    * type must be specified as well. Thus, the dims array should be one element 
    158    * longer than the lengths array, with the final element of dims describing 
    159    * the type of this implicit dimension. Note that the number of images per 
    160    * file is automatically detected and appended to the lengths array, so there 
    161    * is no need to append it manually. Lastly, if there is only one image per 
    162    * file, the final dims element is ignored, and lengths is not affected. 
    163    * 
    164    * @param pattern String pattern describing the dataset. 
    165    * @param ids List of source files, with dimensions rasterized. 
    166    * @param lengths List of dimension lengths. 
    167    * @param dims List of each dimension's meaning (Time, Slice, etc.). 
    168    * @param width Physical width of each image, in microns. 
    169    * @param height Physical height of each image, in microns. 
    170    * @param step Physical distance between image slices, in microns. 
     101  public Dataset(String name, String pattern) { this(name, pattern, null); } 
     102 
     103  /** 
     104   * Constructs a new multidimensional data object from the given file pattern. 
     105   * @param name Label for the dataset. 
     106   * @param pattern File pattern identifying the dataset. 
    171107   * @param listener Listener object to be informed of construction progress. 
    172108   */ 
    173   public Dataset(String name, String pattern, String[] ids, 
    174     int[] lengths, String[] dims, float width, float height, float step, 
    175     StatusListener listener) 
    176   { 
    177     super(null, name, width, height, step); 
     109  public Dataset(String name, String pattern, StatusListener listener) { 
     110    super(null, name); 
    178111    this.pattern = pattern; 
    179     this.ids = ids; 
    180     this.lengths = lengths; 
    181     this.dims = dims; 
    182112    this.listener = listener; 
    183113    initState(null); 
     
    188118  /** Close all open ids. */ 
    189119  public void close() throws FormatException, IOException { 
    190     for (int i=0; i<ids.length; i++) readers[i].close(); 
     120    reader.close(); 
    191121  } 
    192122 
     
    195125 
    196126  /** Gets filenames of all files in dataset. */ 
    197   public String[] getFilenames() { return ids; } 
    198  
    199   /** Gets the number of images per source file. */ 
    200   public int getImagesPerSource() { return numImages; } 
     127  public String[] getFilenames() { return reader.getUsedFiles(); } 
    201128 
    202129  /** Gets a description of the source files' file format. */ 
    203   public String getFileFormat() { return format; } 
    204  
    205   /** Gets metadata associated with the first source file. */ 
    206   public Hashtable getMetadata() { return metadata; } 
    207  
    208   /** Gets the OME node associated with the first source file. */ 
    209   public OMENode getOMENode() { return ome; } 
     130  public String getFileFormat() { return reader.getFormat(); } 
     131 
     132  /** Gets metadata associated with the dataset. */ 
     133  public Hashtable getMetadata() { return reader.getMetadata(); } 
     134 
     135  /** Gets an OME-XML root for the dataset. */ 
     136  public OMEXMLNode getOMEXMLRoot() { 
     137    MetadataStore store = reader.getMetadataStore(); 
     138    return (OMEXMLNode) store.getRoot(); 
     139  } 
    210140 
    211141  // -- ImageTransform API methods -- 
     
    213143  /** Obtains an image from the source(s) at the given dimensional position. */ 
    214144  public BufferedImage getImage(int[] pos) { 
    215     int[] indices = getIndices(pos); 
    216     int fileIndex = indices[0]; 
    217     if (fileIndex < 0 || fileIndex >= ids.length) { 
    218       System.err.println("Invalid file number #" + fileIndex); 
     145    int index = posToIndex(pos); 
     146    BufferedImage img = null; 
     147    try { 
     148      img = reader.openImage(index); 
     149    } 
     150    catch (IOException exc) { 
     151      if (VisBioFrame.DEBUG) exc.printStackTrace(); 
     152    } 
     153    catch (FormatException exc) { 
     154      if (VisBioFrame.DEBUG) exc.printStackTrace(); 
     155    } 
     156    if (img == null) { 
     157      System.err.println("Could not read image at index #" + index); 
    219158      return null; 
    220159    } 
    221     int imgIndex = indices[1]; 
    222     String filename = "\"" + new File(ids[fileIndex]).getName() + "\""; 
    223  
    224     BufferedImage img = null; 
    225  
    226     int numImg = -1; 
    227     try { 
    228       readers[fileIndex].setId(ids[fileIndex]); 
    229       numImg = readers[fileIndex].getImageCount(); 
    230     } 
    231     catch (IOException exc) { numImg = -1; } 
    232     catch (FormatException exc) { numImg = -1; } 
    233     if (numImg < 0) { 
    234       System.err.println("Could not read file " + filename); 
    235       return null; 
    236     } 
    237     else if (numImg == 0) { 
    238       System.err.println("File " + filename + " contains no images"); 
    239       return null; 
    240     } 
    241     if (imgIndex < 0 || imgIndex >= numImg) { 
    242       System.err.println("Invalid image number #" + (imgIndex + 1) + 
    243         " for file " + filename + " (" + numImg + " found)"); 
    244       return null; 
    245     } 
    246  
    247     int tries = 3; 
    248     while (tries > 0) { 
    249       boolean again = false; 
    250       try { 
    251         img = readers[fileIndex].openImage(imgIndex); 
    252       } 
    253       catch (IOException exc) { 
    254         String msg = exc.getMessage(); 
    255         if (msg != null && msg.indexOf("Bad file descriptor") >= 0) { 
    256           // HACK - trap for catching sporadic exception; try again! 
    257           if (tries == 0) { 
    258             System.err.println("Unable to read image #" + (imgIndex + 1) + 
    259               " from file " + filename); 
    260             return null; 
    261           } 
    262           else again = true; 
    263         } 
    264       } 
    265       catch (FormatException exc) { 
    266         System.err.println("Unable to read image #" + (imgIndex + 1) + 
    267           " from file " + filename); 
    268         return null; 
    269       } 
    270       if (again) tries--; 
    271       else break; 
    272     } 
    273160    return img; 
    274161  } 
    275162 
    276163  /** Gets width of each image. */ 
    277   public int getImageWidth() { return resX; } 
     164  public int getImageWidth() { return reader.getSizeX(); } 
    278165 
    279166  /** Gets height of each image. */ 
    280   public int getImageHeight() { return resY; } 
     167  public int getImageHeight() { return reader.getSizeY(); } 
    281168 
    282169  /** Gets number of range components at each pixel. */ 
    283   public int getRangeCount() { return numRange; } 
     170  public int getRangeCount() { return 1; } 
    284171 
    285172  // -- Static DataTransform API methods -- 
     
    297184    File file, Component parent) 
    298185  { 
    299     // create dataset import dialog if it doesn't already exist 
    300     if (datasetImporter == null) { 
    301       datasetImporter = new DatasetPane(dm, SwingUtil.getVisBioFileChooser()); 
    302     } 
    303  
    304     // if clipboard contains a file name, use it as the default file pattern 
    305186    if (file == null) { 
    306       Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); 
    307       if (clip != null) { 
    308         Transferable t = null; 
    309         try { 
    310           t = clip.getContents(null); 
    311         } 
    312         catch (IllegalStateException exc) { 
    313           // clipboard contents unavailable 
    314         } 
    315         if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { 
    316           String s = null; 
    317           try { s = (String) t.getTransferData(DataFlavor.stringFlavor); } 
    318           catch (IOException exc) { exc.printStackTrace(); } 
    319           catch (UnsupportedFlavorException exc) { exc.printStackTrace(); } 
    320           if (s != null) { 
    321             File f = new File(s); 
    322             File dir = f.getParentFile(); 
    323             if (f.exists() || (dir != null && dir.exists())) file = f; 
    324           } 
    325         } 
    326       } 
    327     } 
    328     datasetImporter.selectFile(file); 
    329  
    330     // get file pattern from dataset import dialog 
    331     datasetImporter.showDialog(parent); 
    332  
    333     // dataset import dialog will add the resultant dataset to the Data panel 
     187      // prompt for file to open 
     188      IFormatReader reader = new ChannelSeparator(); 
     189      JFileChooser fc = GUITools.buildFileChooser(reader); 
     190      int rval = fc.showOpenDialog(parent); 
     191      if (rval != JFileChooser.APPROVE_OPTION) return null; 
     192      file = fc.getSelectedFile(); 
     193    } 
     194 
     195    FilePattern fp = new FilePattern(new Location(file)); 
     196    String pattern = fp.getPattern(); 
     197    if (pattern == null) pattern = file.getAbsolutePath(); 
     198    String name = fp.getPrefix(); 
     199    if (name == null) name = file.getName(); 
     200 
     201    // confirm file pattern 
     202    pattern = (String) JOptionPane.showInputDialog(parent, "File pattern", 
     203      "VisBio", JOptionPane.QUESTION_MESSAGE, null, null, pattern); 
     204    if (pattern == null) return null; 
     205 
     206    // data manager will add the resultant dataset to the Data panel 
     207    dm.createDataset(name, pattern, null); 
    334208    return null; 
    335209  } 
     
    357231  public String getCacheId(int[] pos, boolean global) { 
    358232    if (pos == null) return null; 
    359     int[] indices = getIndices(pos); 
    360     int fileIndex = indices[0]; 
    361     int imgIndex = indices[1]; 
    362     String file = global ? ids[fileIndex] : new File(ids[fileIndex]).getName(); 
    363     return file + "/" + imgIndex; 
     233    int index = posToIndex(pos); 
     234    String prefix = global ? pattern : new File(pattern).getName(); 
     235    return prefix + "/" + index; 
    364236  } 
    365237 
     
    390262 
    391263    // image resolution 
     264    int resX = getImageWidth(), resY = getImageHeight(); 
    392265    sb.append("<li>"); 
    393266    sb.append(resX); 
     
    415288 
    416289    // range component count 
     290    int numRange = getRangeCount(); 
    417291    sb.append("<li>"); 
    418292    sb.append(numRange); 
     
    422296    sb.append("</ul>\n"); 
    423297 
     298    // file format 
     299    String format = getFileFormat(); 
     300    sb.append("File format: "); 
     301    sb.append(format); 
     302    sb.append("<br>\n"); 
     303 
    424304    // file count 
    425     sb.append(ids.length); 
    426     sb.append(" "); 
    427     sb.append(format); 
    428     sb.append(" in dataset.<br>\n"); 
     305    sb.append(getFilenames().length); 
     306    sb.append(" files in dataset.<br>\n"); 
    429307 
    430308    // image and pixel counts 
     
    454332    Dataset data = (Dataset) dyn; 
    455333 
    456     return ObjectUtil.objectsEqual(pattern, data.pattern) && 
    457       ObjectUtil.arraysEqual(ids, data.ids); 
     334    return ObjectUtil.objectsEqual(pattern, data.pattern); 
    458335  } 
    459336 
     
    472349    if (data != null) { 
    473350      pattern = data.pattern; 
    474       ids = data.ids; 
    475     } 
    476  
    477     int numTasks = 5; 
    478  
    479     // make sure each file exists 
    480     status(0, numTasks, "Checking files"); 
    481     for (int i=0; i<ids.length; i++) { 
    482       File file = new File(ids[i]); 
    483       if (!file.exists()) { 
    484         System.err.println("File \"" + file.getName() + "\" does not exist."); 
    485         return; 
    486       } 
    487     } 
    488  
    489     // initialize data readers 
    490     readers = new ImageReader[ids.length]; 
    491     for (int i=0; i<ids.length; i++) { 
    492       readers[i] = new ImageReader(); 
    493       readers[i].setMetadataStore(MetadataTools.createOMEXMLMetadata()); 
    494     } 
     351    } 
     352 
     353    int numTasks = 4; 
     354 
     355    // initialize data reader 
     356    reader = new ChannelSeparator(new FileStitcher(true)); 
     357    reader.setMetadataStore(MetadataTools.createOMEXMLMetadata()); 
    495358 
    496359    // determine number of images per source file 
    497     status(1, numTasks, "Determining image count"); 
    498     String filename = "\"" + new File(ids[0]).getName() + "\""; 
     360    status(1, numTasks, "Initializing dataset"); 
    499361    try { 
    500       readers[0].setId(ids[0]); 
    501       numImages = readers[0].getImageCount(); 
    502       format = readers[0].getFormat(ids[0]); 
    503       if (format.startsWith("TIFF")) { 
    504         format = (numImages > 1 ? "multi-page " : "single-image ") + format; 
    505       } 
    506       if (ids.length > 1) format += "s"; 
     362      reader.setId(pattern); 
    507363    } 
    508364    catch (Exception exc) { 
    509       System.err.println("Could not determine number of images per file. " + 
    510         filename + " may be corrupt or invalid."); 
     365      System.err.println("Could not initialize the dataset. '" + 
     366        pattern + "' may be corrupt or invalid."); 
     367      if (VisBioFrame.DEBUG) exc.printStackTrace(); 
    511368      return; 
    512369    } 
    513     if (numImages > 1 && dims.length > lengths.length) { 
    514       int[] nlen = new int[lengths.length + 1]; 
    515       System.arraycopy(lengths, 0, nlen, 0, lengths.length); 
    516       nlen[lengths.length] = numImages; 
    517       lengths = nlen; 
    518     } 
     370    int[] cLen = reader.getChannelDimLengths(); 
     371    lengths = new int[2 + cLen.length]; 
     372    lengths[0] = reader.getSizeT(); 
     373    lengths[1] = reader.getSizeZ(); 
     374    System.arraycopy(cLen, 0, lengths, 2, cLen.length); 
     375    String[] cTypes = reader.getChannelDimTypes(); 
     376    dims = new String[2 + cTypes.length]; 
     377    dims[0] = "Time"; 
     378    dims[1] = "Slice"; 
     379    System.arraycopy(cTypes, 0, dims, 2, cTypes.length); 
    519380    makeLabels(); 
    520  
    521     // initialize offsets convenience array 
    522     int len = numImages > 1 ? lengths.length - 1 : lengths.length; 
    523     offsets = new int[len]; 
    524     if (len > 0) offsets[0] = 1; 
    525     for (int i=1; i<len; i++) { 
    526       offsets[i] = offsets[i - 1] * lengths[i - 1]; 
    527     } 
    528381 
    529382    // load first image for analysis 
    530383    status(2, numTasks, "Reading first image"); 
    531384    BufferedImage img = null; 
    532     try { img = readers[0].openImage(0); } 
     385    try { img = reader.openImage(0); } 
    533386    catch (IOException exc) { img = null; } 
    534387    catch (FormatException exc) { img = null; } 
    535388    catch (NullPointerException exc) { img = null; } 
    536389    if (img == null) { 
    537       System.err.println("Could not read the first image. " + 
    538         filename + " may be corrupt or invalid."); 
     390      System.err.println("Could not read the first image. '" + 
     391        pattern + "' may be corrupt or invalid."); 
    539392      return; 
    540393    } 
     
    552405    } 
    553406 
    554     // determine image resolution 
    555     resX = img.getWidth(); 
    556     resY = img.getHeight(); 
    557  
    558407    // extract range components 
    559408    FunctionType ftype = (FunctionType) ff.getType(); 
     
    571420      return; 
    572421    } 
    573     numRange = color.length; 
    574422 
    575423    // extract domain types 
     
    577425    spatial = domain.getRealComponents(); 
    578426 
    579     // load metadata for the first source file 
    580     String fname = new File(ids[0]).getName(); 
    581     status(3, numTasks, "Reading " + fname + " metadata"); 
    582     metadata = readers[0].getMetadata(); 
    583     if (metadata == null) { 
    584       System.err.println("Could not read metadata from " + 
    585         fname + ". The file may be corrupt or invalid."); 
    586       return; 
    587     } 
    588     MetadataStore ms = readers[0].getMetadataStore(); 
    589     if (ms instanceof OMEXMLMetadata) { 
    590       ome = (OMENode) ((OMEXMLMetadata) ms).getRoot(); 
    591     } 
    592  
    593427    // construct metadata controls 
    594     status(4, numTasks, "Finishing"); 
     428    status(3, numTasks, "Finishing"); 
    595429    controls = new DatasetWidget(this); 
    596430 
    597431    // construct thumbnail handler 
    598     String path = new File(ids[0]).getParent(); 
     432    String path = new File(pattern).getParent(); 
    599433    if (path == null) path = ""; 
    600434    thumbs = new ThumbnailHandler(this, 
     
    610444    super.saveState(child); 
    611445    child.setAttribute("pattern", pattern); 
    612     for (int i=0; i<ids.length; i++) { 
    613       Element fel = XMLUtil.createChild(child, "Filename"); 
    614       XMLUtil.createText(fel, ids[i]); 
    615     } 
    616446  } 
    617447 
     
    620450    super.restoreState(el); 
    621451    pattern = el.getAttribute("pattern"); 
    622     Element[] els = XMLUtil.getChildren(el, "Filename"); 
    623     ids = new String[els.length]; 
    624     for (int i=0; i<ids.length; i++) ids[i] = XMLUtil.getText(els[i]); 
    625452  } 
    626453 
    627454  // -- Helper methods -- 
    628455 
    629   /** 
    630    * Gets the corresponding file and image indices 
    631    * for the given dimensional position. 
    632    */ 
    633   private int[] getIndices(int[] pos) { 
    634     int fileIndex = 0; 
    635     int imgIndex = 0; 
    636     if (numImages > 1) { 
    637       // file images form a new dimension 
    638       for (int i=0; i<offsets.length; i++) fileIndex += offsets[i] * pos[i]; 
    639       imgIndex = pos[pos.length - 1]; 
    640     } 
    641     else { 
    642       // only one image per file 
    643       for (int i=0; i<offsets.length; i++) fileIndex += offsets[i] * pos[i]; 
    644       imgIndex = 0; 
    645     } 
    646     return new int[] {fileIndex, imgIndex}; 
     456  /** Gets the 1-D index for the given position array. */ 
     457  private int posToIndex(int[] pos) { 
     458    int t = pos[0]; 
     459    int z = pos[1]; 
     460 
     461    // rasterize C dimensions 
     462    int[] cLen = reader.getChannelDimLengths(); 
     463    int[] cPos = new int[pos.length - 2]; 
     464    System.arraycopy(pos, 2, cPos, 0, cPos.length); 
     465    int c = FormatTools.positionToRaster(cLen, cPos); 
     466 
     467    int index = reader.getIndex(z, c, t); 
     468    return index; 
    647469  } 
    648470 
  • trunk/loci/visbio/data/DatasetWidget.java

    r3524 r3984  
    2727import java.util.*; 
    2828import javax.swing.*; 
    29 import javax.swing.event.*; 
    3029import javax.swing.table.DefaultTableModel; 
    31 import javax.swing.tree.*; 
     30import loci.formats.gui.XMLCellRenderer; 
    3231import loci.visbio.util.SwingUtil; 
    33 import ome.xml.DOMUtil; 
    34 import org.openmicroscopy.xml.OMENode; 
     32import ome.xml.OMEXMLNode; 
    3533import org.w3c.dom.*; 
    3634 
     
    4240 * <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/visbio/data/DatasetWidget.java">SVN</a></dd></dl> 
    4341 */ 
    44 public class DatasetWidget extends JPanel implements TreeSelectionListener { 
     42public class DatasetWidget extends JPanel { 
    4543 
    4644  // -- Constants -- 
    47  
    48   /** Column headings for OME-XML attributes table. */ 
    49   protected static final String[] TREE_COLUMNS = {"Attribute", "Value"}; 
    5045 
    5146  /** Column headings for metadata table. */ 
     
    5752  protected Dataset dataset; 
    5853 
    59   /** Dataset's associated metadata in OME-XML format. */ 
    60   protected OMENode ome; 
    61  
    6254  /** Dataset's associated metadata. */ 
    6355  protected Hashtable metadata; 
     
    6557  /** Metadata hashtable's sorted key lists. */ 
    6658  protected String[] keys; 
    67  
    68   /** List of dataset source files. */ 
    69   protected JList list; 
    70  
    71   /** Tree displaying metadata in OME-XML format. */ 
    72   protected JTree tree; 
    73  
    74   /** Root of tree displaying OME-XML metadata. */ 
    75   protected DefaultMutableTreeNode treeRoot; 
    76  
    77   /** Table listing OME-XML attributes. */ 
    78   protected JTable treeTable; 
    79  
    80   /** Table model backing OME-XML attributes table. */ 
    81   protected DefaultTableModel treeTableModel; 
    8259 
    8360  /** Table listing metadata fields. */ 
     
    9572 
    9673    // get dataset's metadata 
    97     ome = dataset.getOMENode(); 
    9874    metadata = dataset.getMetadata(); 
    9975 
     
    12096 
    12197    // OME-XML tree 
    122     treeRoot = new DefaultMutableTreeNode(); 
    123     tree = new JTree(treeRoot); 
    124     JScrollPane scrollTree = new JScrollPane(tree); 
     98    OMEXMLNode root = dataset.getOMEXMLRoot(); 
     99    Document doc = root.getDOMElement().getOwnerDocument(); 
     100    JTree xmlTree = XMLCellRenderer.makeJTree(doc); 
     101    JScrollPane scrollTree = new JScrollPane(xmlTree); 
    125102    SwingUtil.configureScrollPane(scrollTree); 
    126     tree.setRootVisible(false); 
    127     tree.setShowsRootHandles(true); 
    128     DefaultTreeSelectionModel treeSelModel = new DefaultTreeSelectionModel(); 
    129     treeSelModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 
    130     tree.setSelectionModel(treeSelModel); 
    131     tree.addTreeSelectionListener(this); 
    132  
    133     // OME-XML attributes table 
    134     treeTableModel = new DefaultTableModel(TREE_COLUMNS, 0); 
    135     treeTable = new JTable(treeTableModel); 
    136     JScrollPane scrollTreeTable = new JScrollPane(treeTable); 
    137     SwingUtil.configureScrollPane(scrollTreeTable); 
    138  
    139     // OME-XML split pane 
    140     JSplitPane treeSplit = 
    141       new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollTree, scrollTreeTable); 
    142103 
    143104    // -- Main GUI -- 
     
    146107    JTabbedPane tabbed = new JTabbedPane(); 
    147108    tabbed.addTab("Original metadata", scrollMetaTable); 
    148     tabbed.addTab("OME-XML", treeSplit); 
     109    tabbed.addTab("OME-XML", scrollTree); 
    149110 
    150111    // lay out components 
     
    159120      metaTableModel.setValueAt(metadata.get(keys[i]), i, 1); 
    160121    } 
    161  
    162     // populate OME-XML tree 
    163     Document doc = null; 
    164     try { doc = ome == null ? null : ome.getOMEDocument(false); } 
    165     catch (Exception exc) { } 
    166     if (doc != null) { 
    167       buildTree(doc.getDocumentElement(), treeRoot); 
    168       SwingUtil.expandTree(tree, treeRoot); 
    169     } 
    170   } 
    171  
    172   // -- TreeSelectionListener API methods -- 
    173  
    174   /** Called when the OME-XML tree selection changes. */ 
    175   public void valueChanged(TreeSelectionEvent e) { 
    176     DefaultMutableTreeNode node = 
    177       (DefaultMutableTreeNode) e.getPath().getLastPathComponent(); 
    178     if (node == null) { 
    179       treeTableModel.setRowCount(0); 
    180       return; 
    181     } 
    182  
    183     // update OME-XML attributes table 
    184     Element el = ((ElementWrapper) node.getUserObject()).el; 
    185     String[] names = DOMUtil.getAttributeNames(el); 
    186     String[] values = DOMUtil.getAttributeValues(el); 
    187     treeTableModel.setRowCount(names.length); 
    188     for (int i=0; i<names.length; i++) { 
    189       treeTableModel.setValueAt(names[i], i, 0); 
    190       treeTableModel.setValueAt(values[i], i, 1); 
    191     } 
    192   } 
    193  
    194   // -- Helper methods -- 
    195  
    196   /** Builds a tree by wrapping XML elements with JTree nodes. */ 
    197   protected void buildTree(Element el, DefaultMutableTreeNode node) { 
    198     DefaultMutableTreeNode child = 
    199       new DefaultMutableTreeNode(new ElementWrapper(el)); 
    200     node.add(child); 
    201     NodeList nodeList = el.getChildNodes(); 
    202     for (int i=0; i<nodeList.getLength(); i++) { 
    203       Node n = (Node) nodeList.item(i); 
    204       if (n instanceof Element) buildTree((Element) n, child); 
    205     } 
    206   } 
    207  
    208   // -- Helper classes -- 
    209  
    210   /** Helper class for OME-XML metadata tree view. */ 
    211   private class ElementWrapper { 
    212     protected Element el; 
    213     ElementWrapper(Element el) { this.el = el; } 
    214     public String toString() { return el == null ? "null" : el.getTagName(); } 
    215122  } 
    216123 
Note: See TracChangeset for help on using the changeset viewer.