diff --git a/pyglance/glance/data.py b/pyglance/glance/data.py
index fe407d66b04665ecca99c809339d2b26150ea300..af8e40591da7b19375260b2c5ce994d5b6f1aabc 100644
--- a/pyglance/glance/data.py
+++ b/pyglance/glance/data.py
@@ -237,14 +237,36 @@ class DiffInfoObject (object) :
     (if both a value and percent are present, two epsilon tests will be done)
     """
     
-    # Upcasts to be used in difference computation to avoid overflow. Currently only unsigned
-    # ints are upcast.
-    # FUTURE: handle uint64s as well (there is no int128, so might have to detect overflow)
+    POSITIVE_UPCASTS = {
+                        np.uint8:   np.int16,
+                        np.uint16:  np.int32,
+                        np.uint32:  np.int64,
+                        np.uint64:  np.float32,
+                       }
+    
+    # Upcasts to be used in difference computation to avoid overflow.
+    # right now this is agressively upcasting the comparison data
     DATATYPE_UPCASTS = {
-        np.uint8:  np.int16,
-        np.uint16: np.int32,
-        np.uint32: np.int64
-        }
+                        np.int8:    np.int16,
+                        np.int16:   np.int32,
+                        np.int32:   np.int64,
+                        np.int64:   np.float32,
+                        
+                        #np.float32: np.float64,
+                        #np.float64: np.float128,
+                       }
+    # FUTURE: right now the actual range of the data isn't being considered when upcasting
+    # (Note: numpy.finfo and numpy.iinfo can be used to get more data on types)
+    TYPE_MAXIMUM = {
+                    np.int16:    32767,
+                    np.int32:    2147483647,
+                    np.int64:    9223372036854775807,
+                    
+                    np.float32:  3.4028235e+38,
+                    
+                    np.float64:  1.7976931348623157e+308,
+                    #np.float128: 1.189731495357231765e+4932,
+                   }
     
     def __init__(self, aDataObject, bDataObject,
                  epsilonValue=0.0, epsilonPercent=None) :
@@ -278,9 +300,17 @@ class DiffInfoObject (object) :
             type_to_return = np.common_type(data1, data2)
             changed_type   = True
         
-        # upcast the type if we need to
+        # make sure we're using a type that has negative values in it
+        if type_to_return in DiffInfoObject.POSITIVE_UPCASTS :
+            type_to_return = DiffInfoObject.POSITIVE_UPCASTS[type_to_return]
+            changed_type = True
+        
+        # upcast the type if we think we'll need more space for subtracting
         if type_to_return in DiffInfoObject.DATATYPE_UPCASTS :
             type_to_return = DiffInfoObject.DATATYPE_UPCASTS[type_to_return]
+            changed_type = True
+        
+        if changed_type :
             LOG.debug('To prevent overflow, difference data will be upcast from ('
                       + str(data1.dtype) + '/' + str(data2.dtype) + ') to: ' + str(type_to_return))
         
diff --git a/pyglance/glance/io.py b/pyglance/glance/io.py
index cbe5223c28ce60ca2759bef167bbbdc07f1ecf6c..55873ddf59245d1bc654dfdbced6471a61f98e3a 100644
--- a/pyglance/glance/io.py
+++ b/pyglance/glance/io.py
@@ -52,6 +52,13 @@ except ImportError:
     LOG.info('no adl_blob format handler available')
     adl_blob = None
 
+try :
+    from osgeo import gdal
+    LOG.info('loading osgeo module for GeoTIFF data file access')
+except :
+    LOG.info('no osgeo available for reading GeoTIFF data files')
+    gdal = None
+
 UNITS_CONSTANT = "units"
 
 fillValConst1 = '_FillValue'
@@ -916,6 +923,174 @@ class aeri(object):
 # handle the variety of file suffixes by building aliases to aeri class
 cxs = rnc = cxv = csv = spc = sum = uvs = aeri
 
+class tiff (object):
+    """wrapper for to open GeoTIFF data sets for comparison
+    __call__ yields sequence of variable names
+    __getitem__ returns individual variables ready for slicing to numpy arrays
+    """
+    
+    _tiff = None
+    
+    # if we are using meaningful names, we will translate between
+    # the band index numbers and these names (otherwise bands use generic names)
+    EXPECTED_BAND_NAME_KEY = {
+                                1: ["grayscale value"],
+                                3: ["red", "green", "blue"],
+                                4: ["red", "green", "blue", "alpha"],
+                             }
+    SPECIAL_NAMES_TO_IDX   =  {
+                                "grayscale value":  1,
+                                "red":              1,
+                                "green":            2,
+                                "blue":             3,
+                                "alpha":            4,
+                              }
+    
+    def _get_generic_band_name (self, number) :
+        """get a generic band name for this number"""
+        
+        return ("band at index " + str(number))
+    
+    def _get_band_index_from_name (self, name) :
+        """get an index for the band from a name
+        
+        name may be either a meaningful name from the list that shows
+        up in SPECIAL_NAMES_TO_IDX's keys or a generic name that was
+        generated by _get_generic_band_name
+        """
+        
+        to_return = None
+        
+        if name in self.SPECIAL_NAMES_TO_IDX.keys() :
+            to_return = self.SPECIAL_NAMES_TO_IDX[name]
+        else :
+            to_return = int(name.split(' ')[-1])
+        
+        return to_return
+    
+    def __init__(self, filename, allowWrite=False, useMeaningfulNames=True):
+        
+        if gdal is None:
+            LOG.error('gdal is not installed and is needed in order to read GeoTIFF files')
+            assert(gdal is not None)
+        
+        if allowWrite:
+            LOG.warn("Write access requested, but is not currently supported for GeoTIFF files. File will be opened read-only.")
+        
+        self._tiff     = gdal.Open(filename)
+        self.niceNames = useMeaningfulNames
+
+    def __call__(self):
+        "yield names of variables to be compared"
+        
+        # GeoTIFF files don't actually have named variables, so get something appropriate based on the numbering of bands
+        num_bands = self._tiff.RasterCount
+        
+        to_return = [ ]
+        if self.niceNames and (num_bands in self.EXPECTED_BAND_NAME_KEY.keys()) :
+            to_return = self.EXPECTED_BAND_NAME_KEY[num_bands][:]
+        else :
+            for bandNumber in range(1, num_bands + 1) :
+                to_return.append(self._get_generic_band_name(bandNumber))
+        
+        return to_return
+    
+    # this returns a numpy array with a copy of the full, scaled
+    # data for this variable, if the data type must be changed to allow
+    # for scaling it will be (so the return type may not reflect the
+    # type found in the original file)
+    def __getitem__(self, name):
+        
+        LOG.debug("opening variable: " + name)
+        
+        # first figure out the index for this variable
+        var_index = self._get_band_index_from_name(name)
+        
+        # get the data out of the file
+        temp_band = self._tiff.GetRasterBand(var_index)
+        temp_data = temp_band.ReadAsArray()
+        
+        # there is no standard scaling procedure for GeoTIFFs, so skip that!
+        
+        return temp_data
+    
+    # TODO, this hasn't been supported in other file types
+    def close (self) :
+        # Dave couldn't find any explicit way to close it other
+        # than let the garbage collector take care of it
+        self._tiff = None
+    
+    def get_variable_object(self, name):
+        return None
+    
+    def missing_value(self, name):
+        return None
+    
+    def create_new_variable(self, variablename, missingvalue=None, data=None, variabletocopyattributesfrom=None):
+        """
+        TODO, this is not yet supported for GeoTIFFs
+        
+        create a new variable with the given name
+        optionally set the missing value (fill value) and data to those given
+        
+        the created variable will be returned, or None if a variable could not
+        be created
+        """
+        
+        LOG.warn ("GeoTIFF io class does not yet support writing. Unable to create new variable in GeoTIFF file.")
+        
+        return None
+    
+    def add_attribute_data_to_variable(self, variableName, newAttributeName, newAttributeValue) :
+        """
+        TODO this is not yet supported for GeoTIFFs
+        
+        if the attribute exists for the given variable, set it to the new value
+        if the attribute does not exist for the given variable, create it and set it to the new value
+        """
+        
+        LOG.warn ("GeoTIFF io class does not yet support writing. Unable to add attribute information to GeoTIFF file.")
+        
+        return
+    
+    def get_variable_attributes (self, variableName, caseInsensitive=True) :
+        """
+        returns all the attributes associated with a variable name
+        """
+        
+        # FUTURE, GeoTIFF files do have attributes, but this isn't hooked up yet
+        
+        return { }
+    
+    def get_attribute(self, variableName, attributeName, caseInsensitive=True) :
+        """
+        returns the value of the attribute if it is available for this variable, or None
+        """
+        
+        # FUTURE, GeoTIFF files do have attributes, but this isn't hooked up yet
+        
+        return None
+    
+    def get_global_attributes(self, caseInsensitive=True) :
+        """
+        get a list of all the global attributes for this file or None
+        """
+        
+        # FUTURE, GeoTIFF files do have attributes, but this isn't hooked up yet
+        
+        return { }
+    
+    def get_global_attribute(self, attributeName, caseInsensitive=True) :
+        """
+        returns the value of a global attribute if it is available or None
+        """
+        
+        # FUTURE, GeoTIFF files do have attributes, but this isn't hooked up yet
+        
+        return None
+
+# people also name tiff files with one f...
+tif = tiff
 
 def _search_xml(pathname):
     xs = '.xml'
diff --git a/pyglance/glance/load.py b/pyglance/glance/load.py
index 034d37af541b50dd9bf0f382cb3a76a460897741..e35ba4167b76d368909523a0c8578bbec12ee12d 100644
--- a/pyglance/glance/load.py
+++ b/pyglance/glance/load.py
@@ -9,7 +9,7 @@ Copyright (c) 2012 University of Wisconsin SSEC. All rights reserved.
 """
 
 import logging
-from pycdf import CDFError
+#from pycdf import CDFError
 import numpy
 
 import glance.delta  as delta
@@ -249,10 +249,11 @@ def load_variable_data(fileObject, variableNameInFile,
     else :
         try :
             variableData = numpy.array(fileObject[variableNameInFile]) if forceDType is None else numpy.array(fileObject[variableNameInFile], dtype=forceDType)
-        except CDFError :
+        except Exception, ex :
+            import traceback
             exceptionToRaise = ValueError('Unable to retrieve ' + variableNameInFile + ' data. The variable name ' + 
                       ' may not exist in this file or an error may have occured while attempting to' +
-                      ' access the data. Details of file access error observed: ' + str(CDFError))
+                      ' access the data. Details of file access error observed: ' + str(ex))
     
     # if we ended up with an exception, raise that now
     if exceptionToRaise is not None :