Skip to content
Snippets Groups Projects
Commit 5ed861bf authored by (no author)'s avatar (no author)
Browse files

adding an io module to handle loading GeoTIFFs

git-svn-id: https://svn.ssec.wisc.edu/repos/glance/trunk@204 8a9318a1-56ba-4d59-b755-99d26321be01
parent 6d136949
No related branches found
No related tags found
No related merge requests found
......@@ -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))
......
......@@ -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'
......
......@@ -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 :
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment