Ignore:
Timestamp:
Mar 21, 2006, 3:51:39 PM (17 years ago)
Author:
nick
Message:

Added functionality to geospatial_data.py including import and exporting pts and xya files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • inundation/geospatial_data/geospatial_data.py

    r2489 r2570  
    77from utilities.numerical_tools import ensure_numeric
    88
    9 from Numeric import concatenate
     9from Numeric import concatenate, array, Float, shape
    1010
    1111from coordinate_transforms.geo_reference import Geo_reference
     12
     13from os import access, F_OK, R_OK
    1214       
    1315class Geospatial_data:
    1416
    1517    def __init__(self,
    16                  data_points,
     18                 data_points = None,
    1719                 attributes = None,
    1820                 geo_reference = None,
    19                  default_attribute_name = None):
     21                 default_attribute_name = None,
     22                 file_name = None):
     23         
    2024
    2125        """Create instance from data points and associated attributes
     
    4145        If None, the default is the 'first'
    4246       
     47        file_name: Name of input file.....
     48       
    4349        """
    4450
    45         self.data_points = ensure_numeric(data_points)
    46         self.set_attributes(attributes)
    47         self.set_geo_reference(geo_reference)
    48         self.set_default_attribute_name(default_attribute_name)
    49        
    50 
    51 
     51        if file_name is None:
     52            self.file_name = None
     53            self.check_data_points(data_points)
     54
     55            self.set_attributes(attributes)
     56            self.set_geo_reference(geo_reference)
     57            self.set_default_attribute_name(default_attribute_name)
     58           
     59       
     60        else:
     61#            print 'from init file name:', file_name
     62            if access(file_name, F_OK) == 0 :
     63                msg = 'File %s does not exist or is not accessable' %file_name
     64                raise msg
     65            else:
     66                data = {}   
     67# watch for case where file name and points, attributes etc are provided!!
     68# if file name then all provided info will be removed!
     69                self.file_name = file_name
     70                data = import_points_file(self.file_name)
     71               
     72#                print 'data: point in init', data['pointlist']
     73#                print 'attrib: point in init', data['attributelist']
     74#                print 'geo_ref: point in init', data['geo_reference']
     75               
     76                data_points = data['pointlist']
     77                attributes = data['attributelist']
     78                get_reference = data['geo_reference']
     79               
     80                self.check_data_points(data_points)
     81                self.set_attributes(attributes)
     82                self.set_geo_reference(geo_reference)
     83                self.set_default_attribute_name(default_attribute_name)
     84
     85       
     86    def check_data_points(self, data_points):
     87        """Checks data points
     88        """
     89       
     90        if data_points is None:
     91            self.data_points = None
     92#           FIXME: should throw an error if bad file name and no data!
     93            print 'There is no data or files to read for data!!'
     94            msg = 'file name %s does not exist in data set and the ' %self.file_name
     95#           some assert
     96           
     97        else:
     98            self.data_points = ensure_numeric(data_points)
    5299
    53100    def set_attributes(self, attributes):
     
    95142        self.default_attribute_name = default_attribute_name
    96143
     144    def set_file_name(self, file_name = None):
     145        if file_name is None:
     146            self.file_name = None
     147        else:
     148            if access(file_name, F_OK) == 0 :
     149                msg = 'Geospatial_data object needs have either data_points \n'
     150                msg += ' or a file with data points'
     151                raise msg
     152            else:   
     153                self.file_name = file_name
     154                print 'file name from set', self.file_name
     155
     156    def set_self_from_file(self, file_name = None):
     157        # check if file_name is a string and also that the file exists
     158        if file_name is None:
     159            self.file_name = None
     160#        else:
     161#            if access(self.file_name, F_OK) == 0 :
     162#                msg = 'Geospatial_data object needs have either data_points \n'
     163#                msg += ' or a file with data points'
     164#                raise msg
     165        else:   
     166            self.file_name = file_name
     167            self = self.import_points_file(file_name)
     168#            print 'data points from set self file name', self.data_points
     169#            print 'attributes from set self file name', self.attributes
     170#            print 'geo_ref from set self file name', self.geo_reference
     171        return self
     172           
    97173
    98174    def get_geo_reference(self):
     
    156232        geo_ref = Geo_reference(zone1, xll, yll)
    157233       
    158         if zone1 == zone2: 
     234        if zone1 == zone2:
    159235            a_rel_points = self.get_data_points()
    160236            b_rel_points = other.get_data_points()
     
    184260            ZONE to allow addition.'
    185261            raise msg
     262
    186263     
     264   
     265    ###
     266    #  IMPORT/EXPORT POINTS FILES
     267    ###
     268    '''
     269    def export_points_file(ofile, point_dict):
     270        """
     271        write a points file, ofile, as a binary (.xya) or text (.pts) file
     272
     273        ofile is the file name, including the extension
     274
     275        The point_dict is defined at the top of this file.
     276        """
     277        #this was done for all keys in the mesh file.
     278        #if not mesh_dict.has_key('points'):
     279        #    mesh_dict['points'] = []
     280        if (ofile[-4:] == ".xya"):
     281            _write_xya_file(ofile, point_dict)
     282        elif (ofile[-4:] == ".pts"):
     283            _write_pts_file(ofile, point_dict)
     284        else:
     285            msg = 'Unknown file type %s ' %ofile
     286        raise IOError, msg
     287
     288    '''       
     289def import_points_file( ofile, delimiter = None, verbose = False):
     290    """ load an .xya or .pts file
     291    Note: will throw an IOError if it can't load the file.
     292    Catch these!
     293    """
     294   
     295    all_data = {}
     296    if ofile[-4:]== ".xya":
     297        try:
     298            if delimiter == None:
     299                try:
     300                    fd = open(ofile)
     301                    all_data = _read_xya_file(fd, ',')
     302                except SyntaxError:
     303                    fd.close()
     304                    fd = open(ofile)
     305                    all_data = _read_xya_file(fd, ' ')
     306            else:
     307                fd = open(ofile)
     308                all_data = _read_xya_file(fd, delimiter)
     309            fd.close()
     310        except (IndexError,ValueError,SyntaxError):
     311            fd.close()   
     312            msg = 'Could not open file %s ' %ofile
     313            raise IOError, msg
     314        except IOError:
     315            # Catch this to add an error message
     316            msg = 'Could not open file %s ' %ofile
     317            raise IOError, msg
     318           
     319    elif ofile[-4:]== ".pts":
     320        try:
     321#            print 'hi from import_points_file'
     322            all_data = _read_pts_file(ofile, verbose)
     323#            print 'hi1 from import_points_file', all_data
     324        except IOError, e:   
     325            msg = 'Could not open file %s ' %ofile
     326            raise IOError, msg       
     327    else:     
     328        msg = 'Extension %s is unknown' %ofile[-4:]
     329        raise IOError, msg
     330
     331    return all_data
     332
     333def export_points_file(ofile, point_dict):
     334    """
     335    write a points file, ofile, as a text (.xya) or binary (.pts) file
     336
     337    ofile is the file name, including the extension
     338
     339    The point_dict is defined at the top of this file.
     340    """
     341    #this was done for all keys in the mesh file.
     342    #if not mesh_dict.has_key('points'):
     343    #    mesh_dict['points'] = []
     344    if (ofile[-4:] == ".xya"):
     345        _write_xya_file(ofile, point_dict)
     346    elif (ofile[-4:] == ".pts"):
     347        _write_pts_file(ofile, point_dict)
     348    else:
     349        msg = 'Unknown file type %s ' %ofile
     350        raise IOError, msg
     351
     352def _read_pts_file(file_name, verbose = False):
     353    """Read .pts NetCDF file
     354   
     355    Return a dic of array of points, and dic of array of attribute
     356    eg
     357    dic['points'] = [[1.0,2.0],[3.0,5.0]]
     358    dic['attributelist']['elevation'] = [[7.0,5.0]
     359    """   
     360    #FIXME: (DSG) This format has issues.
     361    # There can't be an attribute called points
     362    # consider format change
     363
     364#    print 'hi for read points file'
     365    from Scientific.IO.NetCDF import NetCDFFile
     366   
     367    if verbose: print 'Reading ', file_name
     368   
     369       
     370    # see if the file is there.  Throw a QUIET IO error if it isn't
     371    fd = open(file_name,'r')
     372    fd.close()
     373   
     374    #throws prints to screen if file not present
     375    fid = NetCDFFile(file_name, 'r')
     376   
     377    point_atts = {} 
     378        # Get the variables
     379    point_atts['pointlist'] = array(fid.variables['points'])
     380    keys = fid.variables.keys()
     381    if verbose: print 'Got %d variables: %s' %(len(keys), keys)
     382    try:
     383        keys.remove('points')
     384    except IOError, e:       
     385        fid.close()   
     386        msg = 'Expected keyword "points" but could not find it'
     387        raise IOError, msg
     388   
     389    attributes = {}
     390    for key in keys:
     391        if verbose: print "reading attribute '%s'" %key
     392           
     393        attributes[key] = array(fid.variables[key])
     394   
     395    point_atts['attributelist'] = attributes
     396   
     397    try:
     398        geo_reference = Geo_reference(NetCDFObject=fid)
     399        point_atts['geo_reference'] = geo_reference
     400    except AttributeError, e:
     401        #geo_ref not compulsory
     402        point_atts['geo_reference'] = None
     403   
     404    fid.close()
     405    return point_atts
     406
     407
     408def _read_xya_file( fd, delimiter):
     409#    print 'hello from read xya data'
     410    points = []
     411    pointattributes = []
     412    title = fd.readline()
     413    att_names = clean_line(title,delimiter)
     414   
     415    att_dict = {}
     416    line = fd.readline()
     417    numbers = clean_line(line,delimiter)
     418    while len(numbers) > 1:
     419        if numbers != []:
     420            try:
     421                x = float(numbers[0])
     422                y = float(numbers[1])
     423                points.append([x,y])
     424                numbers.pop(0)
     425                numbers.pop(0)
     426                #attributes = []
     427                #print "att_names",att_names
     428                #print "numbers",numbers
     429                if len(att_names) != len(numbers):
     430                    fd.close()
     431                    # It might not be a problem with the title
     432                    #raise TitleAmountError
     433                    raise IOError
     434                for i,num in enumerate(numbers):
     435                    num.strip()
     436                    if num != '\n' and num != '':
     437                        #attributes.append(float(num))
     438                        att_dict.setdefault(att_names[i],[]).append(float(num))
     439                       
     440            except ValueError:
     441                raise SyntaxError
     442        line = fd.readline()
     443        numbers = clean_line(line,delimiter)
     444   
     445    if line == '':
     446            # end of file
     447        geo_reference = None
     448    else:
     449        geo_reference = Geo_reference(ASCIIFile=fd,read_title=line)
     450   
     451    xya_dict = {}
     452    xya_dict['pointlist'] = array(points).astype(Float)
     453   
     454    for key in att_dict.keys():
     455        att_dict[key] = array(att_dict[key]).astype(Float)
     456    xya_dict['attributelist'] = att_dict
     457   
     458    xya_dict['geo_reference'] = geo_reference
     459    #print "xya_dict",xya_dict
     460    return xya_dict
     461
     462
     463
     464def _write_pts_file(file_name, point_atts):
     465    """Write .pts NetCDF file   
     466
     467    WARNING: This function mangles the point_atts data structure
     468    """
     469    #FIXME: (DSG)This format has issues.
     470    # There can't be an attribute called points
     471    # consider format change
     472
     473
     474    legal_keys = ['pointlist', 'attributelist', 'geo_reference']
     475    for key in point_atts.keys():
     476        msg = 'Key %s is illegal. Valid keys are %s' %(key, legal_keys)
     477        assert key in legal_keys, msg
     478   
     479    from Scientific.IO.NetCDF import NetCDFFile
     480    _point_atts2array(point_atts)
     481    # NetCDF file definition
     482    outfile = NetCDFFile(file_name, 'w')
     483   
     484    #Create new file
     485    outfile.institution = 'Geoscience Australia'
     486    outfile.description = 'NetCDF format for compact and portable storage ' +\
     487                      'of spatial point data'
     488   
     489    # dimension definitions
     490    shape = point_atts['pointlist'].shape[0]
     491    outfile.createDimension('number_of_points', shape) 
     492    outfile.createDimension('number_of_dimensions', 2) #This is 2d data
     493   
     494    # variable definition
     495    outfile.createVariable('points', Float, ('number_of_points',
     496                                             'number_of_dimensions'))
     497
     498    #create variables 
     499    outfile.variables['points'][:] = point_atts['pointlist'] #.astype(Float32)
     500    for key in point_atts['attributelist'].keys():
     501        outfile.createVariable(key, Float, ('number_of_points',))
     502        outfile.variables[key][:] = point_atts['attributelist'][key] #.astype(Float32)
     503       
     504    if point_atts.has_key('geo_reference') and not point_atts['geo_reference'] == None:
     505        point_atts['geo_reference'].write_NetCDF(outfile)
     506       
     507    outfile.close()
     508 
     509
     510
     511def _write_xya_file( file_name, xya_dict, delimiter = ','):
     512    """
     513    export a file, ofile, with the xya format
     514   
     515    """
     516    points = xya_dict['pointlist']
     517    pointattributes = xya_dict['attributelist']
     518   
     519    fd = open(file_name,'w')
     520 
     521    titlelist = ""
     522    for title in pointattributes.keys():
     523        titlelist = titlelist + title + delimiter
     524    titlelist = titlelist[0:-len(delimiter)] # remove the last delimiter
     525    fd.write(titlelist+"\n")
     526    #<vertex #> <x> <y> [attributes]
     527    for i,vert in enumerate( points):
     528       
     529        attlist = ","
     530        for att in pointattributes.keys():
     531            attlist = attlist + str(pointattributes[att][i])+ delimiter
     532        attlist = attlist[0:-len(delimiter)] # remove the last delimiter
     533        attlist.strip()
     534        fd.write( str(vert[0]) + delimiter
     535                  + str(vert[1])
     536                  + attlist + "\n")
     537   
     538    # geo_reference info
     539    if xya_dict.has_key('geo_reference') and \
     540           not xya_dict['geo_reference'] is None:
     541        xya_dict['geo_reference'].write_ASCII(fd)
     542    fd.close()
     543   
     544def _point_atts2array(point_atts):
     545    point_atts['pointlist'] = array(point_atts['pointlist']).astype(Float)
     546   
     547    for key in point_atts['attributelist'].keys():
     548        point_atts['attributelist'][key]= array(point_atts['attributelist'][key]).astype(Float)
     549    return point_atts
     550
     551   
    187552
    188553
     
    205570
    206571   
    207    
    208 
    209 
    210 
    211 
    212572def points_dictionary2geospatial_data(points_dictionary):
    213573    """Convert points_dictionary to geospatial data object
     
    229589                           geo_reference = geo)
    230590
    231 
    232            
    233            
    234        
     591def clean_line(line,delimiter):     
     592    """Remove whitespace
     593    """
     594    #print ">%s" %line
     595    line = line.strip()
     596    #print "stripped>%s" %line
     597    numbers = line.split(delimiter)
     598    i = len(numbers) - 1
     599    while i >= 0:
     600        if numbers[i] == '':
     601            numbers.pop(i)
     602        else:
     603            numbers[i] = numbers[i].strip()
     604       
     605        i += -1
     606    #for num in numbers:
     607    #    print "num>%s<" %num
     608    return numbers
     609           
     610#def add_points_files(file):           
     611       
Note: See TracChangeset for help on using the changeset viewer.