[hdf-compass] 03/295: initial checkin

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Sun May 8 10:35:19 UTC 2016


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/master
in repository hdf-compass.

commit 040c72252706553d45dcdf7f00c2d8857d1b129c
Author: John Readey <jreadey at hdfgroup.org>
Date:   Fri Jun 6 17:44:59 2014 -0700

    initial checkin
---
 HDFCompass.py                         |    9 +
 HDFCompass.spec                       |   41 +
 array_model/.DS_Store                 |  Bin 0 -> 6148 bytes
 array_model/__init__.py               |  209 +++++
 compass.icns                          |  Bin 0 -> 167754 bytes
 compass.ico                           |  Bin 0 -> 68714 bytes
 compass_model/.DS_Store               |  Bin 0 -> 6148 bytes
 compass_model/__init__.py             |  477 ++++++++++
 compass_model/icons/.DS_Store         |  Bin 0 -> 6148 bytes
 compass_model/icons/array_16.png      |  Bin 0 -> 800 bytes
 compass_model/icons/array_64.png      |  Bin 0 -> 5320 bytes
 compass_model/icons/folder_16.png     |  Bin 0 -> 365 bytes
 compass_model/icons/folder_64.png     |  Bin 0 -> 1684 bytes
 compass_model/icons/image_16.png      |  Bin 0 -> 689 bytes
 compass_model/icons/image_64.png      |  Bin 0 -> 5749 bytes
 compass_model/icons/kv_16.png         |  Bin 0 -> 903 bytes
 compass_model/icons/kv_64.png         |  Bin 0 -> 6429 bytes
 compass_model/icons/license.txt       |  165 ++++
 compass_model/icons/readme.txt        |    5 +
 compass_model/icons/unknown_16.png    |  Bin 0 -> 900 bytes
 compass_model/icons/unknown_64.png    |  Bin 0 -> 5470 bytes
 compass_model/images.py               |  541 +++++++++++
 compass_model/test.py                 |  231 +++++
 compass_viewer/.DS_Store              |  Bin 0 -> 15364 bytes
 compass_viewer/__init__.py            |  176 ++++
 compass_viewer/array/.DS_Store        |  Bin 0 -> 6148 bytes
 compass_viewer/array/__init__.py      |  358 ++++++++
 compass_viewer/array/plot.py          |   83 ++
 compass_viewer/container/.DS_Store    |  Bin 0 -> 6148 bytes
 compass_viewer/container/__init__.py  |  193 ++++
 compass_viewer/container/list.py      |  232 +++++
 compass_viewer/events.py              |   39 +
 compass_viewer/frame.py               |  309 +++++++
 compass_viewer/icons/.DS_Store        |  Bin 0 -> 6148 bytes
 compass_viewer/icons/go_back_24.png   |  Bin 0 -> 1146 bytes
 compass_viewer/icons/go_back_32.png   |  Bin 0 -> 1479 bytes
 compass_viewer/icons/go_next_24.png   |  Bin 0 -> 1145 bytes
 compass_viewer/icons/go_next_32.png   |  Bin 0 -> 1497 bytes
 compass_viewer/icons/go_up_24.png     |  Bin 0 -> 1127 bytes
 compass_viewer/icons/go_up_32.png     |  Bin 0 -> 1537 bytes
 compass_viewer/icons/license.txt      |  165 ++++
 compass_viewer/icons/logo.png         |  Bin 0 -> 72083 bytes
 compass_viewer/icons/logo.xcf         |  Bin 0 -> 275389 bytes
 compass_viewer/icons/readme.txt       |   11 +
 compass_viewer/icons/view_icon_24.png |  Bin 0 -> 1005 bytes
 compass_viewer/icons/view_icon_32.png |  Bin 0 -> 543 bytes
 compass_viewer/icons/view_list_24.png |  Bin 0 -> 711 bytes
 compass_viewer/icons/view_list_32.png |  Bin 0 -> 508 bytes
 compass_viewer/icons/view_tree_32.png |  Bin 0 -> 743 bytes
 compass_viewer/icons/viz_plot_24.png  |  Bin 0 -> 885 bytes
 compass_viewer/icons/viz_plot_32.png  |  Bin 0 -> 1652 bytes
 compass_viewer/image/.DS_Store        |  Bin 0 -> 6148 bytes
 compass_viewer/image/__init__.py      |   58 ++
 compass_viewer/images.py              | 1582 +++++++++++++++++++++++++++++++++
 compass_viewer/imagesupport.py        |   27 +
 compass_viewer/info.py                |  109 +++
 compass_viewer/keyvalue/.DS_Store     |  Bin 0 -> 6148 bytes
 compass_viewer/keyvalue/__init__.py   |   96 ++
 compass_viewer/platform.py            |   21 +
 docs/.DS_Store                        |  Bin 0 -> 12292 bytes
 docs/Makefile                         |  153 ++++
 docs/conf.py                          |  240 +++++
 docs/index.rst                        |  315 +++++++
 filesystem_model/.DS_Store            |  Bin 0 -> 6148 bytes
 filesystem_model/__init__.py          |  173 ++++
 filesystem_model/test.py              |    8 +
 hdf5_model/.DS_Store                  |  Bin 0 -> 6148 bytes
 hdf5_model/__init__.py                |  357 ++++++++
 hdf5_model/test.py                    |    8 +
 package_icons.py                      |   65 ++
 setup.py                              |   41 +
 71 files changed, 6497 insertions(+)

diff --git a/HDFCompass.py b/HDFCompass.py
new file mode 100644
index 0000000..7d30963
--- /dev/null
+++ b/HDFCompass.py
@@ -0,0 +1,9 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+import compass_viewer
+compass_viewer.run()
\ No newline at end of file
diff --git a/HDFCompass.spec b/HDFCompass.spec
new file mode 100644
index 0000000..9894a07
--- /dev/null
+++ b/HDFCompass.spec
@@ -0,0 +1,41 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+# Builds a single-file EXE for distribution.
+# Note that an "unbundled" distribution launches much more quickly, but
+# requires an installer program to distribute.
+#
+# To compile, execute the following within the source directory:
+#
+# python /path/to/pyinstaller.py HDFCompass.spec
+#
+# The resulting .exe file is placed in the dist/ folder.
+
+a = Analysis(['HDFCompass.py'],
+             pathex=[],
+             hiddenimports=[],
+             hookspath=None,
+             runtime_hooks=None)
+             
+# The following block is necessary to prevent a hard crash when launching
+# the resulting .exe file
+for d in a.datas:
+    if 'pyconfig' in d[0]: 
+        a.datas.remove(d)
+        break
+        
+pyz = PYZ(a.pure)
+exe = EXE(pyz,
+          a.scripts,
+          a.binaries,
+          a.zipfiles,
+          a.datas,
+          name='HDFCompass.exe',
+          debug=False,
+          strip=None,
+          upx=False,
+          console=False , icon='compass.ico')
diff --git a/array_model/.DS_Store b/array_model/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/array_model/.DS_Store differ
diff --git a/array_model/__init__.py b/array_model/__init__.py
new file mode 100644
index 0000000..b14f3ee
--- /dev/null
+++ b/array_model/__init__.py
@@ -0,0 +1,209 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Testing model for array types.
+"""
+
+import os
+import os.path as op
+import numpy as np
+
+import compass_model
+
+import numpy as np
+
+DT_CMP = np.dtype([('a','i'),('b','f')])
+
+DATA = {'a_0d': np.array(1),
+        'a_1d': np.arange(10),
+        'a_2d': np.arange(10*10).reshape((10,10)),
+        'a_3d': np.arange(10*10*10).reshape((10,10,10)),
+        'a_4d': np.arange(10*10*10*10).reshape((10,10,10,10)),
+        'cmp_0d': np.array((1,2), dtype=DT_CMP),
+        'cmp_1d': np.ones((10,), dtype=DT_CMP),
+        'cmp_2d': np.ones((10,10), dtype=DT_CMP),
+        'cmp_3d': np.ones((10,10,10),dtype=DT_CMP),
+        'cmp_4d': np.ones((10,10,10,10),dtype=DT_CMP),
+        's_0d': np.array("Hello"),
+        's_1d': np.array(("Hello",)),
+        'v_0d': np.array('\x01', dtype='|V1'),
+        }
+
+class ArrayStore(compass_model.Store):
+
+    """
+        A "data store" represented by the file system.
+
+        Keys are absolute paths on the local file system.
+    """
+
+    def __contains__(self, key):
+        return key in DATA
+
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def displayname(self):
+        return "Testing arrays"
+
+    @property
+    def root(self):
+        return ArrayContainer(self, None)
+
+    @staticmethod
+    def canhandle(url):
+        if url == "array://localhost":
+            return True
+        return False
+
+    def __init__(self, url):
+        if not self.canhandle(url):
+            raise ValueError(url)
+        self._url = url
+
+    def close(self):
+        pass
+
+    def getparent(self, key):
+        return self.root
+
+
+class ArrayContainer(compass_model.Container):
+
+    """
+        Represents a directory in the filesystem.
+    """
+
+    classkind = "Array Container"
+
+    @staticmethod
+    def canhandle(store, key):
+        return key is None
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._names = sorted(DATA.keys())
+
+    @property
+    def key(self):
+        return None
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        return "Array Container"
+
+    @property
+    def description(self):
+        return self.displayname
+
+    def __len__(self):
+        return len(DATA)
+
+    def __iter__(self):
+        for name in self._names:
+            yield self._store[name]
+
+    def __getitem__(self, idx):
+        key = self._names[idx]
+        return self._store[key]
+
+
+class Array(compass_model.Array):
+
+    """
+        An N-D array
+    """
+
+    classkind = "TestArray"
+
+    @staticmethod
+    def canhandle(store, key):
+        return key in DATA
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self.data = DATA[key]
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        return self.key
+
+    @property
+    def description(self):
+        return self.displayname
+
+    @property
+    def shape(self):
+        return self.data.shape
+
+    @property
+    def dtype(self):
+        return self.data.dtype
+
+    def __getitem__(self, args):
+        return self.data[args]
+
+
+class ArrayKV(compass_model.KeyValue):
+
+    classkind = "Array Key/Value Attrs"
+
+    @staticmethod
+    def canhandle(store, key):
+        return key in DATA
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self.data = {'a': np.array((1,2)), 'b': np.array("Hello"), 'c': np.array('\x01', dtype='|V1')}
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        return self.key
+
+    @property
+    def description(self):
+        return self.displayname
+
+    @property
+    def keys(self):
+        return self.data.keys()
+
+    def __getitem__(self, args):
+        return self.data[args]
+
+
+ArrayStore.push(ArrayKV)
+ArrayStore.push(ArrayContainer)
+ArrayStore.push(Array)
+
+compass_model.push(ArrayStore)
\ No newline at end of file
diff --git a/compass.icns b/compass.icns
new file mode 100644
index 0000000..08ea6bc
Binary files /dev/null and b/compass.icns differ
diff --git a/compass.ico b/compass.ico
new file mode 100644
index 0000000..9aa4298
Binary files /dev/null and b/compass.ico differ
diff --git a/compass_model/.DS_Store b/compass_model/.DS_Store
new file mode 100644
index 0000000..d870cf9
Binary files /dev/null and b/compass_model/.DS_Store differ
diff --git a/compass_model/__init__.py b/compass_model/__init__.py
new file mode 100644
index 0000000..7b9e8ab
--- /dev/null
+++ b/compass_model/__init__.py
@@ -0,0 +1,477 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+The following class definitions represent the pluggable data model.
+
+By subclassing various things in this module, and implementing the missing
+(virtual) methods and properties, you can have the GUI infrastructure display
+your own objects without writing a single line of wxPython code.  GUI
+support exists for generic kinds of objects including browsable containers,
+array-like datasets, and images.
+
+More importantly, you can add support for entirely new file formats.
+
+To implement support for a new kind of "datastore" (HDF5, HDF4, NetCDF, etc.),
+start by subclassing Store and overriding the appropriate methods and
+properties.  Then, subclass the various Node classes this module provides
+(Container, Array, Image, etc.) and implement the various virtual bits of
+those classes as well:
+
+    class FooStore(compass_model.Store):
+        ...
+
+    class FooGroup(compass_model.Container):
+        ...
+
+    class FooDataset(compass_model.Array):
+        ...
+
+    class FooPicture(compass_model.Image):
+        ...
+
+You're not required to do all of them (and of course not all formats provide
+something like an Image), but the more you implement the more capable the
+interface will be.
+
+So that your Store class knows which kinds of nodes are available to open,
+manually register your Node subclasses:
+
+    FooStore.push(FooGroup)
+    FooStore.push(FooDataset)
+    FooStore.push(FooPicture)
+
+Finally, let the rest of the world know about your new data store support by
+calling this module's register() function:
+
+    compass_model.push(FooStore)
+
+You can also extend other peoples' stores.  Suppose there's a module for
+reading HDF5 files, with a store class called foohdf5.HDF5Store,
+but the author didn't support the HDF5 Image standard.  Just write a subclass
+of Image, and register it with the other person's class:
+
+    class MyHDF5Image(Image):
+        ...
+
+    foohdf5.HDF5Store.push(MyHDF5Image)
+
+Of course, this assumes you know enough about the internals of the other
+person's Store to make your new class useful.
+"""
+
+from . import images
+
+_stores = []
+
+def push(store):
+    """ Register a new data store class """
+    _stores.insert(0, store)
+
+def getstores():
+    """ Get a list containing known data store classes """
+    return _stores[:]
+
+
+class Store(object):
+
+    """
+    Represents a data store (i.e. a file or remote resource).
+    """
+
+    # -------------------------------------------------------------------------
+    # Plugin support
+
+    __nodeclasses = None
+
+    @classmethod
+    def push(cls, nodeclass):
+        """ Register a Node subclass.
+
+        When a key is being opened, each subclass is queried in turn.  The
+        first one which reports it can handle the key is used.
+        """
+        if cls.__nodeclasses is None:
+            cls.__nodeclasses = [Unknown]
+        cls.__nodeclasses.insert(0, nodeclass)
+
+
+    def __contains__(self, key):
+        """ Check if a key is valid. """
+        raise NotImplementedError
+
+
+    def __getitem__(self, key):
+        """ Return a Node instance  for *key*.
+
+        Figures out the appropriate Node subclass for the object identified by
+        "key", creates an instance and returns it.
+        """
+        return self.gethandlers(key)[0](self, key)
+
+
+    def gethandlers(self, key=None):
+        """ Rather than picking a handler and returning the Node, return a
+        list of all handlers which can do something useful with *key*.
+
+        If *key* is not specified, returns all handlers
+        """
+        if self.__nodeclasses is None:
+            self.__nodeclasses = [Unknown]
+
+        if key is None:
+            return self.__nodeclasses
+        if key not in self:
+            raise KeyError(key)
+
+        return [nc for nc in self.__nodeclasses if nc.canhandle(self, key)]
+        
+    # End plugin support
+    # -------------------------------------------------------------------------
+
+
+    @property
+    def url(self):
+        """ Identifies the file or Web resource (string).
+
+        Examples might be "file:///path/to/foo.hdf5" or 
+        "http://www.example.com/web/resource"
+        """
+        raise NotImplementedError
+
+
+    @property
+    def displayname(self):
+        """ Short name for display purposes.
+
+        For example, for a file-based store you could implement this with
+        os.path.basename(self.path).
+        """
+        raise NotImplementedError
+
+
+    @property
+    def root(self):
+        """ The root node.
+        
+        Serves as the entry point into the resource.  Every Store must
+        implement this, and is required to return a Container instance.
+        """
+        raise NotImplementedError
+
+
+    @staticmethod
+    def canhandle(url):
+        """ Test if this class can open the resource.
+
+        Returns True or False.  Note this may have side effects, but
+        the resource must not be modified.
+        """
+        raise NotImplementedError
+
+
+    @property
+    def valid(self):
+        """ True if the store is open and ready for use, False otherwise.
+        """
+        raise NotImplementedError
+
+
+    def __init__(self, url):
+        """ Open the resource.
+        """
+        raise NotImplementedError
+
+
+    def close(self):
+        """ Discontinue access to the resource.
+
+        Any further use of this object, or retrieved nodes, is undefined.
+        """
+        pass
+
+
+    def getparent(self, key):
+        """ Return the parent node of the object identified by *key*.
+
+        If an object has no parent, or contains itself, this should return
+        None.  That way, the "up" arrow on the Container view will be
+        grayed out.
+        """
+        pass
+
+
+class Node(object):
+    
+    """
+    Base class for all objects which live in a data store.
+
+    You generally shouldn't inherit from Node directly, but from one of the
+    more useful Node subclasses in this file.  Direct Node subclasses can't
+    do anything interesting in the GUI; all they do is show up in the browser.
+    """
+    
+    # Class attribute containing a dict for icon support.
+    # Keys should be integers giving icon size; values are a callable returning
+    # a byte string with PNG image data.
+    # Example:      icons = {16: get_png_16, 32: get_png_32}
+
+    icons = NotImplemented  
+
+    
+    # A short string (2 or 3 words) describing what the class represents.
+    # This will show up in e.g. the "Open As" context menu.
+    # Example:  "HDF5 Image" or "Swath"
+
+    classkind = NotImplemented
+
+
+    @staticmethod
+    def canhandle(store, key):
+        """ Determine whether this class can usefully represent the object.
+
+        Keep in mind that keys are not technically required to be strings.
+        """
+        raise NotImplementedError
+
+
+    def __init__(self, store, key):
+        """ Create an instance of this class.
+
+        Subclasses must not modify the signature.
+        """
+        raise NotImplementedError
+
+
+    @property
+    def key(self):
+        """ Unique key which identifies this object in the store.
+
+        Keys may be any hashable object, although strings are the most common.
+        """
+        raise NotImplementedError
+
+
+    @property
+    def store(self):
+        """ The data store to which the object belongs. """
+        raise NotImplementedError
+
+
+    @property
+    def displayname(self):
+        """ A short name for display purposes """
+        raise NotImplementedError
+
+
+    @property
+    def displaytitle(self):
+        """ A longer name appropriate for display in a window title.
+
+        Defaults to *displayname*.
+        """
+        return self.displayname
+
+
+    @property
+    def description(self):
+        """ Descriptive string (possibly multi-line) """
+        raise NotImplementedError
+
+
+    def preview(self, w, h):
+        """ [Optional] PNG image preview """
+        return None
+
+
+class Container(Node):
+
+    """
+    Represents an object which holds other objects (like an HDF5 group).
+    
+    Subclasses will be displayed using the browser view.
+    """
+
+    icons = {16:    images.folder_16,
+             64:    images.folder_64    }
+
+    def __len__(self):
+        """ Number of child objects """
+        raise NotImplementedError
+
+
+    def __iter__(self):
+        """ Iterator over child objects.
+
+        Should yield Nodes, not keys (use your Store.open method).
+        """
+        raise NotImplementedError
+
+
+    def __getitem__(self, idx):
+        """ Open an item by index (necessary to support ListCtrl).
+    
+        Should return a Node, not a key (use your Store.open method).
+        """
+        raise NotImplementedError
+
+
+class KeyValue(Node):
+
+    """
+    Represents an object which contains a sequence of key: value attributes.
+
+    Keys must be strings.
+
+    Subclasses will be displayed using a list-like control.
+    """
+
+    icons = {16:    images.kv_16,
+             64:    images.kv_64 }
+
+    @property
+    def keys(self):
+        """ Return a list of attribute keys. """
+        raise NotImplementedError
+
+
+    def __getitem__(self, name):
+        """ Return the raw attribute value """
+        raise NotImplementedError
+
+
+class Array(Node):
+
+    """
+    Represents a NumPy-style regular, rectangular array.
+
+    Subclasses will be displayed in a spreadsheet-style viewer.
+    """
+
+    icons = {16:    images.array_16,
+            64:     images.array_64}
+
+    @property
+    def shape(self):
+        """ Shape tuple """
+        raise NotImplementedError
+
+
+    @property
+    def dtype(self):
+        """ Data type """
+        raise NotImplementedError
+
+
+    def __getitem__(self, args):
+        """ Retrieve data elements """
+        raise NotImplementedError
+
+
+class Image(Node):
+
+    """
+    A single raster image.
+    """
+
+    icons = {16:    images.image_16,
+             64:    images.image_64 }
+
+    @property
+    def width(self):
+        """ Image width in pixels """
+        pass
+
+
+    @property
+    def height(self):
+        """ Image height in pixels """
+        pass
+
+
+    @property
+    def palette(self):
+        """ Palette array, or None. """
+        raise NotImplementedError
+
+    
+    @property
+    def data(self):
+        """ Image data """
+
+
+class Plottable(Node):
+
+    """
+    Represents anything that can be plotted to a 2D canvas using Matplotlib.
+
+    Unlike the rest of the GUI elements, for this node the viewing experience
+    is completely up to you.
+
+    Subclasses may be requested to pop up a Matplotlib window, or render their
+    contents to a PNG byte string for display or export elsewhere in the GUI.
+    """
+
+    def show(self):
+        """ Pop up a Matplotlib display window """
+        raise NotImplementedError
+
+
+    def render(self, width, height):
+        """ Render the image as PNG.
+
+        Should return a byte string; width and height are in pixels.
+        """
+        raise NotImplementedError
+
+
+class Unknown(Node):
+
+    """
+    "Last resort" node (and the only concrete class in this module).
+    These can always be created, but do nothing useful.
+    """
+
+    icons = {   16: images.unknown_16,
+                64: images.unknown_64  }
+    
+    classkind = "Unknown"
+
+    @staticmethod
+    def canhandle(store, key):
+        return True
+
+    def __init__(self, store, key):
+        self._key = key
+        self._store = store
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        import os.path
+        try:
+            return os.path.basename(str(self.key))
+        except Exception:
+            return "Unknown"
+
+    @property
+    def description(self):
+        return "Unknown object"
+
+
+
+
+
+
+
diff --git a/compass_model/icons/.DS_Store b/compass_model/icons/.DS_Store
new file mode 100644
index 0000000..cb8f174
Binary files /dev/null and b/compass_model/icons/.DS_Store differ
diff --git a/compass_model/icons/array_16.png b/compass_model/icons/array_16.png
new file mode 100644
index 0000000..799779c
Binary files /dev/null and b/compass_model/icons/array_16.png differ
diff --git a/compass_model/icons/array_64.png b/compass_model/icons/array_64.png
new file mode 100644
index 0000000..a715d55
Binary files /dev/null and b/compass_model/icons/array_64.png differ
diff --git a/compass_model/icons/folder_16.png b/compass_model/icons/folder_16.png
new file mode 100644
index 0000000..96588ea
Binary files /dev/null and b/compass_model/icons/folder_16.png differ
diff --git a/compass_model/icons/folder_64.png b/compass_model/icons/folder_64.png
new file mode 100644
index 0000000..9b75a46
Binary files /dev/null and b/compass_model/icons/folder_64.png differ
diff --git a/compass_model/icons/image_16.png b/compass_model/icons/image_16.png
new file mode 100644
index 0000000..54a3b42
Binary files /dev/null and b/compass_model/icons/image_16.png differ
diff --git a/compass_model/icons/image_64.png b/compass_model/icons/image_64.png
new file mode 100644
index 0000000..c3e5c4f
Binary files /dev/null and b/compass_model/icons/image_64.png differ
diff --git a/compass_model/icons/kv_16.png b/compass_model/icons/kv_16.png
new file mode 100644
index 0000000..65f4135
Binary files /dev/null and b/compass_model/icons/kv_16.png differ
diff --git a/compass_model/icons/kv_64.png b/compass_model/icons/kv_64.png
new file mode 100644
index 0000000..ed4d088
Binary files /dev/null and b/compass_model/icons/kv_64.png differ
diff --git a/compass_model/icons/license.txt b/compass_model/icons/license.txt
new file mode 100644
index 0000000..02bbb60
--- /dev/null
+++ b/compass_model/icons/license.txt
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff --git a/compass_model/icons/readme.txt b/compass_model/icons/readme.txt
new file mode 100644
index 0000000..c174550
--- /dev/null
+++ b/compass_model/icons/readme.txt
@@ -0,0 +1,5 @@
+This folder contains icons from the KDE Oxygen project, used as the default
+icons for various Node classes.  They are packaged up into a .py file by
+the "package_icons.py" script which comes with HDFCompass.
+
+Refer to "license.txt" for the icon licensing terms.
\ No newline at end of file
diff --git a/compass_model/icons/unknown_16.png b/compass_model/icons/unknown_16.png
new file mode 100644
index 0000000..53e61b0
Binary files /dev/null and b/compass_model/icons/unknown_16.png differ
diff --git a/compass_model/icons/unknown_64.png b/compass_model/icons/unknown_64.png
new file mode 100644
index 0000000..f869252
Binary files /dev/null and b/compass_model/icons/unknown_64.png differ
diff --git a/compass_model/images.py b/compass_model/images.py
new file mode 100644
index 0000000..e86bbeb
--- /dev/null
+++ b/compass_model/images.py
@@ -0,0 +1,541 @@
+import base64
+
+def array_16():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC50lEQVR42nVTS0iiURQ+1//3kY4"
+"pWpCMZZFJrwmip+GmRW0KpDZC0KoBaRVE0MYiaFZBi1a2mEWbgiEohGjTLgSjoKLpxWSR5WDRKO"
+"P4yGfOOf/MLzUwBy7Kvf/9XudcBv+Uw+HQtLe3W2tray0VFRV62nt8fAzf3Nx8Ozw89K2urkZff"
+"8/EPy6X64Pdbp+zWCyDJSUlMolEAoz9OX55eRHW8/Nzxu/3b21vb8/Nzs5+LQK43W77wMDAF6VS"
+"KZdKpcDzfPFyoVAoguTzecjlcpBMJtM7OzuOsbExD2tra2MI8F2n0xk4jnvD+LpIES0qAopEIqG"
+"pqan3rK+vTzIzM5NRq9WceInYxSUWKREX7cfj8fzi4qKM1dfXyycmJmI1NTVStPDm0v8KLQCGml"
+"1eXlaz3t5erqenJ9XY2MijCkArAogoVyxSR+woHWKxGJyfn+ewKwrKQDo6OprATWk4HIahoSEwG"
+"o0QCoVApVIJlxOJBBgMBggGg7C5uQl6vR6QLLu+vq5iXV1d0v7+/iRa4e/v74FsNDc3w+3tLZjN"
+"ZgEAWwfV1dVwenoqyK+srITLy8vc7u6ukmHf5U6nM47t4UkezgLI5XIIBAIgdoVSN5lMkE6nweP"
+"xCDax1bmVlZV3TKvVlk5OTkaqqqq4q6sr4UObzQb7+/uCFSqS3tnZCV6vVwCuq6uDu7u7/NLSko"
+"7h4Gjm5+d/ICufSqUALQH9UlBkR0ydAsYJhb29PVAoFKQmh9NYRgBl09PTAWRWXlxcgNVqhZaWF"
+"jg4OBCCo6JAOzo64OTkBHw+HzQ0NJCS5MLCggk7xjhkdY+MjHzMZrOMgiOGp6cn0Gg0AkA0GoXy"
+"8nJBGQWKpIW1tbXPaHNcmBoMRNXa2upC5PHh4eHSpqYmdnR0BPgaBYCHhwfAczg7OytsbGz8QqX"
+"u4+PjT0iYKI4dScEcjGhlsLu72yaTycz4pLV0dn19/TOTyfjRvxelb6H/YOHvK/sNnUhb2UtdBS"
+"IAAAAASUVORK5CYII=")
+
+def array_64():
+    return base64.b64decode(
+"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")
+
+def folder_16():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABNElEQVR42mNkoBAwgoiaRc82sTH"
+"99wWx//9nfPPq0yePqdkaZ4k2IG/hvf0sTP8dYIL/IQbh1fjnH8POKQlKHow1Cx+WfPr7J/Mfwz"
+"8lUpzOxMB0j5+FZTqjetrtR4zMDGJAt7CT5Pn/DD///2V4xSiT/fTaP0ag7Yz/STSA8SfTf6Z7j"
+"NJFb0/9+v9Xj4HxH4kGMP1kY2S+xKhZ93Hfjz+/rYAipBnAwPiTg4X1GKNF55dNX3/9dgcawEai"
+"Ab+42Fh3MrpP/b7s0/dfwcB4I80ARsZfvJxsaxnDF/6a9f7Lr4T///+xkqaf6bcAN9sCxrQ1f/t"
+"ef/iZ+///fxbSDGD8I8zHPpnRqfxI4yc2jVoGaKokAfzn+X2nGWgQkwTQ+YZAAWYSDfjLyMR8nl"
+"RbMb1CqQEACmp1y80wWngAAAAASUVORK5CYII=")
+
+def folder_64():
+    return base64.b64decode(
+"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")
+
+def image_16():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACeElEQVR42q3TX0hTURwH8O9tf5o"
+"6N116lVU6ZEjgIJdGoEEE0h+pIMggwh6kMpcQERiCECVCz2YvEZYUEVmWzYjASp1FFpKENjEsrR"
+"m1Tduuu3PunHtv517N3nqxC4fzcPh++J3z+10Oq/y4VQM2m01/2uOp0en1f0Xu3656KssybnZ03"
+"OesVmuqt/Wq+PpBK35NFYI35MNaMQxXRi7e2qoxa+FBqARKZEiUsrCC+e+TqK5041RNlVsDrrc1"
+"i0/vXkF8yAFXmguf903hxG4zJqd2YSilCIRQtmSGEEiSArNBxo58gpYLZ4s1oL39jnirvg2mqBF"
+"lvAuuHCfmauPwG0sQXDCysFqBpEGUVVOcq8MmnkNjQ+0S4PWNiV11LZjzvwfJtaPRuR8jVQUImb"
+"NAkgRZayneTKthCuMaBUWWBLa5HTh+7OAyMOgXB/1hvOtsht1RirzSMkSlDJSn/8B8TMCXYAJjI"
+"Q6cIQXJWASHyx1wZutwtNazBDxmQN/oDGK9TUipuAwKPXs4oMQcRmB8BGbegeFAHFscPMa+hrHT"
+"mQo+TcLJ802bVwDfRARC6BtMmRtAJRnsykjVKXBK0whwOVhPZ/BBzERsLoysdD2KsxORMw3nCjX"
+"gkY8BnwRIrLeSFlbYDhSYCUZ/Uiiygq3r4ggKi9iYbweJzYrtrZcODPS/fKEBD1VgIqoBlIW1RR"
+"XkmeIYDzFwcRF77FEkhSC2V+5N1HvqDnl7ep5oQ6UCXQMflwFFK589trar1ai91ykEpYZpENCF7"
+"u57R1i4e2UqrRaL6dqN232RBcqpQ6ooSwd/dlmWtFYKQjT5zNt58VX/897/+zOtFvgNaG5CIp4s"
+"FioAAAAASUVORK5CYII=")
+
+def image_64():
+    return base64.b64decode(
+"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"
+"AAAABJRU5ErkJggg==")
+
+def kv_16():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADTklEQVR42nVTbUhTURg+d9t1qTM"
+"/mk6707lqdtfSlSXEolWzrxEVU0FK8GM/+jFSJwUly38OWTBYOiP6kSWYIGkQlKItLUkSy/zAbT"
+"rNXdaymV+lY2x37nbu8MeMeuHlnPue8z73fZ/3OQj4y1AURUiSpBAEYZaXq7UIAsDTp09Mm9BQN"
+"AqeBajI+0jkR3p6xj69Xm80GAxGq3Vq3GIZ+EzH8/NPHcFxsbS2tvZmXV3dTYJwzv4TIDmZd9xu"
+"t/cTBLEAq/Dl5GSL6PjExKQDVhYtEAjScBw//fOn58M2gIwMwV4Wi7mDJIMxPT29fZmZgni4By7"
+"Xt63K+LA1FnA6iV9K5bmzTCbTR1HA53TOz9EATLP54cvCwsIzS0vL6xi2e9fIyCiwWN4Dr3c9DB"
+"AbGwfbkIO8vFzgdruXuVxuXGdn55uqKs1lGoAhEAgLHj1qMUul2bypKRtMfuf3eIjbdru1FXIHx"
+"GJJaVpapgFywZZIxGB8fNJz/XrFDYKY70Jo1oPBYNyLF6+/SKXSPd3dvWBuzqo1Gu/dj+SnpuZW"
+"tUh00ARbgAATX1Uq5WGYu45cuVJ0p6ysogLHD+wLhTYZQ0NDoL+/J6m9/dlqJIBKpUpUKlUrMpk"
+"MMBjMkN1um21tbWlB5PLz9fn5F9UiEc5LSOAw/P412EJ3ktnctA1ArVYnXrpUtMJmJ4C1NW/I4b"
+"B5LJZXj2kOdkDn6fUP3u3fLxaIxenAZpvQFhUVbGuho+N5tURyyGS1usDMjI3Q6TQnYdgTHmNWF"
+"n5Cq61rFwr3Ynx+CmQ9yu90zt4eHv7YGgySQCY7XioUZhm8Xj/b5VoE8/Nz7sZG/dXpadsgDcCC"
+"yT1yueIkRQX8GIbFpqbuAhxODNjY2Aj/ncPhwL0XLCwswzF+9yIIyh4cfDtgMtUrwxUkJiblQnF"
+"wITloR0fXMz6fv5PNRkF0NBtQtGJ8fhAIhIX1u7i44BocLQkJX1pdXRndJmUM4+f29Q189Hjcvy"
+"hqMwDHmkrHx8bGfyAII4rHw+IvXFAcc7lco/95CylSne5uU3Oz2eRwzHyyQDnCVwkUCoVcJBId1"
+"Wgqaxoa6isXFxfH/gmwZfRUSFqhJSUlejrQ1tamg0sIehR0X+TlP63+Zv7Pji/oAAAAAElFTkSu"
+"QmCC")
+
+def kv_64():
+    return base64.b64decode(
+"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"
+"W/yUvjAAAAAElFTkSuQmCC")
+
+def unknown_16():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADS0lEQVR42l2TbUxbVRjH/13p7ct"
+"db1uUtwWMFgIFSWYkBBQDzYBqMlgjGj4wwwiYaUw1gIqWGLMPBj4QItFgyIKgBowBwza2ZENjQA"
+"KrxBQIGxiSOqcJW0E2WN9u7+3L9bkNMPAk/3tyT875Pc95zvNX4H9DQUOj0aRYrdaqgoKCQrVar"
+"fF6vffn5uZ+9Xg8y/F4XDyy//CPSqXSOxyOj1tbW9/R6XTGSCQCSZKgVCrBMIw0Pz//m9Pp/HBt"
+"be0mgaQjAJZlnxgZGZkoKysr53ke614ed7ZCiMbiOK5WotjMwcCqZRjf3Nx8fmpqalSGKPbSVg0"
+"MDPxgt9vrvDtBTNwOQ1LpYGQk6FTAA7+Iew8CKMlKgjXfJGfDV1VVVa+urs4nABS1dnJy8sr2jk"
+"/xhSsMDZeMp3QCHJWZOKZQwBcS0XPNgz83Q6jOVsJ2MhVLS0suCmiVAcqhoaFLNputdmzZj5sPD"
+"ZDoekkxHmmaCE6wCnxkz8M303/hW9e/iAQf4eK5bGSkmKRSGjKAXV9fv0OVT31rMoBtGBERRQiC"
+"iDAvoOl5DT6156Dhy98x6wkiKoZx4eVk1L34NDo7OztkQPLu7u4WSXlq2AcFa6JNYkJZWgEz7xd"
+"imKJ/8ONdxKKxxHrrSyzazljQ39//uQwwbG5u3qfKa0+P+BBmHgOanmPw2atmPNM+je0QDtY7Kz"
+"m8/Uouent7u2UAMzMz4zabzYXOn/xwPdQjJkZAH7AxP3K4KBY2YggLUQh0pQgfxFVHLorz0tHY2"
+"Hg28Qrt7e1dHR0dTvddH979md6dVYFjonivRI/Xi9Jx/rtbWPg7iA1vAEVPxjD4ZoF8bNdiseQl"
+"ABzHZbrd7kVq25SJFT++viXBoE/CSS6MmmdN6PllA1tBAosBfHU2G5mpBnR3d3f19fV9ctCJFRU"
+"Vr42NjX0vCAKzshHC6GIAi/8E4A/yyDQysOXq8MYLaTDqdXC5XLP19fU11Or+w15Ql5eXNwwODv"
+"ZSRiaRikWtum+whB+0Wq00Pj5+va2trYWK7j3shWMkEylVr9dbWlpa6qnLSvPz8zPoWip6pUdkp"
+"D8Ifpmi36B990g7pPgRN+4Bk2RjkrR7kuECKbg3R0nS/oH/AJhpcrTdb2V5AAAAAElFTkSuQmCC")
+
+def unknown_64():
+    return base64.b64decode(
+"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"
+"/5AAAAABJRU5ErkJggg==")
+
diff --git a/compass_model/test.py b/compass_model/test.py
new file mode 100644
index 0000000..8b8b744
--- /dev/null
+++ b/compass_model/test.py
@@ -0,0 +1,231 @@
+
+"""
+Provides support for testing basic properties of data model implementations.
+
+Checks to make sure all required properties and methods are implemented, and
+does basic sanity/consistency checking.  More specific tests must be written
+by plugin authors.
+
+The public interface consists of the following functions, each of which
+provides a TestCase sublass which may be used with unittest:
+
+- store
+- container
+- array
+- keyvalue
+- image
+
+Example, in my_model.test:
+
+    from compass_model.test import store, container
+    from my_model import MyStore, MyContainer
+
+    URL = "file:///path/to/myfile.ext"
+
+    store_tests = store(MyStore, URL)
+    container_tests = container(MyStore, URL, MyContainer, "some-key")
+
+To run unittest, which discovers classes "store_tests" and "container_tests":
+
+    $ python -m unittest my_model.test
+
+"""
+
+from . import Node, Store
+import unittest as ut
+
+
+# --- Public API --------------------------------------------------------------
+
+def store(storecls_, url_):
+    """ Construct a TestCase appropriate for a Store subclass.
+
+    storecls:   Your compass_model.Store implementation.
+    url:        A URL representing a valid datastore to test against.
+    """
+    class TestStore(_TestStore):
+        storecls = storecls_
+        url = url_
+    return TestStore
+
+
+def container(storecls_, url_, nodecls_, key_):
+    """ Construct a TestCase class appropriate for a Container subclass.
+
+    storecls:   Your compass_model.Store implementation.
+    url:        A URL representing a valid datastore to test against.
+    nodecls:    Your compass_model.Container implementation.
+    key:        A valid key which points to a container.
+    """
+    class TestContainer(_TestContainer):
+        storecls = storecls_
+        url = url_
+        nodecls = nodecls_
+        key = key_
+    return TestContainer
+
+# --- End public API ----------------------------------------------------------
+
+
+class _TestStore(ut.TestCase):
+
+    """
+    Base class for testing Stores.
+    """
+
+    storecls = None
+    url = None
+
+
+    def setUp(self):
+        self.store = self.storecls(self.url)
+
+
+    def tearDown(self):
+        if self.store.valid:
+            self.store.close()
+
+
+    def test_class(self):
+        """ Verify the thing we get from storecls is actually a Store """
+        self.assertIsInstance(self.store, Store)
+
+
+    def test_url(self):
+        """ Verify store.url produces a string """
+        self.assertIsInstance(self.store.url, basestring)
+
+
+    def test_displayname(self):
+        """ Verify store.displayname produces a string. """
+        self.assertIsInstance(self.store.displayname, basestring)
+
+
+    def test_root(self):
+        """ Verify store.root exists and has no parent """
+        self.assertIsInstance(self.store.root, Node)
+        self.assertIs(self.store.getparent(self.store.root.key), None)
+
+
+    def test_close_valid(self):
+        """ Verify that store.close() works and is reflected by store.valid """
+        self.assertTrue(self.store.valid)
+        self.store.close()
+        self.assertFalse(self.store.valid)
+
+
+    def test_canhandle(self):
+        """ Verify canhandle() works properly """
+        self.assertTrue(self.storecls.canhandle(self.url))
+        self.assertFalse(self.storecls.canhandle("file:///no/such/path"))
+
+
+    def test_handlers(self):
+        """ The implementation has at least one Node handler registered """
+        h = self.store.gethandlers()
+        # Test for N > 1 because compass_model.Unknown is always present
+        self.assertGreater(len(h), 1) 
+
+
+class _TestNode(ut.TestCase):
+
+    """
+    Base class for testing Node objects.
+    """
+
+    storecls = None
+    nodecls = None
+    url = None
+    key = None
+
+
+    def setUp(self):
+        self.store = self.storecls(self.url)
+        self.node = self.nodecls(self.store, self.key)
+
+
+    def tearDown(self):
+        if self.store.valid:
+            self.store.close()
+
+
+    def test_contains(self):
+        """ Consistency check for store __contains___ """
+        self.assertTrue(self.key in self.store)
+        self.assertFalse("keynotinstore" in self.store)
+
+
+    def test_icons(self):
+        """ Icon dict is present and contains valid items:
+
+        keys: int
+        values: callables returning PNG data
+
+        Required sizes: 16x16 and 64x64
+        """
+        for key, val in self.nodecls.icons.iteritems():
+            self.assertIsInstance(key, int)
+            data = val()
+            self.assertIsInstance(data, bytes)
+            self.assertEqual(data[0:8], b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
+        
+        # required resolutions
+        self.assertIn(16, self.nodecls.icons)
+        self.assertIn(64, self.nodecls.icons)
+
+
+    def test_classkind(self):
+        """ classkind is present, and a string """
+        self.assertIsInstance(self.nodecls.classkind, basestring)
+
+
+    def test_canhandle(self):
+        """ canhandle() consistency check """
+        self.assertTrue(self.nodecls.canhandle(self.store, self.key))
+        self.assertFalse(self.nodecls.canhandle(self.store, "/some/random/key"))
+
+
+    def test_key(self):
+        """ Node.key returns a hashable object.
+
+        We also require that the key be unchanged.
+        """
+        out = self.node.key
+        hash(out)
+        self.assertEqual(self.node.key, self.key)
+
+
+    def test_store(self):
+        """ Node.store returns a data store of the same class and URL. """
+        self.assertIsInstance(self.node.store, self.storecls)
+        self.assertEqual(self.node.store.url, self.store.url)
+
+
+    def test_displayname(self):
+        """ displayname exists and is a string """
+        self.assertIsInstance(self.node.displayname, basestring)
+
+
+class _TestContainer(_TestNode):
+
+    """
+    Class for testing compass_model.Container implementations.
+    """
+
+    def test_len(self):
+        """ Object length is consistent with iter() result """
+        self.assertGreaterEqual(len(self.node), 0)
+        self.assertEqual(len(self.node), len(list(self.node)))
+
+
+    def test_getitem(self):
+        """ __getitem__ works properly """
+        for idx in xrange(len(self.node)):
+            out = self.node[idx]
+            self.assertIsInstance(out, Node)
+
+
+    def test_getitem_exception(self):
+        """ out-of range indices raise IndexError """
+        with self.assertRaises(IndexError):
+            self.node[len(self.node)]
diff --git a/compass_viewer/.DS_Store b/compass_viewer/.DS_Store
new file mode 100644
index 0000000..2483741
Binary files /dev/null and b/compass_viewer/.DS_Store differ
diff --git a/compass_viewer/__init__.py b/compass_viewer/__init__.py
new file mode 100644
index 0000000..b13bd55
--- /dev/null
+++ b/compass_viewer/__init__.py
@@ -0,0 +1,176 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Main module for HDFCompass.
+
+Defines the App class, along with supporting infrastructure.
+"""
+
+# Must be at the top, to ensure we're the first to call matplotlib.use.
+import matplotlib
+matplotlib.use('WXAgg')
+
+import wx
+
+import compass_model
+
+from .imagesupport import png_to_bitmap
+from . import platform
+from .events import ID_COMPASS_OPEN
+from . import container, array, keyvalue, image, frame
+
+__version__ = platform.VERSION
+
+
+class CompassImageList(wx.ImageList):
+
+    """
+    A specialized type of image list, to support icons from Node subclasses.
+
+    Instances of this class hold only square icons, of the size specified
+    when created.  The appropriate icon index for a particular Node subclass is
+    retrieved using get_index(nodeclass).
+
+    Image addition and indexing is completely bootstrapped; there's no need
+    to manually add or register Node classes with this class.  Just call
+    get_index and the object will figure it out.
+    """
+
+    def __init__(self, size):
+        """ Create a new list holding square icons of the given size. """
+        wx.ImageList.__init__(self, size, size)
+        self._indices = {}
+        self._size = size
+
+
+    def get_index(self, nodeclass):
+        """ Retrieve an index appropriate for the given Node subclass. """
+
+        if nodeclass not in self._indices:
+            png = nodeclass.icons[self._size]()
+            idx = self.Add(png_to_bitmap(png))
+            self._indices[nodeclass] = idx
+
+        return self._indices[nodeclass]
+
+
+class CompassApp(wx.App):
+
+    """
+    The main application object for HDFCompass.
+
+    This mainly handles ID_COMPASS_OPEN events, which are requests to launch
+    a new window viewing a particular node.  Also contains a dict of
+    CompassImageLists, indexed by image width.
+    """
+
+    def __init__(self, redirect):
+        """ Constructor.  If *redirect*, show a windows with console output.
+        """
+        wx.App.__init__(self, redirect)
+
+        self.imagelists = {}
+        for size in (16, 24, 32, 48, 64):
+            self.imagelists[size] = CompassImageList(size)
+
+        self.Bind(wx.EVT_MENU, self.on_compass_open, id=ID_COMPASS_OPEN)
+
+        self.SetAppName("HDFCompass")
+
+
+    def on_compass_open(self, evt):
+        """ A request has been made to open a node from somewhere in the GUI
+        """
+        open_node(evt.node, evt.kwds.get('pos'))
+
+
+    def MacOpenFile(self, filename):
+        """ A file has been dropped onto the app icon """
+        url = 'file://'+filename
+        open_store(url)
+
+
+def open_node(node, pos=None):
+    """ Open a viewer frame appropriate for the given Node instance.
+    
+    node:   Node instance to open
+    pos:    2-tuple with current window position (used to avoid overlap).
+    """
+    
+    if pos is not None:
+        # The thing we get from GetPosition isn't really a tuple, so
+        # you have to manually cast entries to int or it silently fails.
+        newpos =(int(pos[0])+80, int(pos[1])+80)
+    else:
+        newpos = None
+
+    print "Top-level open called for ", node
+
+    if isinstance(node, compass_model.Container):
+        f = container.ContainerFrame(node, pos=newpos)
+        f.Show()
+    elif isinstance(node, compass_model.Array):
+        f = array.ArrayFrame(node, pos=newpos)
+        f.Show()
+    elif isinstance(node, compass_model.KeyValue):
+        f = keyvalue.KeyValueFrame(node, pos=newpos)
+        f.Show()
+    elif isinstance(node, compass_model.Image):
+        f = image.ImageFrame(node, pos=pos)
+        f.Show()
+    else:
+        pass
+
+        
+def open_store(url):
+    """ Open the url using the first matching registered Store class.
+
+    Returns True if the url was successfully opened, False otherwise.
+    """
+    stores = [x for x in compass_model.getstores() if x.canhandle(url)]
+
+    if len(stores) > 0:
+        instance = stores[0](url)
+        open_node(instance.root)
+        return True
+
+    return False
+
+
+def run():
+    """ Run HDFCompass.  Handles all command-line arguments, etc.
+    """
+
+    # These are imported to register their classes with
+    # compass_model.  We don't use them directly.
+    import filesystem_model
+    import array_model
+    import hdf5_model
+
+    import sys
+    import os.path as op
+
+    app = CompassApp(False)
+
+    urls = sys.argv[1:]
+
+    for url in sys.argv[1:]:
+        if "://" not in url:
+            # assumed to be file path
+            url = 'file://'+op.abspath(url)
+        if not open_store(url):
+            print 'Failed to open "%s"; no handlers'%url
+
+    f = frame.InitFrame()
+    
+    if platform.MAC:
+        wx.MenuBar.MacSetCommonMenuBar(f.GetMenuBar())
+    else:
+        f.Show()
+        
+    app.MainLoop()
\ No newline at end of file
diff --git a/compass_viewer/array/.DS_Store b/compass_viewer/array/.DS_Store
new file mode 100644
index 0000000..9d80d31
Binary files /dev/null and b/compass_viewer/array/.DS_Store differ
diff --git a/compass_viewer/array/__init__.py b/compass_viewer/array/__init__.py
new file mode 100644
index 0000000..e62731f
--- /dev/null
+++ b/compass_viewer/array/__init__.py
@@ -0,0 +1,358 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Implements a viewer frame for compass_model.Array.
+"""
+
+import wx
+import wx.grid
+from wx.lib.newevent import NewCommandEvent
+
+from .. import imagesupport
+
+from ..frame import NodeFrame
+from .plot import LinePlotFrame, ContourPlotFrame
+
+# Indicates that the slicing selection may have changed.
+# These events are emitted by the SlicerPanel.
+ArraySlicedEvent, EVT_ARRAY_SLICED = NewCommandEvent()
+
+# Menu and button IDs
+ID_VIS_MENU_PLOT = wx.NewId()
+
+
+class ArrayFrame(NodeFrame):
+
+    """
+    Top-level frame displaying objects of type compass_model.Array.
+
+    From top to bottom, has:
+
+    1. Toolbar (see ArrayFrame.init_toolbar)
+    2. SlicerPanel, with controls for changing what's displayed.
+    3. An ArrayGrid, which displays the data in a spreadsheet-like view.
+    """
+
+    def __init__(self, node, **kwds):
+        """ Create a new array viewer, to display *node*. """
+        NodeFrame.__init__(self, node, title=node.displayname, **kwds)
+
+        self.node = node
+
+        # The Slicer is the panel with indexing controls
+        self.slicer = SlicerPanel(self, node.shape, node.dtype.fields is not None)
+        self.grid = ArrayGrid(self, node, self.slicer)
+
+        vis_menu = wx.Menu()
+        vis_menu.Append(ID_VIS_MENU_PLOT, "Plot Data\tCtrl-D")
+        self.add_menu(vis_menu, "Visualize")
+
+        self.init_toolbar()
+
+        gridsizer = wx.BoxSizer(wx.VERTICAL)
+        gridsizer.Add(self.slicer, 0, wx.EXPAND)
+        gridsizer.Add(self.grid, 1, wx.EXPAND)
+
+        self.view = gridsizer
+
+        self.Bind(EVT_ARRAY_SLICED, self.on_sliced)
+        self.Bind(wx.EVT_MENU, self.on_plot, id=ID_VIS_MENU_PLOT)
+
+        # Workaround for wxPython bug (see SlicerPanel.enable_spinctrls)
+        ID_WORKAROUND_TIMER = wx.NewId()
+        self.Bind(wx.EVT_TIMER, self.on_workaround_timer, id=ID_WORKAROUND_TIMER)
+        self.timer = wx.Timer(self, ID_WORKAROUND_TIMER)
+        self.timer.Start(100)
+
+
+    def on_workaround_timer(self, evt):
+        """ See slicer.enable_spinctrls docs """
+        self.timer.Destroy()
+        self.slicer.enable_spinctrls()
+
+
+    def init_toolbar(self):
+        """ Set up the toolbar at the top of the window. """
+        tsize = (24,24)
+        plot_bmp = imagesupport.getbitmap('viz_plot_24')
+
+        self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.NO_BORDER|wx.TB_FLAT|wx.TB_TEXT)
+
+        self.toolbar.SetToolBitmapSize(tsize)
+        self.toolbar.AddStretchableSpace()
+        self.toolbar.AddLabelTool(ID_VIS_MENU_PLOT, "Plot Data", plot_bmp, shortHelp="Plot data in a popup window", longHelp="Long help for 'New'")
+        self.toolbar.Realize()
+
+
+    def on_sliced(self, evt):
+        """ User has chosen to display a different part of the dataset. """
+        self.grid.Refresh()
+
+
+    def on_plot(self, evt):
+        """ User has chosen to plot the current selection """
+        cols = self.grid.GetSelectedCols()
+        rows = self.grid.GetSelectedRows()
+
+        # Scalar data can't be line-plotted.
+        if len(self.node.shape) == 0:
+            return
+
+        # Columns in the view are selected
+        if len(cols) != 0:
+
+            # The data is compound
+            if self.node.dtype.names is not None:
+                names = [self.grid.GetColLabelValue(x) for x in cols]
+                data = self.node[self.slicer.indices]  # -> 1D compound array
+                data = [data[n] for n in names]
+                f = LinePlotFrame(data, names)
+                f.Show()
+
+            # Plot multiple columns independently
+            else:
+                if len(self.node.shape) == 1:
+                    data = [self.node[self.slicer.indices]]
+                else:
+                    data = [self.node[self.slicer.indices+(c,)] for c in cols]
+
+                names = ["Col %d"%c for c in cols] if len(data) > 1 else None
+
+                f = LinePlotFrame(data, names)
+                f.Show()
+
+
+        # Rows in view are selected
+        elif len(rows) != 0:
+        
+            data = [self.node[self.slicer.indices+(slice(None,None,None),r)] for r in rows]
+            names = ["Row %d"%r for r in rows] if len(data) > 1 else None
+
+            f = LinePlotFrame(data, names)
+            f.Show()
+
+
+        # No row or column selection.  Plot everything
+        else:
+
+            data = self.node[self.slicer.indices]
+
+            # The data is compound
+            if self.node.dtype.names is not None:
+                names = [self.grid.GetColLabelValue(x) for x in xrange(self.grid.GetNumberCols())]
+                data = [data[n] for n in names]
+                f = LinePlotFrame(data, names)
+                f.Show()
+
+            # Plot 1D
+            elif len(self.node.shape) == 1:
+                f = LinePlotFrame([data])
+                f.Show()
+
+            # Plot 2D
+            else:
+                f = ContourPlotFrame(data)
+                f.Show()
+
+
+class SlicerPanel(wx.Panel):
+
+    """
+    Holds controls for data access.
+
+    Consult the "indices" property, which returns a tuple of indices that
+    prefix the array.  This will be RANK-2 elements long, unless hasfields
+    is true, in which case it will be RANK-1 elements long.
+    """
+
+    @property
+    def indices(self):
+        """ A tuple of integer indices appropriate for slicing.
+
+        Will be RANK-2 elements long, RANK-1 if compound data is in use
+        (hasfields == True).
+        """
+        return tuple([x.GetValue() for x in self.spincontrols])
+
+
+    def __init__(self, parent, shape, hasfields):
+        """ Create a new slicer panel.
+
+        parent:     The wxPython parent window
+        shape:      Shape of the data to visualize
+        hasfields:  If True, the data is compound and the grid can only
+                    display one axis.  So, we should display an extra spinbox.
+        """
+        wx.Panel.__init__(self, parent)
+
+        self.shape = shape
+        self.hasfields = hasfields
+        self.spincontrols = []
+
+        # Rank of the underlying array
+        rank = len(shape)
+
+        # Rank displayable in the grid.  If fields are present, they occupy
+        # the columns, so the data displayed is actually 1-D.
+        visible_rank = 1 if hasfields else 2
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)  # Will arrange the SpinCtrls
+
+        if rank > visible_rank:
+            infotext = wx.StaticText(self, wx.ID_ANY, "Array Indexing: ")
+            sizer.Add(infotext, 0, flag=wx.EXPAND|wx.ALL, border=10)
+
+            for idx in xrange(rank-visible_rank):
+                sc = wx.SpinCtrl(self, max=shape[idx]-1, value="0", min=0)
+                sizer.Add(sc, 0, flag=wx.EXPAND|wx.ALL, border=10)
+                sc.Disable()
+                self.spincontrols.append(sc)
+
+        self.SetSizer(sizer)
+
+        self.Bind(wx.EVT_SPINCTRL, self.on_spin)
+
+
+    def enable_spinctrls(self):
+        """ Unlock the spin controls.
+
+        Because of a bug in wxPython on Mac, by default the first spin control
+        has bizarre contents (and control focus) when the panel starts up.
+        Call this after a short delay (e.g. 100 ms) to enable indexing.
+        """
+        for sc in self.spincontrols:
+            sc.Enable()
+
+
+    def on_spin(self, evt):
+        """ Spinbox value changed; notify parent to refresh the grid. """
+        wx.PostEvent(self, ArraySlicedEvent(self.GetId()))
+
+
+
+class ArrayGrid(wx.grid.Grid):
+
+    """
+    Grid class to display the Array.
+    
+    Cell contents and appearance are handled by the table model in ArrayTable.
+    """
+
+    def __init__(self, parent, node, slicer):
+        wx.grid.Grid.__init__(self, parent)
+        table = ArrayTable(node, slicer)
+        self.SetTable(table, True)
+
+        # Column selection is always allowed
+        selmode = wx.grid.Grid.wxGridSelectColumns
+
+        # Row selection is forbidden for compound types, and for
+        # scalar/1-D datasets
+        if node.dtype.names is None and len(node.shape) > 1:
+            selmode |= wx.grid.Grid.wxGridSelectRows
+
+        self.SetSelectionMode(selmode)
+
+
+
+class ArrayTable(wx.grid.PyGridTableBase):
+
+    """
+    "Table" class which provides data and metadata for the grid to display.
+
+    The methods defined here define the contents of the table, as well as
+    the number of rows, columns and their values.
+    """
+
+    def __init__(self, node, slicer):
+        """ Create a new Table instance for use with a grid control.
+
+        node:     An compass_model.Array implementation instance.
+        slicer:   An instance of SlicerPanel, so we can see what indices the
+                  user has requested.
+        """
+        wx.grid.PyGridTableBase.__init__(self)
+
+        self.node = node
+        self.slicer = slicer
+
+        self.rank = len(node.shape)
+        self.names = node.dtype.names
+
+
+    def GetNumberRows(self):
+        """ Callback for number of rows displayed by the grid control """
+        if self.rank == 0:
+            return 1
+        return self.node.shape[-1]
+
+
+    def GetNumberCols(self):
+        """ Callback for number of columns displayed by the grid control.
+
+        Note that if compound data is in use, columns display the field names.
+        """
+        if self.names is not None:
+            return len(self.names)
+        if self.rank < 2:
+            return 1
+        return self.node.shape[-2]
+
+
+    def GetValue(self, row, col):
+        """ Callback which provides data to the Grid.
+
+        row, col:   Integers giving row and column position (0-based).
+        """
+        # Scalar case
+        if self.rank == 0:  
+            data = self.node[()]
+            if self.names is None:
+                return data
+            return data[col]
+
+        # 1D case
+        if self.rank == 1:
+            data = self.node[row]
+            if self.names is None:
+                return data
+            return data[self.names[col]]
+
+        # ND case.  Watch out for compound mode!
+        if self.names is None:
+            args = self.slicer.indices + (col,row)
+        else:
+            args = self.slicer.indices + (row,)
+
+        data = self.node[args]
+        if self.names is None:
+            return data
+        return data[self.names[col]]
+
+
+    def GetRowLabelValue(self, row):
+        """ Callback for row labels.
+
+        Row number is used unless the data is scalar.
+        """
+        if self.rank == 0:
+            return "Value"
+        return str(row)
+
+
+    def GetColLabelValue(self, col):
+        """ Callback for column labels.
+
+        Column number is used, except for scalar or 1D data, or if we're
+        displaying field names in the columns.
+        """
+        if self.names is not None:
+            return self.names[col]
+        if self.rank == 0 or self.rank == 1:
+            return "Value"
+        return str(col)
diff --git a/compass_viewer/array/plot.py b/compass_viewer/array/plot.py
new file mode 100644
index 0000000..c1be7ab
--- /dev/null
+++ b/compass_viewer/array/plot.py
@@ -0,0 +1,83 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Matplotlib window with toolbar.
+"""
+
+import numpy as np
+import wx
+
+from matplotlib.figure import Figure
+from matplotlib.backends.backend_wxagg import \
+    FigureCanvasWxAgg as FigCanvas, \
+    NavigationToolbar2WxAgg as NavigationToolbar
+
+from ..frame import BaseFrame
+
+
+class PlotFrame(BaseFrame):
+
+    """
+    Base class for Matplotlib plot windows.
+
+    Override draw_figure() to plot your figure on the provided axes.
+    """
+
+    def __init__(self, data):
+        """ Create a new Matplotlib plotting window for a 1D line plot
+        """
+
+        BaseFrame.__init__(self, id=wx.ID_ANY, title="Line plot", size=(800,400))
+        
+        self.data = data
+
+        self.panel = wx.Panel(self)
+        
+        self.dpi = 100
+        self.fig = Figure((6.0, 4.0), dpi=self.dpi)
+        self.canvas = FigCanvas(self.panel, -1, self.fig)
+
+        self.axes = self.fig.add_subplot(111)
+        self.toolbar = NavigationToolbar(self.canvas)
+
+        self.vbox = wx.BoxSizer(wx.VERTICAL)
+        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
+        self.vbox.Add(self.toolbar, 0, wx.EXPAND)
+
+        self.panel.SetSizer(self.vbox)
+        self.vbox.Fit(self)
+
+        self.draw_figure()
+
+    def draw_figure(self):
+        raise NotImplementedError
+
+
+class LinePlotFrame(PlotFrame):
+
+    def __init__(self, data, names=None):
+        self.names = names
+        PlotFrame.__init__(self, data)
+
+
+    def draw_figure(self):
+
+        lines = [self.axes.plot(d)[0] for d in self.data]
+        if self.names is not None:
+            for n in self.names:
+                self.axes.legend(tuple(lines), tuple(self.names))
+        
+
+class ContourPlotFrame(PlotFrame):
+
+    def draw_figure(self):
+        import pylab
+        xx = np.arange(self.data.shape[0])
+        yy = np.arange(self.data.shape[1])
+        out = self.axes.contourf(xx, yy, self.data, 25)
+        pylab.colorbar(out)
diff --git a/compass_viewer/container/.DS_Store b/compass_viewer/container/.DS_Store
new file mode 100644
index 0000000..9d80d31
Binary files /dev/null and b/compass_viewer/container/.DS_Store differ
diff --git a/compass_viewer/container/__init__.py b/compass_viewer/container/__init__.py
new file mode 100644
index 0000000..4c55f3d
--- /dev/null
+++ b/compass_viewer/container/__init__.py
@@ -0,0 +1,193 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Implements a viewer for compass_model.Container instances.
+
+This frame is a simple browser view with back/forward/up controls.
+
+Currently list and icon views are supported.
+"""
+
+import wx
+import compass_model
+
+from .. import imagesupport
+from ..frame import NodeFrame
+from ..events import ID_COMPASS_OPEN, CompassOpenEvent
+from ..events import ContainerSelectionEvent, EVT_CONTAINER_SELECTION
+from .list import ContainerReportList, ContainerIconList
+
+ID_GO_MENU_BACK = wx.NewId()
+ID_GO_MENU_NEXT = wx.NewId()
+ID_GO_MENU_UP = wx.NewId()
+
+ID_VIEW_MENU_LIST = wx.NewId()
+ID_VIEW_MENU_ICON = wx.NewId()
+
+
+class ContainerFrame(NodeFrame):
+
+    """
+    A frame to display a Container class, and browse its contents.
+    """
+
+    def __init__(self, node, pos=None):
+        """ Create a new frame.
+
+        node:   Container instance to display.
+        pos:    Screen position at which to display the window.
+        """
+        NodeFrame.__init__(self, node, size=(800, 400), title=node.displaytitle, pos=pos)
+
+        view_menu = wx.Menu()
+        view_menu.Append(ID_VIEW_MENU_LIST, "List view")
+        view_menu.Append(ID_VIEW_MENU_ICON, "Icon view")
+        self.add_menu(view_menu, "View")
+        self.view_menu = view_menu
+
+        go_menu = wx.Menu()
+        go_menu.Append(ID_GO_MENU_BACK, "Back\tCtrl-[")
+        go_menu.Append(ID_GO_MENU_NEXT, "Next\tCtrl-]")
+        go_menu.Append(ID_GO_MENU_UP, "Up\tCtrl-Up")
+        self.add_menu(go_menu, "Go")
+        self.go_menu = go_menu
+
+        self.Bind(wx.EVT_MENU, self.on_open, id=ID_COMPASS_OPEN)
+        self.Bind(EVT_CONTAINER_SELECTION, lambda evt: self.update_info())
+
+        self.Bind(wx.EVT_MENU, lambda evt: self.go_back(), id=ID_GO_MENU_BACK)
+        self.Bind(wx.EVT_MENU, lambda evt: self.go_next(), id=ID_GO_MENU_NEXT)
+        self.Bind(wx.EVT_MENU, lambda evt: self.go_up(), id=ID_GO_MENU_UP)
+        self.Bind(wx.EVT_MENU, lambda evt: self.list_view(), id=ID_VIEW_MENU_LIST)
+        self.Bind(wx.EVT_MENU, lambda evt: self.icon_view(), id=ID_VIEW_MENU_ICON)
+
+        self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.NO_BORDER|wx.TB_FLAT|wx.TB_TEXT)
+
+        tsize = (24,24)
+        back_bmp =  imagesupport.getbitmap('go_back_24')
+        next_bmp = imagesupport.getbitmap('go_next_24')
+        up_bmp = imagesupport.getbitmap('go_up_24')
+        icon_bmp = imagesupport.getbitmap('view_icon_24')
+        list_bmp = imagesupport.getbitmap('view_list_24')
+
+        self.toolbar.SetToolBitmapSize(tsize)
+        self.toolbar.AddLabelTool(ID_GO_MENU_BACK, "Back", back_bmp, shortHelp="New", longHelp="Long help for 'New'")
+        self.toolbar.AddLabelTool(ID_GO_MENU_NEXT, "Next", next_bmp, shortHelp="New", longHelp="Long help for 'New'")
+        self.toolbar.AddSeparator()
+        self.toolbar.AddLabelTool(ID_GO_MENU_UP, "Up", up_bmp, shortHelp="New", longHelp="Long help for 'New'")
+        self.toolbar.AddStretchableSpace()
+        self.toolbar.AddLabelTool(ID_VIEW_MENU_LIST, "List View", list_bmp, shortHelp="New", longHelp="Long help for 'New'")
+        self.toolbar.AddLabelTool(ID_VIEW_MENU_ICON, "Icon View", icon_bmp, shortHelp="New", longHelp="Long help for 'New'")
+
+        self.toolbar.Realize()
+
+        self.view = ContainerReportList(self, node)
+
+        self.history = [node]
+        self.history_ptr = 0
+        self.update_view()
+
+
+    def list_view(self):
+        """ Switch to list view """
+        if not isinstance(self.view, ContainerReportList):
+            self.view = ContainerReportList(self, self.history[self.history_ptr])
+
+
+    def icon_view(self):
+        """ Switch to icon view """
+        if not isinstance(self.view, ContainerIconList):
+            self.view = ContainerIconList(self, self.history[self.history_ptr])
+
+
+    # --- Begin history support functions -------------------------------------
+
+    @property
+    def node(self):
+        return self.history[self.history_ptr]
+
+    def go_back(self):
+        """ Go to the previously displayed item """
+        if self.history_ptr > 0:
+            self.history_ptr -= 1
+        self.update_view()
+
+
+    def go_next(self):
+        """ Go to the next displayed item """
+        if self.history_ptr < (len(self.history)-1):
+            self.history_ptr += 1
+        self.update_view()
+
+
+    def go_up(self):
+        """ Go to the enclosing container """
+        node = self.history[self.history_ptr]
+        parent = node.store.getparent(node.key)
+        if parent.key != node.key:  # at the root item
+            self.go(parent)
+
+
+    def go(self, newnode):
+        """ Go to a particular node.
+
+        Adds the node to the history.
+        """
+        del self.history[self.history_ptr+1:]
+        self.history.append(newnode)
+        self.history_ptr += 1
+        self.update_view()
+
+    # --- End history support functions ---------------------------------------
+
+
+    def update_view(self):
+        """ Refresh the entire contents of the frame according to self.node.
+        """
+        self.SetTitle(self.node.displaytitle)
+        self.view = type(self.view)(self, self.node)
+        self.update_info()
+
+        can_go_back = self.history_ptr > 0
+        can_go_next = self.history_ptr < (len(self.history)-1)
+        can_go_up = self.node.store.getparent(self.node.key) is not None
+        self.go_menu.Enable(ID_GO_MENU_BACK, can_go_back)
+        self.go_menu.Enable(ID_GO_MENU_NEXT, can_go_next)
+        self.go_menu.Enable(ID_GO_MENU_UP, can_go_up)
+        self.toolbar.EnableTool(ID_GO_MENU_BACK, can_go_back)
+        self.toolbar.EnableTool(ID_GO_MENU_NEXT, can_go_next)
+        self.toolbar.EnableTool(ID_GO_MENU_UP, can_go_up)
+
+        icon_view_allowed = len(self.node) <= 1000
+        self.view_menu.Enable(ID_VIEW_MENU_ICON, icon_view_allowed)
+        self.toolbar.EnableTool(ID_VIEW_MENU_ICON, icon_view_allowed)
+
+
+    def update_info(self):
+        """ Refresh the left-hand side information panel, according to the
+        current selection in the view.
+        """
+        node = self.view.selection
+        if node is None:
+            node = self.node  # Nothing selected; show this node's info
+        self.info.display(node)
+
+
+    def on_open(self, evt):
+        """ Trap Container open events, so we can browse instead of launching
+        new windows.
+        """
+        newnode = evt.node
+        print "Got request to open node", newnode.key
+        if isinstance(newnode, compass_model.Container):
+            self.go(newnode)
+        else:
+            evt.Skip()
+
+
+        
\ No newline at end of file
diff --git a/compass_viewer/container/list.py b/compass_viewer/container/list.py
new file mode 100644
index 0000000..f3991e0
--- /dev/null
+++ b/compass_viewer/container/list.py
@@ -0,0 +1,232 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Handles list and icon view for Container display.
+"""
+
+import wx
+import compass_model
+
+from ..events import ID_COMPASS_OPEN, CompassOpenEvent
+from ..events import ContainerSelectionEvent, EVT_CONTAINER_SELECTION
+
+ID_CONTEXT_MENU_OPEN = wx.NewId()
+ID_CONTEXT_MENU_OPENWINDOW = wx.NewId()
+
+
+class ContainerList(wx.ListCtrl):
+
+    """
+    Base class for list and icons views, both of which use wx.ListCtrl.
+    
+    Defines the current selection (via .selection property) as well as
+    handling item activation (double-click, Enter) and right-click context
+    menu.
+    """
+
+    def __init__(self, parent, node, **kwds):
+        wx.ListCtrl.__init__(self, parent, **kwds)
+
+        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.on_rclick)
+        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_activate)
+        self.Bind(wx.EVT_MENU, self.on_context_open, id=ID_CONTEXT_MENU_OPEN)
+        self.Bind(wx.EVT_MENU, self.on_context_openwindow, id=ID_CONTEXT_MENU_OPENWINDOW)
+
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.hint_select)
+        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.hint_select)
+        self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.hint_select)
+        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.hint_select)
+
+    @property
+    def selection(self):
+        """ The currently selected item, or None. """
+        idx = self.GetFirstSelected()
+        if idx < 0:
+            return None
+        return self.node[idx]
+
+    def hint_select(self, evt):
+        """ Fire off a ContainerSelectionEvent """
+        wx.PostEvent(self, ContainerSelectionEvent(self.GetId()))
+        evt.Skip()
+
+    def on_activate(self, evt):
+        """ Emit a CompassOpenEvent when an item is double-clicked.
+        """ 
+
+        # wxPython Mac incorrectly treats a rapid left-right click as activate
+        ms = wx.GetMouseState()
+        if ms.RightIsDown():
+            return
+
+        idx = evt.GetIndex()
+        newnode = self.node[idx]
+        evt = CompassOpenEvent(newnode)
+        wx.PostEvent(self, evt)
+
+    # ---------------------------------------------------------
+    # Context menu support
+
+    def on_rclick(self, evt):
+        """ Pop up a context menu appropriate for the item """
+
+        # Click didn't land on an item
+        idx = evt.GetIndex()
+        if idx < 0:
+            return
+
+        # The node which was right-clicked in the view.
+        node = self.node[idx]
+        self._menu_node = node
+
+        # Determine a list of handlers which can understand this object.
+        # We exclude the default handler, "Unknown", as it can't do anything.
+        handlers = [x for x in node.store.gethandlers(node.key) if x != compass_model.Unknown]
+
+        # This will map menu IDs -> Node subclass handlers
+        self._menu_handlers = {}
+
+        menu = wx.Menu()
+        menu.Append(ID_CONTEXT_MENU_OPEN, "Open")
+        menu.Append(ID_CONTEXT_MENU_OPENWINDOW, "Open in New Window")
+
+        if len(handlers) > 0:
+
+            # Populate the "Open As" submenu, and record what
+            # menu IDs map to what Node subclasses
+            submenu = wx.Menu()
+            for h in handlers:
+                id_ = wx.NewId()
+                self._menu_handlers[id_] = h
+                submenu.Append(id_, h.classkind)
+                self.Bind(wx.EVT_MENU, self.on_context_openas, id=id_)
+            menu.AppendSubMenu(submenu, "Open As")
+
+        else:
+            # No handlers were available, so gray out the "Open" entries
+            id1 = wx.NewId()
+            menu.Append(id1, "Open As")
+            menu.Enable(ID_CONTEXT_MENU_OPEN, 0)
+            menu.Enable(ID_CONTEXT_MENU_OPENWINDOW, 0)
+            menu.Enable(id1, 0)
+
+        self.PopupMenu(menu)
+
+        del self._menu_node
+        del self._menu_handlers
+
+        menu.Destroy()
+
+
+    def on_context_open(self, evt):
+        """ Called in response to a plain "Open" in the context menu.
+
+        Posts an event requesting that the node be opened as-is.
+        """
+        wx.PostEvent(self, CompassOpenEvent(self._menu_node))
+
+
+    def on_context_openwindow(self, evt):
+        """ Called in response to a plain "Open in New Window" in the context
+        menu.
+        
+        Posts an event directly to the app object.
+        """
+        pos = wx.GetTopLevelParent(self).GetPosition()
+        wx.PostEvent(wx.GetApp(), CompassOpenEvent(self._menu_node, pos=pos))
+
+
+    def on_context_openas(self, evt):
+        """ Called in response to one of the "Open As" context menu items.
+        """
+        # The "Open As" submenu ID
+        id_ = evt.GetId()               
+
+        # Node which was right-clicked in the view
+        node_being_opened = self._menu_node 
+
+        # The requested Node subclass to instantiate
+        h = self._menu_handlers[id_]
+
+        # Brand new Node instance of the requested type
+        node_new = h(node_being_opened.store, node_being_opened.key)
+
+        # Send off a request for it to be opened in the appropriate viewer
+        wx.PostEvent(self, CompassOpenEvent(node_new))
+
+
+    # End context menu support
+    # -------------------------------------------------------------------
+
+
+class ContainerIconList(ContainerList):
+
+    """
+    Icon view of nodes in a Container.
+    """
+
+    def __init__(self, parent, node):
+        """ New icon list view
+        """
+        ContainerList.__init__(self, parent, node, style=wx.LC_ICON | wx.LC_AUTOARRANGE | wx.BORDER_NONE | 0x400)
+        self.node = node
+
+        self.il = wx.GetApp().imagelists[64]
+        self.SetImageList(self.il, wx.IMAGE_LIST_NORMAL)        
+
+        for item in xrange(len(self.node)):
+            subnode = self.node[item]
+            image_index = self.il.get_index(type(subnode))
+            self.InsertImageStringItem(item, subnode.displayname, image_index)
+
+
+class ContainerReportList(ContainerList):
+
+    """
+    List view of the container's contents.
+
+    Uses a wxPython virtual list, allowing millions of items in a container
+    without any slowdowns.
+    """
+
+    def __init__(self, parent, node):
+        """ Create a new list view.
+
+        parent: wxPython parent object
+        node:   Container instance to be displayed
+        """
+
+        ContainerList.__init__(self, parent, node, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_SINGLE_SEL|wx.BORDER_NONE)
+
+        self.node = node
+
+        self.InsertColumn(0, "Name")
+        self.InsertColumn(1, "Kind")
+        self.SetColumnWidth(0, 300)
+        self.SetColumnWidth(1, 200)
+
+        self.il = wx.GetApp().imagelists[16]
+        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
+
+        self.SetItemCount(len(node))
+        self.Refresh()
+
+
+    def OnGetItemText(self, item, col):
+        """ Callback method to support virtual list ctrl """
+        if col == 0:
+            return self.node[item].displayname
+        elif col == 1:
+            return type(self.node[item]).classkind
+        return ""
+
+
+    def OnGetItemImage(self, item):
+        """ Callback method to support virtual list ctrl """
+        subnode = self.node[item]
+        return self.il.get_index(type(subnode))
diff --git a/compass_viewer/events.py b/compass_viewer/events.py
new file mode 100644
index 0000000..7da0957
--- /dev/null
+++ b/compass_viewer/events.py
@@ -0,0 +1,39 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Defines a small number of custom events, which are useful for the GUI.
+"""
+
+import wx
+from wx.lib.newevent import NewCommandEvent
+
+ID_COMPASS_OPEN = wx.NewId()
+
+
+class CompassOpenEvent(wx.PyCommandEvent):
+
+    """
+    Event posted when a request has been made to "open" a object in
+    the container.  The source should always be ID_COMPASS_OPEN.
+
+    The type of event is EVT_MENU, because wxPython doesn't like it if we
+    use anything else.  When binding handlers, make sure to explicitly
+    specify the source ID (or check it in the callback) to avoid catching
+    these events by mistake.
+    """
+    
+    def __init__(self, newnode, **kwds):
+        """ Request that *newnode* be displayed by the GUI """
+        wx.PyCommandEvent.__init__(self, wx.EVT_MENU.typeId, ID_COMPASS_OPEN)
+        self.node = newnode
+        self.kwds = kwds
+
+
+# Hints that the selected item in the view may have changed.
+# Interested parties should inspect the view to figure out the new selection.
+ContainerSelectionEvent, EVT_CONTAINER_SELECTION = NewCommandEvent()
diff --git a/compass_viewer/frame.py b/compass_viewer/frame.py
new file mode 100644
index 0000000..1cbcae0
--- /dev/null
+++ b/compass_viewer/frame.py
@@ -0,0 +1,309 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Defines wx.Frame subclasses which are the foundation of the various windows
+displayed by HDFCompass.
+
+Much of the common functionality (e.g. "Open File..." menu item) is implemented
+here.
+"""
+
+import wx
+from wx.lib.pubsub import pub
+
+from . import imagesupport
+from .info import InfoPanel
+from . import platform
+
+ID_OPEN_RESOURCE = wx.NewId()
+ID_CLOSE_FILE = wx.NewId()
+
+
+class BaseFrame(wx.Frame):
+
+    """
+    Base class for all frames used in HDF Compass.
+
+    Implements common menus including File and Help, and handles their
+    events.
+
+    When implementing a new viewer window, you should instead inherit from
+    BaseFrame (below), which adds a left-hand side information panel, and
+    participates in the reference counting that automatically shows the
+    initial window when all other frames are closed.
+    """
+
+    def __init__(self, **kwds):
+        """ Constructor; any keywords are passed on to wx.Frame.
+        """
+
+        wx.Frame.__init__(self, None, **kwds)
+        menubar = wx.MenuBar()
+
+        # File menu
+        fm = wx.Menu()
+
+        fm.Append(wx.ID_OPEN, "&Open...\tCtrl-O")
+        fm.Append(ID_OPEN_RESOURCE, "Open &Resource...\tCtrl-R")
+
+        fm.AppendSeparator()
+ 
+        fm.Append(wx.ID_CLOSE, "&Close Window\tCtrl-W")
+        fm.Append(ID_CLOSE_FILE, "Close &File\tShift-Ctrl-W")
+        fm.Enable(ID_CLOSE_FILE, False)
+        fm.Append(wx.ID_EXIT,"E&xit"," Terminate the program")   
+        
+        menubar.Append(fm, "&File")
+
+        # Help menu; note that on the Mac, the About entry is automatically
+        # moved to the main application menu by wxPython.
+        help_menu = wx.Menu()
+        help_menu.Append(wx.ID_ABOUT, "&About HDFCompass"," Information about this program")
+        menubar.Append(help_menu, "&Help")
+
+        self.SetMenuBar(menubar)
+
+        self.Bind(wx.EVT_MENU, self.on_window_close, id=wx.ID_CLOSE)
+        self.Bind(wx.EVT_MENU, self.on_file_open, id=wx.ID_OPEN)
+        self.Bind(wx.EVT_MENU, self.on_resource_open, id=ID_OPEN_RESOURCE)
+        self.Bind(wx.EVT_MENU, self.on_about, id=wx.ID_ABOUT)
+        self.Bind(wx.EVT_MENU, self.on_exit, id=wx.ID_EXIT)
+
+    
+    def on_exit(self, evt):
+        """ Called on "exit" event from the menu """
+        wx.GetApp().Exit()
+        
+        
+    def on_about(self, evt):
+        """ Display an "About" dialog """
+        info = wx.AboutDialogInfo()
+        info.Name = "HDFCompass"
+        if platform.MAC:
+            info.Version = "release"
+        else:
+            info.Version = platform.VERSION
+        info.Copyright = "(c) 2013-2014 Heliosphere Research LLC"
+        wx.AboutBox(info)
+    
+
+    def on_file_open(self, evt):
+        """ Request to open a file via the Open entry in the File menu """
+        from . import open_store
+        dlg = wx.FileDialog(self, "Open Local File", style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
+        if dlg.ShowModal() != wx.ID_OK:
+            return
+        path = dlg.GetPath()
+        url = 'file://'+path
+        if not open_store(url):
+            dlg = wx.MessageDialog(self, 'The following file could not be opened:\n\n%s' % path,
+                               'No handler for file', wx.OK | wx.ICON_INFORMATION)
+            dlg.ShowModal()
+            dlg.Destroy()
+
+        
+    def on_window_close(self, evt):
+        """ Close Window file event, or cmd-W """
+        self.Destroy()
+        
+        
+    def on_resource_open(self, evt):
+        """ Request to open a URL via the File menu """
+        from . import open_store
+        dlg = wx.TextEntryDialog(self, 'Enter resource URL:')
+
+        if dlg.ShowModal() != wx.ID_OK or dlg.GetValue() == "":
+            dlg.Destroy()
+            return
+
+        url = dlg.GetValue()
+        dlg.Destroy()
+
+        if not open_store(url):
+            dlg = wx.MessageDialog(self, 'The following URL could not be opened:\n\n%s' % url,
+                               'No handler for URL', wx.OK | wx.ICON_INFORMATION)
+            dlg.ShowModal()
+            dlg.Destroy()
+
+
+    def add_menu(self, menu, title):
+        """ Add a menu at the appropriate place in the menubar """
+        mb = self.GetMenuBar()
+        mb.Insert(1, menu, title)
+
+
+class InitFrame(BaseFrame):
+
+    """
+    Frame displayed when the application starts up.
+
+    This includes the menu bar provided by TopFrame.  On the Mac, although it
+    still exists (to prevent the application from exiting), the frame
+    is typically not shown.
+    """
+
+    def __init__(self):
+        
+        style = wx.DEFAULT_FRAME_STYLE & (~wx.RESIZE_BORDER) & (~wx.MAXIMIZE_BOX)
+        title = "HDFCompass"
+        BaseFrame.__init__(self, size=(552,247), title=title, style=style)
+
+        data = imagesupport.getbitmap('logo')
+        bmp = wx.StaticBitmap(self, wx.ID_ANY, data)
+
+        self.Center()
+            
+            
+class NodeFrame(BaseFrame):
+
+    """
+    Base class for any frame which displays a Node instance.
+
+    Provides a "Close file" menu item and manages open data stores.
+
+    Has three attributes of note:
+
+    .node:  Settable Node instance to display
+    .info:  Read-only InfoPanel instance (left-hand sidebar)
+    .view:  Settable wx.Panel instance for the right-hand view.
+
+    In order to coordinate file-close events across multiple frames,
+    a reference-counting system is used.  When a new frame that uses a store
+    is created, that store's reference count (in cls._stores) is incremented.
+    When the frame is closed, the store's count is decremented.  
+
+    When the reference count reaches 0 or the "Close File" is selected from the
+    menu, the store is closed and a pubsub notification is sent out to all
+    other frames.  They check to see if their .node.store's are valid, and
+    if not, close themselves.
+    """
+
+
+    # --- Store reference-counting methods ------------------------------------
+
+    _stores = {}
+
+
+    @classmethod
+    def _incref(cls, store):
+        """ Record that a client is using the specified store. """
+        try:
+            cls._stores[store] = cls._stores[store] + 1
+        except KeyError:
+            cls._stores[store] = 1
+
+
+    @classmethod
+    def _decref(cls, store):
+        """ Record that a client is finished using the specified store. """
+        try:
+            val = cls._stores[store]
+            if val == 1:
+                cls._close(store)
+                del cls._stores[store]
+            else:
+                cls._stores[store] = val-1
+        except KeyError:
+            pass
+
+
+    @classmethod
+    def _close(cls, store):
+        """ Manually close the store, and broadcast a pubsub notification.
+        """
+        cls._stores.pop(store, None)
+        store.close()
+        pub.sendMessage('store.close')
+
+    # --- End store reference-counting ----------------------------------------
+
+
+    @property
+    def info(self):
+        """ The InfoPanel object used for the left-hand sidebar.
+        """
+        return self.__info
+
+
+    @property
+    def node(self):
+        """ Node instance displayed by the frame. """
+        return self.__node
+
+
+    @node.setter
+    def node(self, newnode):
+        self.__node = newnode
+
+
+    @property
+    def view(self):
+        """ Right-hand view """
+        return self.__view
+
+
+    @view.setter
+    def view(self, window):
+        if self.__view is None:
+            self.__sizer.Add(window, 1, wx.EXPAND)
+        else:
+            self.__sizer.Remove(self.__view)
+            self.__view.Destroy()
+            self.__sizer.Add(window, 1, wx.EXPAND)
+        self.__view = window
+        self.Layout()
+
+
+    def __init__(self, node, **kwds):
+        """ Constructor.  Keywords are passed on to wx.Frame.
+
+        node:   The compass_model.Node instance to display.
+        """
+
+        BaseFrame.__init__(self, **kwds)
+
+        # Enable the "Close File" menu entry
+        fm = self.GetMenuBar().GetMenu(0)
+        fm.Enable(ID_CLOSE_FILE, True)
+
+        self.__node = node
+        self.__view = None
+        self.__info = InfoPanel(self)
+
+        self.__sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.__sizer.Add(self.__info, 0, wx.EXPAND)
+        self.SetSizer(self.__sizer)
+
+        self.info.display(node)
+
+        self.Bind(wx.EVT_CLOSE, self.on_close_evt)
+        self.Bind(wx.EVT_MENU, self.on_menu_closefile, id=ID_CLOSE_FILE)
+
+        self._incref(node.store)
+        pub.subscribe(self.on_notification_closefile, 'store.close')
+
+
+    def on_notification_closefile(self):
+        """ Pubsub notification that a file (any file) has been closed """
+        if not self.node.store.valid:
+            self.Destroy()
+
+
+    def on_close_evt(self, evt):
+        """ Window is about to be closed """
+        self._decref(self.node.store)
+        evt.Skip()
+
+
+    def on_menu_closefile(self, evt):
+        """ "Close File" menu item activated.
+
+        Note we rely on the pubsub message (above) to actually close the frame.
+        """
+        self._close(self.node.store)
+
diff --git a/compass_viewer/icons/.DS_Store b/compass_viewer/icons/.DS_Store
new file mode 100644
index 0000000..968b781
Binary files /dev/null and b/compass_viewer/icons/.DS_Store differ
diff --git a/compass_viewer/icons/go_back_24.png b/compass_viewer/icons/go_back_24.png
new file mode 100644
index 0000000..abd6703
Binary files /dev/null and b/compass_viewer/icons/go_back_24.png differ
diff --git a/compass_viewer/icons/go_back_32.png b/compass_viewer/icons/go_back_32.png
new file mode 100644
index 0000000..1add104
Binary files /dev/null and b/compass_viewer/icons/go_back_32.png differ
diff --git a/compass_viewer/icons/go_next_24.png b/compass_viewer/icons/go_next_24.png
new file mode 100644
index 0000000..2574c25
Binary files /dev/null and b/compass_viewer/icons/go_next_24.png differ
diff --git a/compass_viewer/icons/go_next_32.png b/compass_viewer/icons/go_next_32.png
new file mode 100644
index 0000000..c88f176
Binary files /dev/null and b/compass_viewer/icons/go_next_32.png differ
diff --git a/compass_viewer/icons/go_up_24.png b/compass_viewer/icons/go_up_24.png
new file mode 100644
index 0000000..ad51a4d
Binary files /dev/null and b/compass_viewer/icons/go_up_24.png differ
diff --git a/compass_viewer/icons/go_up_32.png b/compass_viewer/icons/go_up_32.png
new file mode 100644
index 0000000..fead6a1
Binary files /dev/null and b/compass_viewer/icons/go_up_32.png differ
diff --git a/compass_viewer/icons/license.txt b/compass_viewer/icons/license.txt
new file mode 100644
index 0000000..02bbb60
--- /dev/null
+++ b/compass_viewer/icons/license.txt
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff --git a/compass_viewer/icons/logo.png b/compass_viewer/icons/logo.png
new file mode 100644
index 0000000..b4ed3f4
Binary files /dev/null and b/compass_viewer/icons/logo.png differ
diff --git a/compass_viewer/icons/logo.xcf b/compass_viewer/icons/logo.xcf
new file mode 100644
index 0000000..3305d4b
Binary files /dev/null and b/compass_viewer/icons/logo.xcf differ
diff --git a/compass_viewer/icons/readme.txt b/compass_viewer/icons/readme.txt
new file mode 100644
index 0000000..29ca2ea
--- /dev/null
+++ b/compass_viewer/icons/readme.txt
@@ -0,0 +1,11 @@
+This folder contains icons from the KDE Oxygen project, used in the HDFCompass
+GUI.  They are packaged up into a .py file by the "package_icons.py" script
+which comes with HDFCompass.
+
+Refer to "license.txt" for the icon licensing terms.
+
+The following images are NOT under the LGPL, and are (c) Heliosphere Research
+LLC (all rights reserved):
+
+logo.png
+logo.xcf
\ No newline at end of file
diff --git a/compass_viewer/icons/view_icon_24.png b/compass_viewer/icons/view_icon_24.png
new file mode 100644
index 0000000..39514b4
Binary files /dev/null and b/compass_viewer/icons/view_icon_24.png differ
diff --git a/compass_viewer/icons/view_icon_32.png b/compass_viewer/icons/view_icon_32.png
new file mode 100644
index 0000000..b101adf
Binary files /dev/null and b/compass_viewer/icons/view_icon_32.png differ
diff --git a/compass_viewer/icons/view_list_24.png b/compass_viewer/icons/view_list_24.png
new file mode 100644
index 0000000..80bbd75
Binary files /dev/null and b/compass_viewer/icons/view_list_24.png differ
diff --git a/compass_viewer/icons/view_list_32.png b/compass_viewer/icons/view_list_32.png
new file mode 100644
index 0000000..5013998
Binary files /dev/null and b/compass_viewer/icons/view_list_32.png differ
diff --git a/compass_viewer/icons/view_tree_32.png b/compass_viewer/icons/view_tree_32.png
new file mode 100644
index 0000000..256547a
Binary files /dev/null and b/compass_viewer/icons/view_tree_32.png differ
diff --git a/compass_viewer/icons/viz_plot_24.png b/compass_viewer/icons/viz_plot_24.png
new file mode 100644
index 0000000..2ac4527
Binary files /dev/null and b/compass_viewer/icons/viz_plot_24.png differ
diff --git a/compass_viewer/icons/viz_plot_32.png b/compass_viewer/icons/viz_plot_32.png
new file mode 100644
index 0000000..2ead4a9
Binary files /dev/null and b/compass_viewer/icons/viz_plot_32.png differ
diff --git a/compass_viewer/image/.DS_Store b/compass_viewer/image/.DS_Store
new file mode 100644
index 0000000..9d80d31
Binary files /dev/null and b/compass_viewer/image/.DS_Store differ
diff --git a/compass_viewer/image/__init__.py b/compass_viewer/image/__init__.py
new file mode 100644
index 0000000..ff435d7
--- /dev/null
+++ b/compass_viewer/image/__init__.py
@@ -0,0 +1,58 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Implements a simple true-color image viewer.
+"""
+
+import wx
+import wx.grid
+from wx.lib.newevent import NewCommandEvent
+
+from ..frame import NodeFrame
+
+class ImageFrame(NodeFrame):
+
+    """
+        Top-level frame displaying objects of type compass_model.Image.
+    """
+
+    def __init__(self, node, **kwds):
+        """ Create a new array viewer, to display *node*. """
+        NodeFrame.__init__(self, node, title=node.displayname, size=(800,400), **kwds)
+        self.node = node
+
+        p = ImagePanel(self, node)
+        self.view = p
+
+
+class ImagePanel(wx.Panel):
+
+    """
+    Panel inside the image viewer pane which displays the image.
+    """
+
+    def __init__(self, parent, node):
+        """ Display a truecolor, pixel-interlaced (not pixel-planar) image
+        """
+        wx.Panel.__init__(self, parent)
+        b = wx.BitmapFromBuffer(node.width, node.height, node.data)
+        b.CopyFromBuffer(node.data)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        sb = wx.StaticBitmap(self, wx.ID_ANY, b)
+        sizer.AddStretchSpacer()
+        sizer.Add(sb, 1, wx.EXPAND|wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL)
+        sizer.AddStretchSpacer()
+
+        sizer2 = wx.BoxSizer(wx.VERTICAL)
+        sizer2.AddStretchSpacer()
+        sizer2.Add(sizer, 1)
+        sizer2.AddStretchSpacer()
+
+        self.SetSizer(sizer2)
\ No newline at end of file
diff --git a/compass_viewer/images.py b/compass_viewer/images.py
new file mode 100644
index 0000000..371c8f7
--- /dev/null
+++ b/compass_viewer/images.py
@@ -0,0 +1,1582 @@
+import base64
+
+def go_back_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAEQUlEQVR42rWUb2xTVRTAz3l/e19"
+"f/60dQ8eGnaMTtzAWMU7mCMMtsA9mmS4ZMWiUxWTiNAofdCTKOt1QDEIY0cXFpKBzYEgMGND4wa"
+"b+IVFDMoUgZhMcH4a4QNut6+tr33vX+1b5QDBGoZzm9Oa9d8/5nX/3ItxmwZs13B85ij1PtdGCA"
+"4Jt+6VAoGhgZ3fDE9FTF98c6G7cWzBARdtQlUKkj7s21tc1rKqAzVsjsTOfPN9UEEBF276nQ0t9"
+"+7oef8jp8qq2Hd387J7YdHTw1gCVHSMejhrDrY3BzsbVIbSYY/ZbAPS8sCv25/fDNw8IbTy42u8"
+"WP3q0OXiX36+yzZi3oHnLbS++Hrv686H/D6hof48XZGfvikrva433lQg8zyFyHLA/24C5R3uhr7"
+"y0fYoT5AiKTuBkFTiBANsG7Q/XQc2yO0ef29QyeQNgWeeBJQ6J+7Cx1re2bLECHC9QnheQ4/k8g"
+"OPy8VNKL12cQvuBUqQWK5tFKZiGQYnIYfTr8R0/fDrQj9c7j7Qv8vAjq6qUIjYtIEgSiIII/DXl"
+"eBvw924KlmmBaRpgGDnI5Zhms0x1uHx5Bo6f+C58dfxAGPMleZcIorw7WALd5cU8ipJEJdmBkiQ"
+"DUypKMgqCxCACKwFHkQlLgJqmheaCc51mdR11XYesrtHZRAKPfRbtS5weC2N561sB1e2JVhRnq1"
+"nQILBIHUQB2UHAwdReGcwGsW8C8KxUdguoXQ7TBCNngM6i1jMaZLQ0GNkMQC4NY4ePh5Nnj4Sxb"
+"P1gQFWVaJE8Wy1wFvp8XiCKSh2KEwlxgkNRKAOivJCNCALrCbKes6KzDEzWFdMuD03NpTAeT8Cl"
+"P2bo+QsX8PeJs31z547mS7SkeQdh0b1N9fgWsAz0+wPUXxxgsCLweL1UVVVUFQIKcYAsS5SVCS3"
+"Lolomi1fiKYgn5+hcKoVzyQTMJhM0k47jxOkf+1ITJ8LXNbm06eVHnIT/QHU6A4S40O31gdvjpS"
+"6Xii5VBfYenAqhoiiiwaYlrWmYSqWBOV8AzNqARJxqWhzPnfqmLzX5ZfiGMS15cMsdDiJFyoPBF"
+"re7GNxuDzAAuFUXW51gg+xM9FwWJifPQFrLgKZnQcvooGkapOdTQAjC/PT5vm+P7O3/x4Pmq+lA"
+"kbi2Lg1VDlSGVkoqcaINcal2BgqVJRFzbI76e9qmslougoIDgJeBnTT7UECoKkjXNDWMDvV2/fa"
+"vV4V/RWedp9g7ev/a1uWLPCUscgWIQ6a8wKMlIH2n98lYcvLkrV127soWRZClPbXr1j9Tfc8DIH"
+"P2qHJgyQKMDPbEkr/GCnNdq8E17YuX3/t+fXOHX6UyWkSih4Z6Y7O/fFUYgC2krL5UdnsOrmx9b"
+"F3p3dX0i+E3Yld++rxwAFukklqOF8m2mg0tr+bm08fGx3ZvKijgmnRs3yVPz8SNkyM7zdsC+K/y"
+"F4m9oSi8YrWSAAAAAElFTkSuQmCC")
+
+def go_back_32():
+    return base64.b64decode(
+"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"
+"8rvGYqAAAAAElFTkSuQmCC")
+
+def go_next_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAEQElEQVR42rWUa2wUVRTHz519dbt"
+"9bLttJWpKoaiBVOUDaozEtkn7wQQbEzBCgFJDMCVRgZCqoaZDJITEKD4QaURrA5KmgVLEDyVt2p"
+"VatPHRggG7sPZhS2nK7sJud+bO3Hnc651tiWlq6CrlTk5mJjP3/zvnf04ugvu8UDI/HTl2Fm2vr"
+"GD3BfD24fM7y58ueOfdL346fjMSrR06Xa0tKKDo5UP+E5++WtzZOwgNzb39iqpvGDzz+rUFAzxY"
+"usff3FBTImsmxKMSfHXiByk4Gn1z8MwbXy8IIO+Zan/j0boSRTdnNjDWfSEAbd1DzRQ5qoMnt8b"
+"uCZD9xHr/kfr9xZpBE++MMbCuSFiC0x3BkXBM3xRo2vzjXQGfNJ4rDI6GNrV09IFpMqCGClSTgP"
+"GgBqk6ePiDApPe2cKshSiljJoU9fRN6P2ByHuGrh7489Q2818Bq17aU7d2zeq9t7GGAAlgJckYR"
+"YxSsISWPLIMzZLnAP6NmdREzDThxk3Mvv9t8jwm5uarTZXX5wCyVm4R168rE72+bHA6XWB3OMBm"
+"52GzgSDYAKF/nLQsogmwyavlYRj8boBGDPhlIHZrPKxuCzRtaZ0F8D6+QXxxTanoy81BTpebQ5z"
+"M7nAiCyIIAkNIQBYk4T+btoaL8uQNZBg6GLrOdF1HAjOhbyDERiOonjFz93DrdiUByFixTiwrf1"
+"7MycuDFLcHXCkp4LAqsTt5FQKvQLiTPlAeVuaMZ00IAUnGEIvGIRK5DdfHJ0GKx4HwiXPnFF4Bm"
+"6s0AUh/rEIsXF4kZmXnoWyfD9IyMpjbnYp4JZZNjDcGUX5QWMK6YTKN6EjGKsMYI6IqoCqYP8tI"
+"kSWQ5TgzDBM5Mh++zGyp0wDPshfE/EeLxFSPD2X5ciE908s8qR7kcjl5FXbGbUr8Z3nPIUw3DKR"
+"pOiOqihQFg4IlhmUpATC4j8R0fK4btGasvW7aIs/ScjF/+UrR48lBvrxF4M3K5oBUlGJZNQNgMw"
+"DuOePiiGgaU1WCFCwD5lmrqoxisVhoSiJbxzoPfDeryc+t3VEneB/YSzSBi3OL0tLBneIEp8MOd"
+"t6D3NzFPHM6bZFuTQwBlQdWVMBYgng8AqPDQx2KolVN9ByamDOmO99vLOz2X9gYGBi07Oap6sAM"
+"whtJuEWo6q2PThYYCp8WPpKWNSq3Bqu8B6qCRoYvk7+uBWs1RT4Yudg050if96hIy3/KX/tZSwn"
+"FGmi6DtwWhhUFhadC7Nee9kB0MrIx1N/U/7/PorQlz/rF+tZiJhFQVBVkHpf+6IW+rrajGia7Yl"
+"fb8N32zwvwLF3t3/fltyVmTIYbU2FoP3s8PPb7pdemgl2t8+1NCpC1osy/4+NjJQMXf4bO5oYuJ"
+"XKrUh7pGU9GPCnAk6/s+sblzay4cq5jn6EpH5KJPpqMcNKAVVW7bYsfWmRv2V9D/otw0oB7XX8D"
+"xbt0a+KWV20AAAAASUVORK5CYII=")
+
+def go_next_32():
+    return base64.b64decode(
+"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")
+
+def go_up_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAELklEQVR42q2Uf2wURRTH3+zv+92"
+"7poXrSVu19SrYIrSSpijFSg0EqaX1Bz9ME0QwCPFXFLWl9kdMjBiJ0WCiYmJTCyJiqiJU+4caGx"
+"W1hhIUKpz1SktLew3t7d7d3t7ujrN7hohGbc++ZHZmZ2fe5703+x0EM7BNrR9lMAyL36xfFZruH"
+"jTdhbmrnrMsLZn/vY5Y7cczo6X9722JzSrg+urde+sfr35I1xF+6a1vXjvZXrdj1gDZtz1Tta62"
+"vHPxojzzvffkCBz5cmDt6f11H/5vgLdsu7fwhvy+e++uyMAYG1MYETv8WSAUGBJv7D9QN5wywFO"
+"0jvJkzO3a+kB1Jc9zgJPTRocURccdx4KfS1KkMnB4q54SILO47onamsrdV2V7iVt8xTfjbSSkQP"
+"d3Ew2/vFv3/IwBnsJ7FhcVFXxddnMxR3z/aZ1JQuRplurEWVkJjMTLCeTbaQNc/jVWd3p67x1VK"
+"woQRWOj7H8JHpFnEkSGPT8pv0oxddG5Q5vD0wK459/5esWK8i0ut9NcQgI1W3I5NnPAWAecHEBU"
+"QfBDv3wg0Llj438CHPkra/wF/vevuS4P0RQNNMNgmqYRRcZgQrBhSNd0rGkqUlUVdE3DY5M6BC8"
+"qm347urPtHwG2qyt8bo/nxMKblqSzHAcsm2wEAgYAUcgskBE5cQ4acZ5IKJBQFAJR4fy4Jl2StO"
+"JgV8PZvwEEXynFWx3dhcVLKmx2J+YFC+J4ngB4zLAsIlkQAJU8ZSJnEjlW1QRCWAOWwliORpEUi"
+"cHpIaVXw1TZ4Ke7lCsAtpxlO+dd63/B5ZkDgtWGBYsVCYIVeEHALMcjxsgCUWYCpCSIRI1lWUZT"
+"UyKMjYewKIZRRAyDzenCjszcF08dfOSpy4CaXa8IQxfGxicGRTtFc2BkYLM7kNVmJxkkARwpFUW"
+"ygD8AihLHCSWOFFWGWETCEUkkABEoFuOSDVUXOzYu814GLN3eTEcmxPbBvlNZqhInM7rhhnRq7v"
+"LaB7OdTi9wHAt0EkDqr0FcSYAYvgBfde4L0rwzSAsuoC1pYHdlgL9kQefHretf/lehmefiLW5Zs"
+"/nJRk9aFuLJeTBMMgNSfyTH43hyahR1vfNqU3igp3XGSjbM4ittWbvt6cY5bh+yWATgWNY8AyWR"
+"QLFYDIfCY+iTtr1Nl84cSxEw75aWux6ub/S5s8Bus4IgCKbQYnIcJCkKo1IIjrz9RvNE38EUATm"
+"3ttQ+2tCYkzYXOR12sNttpghEKYLCooSHo5PoaHtb0/jxfakDah5raMx2ZCIHcW61WMyLIhqTEb"
+"mm8bAcRt2HPmga+WJPaoC82+9vXli9/lmbxgBvio4xt6gq+YsSKsQtDEwMnGvubr0vNcDqPfvzz"
+"/cc3xDo+5ncdkRoRCOIZoFiDE2wkO7z6gtWL+/o3LYykBJgNux3CZvXKMisXrMAAAAASUVORK5C"
+"YII=")
+
+def go_up_32():
+    return base64.b64decode(
+"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"
+"Zc/KoDT3AAAAABJRU5ErkJggg==")
+
+def logo():
+    return base64.b64decode(
+"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"
+"auWeZW/5/vINaP5aWlKAAAAAASUVORK5CYII=")
+
+def view_icon_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADtElEQVR42rWUf2hbVRTHz3lpmve"
+"SvKVNDTTpD2ed/TGUoMyx1h8R2qGoKAqjm3YVRTKkq2hARLB/qTARXIujtIvKEKVus8oYChMxpe"
+"53UbHYunbrxLRNp12arPn1kte8483NWjvSre3s7j/v3PvOe597zvd+L2J26OAWDCJKo91ud7nd7"
+"pduBcDr9X6KLpfLfejQV91EGrE1nIdfJ148v2E+ogA7djS6OeDAgc+6JEkEs9kEodAVUFV12d0Z"
+"jdJCvl6flxOHw7PQ3Ny0iwO83k+6E4kYKYqCZrMMeXn6ZStQlPhC/tycmhPL8jrYvbslW0FnZ1e"
+"3pmmUTCZRFMUVtYgJuJC/VCxJErS2XgV0dHzUxdbXVGAmAng8r2Vb1NPzZTdlCWsoMkJT0/PZCv"
+"r6+jjgi5/8WGqVwH85Rs2P3ME/+PaXKTIZdKiqaSizmaHKYaaTo0E219i509DARK2rKqKRQBQng"
+"zEQBKSYksYnNzmgvr4+C/D5fF2Zn+3pHYKEitB/Pg6+tk18Ox//MAZKUmVraWh9rBgeqi6Cr88E"
+"IBGPwffDKdhSKcMrW8vhxMgMXJoOg28kAYwC+16sgYaGhl3XVGBrGUaLXAypVITG967nFTz14Rg"
+"NTpkxPy8fvDvT8HBNEe05OomdfQJJohFfrkvAG08UU/8fQXxufxxMkkz32KPY+2pZbgXH2S7SzG"
+"86AeHBKiuvYHgiAtORFI/vrygAo0EHgZAC5y/F+NpdxSZwFIoQT6Zh4GKYr9nkfNhYKudWMDAWx"
+"qsA2ryhkFdwLhChUFTFjHLO8nUZAE2FFfxrOsHFvN0mgb1AJAbAQf8VfoILTXqsLpH/q2Ae8N3P"
+"E1jjMMLB03/TW89u5IBjvwbo3nIjnrkwC9YCE9RVWunH3//B+8okGhyPYjCuwTObS5jwM1hp08P"
+"kjEJn/4yge+uduYDatgFUyALxFNHoB9Uc4N4/RL9NACbBAh3bRa7BvmN+7D07SzMpC75QqwPP4w"
+"7qPxfE974JwFTUTHeXAPa0VORq8PTei6CBAQRIwpHXK3g/3z48CQzAj/f72yy8twdPX4bPTyX5+"
+"6ZaAzRuuY1r9eZh3iJwlgK8u60kVwPuDuD3+JLx4vlK8nNa1HPcj45CCcaDcdrpWn9do60acI3R"
+"5pjRRpcw2gVmtEezRlvpuGmj3XSLTo6GUE1roNcJ9ECVlScNjc8SMxouMtrqAE6ns7G9vb1t/pZ"
+"dq9s08/R4PO9kYCKDiqu/8ZcfgiAo+P9/c+PxLywgePGMeCYCAAAAAElFTkSuQmCC")
+
+def view_icon_32():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB5klEQVR42u2Xv0rDUBTGv5t20aR"
+"tYitWalOqnZVWNwcfRBwVX0Fwc1B8AhEcHMR3cK5OqQgK4mJr8R9am9ymwUUSr4l2qGmgmiYOni"
+"X38HHO+XHzJXAIQg7CcVySPWVCCBfkYMuyTDa7Tti5SCk95nl+KEgAwzBeJUma/wCYbTZVpd02g"
+"pwPQeAxOpqaswGenxs2QDweQywmQNfbaLX0vpt213vlpmkinR5zAB4fnxRd10GI1WlmWaRvgO56"
+"r1wQ4shkxh2A+/sHhdIWKNWgaSpEUUIiIfYN0F3vlcuyjGx2wgG4vb1TNI0O5F33ClFMIJeTHYC"
+"bm7qiqlqgAJIkYnIy7wBUqzXl5aUZKEAyOYJCYcoBYD8FJdDpnxGNRr8DrB2co5QXYVomKtcatp"
+"dmOgXrhxeYySVs7axGsbk4/SvNFWDv6ApFeRj7xw1Uai2UNxYwKM0VYGS5DGFYRDo1Dt1QcblVw"
+"KA0VwBppQKLi9lnYupQd2c7jVKrp3iD4BSjjcZO6VeaK0DoJgwdwG+ne2n/X4ErgN9O99L+pglD"
+"B/ip030D6Dj2hDm22sPNLppvALZjeebYZA8399B8A/ip030DCDK+AIoM4DQMgEgkUrJ3Q7YkyCw"
+"PdDdkYbIbqPe/ffgcoQO8A3MB8rhyIKcDAAAAAElFTkSuQmCC")
+
+def view_list_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACjklEQVR42r1VPWtaURh+jx/kqje"
+"iSCQJAV2io5urgy4iQRwkSGOGDnZoAsW9U/+AoRDuRVpCF0ssZAjB4KL/wUUyiA4Zoqjxq357es"
+"65alOS6i01vovnnvve+9zn47wiJJUSXqEwxmO0s7PjikQib18DIB6Pf0UulytyeflDxHiCyR6ag"
+"f9l/fR6YT9CCgiFDiMM4OLim6DRcMDzOqjXGzAcDpd+nVarmfer1apn68fHJhwfH71jAPH4F7Hb"
+"7eBer4d4fhNUKvVSBr3ez3n/aDR8tt7c1MPJyXuJwfm5IE4mE9zv9xHHcbIkIgbO+19aazQaOD2"
+"dApydfRbI/koNJiZANPpBkiiR+C5iCWGFJiM4OnojMchmswyA7QLL74vrp9dy+t1utwSQTqcFYo"
+"xs+lRrtVoNxDfodDpMDp7n2b1ut0uMHrEer9crSXR9fS3W63XZEhmNRpIYHg8GA/Tw8AAKhQLv7"
+"e2xnkqlggkIMhgMEAgEJAaZTEZYqcPT8ng8EoPb21uRUJXNQKfToY2NDTwej1Gj0WAMKCt6s9Vq"
+"MWakB3w+n8Tg6upKLJfLsgHMZjOVgOW9VCoxgP39fdZzf3+P2+022tragmAwuKYUpVIpgVJdVPQ"
+"Zk8kESuXvyU4kgmq1+sc+fQ9NpF6vh4ODA8mDZDIpUmrLJLLb7TR+cwZ05tzd3YHNZsNkNLCeQq"
+"GAm80m2t3dJdM0tCaJbm5uBHIOZMePJIaMay07UNNzAOSPi92r1WrssNFz4Pf7Z7MoIRaLRdkps"
+"lqtaHt7G5Noo1wuR/XHTqeT9eTzeUw+FlksFgiHw2uQyOFwHMZisY+zsMhhADKmKf2NRqOfKBhH"
+"QDnZBvxDEW966P9fs7h+AS+j7OL7mYj1AAAAAElFTkSuQmCC")
+
+def view_list_32():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABw0lEQVR42u2XTWrCUBDH/89vMWp"
+"SK7VYI7VewFpX3YoXcOEFBM8keAEXXkDcdmXsFaxirdSqiYn4BUlfTLEgVaq00YWzefnPY2Z+TG"
+"B4Q3BkIxaLJUBPnhBiMbOwpmkqrd0m9DshSdKTx+NxmwkwmUymHMc96gDJ4XAkKMrEzPpgGA+Cw"
+"cuHFUC//7EC8Pm88HoZyLKC8VjeO+lm/C6tqipCoSsDoNd7F2RZBiHaOpmmkb0BNuN3aYbxIRy+"
+"NgC63TdBksaQJBGiOALLcvD72b0BNuN3aZ7nEYncGACdzqsgitK//OttxrJ+RKO8AdBqtYXRSDQ"
+"VgONYxGK3BkCz+SIMBkNTAQKBC8TjdwYAHQqCqdW/zGaznQG+ARqNBubz+UGJnE4nksnkWtfrdS"
+"yXS9jtdqRSqa3+0+rAGaBWq2E2mx2UyOVyIZ1Or3W1WsVisYDD4UAmk9nqP60OnAEqlYr+TPp1M"
+"H3CIZvN/nin59Jt875cLq9mjT43crnciXXgDFAqlaAoykGJGIZBPp9f62KxiOl0CrfbjUKhsNV/"
+"Wh04JkCCAjwfA8Bqtd6vdkO6JPBUm7obUlNpB9r7bx9/bEcH+ASlAhS4AQ1IHgAAAABJRU5ErkJ"
+"ggg==")
+
+def view_tree_32():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACrklEQVR42sWXP0wTURzHv9c/GtI"
+"rvROqbSiHIAtuLRg1Lo3RRWVhYGFgEzsQkaEOkEANLJjUgYEF/zAQEtSa2M3FqnHQnIwQJ6CBUu"
+"VP77g2Nan2fL2DExolafBdf8vd9+7ee5+89/K5PAZVLsZisdSRq8AwjMXMgVVVLZKxkwy598uy/"
+"NHhcNSYCZDL5fI8z18pAbTv7GTEbDZn5vhgWQfc7voODWBzc0sDqK11wulkoShZ7O4qFXda3v6o"
+"XCwW4fGc0QHS6e+ioihgGNXoTFWZigHK2x+VWbYWDQ1eHSCV2hBleReyLEGSMuA4Hi4XVzFAefu"
+"jsiAIaGz06QBra+uiJMlU1vpfxXEuNDUJOsDqalLMZCRTAXieQ0tLsw6wvLwibm/vmApQV3cKra"
+"3ndAAiBfHgy0QigWAwSB3CZrP9HSAej6Ozs7N6ALFYDF1dXdUDmJ+fR3d39x+gT+t4/Ha15G8tW"
+"ywMQtebcTPgpQMwOzuLnp4eI1998AEv7gZwwm7VIAqFAvqeLuH5vYt0AGZmZtDb22vkYOQ95u60"
+"YWFFwaM337CYyqOjuQavw5fpAExPTx/68KHoxNYvN2lQA2+9D5zTBae6iPj9S3QApqamEAqFDi3"
+"BV+k8WXub8cx/eonMACWAyclJ9Pf3Gzn2OYVniSSKe/8SsgfRd+0s2YQeOgDRaBSDg4PH6vxYAB"
+"MTEwiHw9UDGB8fx9DQkJFfah5YgWosge6BW+2UPBCJRDAyMmJkzQMDAZy07XngZwG3n1D0wPDwM"
+"MbGxoy874EvyyUPpLG48QMXaHpgdHQU+XzeyHPpNmTtAux24gG3DzzrAkvTA+VlugfK61XJA+8O"
+"eoAhHmjCDT8lD5hV+wB+ArBQDQCr1RrQzobkkCCQbOrZkFSRzECy8tPHf66qA/wGcEBnuLfzwNo"
+"AAAAASUVORK5CYII=")
+
+def viz_plot_24():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADPElEQVR42u2Ve0hTcRTHz2+KCoI"
+"Y2nxM52upQ1ch+K5MTajMkrLCEiJEyETLHkJChb0otP4IWjGIIpQwxMKJvYwwxSlaK5pWmizzhU"
+"PMB2ntzt/pd+9lV/pvfywi6IyzH5d7zvnse865dwT+sJH/ALsVDxW3DywMpC4uLQrXMvbJ9M7sd"
+"BogrTuNVvlXEeuSFZnzJ2i/adFpAE2rBi+EXgAewC1xAuDq+FXnAdTNalqpquQBkutGdM6bQWRD"
+"JJZFlwkKrFRs0X3zfecpCK8Nx0JNodgiKrZIP6h3DDD2vqZzfuJZEvdzml0hyFzcQR5V0rsyYn+"
+"CPUZ5W0nz4/LF9lCxRW39bY616HVtLI1KKCfIkpBaEdiWfDbVYdy+tzJ7jOKGAnOScvji0hYZ3x"
+"kdU2DQqmhs+mHgAUB5CAf9hgeQXPxJAvhd86MZGzKAtUdQwDYJzD1mxxS8qg7FtVsOsOKcoIA5e"
+"f/yCa4/PiAB5JflGL8pXlDgRtzILDcLb1rfOKbgxdlgjM/L44vzCgSAsaUL008vK/A/74/qbDW4"
+"E3c0zZvI6I9R8OrwcgzwtCIYkwuylgHIkZ7Gj5h18cPyDM4q0HObJ7DXBQL/CmLfPs99kAxVV3d"
+"a9PokbnoaWCbIPDwgvLy8V1FQIG1IS6mSriuKF3oPKAwauuossPmaSQL4nvKlU7lT/JKJziygKQ"
+"BIU3Q0Ddq5k9isVjZDK3/CXHc3ZhuNUrK+KBQ3Hl3NfoAN0DbHjhnSrpvDHN1XKSagIgAn8idAK"
+"I+iAmW9EkltUBBGr1kDlBDWWyoAvpjNuH9oSEp+WBCI6Udm2RZ9lwq03QzE3HvjUkzIiRAcPjj8"
+"G0B1V4Xklrc3jZuZAcru2N0kl8Mhi0VKbtitoFmVY5J03lqvhMCu+mEpZlX5KjpYMvhbi9RaNZD"
+"rfn50++QkYYWROX/Ck+BgLBsZkZLrd4TRrZfM4kKgkE4en4nCPY3LWxRTGkP7TvYR4T6K66+p0S"
+"A5l5jY4WGxpCxxbICEmasrusXEGI41N6fak++sS+nw9J1NoTaOsBgkMlcWG2HY+6hJiknNT+1YW"
+"LGQwj/BPMAFXDCMhBn+nb/Mvwb4BXPJzucFc+fpAAAAAElFTkSuQmCC")
+
+def viz_plot_32():
+    return base64.b64decode(
+"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGO0lEQVR42s2XS0wUSRjHv+6Znuk"
+"ZYCAEmJBdlLeKiWLCIhgT10cEN5p48XVQD9w18eAmHIgXY6IHwwEPhhgSk43h5mENG1dl9+CDRJ"
+"ZVOGxARlYDKyI6D+jp7pnp/b6vp5oZp3ezHozbSTFVXdX1/32PeiDBF36k/x1AKBSSLMv6bILxe"
+"Dxvcgegp6cnMDs7W7G8vKwiwGfxjCRJVnl5ebKhoWFpcHBQcwAOHz4cuHTp0o+1tbXf2uMk+iM+"
+"cn7d3tEjPJb7+y/vrLm5uV8uXrz43c2bNzWeoaqqKhyJRBbS6bSExRH7WNTtnZtILoDH4yl4j++"
+"s1tbWr6anpxekrBdqEonEXG9vL0xNTfHEXq8XCEY8sixDKpVyhGiMaZo8JpPJcNswDK7TOxpP7b"
+"a2NhgYGIB3794BWg6VlZVQU1MD4XC4fnV19aUAWI8AkePHj0NZWRmLEAAJCOqP22SZrussJgQ1T"
+"Sto47zw6NEjuHPnDjQ2NgLmGRw4cAAqKioa8PuIA4DZGTlx4gSUlpaygKIobIFwpVfxgqEbXCcr"
+"CSiZTK4JelBwdQ3Ag+1VbK+srMDjx49hcXERxsfHef6Ojg4KeyHAkSNHoKSkhEUUn8KCAoCAyGJ"
+"qEwB5QAAIILJYhMCH32takgEePnzIfcJ7xcXFFIp8gFgsFjl67CiUhkJAmgpZbJg5FnmwrYPYIg"
+"jINA1uixDp1J8RIaMQGbTu4d69e/D8+XNYWlpi8fb29kIPEMChQ4d4ACUbTYhJ4iSgqqocEpH9f"
+"r+fPSCS0ufz5VlJHhAhGB0dhadPn8KbN2+47+DBg5SEhQD79u1jIRIIBAMcAqrLsgRqgNq6s3ep"
+"KgHojiABCQAKA7XJAErC+/fvc528SECYgO4Au3fvZg+QaLAoCDoKBAIS5gUBqWAaOouvrEgoFOA"
+"YCwACJ5E1IJ8DcPfuz4A7LLx69YqX4bp169xDsGfPHgegqKgIQ5GEzZsNJDY45pmMjkIWWu6FiY"
+"kqeP/eyAPQtFX8Po1L2URwH+aAhsIJGBwchZGREdiwYQPMzMzwMnQF6O7uhpJQCcgIQBOqARM2t"
+"8Rhft6LOaEgkInL0YL163VccsXw2wR6xaQkAI65LGvQ3f0XHmgxNEJGYANev9bh9OkpePv2LUJP"
+"0GEHO3bscA/Bzp072XLyQCgUhLq6BMczGgUIBv0opqOIhdYBtLZmYGwsAC9fenGMxf0bNy6jx2I"
+"wOeljYNNM4g6oQX//uLOjij3G1QOdnR04eZCTLhwOQlNTDOMmsUAABVIMAAxRWeWDxoY4PHlSCr"
+"Q4ysoU6Oych2fP/JgjlIQKAy8vJ+HatYm8U5FWmCvA9u1t6EoVB8hoob2solGLRSmmZhYAkxnbC"
+"npJh9paA8fTspPhxQsJBdlOBPDy+A8fdLh+fRL6+vpg06ZNvBecOXMGqqurCwH27v0GP8TYqxLU"
+"11tofYqtl1HQ76PDycx6gGLuwb4UwtDBhG6lfswRqttt7MfxBHDjxiQMDQ1Bc3Mzr4Suri5oaWk"
+"pBOjq2oiupPgBWu/FXcxwBMmleQB+W5DCQaeyzwG0AQiQkjYeT8Hw8DTcunULQ9qESfkadu3a5Q"
+"6wdWs9utbLOUATkoU0uQ1AAiknB2irtvvtECmKx2kLj5AHEok03L49C6dOneLY0+q6evUqJnhdI"
+"cC2bc1YNfMAaHLbQhJIO0BrgqItZ49hsAGwn4DTaQUB/qBbF4bjAyZqJ1y5csU9CYeHf4AHD36i"
+"A5cPEyFIhRLTsjJOm47btbbl0ra37Pb2/bB//zE4efIknzFbtmyBCxcuuAPQaadlfoX3i2UQj6q"
+"8XumCQh9SIQtFnfYHKuKwokIupkJ7/sf1s2fP4l4RxOSuh/PnzxcCRKPRiJ6aBzPwPUyMWTA0oO"
+"KyeoEJNOwIi6NZiIu7gn1g2RAkKERzQS5fvsznAG10eAMv2Am/XlhYmMPYS5byBDzQBLIVZhEhL"
+"ESFcO7FM/eyKkAEDP2Ky6u4O+KvhdezOjwZ/5SyO1PpuXPnRvAw2i7ZT8Gd/lP/WfmnObBYeD8Y"
+"6+/v78KNLiplr84yWlmN1a1YQhTWT1L77w8lTQzL75hfC3jJzeRiUt2TLZ/zSWeLJUS/6PPFAf4"
+"GdM1JrpkhwBgAAAAASUVORK5CYII=")
+
diff --git a/compass_viewer/imagesupport.py b/compass_viewer/imagesupport.py
new file mode 100644
index 0000000..be854c7
--- /dev/null
+++ b/compass_viewer/imagesupport.py
@@ -0,0 +1,27 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Small module to handle common image operations.
+
+Images themselves come from the auto-generated "images.py" module.
+"""
+
+import wx
+import cStringIO
+from . import images
+
+def getbitmap(name):
+    """ Return a wx.Bitmap of the given icon """
+    png = getattr(images, name)()
+    return png_to_bitmap(png)
+
+def png_to_bitmap(png):
+    """ Convert a string with raw PNG data to a wx.Bitmap """
+    stream = cStringIO.StringIO(png)
+    img = wx.ImageFromStream(stream, wx.BITMAP_TYPE_PNG)
+    return img.ConvertToBitmap()
\ No newline at end of file
diff --git a/compass_viewer/info.py b/compass_viewer/info.py
new file mode 100644
index 0000000..8ec27db
--- /dev/null
+++ b/compass_viewer/info.py
@@ -0,0 +1,109 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Defines the left-hand side information panel used to display context info.
+"""
+
+import wx
+import compass_model
+
+from .imagesupport import png_to_bitmap
+from . import platform
+
+# Info panel width
+PANEL_WIDTH = 200
+
+# Size of the main title font
+FONTSIZE = 16 if platform.WINDOWS else 18
+
+
+class InfoPanel(wx.Panel):
+
+    """
+    Panel displaying general information about the selected object.
+
+    Designed to be displayed vertically; sets its own width (PANEL_WIDTH).
+    """
+
+    def __init__(self, parent):
+        """ Constructor.  *parent* should be the containing frame.
+        """
+        wx.Panel.__init__(self, parent, size=(PANEL_WIDTH, 10), style=wx.BORDER_NONE)
+
+        font = wx.Font(FONTSIZE, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
+
+        # Sidebar title text
+        self.nametext = wx.StaticText(self, style=wx.ALIGN_LEFT|wx.ST_ELLIPSIZE_MIDDLE, size=(PANEL_WIDTH-40,30))
+        self.nametext.SetFont(font)
+
+        # Sidebar icon (see display method)
+        self.staticbitmap = None
+
+        # Descriptive text below the icon
+        self.proptext = wx.StaticText(self, style=wx.ALIGN_LEFT)
+
+        self.sizer = sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(self.nametext, 0, wx.LEFT|wx.TOP|wx.RIGHT, border=20)
+        sizer.Add(self.proptext, 0, wx.LEFT|wx.RIGHT, border=20)
+        sizer.AddStretchSpacer(1)
+        self.SetSizer(sizer)
+
+        self.SetBackgroundColour(wx.Colour(255,255,255))
+
+
+    def display(self, node):
+        """ Update displayed information on the node.
+
+        See the get* methods for specifics on what's displayed.
+        """
+
+        self.nametext.SetLabel(node.displayname)
+        self.proptext.SetLabel(describe(node))
+
+        if self.staticbitmap is not None:
+            self.sizer.Remove(self.staticbitmap)
+            self.staticbitmap.Destroy()
+
+        # We load the PNG icon directly from the appropriate Node class
+        png = type(node).icons[64]()
+        b = png_to_bitmap(png)
+
+        self.staticbitmap = wx.StaticBitmap(self, wx.ID_ANY, b)
+        self.sizer.Insert(1, self.staticbitmap, 0, wx.ALL, border=20)
+        self.sizer.Layout()
+        self.Layout()
+
+
+def describe(node):
+    """ Return a (possibly multi-line) text description of a node.
+    """
+    desc = "%s\n\n" % type(node).classkind
+
+    if isinstance(node, compass_model.Array):
+        desc += "Shape\n%s\n\nType\n%s" % \
+        (node.shape, dtypetext(node.dtype))
+
+    elif isinstance(node, compass_model.Container):
+        desc += "%d items\n" % len(node)
+
+    return desc
+
+
+def dtypetext(dt):
+    """ String description appropriate for a NumPy dtype """
+    if dt.names is not None:
+        return "Compound (%d fields)" % len(dt.names)
+    if dt.kind == 'f':
+        return "%d-byte floating point" % dt.itemsize
+    if dt.kind == 'u':
+        return "%d-byte unsigned integer" % dt.itemsize
+    if dt.kind == 'i':
+        return "%d-byte signed integer" % dt.itemsize
+    if dt.kind == 'S':
+        return "ASCII String (%d characters)" % dt.itemsize
+    return "Unknown"
diff --git a/compass_viewer/keyvalue/.DS_Store b/compass_viewer/keyvalue/.DS_Store
new file mode 100644
index 0000000..9d80d31
Binary files /dev/null and b/compass_viewer/keyvalue/.DS_Store differ
diff --git a/compass_viewer/keyvalue/__init__.py b/compass_viewer/keyvalue/__init__.py
new file mode 100644
index 0000000..0006035
--- /dev/null
+++ b/compass_viewer/keyvalue/__init__.py
@@ -0,0 +1,96 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Implements a viewer for key-value stores (instances of compass_model.KeyValue).
+
+Keys are strings, values are any data type HDFCompass can understand.
+Presently this means all NumPy types, plus Python str/unicode.
+"""
+
+import wx
+import compass_model
+
+from ..frame import NodeFrame
+
+
+class KeyValueFrame(NodeFrame):
+
+    """
+    A frame to display a list of key/value pairs, their types and shapes.
+    """
+
+    def __init__(self, node, pos=None):
+        """ Create a new frame.
+
+        node:   Container instance to display.
+        """
+        title = 'Attributes of "%s"' % node.displayname
+        NodeFrame.__init__(self, node, size=(800, 400), title=title, pos=pos)
+
+        self.list = KeyValueList(self, node)
+        self.view = self.list
+
+
+class KeyValueList(wx.ListCtrl):
+
+    """
+    A simple list view of key/value attributes
+    """
+
+    def __init__(self, parent, node):
+        """ Create a new attribute list view.
+
+        parent: wxPython parent object
+        node:   compass_model.KeyValue instance
+        """
+
+        wx.ListCtrl.__init__(self, parent, style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.BORDER_NONE|wx.LC_HRULES)
+
+        self.node = node
+
+        self.InsertColumn(0, "Name")
+        self.InsertColumn(1, "Value")
+        self.InsertColumn(2, "Type")
+        self.InsertColumn(3, "Shape")
+
+        names = node.keys
+        values = [self.node[n] for n in names]
+
+        def itemtext(item, col):
+            name = names[item]
+            data = values[item]
+            text = ""
+            if col == 0:
+                text = name
+            elif col == 1:
+                text = str(data)
+            elif col == 2:
+                if hasattr(data, 'dtype'):
+                    text = str(data.dtype)
+                else:
+                    text = str(type(data))
+            elif col == 3:
+                if hasattr(data, 'shape'):
+                    text =  str(data.shape)
+                else:
+                    text = "()"
+            return text
+
+        for n in names:
+            row = self.InsertStringItem(9999, n)
+            for col in xrange(1,4):
+                self.SetStringItem(row, col, itemtext(row, col))
+
+        self.SetColumnWidth(0, 200)
+        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+        self.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+        self.SetColumnWidth(3, wx.LIST_AUTOSIZE)
+
+
+
+        
\ No newline at end of file
diff --git a/compass_viewer/platform.py b/compass_viewer/platform.py
new file mode 100644
index 0000000..7c50096
--- /dev/null
+++ b/compass_viewer/platform.py
@@ -0,0 +1,21 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+    Module for platform- and version-specific feature detection.
+"""
+
+import sys
+
+MAC = sys.platform == 'darwin'
+WINDOWS = sys.platform == 'win32'
+LINUX = sys.platform == 'linux2'
+
+if not any((MAC, WINDOWS, LINUX)):
+    raise ValueError('Unknown platform "%s"' % sys.platform)
+
+VERSION = "0.4a"
\ No newline at end of file
diff --git a/docs/.DS_Store b/docs/.DS_Store
new file mode 100644
index 0000000..61c868c
Binary files /dev/null and b/docs/.DS_Store differ
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..763f67c
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/HDFCompass.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/HDFCompass.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/HDFCompass"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/HDFCompass"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..2fcdb96
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+#
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'HDFCompass Data Model'
+copyright = u'2014, Heliosphere Research LLC'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.3a'
+# The full version, including alpha/beta/rc tags.
+release = '0.3a'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'HDFCompassdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'HDFCompass.tex', u'HDFCompass Data Model',
+   u'Heliosphere Research LLC', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'hdfcompass', u'HDFCompass Documentation',
+     [u'Heliosphere Research LLC'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'HDFCompass', u'HDFCompass Documentation',
+   u'Heliosphere Research LLC', 'HDFCompass', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..7a61015
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,315 @@
+..  This file is part of HDFCompass, a viewer for HDF5 and other formats.
+    Copyright 2013-2014 Heliosphere Research LLC
+    All rights reserved.
+    This software product comes with ABSOLUTELY NO WARRANTY.
+
+####
+Root
+####
+
+Data & Object Model
+===================
+
+Introduction
+------------
+
+This document describes the publically accessible data model package which is
+used by HDFCompass to display objects in a file, OpenDAP server or other
+resource.
+
+The data model is implemented as a collection of classes in a top-level Python
+package, ``compass_model``, which is completely independent of the GUI code.
+It has no dependencies beyond the Python standard library.  This makes it
+possible to develop and test new plugins independently of GUI development;
+in particular, the automated Python unit-testing framework can be used, which
+is impossible for code that depends on the GUI.
+
+The classes in ``compass_model`` are abstract, and define a standard interface
+for objects like containers, regular multidimensional arrays, images, and
+key/value stores.  "Plug-ins" consist of concrete implementations which
+satisfy this interface.  For example, the built-in HDF5 plugin which ships
+with HDFCompass implements a ``Group`` class which inherits from
+``compass_model.Container``, and a Dataset class which inherits from
+``compass_model.Array``.
+
+The GUI has a collection of viewers which can display any object following
+the interfaces defined in ``compass_model``.  For example,
+``compass_model.Container``
+implementations are displayed in a browser-style view, with list, icon, and
+tree displays possible.  Likewise, ``compass_model.Array`` implementations
+are displayed in a spreadsheet-like view, with facilities for plotting data.
+
+Multiple concrete classes can handle the same object in a file.  For example,
+an HDF5 image is implemented as a dataset with special attributes.  Three
+classes in the HDF5 plugin are capable of handling such an object, which
+inherit respectively from ``compass_model.Image``, ``compass_model.Array``, and
+``compass_model.KeyValue``; the last represents HDF5 attributes.
+
+When an icon in the GUI is double-clicked, the default (last-registered) class is
+used to open to object in the file.  The other classes are made available in a
+context menu, for example, if the user wants to open an image with the
+Array viewer or see the HDF5 attributes.
+
+
+Numeric types (integers, floats, multidimensional data) are handled with the
+NumPy type model, which can represent nearly all formats.  Python strings
+(byte and Unicode) are also supported. 
+
+
+Data stores
+-----------
+
+.. class:: Store
+
+    Represents a file or remote resource which contains objects.  Objects
+    within the store can be retrieved using *keys*, which may be any hashable
+    Python object.  For example, an HDF5 store generally uses string keys
+    representing paths in the file, although object and region reference
+    objects are also valid.
+
+    Objects may be retrieved using the __getitem__ syntax (``obj = store[key]``).
+    The retrieved object is a Node instance.  The exact class depends on
+    the order in which Node handlers were registered; see the `push` method
+    below.
+
+Methods related to the plugin system
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Typically, a model will implement several classes based on the ``compass_model``
+abstract classes such as ``Container`` or ``Array``.  This rasises the
+question: when an object is retrieved from the data store, which class
+should be used?
+
+The answer is that each ``Node`` subclass you write should be "registered" with
+your ``Store`` subclass, and have a static method called ``canhandle``.  When
+an object is opened, by default the most recently registered class which
+reports it can understand the object is used.
+
+All registered subclasses may be retrieved via the ``gethandlers`` function,
+which an optionally request that only subclasses capable of handling *key*
+be returned.  This is the basis for the right-click "Open As" menu in the GUI.
+
+.. classmethod:: Store.push(nodeclass)
+    
+    Register a Node subclass.  These are kept in a list inside the class;
+    when an object is retrieved from the store, the first class for
+    which `nodeclass.canhandle(store, key)` returns True is instantiated
+    and returned.
+
+.. method:: Store.__getitem__(key)
+
+    Open an object in the store, using the last registered class which
+    reports it can open the key.
+
+.. method:: Store.gethandlers(key=None)
+
+    Retrieve all registered Node subclasses, optionally filtering by
+    those which report they can handle *key*.
+
+.. method:: Store.__contains__(key)
+
+    **(Abstract)** True if *key* is exists in the store, False otherwise.
+
+Other methods & properties
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. staticmethod:: Store.canhandle(url)
+
+    **(Abstract)** Return True if this class can make sense of *url*, False otherwise.  This
+    method is used by the GUI when determining which Store implementation to
+    use when opening a file.  For example, the HDF5 plugin uses
+    ``h5py.is_hdf5(filename)``.
+
+.. method:: Store.__init__(url)
+
+    **(Abstract)** Create a new store instance from the data at *url*.  URLs are given
+    in the ``scheme://locator`` fashion.  For example, an HDF5 file might
+    be located by ``file:///path/to/file.hdf5``.
+
+.. method:: Store.close():
+
+    **(Abstract)** Discontinue access to the data store.
+
+.. method:: Store.getparent(key)
+
+    **(Abstract)** Return the object which contains *key*, or None if no such object exists.
+
+.. attribute:: Store.url
+
+    **(Abstract)** The URL used to open the store
+
+.. attribute:: Store.displayname
+    
+    **(Abstract)** A short name used for the store (e.g. ``basename(filepath)``).
+
+.. attribute:: Store.root
+
+    **(Abstract)** A Node instance representing the starting point in the file.
+    For hierarchical formats, this would be the root container.  For scalar
+    formats (FITS, for example), this could be e.g. an Array or Image instance.
+
+
+Nodes
+-----
+
+A "node" is any object which lives in the data store.  The Node class defined
+below is the base class for more interesting abstract classes like containers
+and arrays.  It defines much of the interface.
+
+.. class:: Node
+
+    Base class for all objects which live in a data store.
+
+    You generally shouldn't inherit from Node directly, but from one of the
+    more useful Node subclasses in this file.  Direct Node subclasses can't
+    do anything interesting in the GUI; all they do is show up in the browser.
+
+
+.. attribute:: Node.icons
+
+    Class attribute containing a dict for icon support.
+    Keys should be integers giving icon size; values are a callable returning
+    a byte string with PNG image data.
+    Example:      ``icons = {16: get_png_16, 32: get_png_32}``.
+    Since icons are a pain to handle, default icons are provided by
+    ``compass_model`` and this attribute is optional.
+
+.. attribute:: Node.classkind
+
+    **(Abstract)**
+    A short string (2 or 3 words) describing what the class represents.
+    This will show up in e.g. the "Open As" context menu.
+    Example:  "HDF5 Image" or "Swath".
+
+.. staticmethod:: Node.canhandle(store, key)
+
+    **(Abstract)** Determine whether this class can usefully represent the object.
+    Keep in mind that keys are not technically required to be strings.
+
+.. method:: Node.__init__(store, key):
+
+    **(Abstract)** Create a new instance representing the object pointed to by *key*
+    in *store*.
+
+
+.. attribute:: Node.key
+
+    **(Abstract)** Unique key which identifies this object in the store.
+    Keys may be any hashable object, although strings are the most common.
+
+
+.. attribute:: Node.store
+
+    **(Abstract)** The data store to which the object belongs.
+
+.. attribute:: Node.displayname
+
+    **(Abstract)** 
+    A short name for display purposes (16 chars or so; more will be ellipsized).
+
+.. attribute:: Node.description
+
+    **(Abstract)** 
+    Descriptive string (possibly multi-line).
+
+
+Containers
+----------
+
+.. class:: Container(Node)
+
+    Represents an object which holds other objects, like an HDF5 group
+    or a filesystem directory.
+    Implementations will be displayed using the browser view.
+
+.. method:: Container.__len__()
+
+    **(Abstract)** 
+    Get the number of objects directly attached to the container.
+
+.. method:: Container.__getitem__(index)
+
+    **(Abstract)** 
+    Retrieve the node at *index*.  Note this returns a Node instance, not a key.
+
+
+Arrays
+------
+
+.. class:: Array(Node)
+
+    The array type represents a multidimensional array, using an interface
+    inspired by Numpy arrays.
+
+    Implementations will be displayed in a spreadsheet-style viewer with
+    controls for subsetting and plotting.
+
+.. attribute:: Array.shape
+
+    Shape of the array, as a Python tuple.
+
+.. attribute:: Array.dtype
+
+    NumPy data type object representing the type of the array.
+
+.. method:: Array.__getitem__(indices)
+
+    Retrieve data from the array, using the standard array-slicing syntax
+    ``data = array[idx1, idx2, idx3].  *indices* are the slicing arguments.
+    Only integer indexes and slice objects (representing ranges) are
+    supported.
+
+
+Key-Value lists
+---------------
+
+.. class:: KeyValue(Node)
+
+    Represents an object which contains a sequence of key: value attributes.
+    Keys must be strings.  Values may be Python or NumPy objects.
+    Implementations will be displayed using a list-like control.
+
+.. attribute:: KeyValue.keys
+
+    **(Abstract)** 
+    A list containing all (string) keys contained in the object.
+
+.. method:: KeyValue.__getitem__(name)
+
+    **(Abstract)** Retrieve the value associated with string *name*.
+
+
+Images
+------
+
+.. class:: Image(Node)
+
+    Represents an image.  The current interface supports only true-color RGB
+    images with the origin at upper left, although this could easily be
+    extended to more complex formats including RGBA or palette-based images.
+
+    Implementations are displayed in an image viewer.
+
+.. attribute:: Image.width
+
+    Image width in pixels
+
+.. attribute:: Image.height
+
+    Image height in pixels
+
+.. attribute:: Image.data
+
+    Image data.  Currently RGB, pixel-interlaced.
+
+
+Top-level functions
+-------------------
+
+One public function is defined in ``compass_model``:
+
+.. function:: push(storeclass)
+
+    Register a new Store subclass with HDFCompass.  When a URL is being
+    opened, the class will be queried (via ``storeclass.canhandle``) to see
+    if it can make sense of the URL.
\ No newline at end of file
diff --git a/filesystem_model/.DS_Store b/filesystem_model/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/filesystem_model/.DS_Store differ
diff --git a/filesystem_model/__init__.py b/filesystem_model/__init__.py
new file mode 100644
index 0000000..146e678
--- /dev/null
+++ b/filesystem_model/__init__.py
@@ -0,0 +1,173 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Example data model which represents the file system.
+
+Subclasses just two node types: Container and Array, representing
+directories and files respectively.
+"""
+
+import os
+import os.path as op
+import numpy as np
+
+import compass_model
+
+class Filesystem(compass_model.Store):
+
+    """
+        A "data store" represented by the file system.
+
+        Keys are absolute paths on the local file system.
+    """
+
+    def __contains__(self, key):
+        return op.exists(key)
+
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def displayname(self):
+        return "Local file system"
+
+    @property
+    def root(self):
+        return self['/']
+
+    @property
+    def valid(self):
+        return self._valid
+
+    @staticmethod
+    def canhandle(url):
+        if url == "file://localhost":
+            return True
+        return False
+
+    def __init__(self, url):
+        if not self.canhandle(url):
+            raise ValueError(url)
+        self._url = url
+        self._valid = True
+
+    def close(self):
+        self._valid = False
+
+    def getparent(self, key):
+        if key == "/":
+            return None
+        return self[op.dirname(key)]
+
+
+class Directory(compass_model.Container):
+
+    """
+        Represents a directory in the filesystem.
+    """
+
+    classkind = "Directory"
+
+    @staticmethod
+    def canhandle(store, key):
+        return op.isdir(key)
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        try:
+            self._names = os.listdir(key)
+        except OSError:  # Permissions, etc.
+            self._names = []
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        bn = op.basename(self.key)
+        if len(bn) == 0:
+            return "/"
+        return bn
+
+    @property
+    def description(self):
+        return 'Folder "%s" (%d members)' % (self.displayname, len(self))
+
+    def __len__(self):
+        return len(self._names)
+
+    def __iter__(self):
+        for name in self._names:
+            key = op.join(self.key, name)
+            yield self._store[key]
+
+    def __getitem__(self, idx):
+        key = op.join(self.key, self._names[idx])
+        return self._store[key]
+
+
+class File(compass_model.Array):
+
+    """
+        Represents a file (all loaded as an array of bytes)
+    """
+
+    classkind = "File"
+
+    @staticmethod
+    def canhandle(store, key):
+        return op.isfile(key)
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def displayname(self):
+        return op.basename(self.key)
+
+    @property
+    def description(self):
+        return 'File "%s", size %d bytes' % (self.displayname, op.getsize(self.key))
+
+    @property
+    def shape(self):
+        return (op.getsize(self.key),)
+
+    @property
+    def dtype(self):
+        return np.dtype('u1')
+
+    def __getitem__(self, args):
+        try:
+            with open(self.key, 'rb') as f:
+                data = np.fromstring(f.read(), dtype='u1')
+        except OSError, IOError:
+            data = np.zeros((len(self),), dtype='u1')
+
+        return data[args]
+
+Filesystem.push(File)
+Filesystem.push(Directory)
+
+compass_model.push(Filesystem)
\ No newline at end of file
diff --git a/filesystem_model/test.py b/filesystem_model/test.py
new file mode 100644
index 0000000..e4712c7
--- /dev/null
+++ b/filesystem_model/test.py
@@ -0,0 +1,8 @@
+from compass_model.test import container, store
+from . import Filesystem, Directory, File
+
+url = "file://localhost"
+
+s = store(Filesystem, url)
+c = container(Filesystem, url, Directory, "/")
+
diff --git a/hdf5_model/.DS_Store b/hdf5_model/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/hdf5_model/.DS_Store differ
diff --git a/hdf5_model/__init__.py b/hdf5_model/__init__.py
new file mode 100644
index 0000000..3a064fb
--- /dev/null
+++ b/hdf5_model/__init__.py
@@ -0,0 +1,357 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Implementation of compass_model classes for HDF5 files.
+"""
+
+from itertools import groupby
+import os
+import os.path as op
+import posixpath as pp
+import numpy as np
+import h5py
+
+# Py2App can't successfully import otherwise
+from h5py import defs, utils, h5ac, _proxy, _conv
+
+import compass_model
+
+
+def sort_key(name):
+    """ Sorting key for names in an HDF5 group.
+
+    We provide "natural" sort order; e.g. "7" comes before "12".
+    """
+    return [(int(''.join(g)) if k else ''.join(g)) for k, g in groupby(name, key=unicode.isdigit)]
+
+
+class HDF5Store(compass_model.Store):
+
+    """
+    Data store implementation using an HDF5 file.
+
+    Keys are the full names of objects in the file.
+    """
+
+    def __contains__(self, key):
+        return key in self.f
+
+
+    @property
+    def url(self):
+        return self._url
+
+
+    @property
+    def displayname(self):
+        return op.basename(self.f.filename)
+
+
+    @property
+    def root(self):
+        return self['/']
+
+
+    @property
+    def valid(self):
+        return bool(self.f)
+
+
+    @staticmethod
+    def canhandle(url):
+        if not url.startswith('file://'):
+            return False
+        path = url.replace('file://','')
+        if not h5py.is_hdf5(path):
+            return False
+        return True
+
+
+    def __init__(self, url):
+        if not self.canhandle(url):
+            raise ValueError(url)
+        self._url = url
+        path = url.replace('file://','')
+        self.f = h5py.File(path, 'r')
+
+
+    def close(self):
+        self.f.close()
+
+
+    def getparent(self, key):
+        # HDFCompass requires the parent of the root container be None
+        if key == "" or key == "/":     
+            return None
+        pkey = pp.dirname(key)
+        if pkey == "":
+            pkey = "/"
+        return self[pkey]
+
+
+
+class HDF5Group(compass_model.Container):
+
+    """
+    Represents an HDF5 group, to be displayed in the browser view.
+    """
+
+    classkind = "HDF5 Group"
+
+
+    @staticmethod
+    def canhandle(store, key):
+        return key in store and isinstance(store.f[key], h5py.Group)
+
+
+    @property
+    def _names(self):
+
+        # Lazily build the list of names; this helps when browsing big files
+        if self._xnames is None:
+
+            self._xnames = list(self._group)
+
+            # Natural sort is expensive
+            if len(self._xnames) < 1000:
+                self._xnames.sort(key=sort_key)
+
+        return self._xnames
+
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._group = store.f[key]
+        self._xnames = None
+
+
+    @property
+    def key(self):
+        return self._key
+
+
+    @property
+    def store(self):
+        return self._store
+
+
+    @property
+    def displayname(self):
+        name = pp.basename(self.key)
+        if name == "":
+            name = '/'
+        return name
+
+
+    @property
+    def displaytitle(self):
+        return "%s %s" % (self.store.displayname, self.key)
+
+
+    @property
+    def description(self):
+        return 'Group "%s" (%d members)' % (self.displayname, len(self))
+
+
+    def __len__(self):
+        return len(self._group)
+
+
+    def __iter__(self):
+        for name in self._names:
+            yield self.store[pp.join(self.key,name)]
+
+
+    def __getitem__(self, idx):
+        name = self._names[idx]
+        return self.store[pp.join(self.key, name)]
+
+
+class HDF5Dataset(compass_model.Array):
+
+    """
+    Represents an HDF5 dataset.
+    """
+
+    classkind = "HDF5 Dataset"
+
+
+    @staticmethod
+    def canhandle(store, key):
+        return key in store and isinstance(store.f[key], h5py.Dataset)
+
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f[key]
+
+
+    @property
+    def key(self):
+        return self._key
+
+
+    @property
+    def store(self):
+        return self._store
+
+
+    @property
+    def displayname(self):
+        return pp.basename(self.key)
+
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.displayname,)
+
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+class HDF5KV(compass_model.KeyValue):
+
+    """
+    A KeyValue node used for HDF5 attributes.
+    """
+
+    classkind = "HDF5 Attributes"
+
+
+    @staticmethod
+    def canhandle(store, key):
+        return key in store.f
+
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._obj = store.f[key]
+        self._names = self._obj.attrs.keys()
+
+
+    @property
+    def key(self):
+        return self._key
+
+
+    @property
+    def store(self):
+        return self._store
+
+
+    @property
+    def displayname(self):
+        n = pp.basename(self.key)
+        return n if n != '' else '/'
+
+
+    @property
+    def description(self):
+        return self.displayname
+
+
+    @property
+    def keys(self):
+        return self._names[:]
+
+
+    def __getitem__(self, name):
+        return self._obj.attrs[name]
+
+
+class HDF5Image(compass_model.Image):
+
+    """
+    True-color images.
+    """
+
+    classkind = "HDF5 Truecolor Image"
+
+
+    @staticmethod
+    def canhandle(store, key):
+        if key not in store:
+            return False
+        obj = store.f[key]
+        if obj.attrs.get('CLASS') != 'IMAGE':
+            return False
+        if obj.attrs.get('IMAGE_SUBCLASS') != 'IMAGE_TRUECOLOR':
+            return False
+        if obj.attrs.get('INTERLACE_MODE') != 'INTERLACE_PIXEL':
+            return False
+        return True
+
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._obj = store.f[key]
+
+
+    @property
+    def key(self):
+        return self._key
+
+
+    @property
+    def store(self):
+        return self._store
+
+
+    @property
+    def displayname(self):
+        n = pp.basename(self.key)
+        return n if n != '' else '/'
+
+
+    @property
+    def description(self):
+        return self.displayname
+
+
+    @property
+    def width(self):
+        return self._obj.shape[1]
+
+
+    @property
+    def height(self):
+        return self._obj.shape[0]
+
+
+    @property
+    def palette(self):
+        return None
+
+
+    @property
+    def data(self):
+        return self._obj[:]
+
+
+# Register handlers    
+HDF5Store.push(HDF5KV)
+HDF5Store.push(HDF5Dataset)
+HDF5Store.push(HDF5Group)
+HDF5Store.push(HDF5Image)
+
+compass_model.push(HDF5Store)
\ No newline at end of file
diff --git a/hdf5_model/test.py b/hdf5_model/test.py
new file mode 100644
index 0000000..c4e3028
--- /dev/null
+++ b/hdf5_model/test.py
@@ -0,0 +1,8 @@
+from compass_model.test import container, store
+from . import HDF5Group, HDF5Store
+
+url = "file:///Users/andrew/Documents/Compass/Demo files/2_5.hdf5"
+
+s = store(HDF5Store, url)
+c = container(HDF5Store, url, HDF5Group, "/")
+
diff --git a/package_icons.py b/package_icons.py
new file mode 100644
index 0000000..5ce3fb1
--- /dev/null
+++ b/package_icons.py
@@ -0,0 +1,65 @@
+# This file is part of HDFCompass, a viewer program for HDF5 and other formats
+#
+# Copyright (c) 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+
+"""
+Program to embed PNG icon files in an importable Python module.
+
+Syntax: python package_icons.py outfile.py file1.png [file2.png ...]
+
+"""
+
+import sys
+import glob
+import base64
+import os.path as op
+
+def chunker(seq, size):
+    """ Return a generator which breaks *seq* in to *size*-length chunks.
+    """
+    return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
+
+
+def run(in_names, out_name):
+    """ Main program.
+
+    out_fname: Name of Python module to write.
+    """
+
+    dct = {}    # File name -> Base64 encoded content
+
+    for fname in in_names:
+
+        with open(fname, 'rb') as f:
+            data = f.read()
+            if data[0:8] != b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A":
+                raise ValueError('"%s" is not a valid PNG file' % fname)
+            bname = op.basename(fname)
+            dct[bname] = base64.b64encode(data)
+
+    with open(out_name, 'w') as f:
+
+        f.write('import base64\n\n')
+        for name, string in sorted(dct.iteritems()):
+            string = [('"%s"'%s) for s in chunker(string, 75)]
+            string = "\n".join(string)
+            name = op.basename(name).split('.')[0]
+            f.write(
+"""\
+def %s():
+    return base64.b64decode(
+%s)
+
+""" % (name, string))
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 3:   # program name, infile, outfile
+        sys.stderr.write(__doc__)
+        sys.exit(1)
+
+    in_names = sys.argv[2:]
+    out_name = sys.argv[1]
+
+    run(in_names, out_name)
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..718805d
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,41 @@
+# This file is part of HDFCompass, a viewer for HDF5 and other formats.
+#
+# Copyright 2013-2014 Heliosphere Research LLC
+# All rights reserved.
+#
+# This software product comes with ABSOLUTELY NO WARRANTY.
+
+"""
+Setup script for HDFCompass on Mac OS X.  
+
+Usage:
+    python setup.py py2app
+
+The output is HDFCompass.app, in the dist/ folder.
+
+PyInstaller, for Windows and Linux distribution, does not use setup.py.
+"""
+
+from setuptools import setup
+
+APP = ['HDFCompass.py']
+DATA_FILES = []
+PLIST = {   "CFBundleDocumentTypes": [ { "CFBundleTypeExtensions": ["hdf5","h5"],
+                                      "CFBundleTypeName": "HDF5 Data File",
+                                      "CFBundleTypeRole": "Viewer"} ],
+            "CFBundleIdentifer": "org.alfven.hdfcompass",
+            "CFBundleDisplayName": "HDFCompass",
+            "CFBundleVersion": "0.4.0" }
+
+OPTIONS = { 'argv_emulation': True,
+            'excludes': ['scipy'],
+            'matplotlib_backends': ['wxagg'],
+            'iconfile': 'compass.icns',
+            'plist': PLIST }
+
+setup(
+    app=APP,
+    data_files=DATA_FILES,
+    options={'py2app': OPTIONS},
+    setup_requires=['py2app'],
+)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/hdf-compass.git



More information about the debian-science-commits mailing list