floatingpointraster.py 7.4 KB
Newer Older
Hoek, Steven's avatar
Hoek, Steven committed
1
import os.path;
2
3
import stat
from array import array
4
5
from .const import Const, constants as const
from .raster import Raster
Hoek, Steven's avatar
Hoek, Steven committed
6
7
from .gridenvelope2d import GridEnvelope2D;

8
9
10
__author__ = "Steven B. Hoek"

class FloatingPointRaster(Raster, GridEnvelope2D):
11
    """A raster represented by 2 files, with extensions 'flt' and 'hdr'"""
Hoek, Steven's avatar
Hoek, Steven committed
12
    
13
14
15
16
    # Attributes - assign some dummy values for the mean time
    _const = None

    # Data attributes 
Hoek, Steven's avatar
Hoek, Steven committed
17
18
    name = "dummy.flt";
    folder = os.getcwd();
19
20
    cellsize = 1; # default
    nodatavalue = -9999.0; # default
Hoek, Steven's avatar
Hoek, Steven committed
21
22
    
    # Private attributes
23
    datatype = const.FLOAT;
Hoek, Steven's avatar
Hoek, Steven committed
24
25
26
27
    datafile = None;
    currow = 0;
    __envelope = None;
    
28
29
30
31
32
    def __init__(self, filepath='', *datatype): 
        # Check input
        if filepath == '':
            print('File path cannot be an empty string (method __init__).')
        
Hoek, Steven's avatar
Hoek, Steven committed
33
        # Initialise
34
        Raster.__init__(self, filepath)
Hoek, Steven's avatar
Hoek, Steven committed
35
        GridEnvelope2D.__init__(self, 1, 1, 0.0, 0.0, 0.1, 0.1)
36
37
38
39
40
41
        self._const = Const()
        
        # Class and subclass wide constants
        self._const.LSBFIRST = "LSBFIRST";
        self._const.BYTESPERCELL = 4;
        self._const.DATAFILEXT = "flt"
42
        self._const.DATAFILEXTALT = "int"
43
44
45
        self._const.WORLDEXT = "wld"
        self.byteorder = self._const.LSBFIRST        

Hoek, Steven's avatar
Hoek, Steven committed
46
47
48
49
50
51
52
53
54
55
56
        # Retrieve the name from the filepath and assign - incl. extension
        self.name = os.path.basename(filepath);
        # Also derive the folder
        self.folder = os.path.dirname(filepath);
        # Finally set the datatype
        if len(datatype) > 0:
            if (datatype[0] == const.INTEGER): 
                self.datatype = const.INTEGER;
            else: 
                self.datatype = const.FLOAT;        
        
57
    def open(self, mode, ncols=1, nrows=1, xll=0, yll=0, cellsize=100, nodatavalue=-9999.0, byteorder="LSBFIRST"):
Hoek, Steven's avatar
Hoek, Steven committed
58
59
60
61
62
        # Initialise
        super(FloatingPointRaster, self).open(mode); 
        
        # If file does not exist and mode[0] = 'w', create it!
        if (mode[0] == 'w') and (not os.path.exists(self.folder + os.path.sep + self.name)):
63
            self.datafile = open(self.folder + os.path.sep + self.name, 'wb');
Hoek, Steven's avatar
Hoek, Steven committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
            self.__envelope = GridEnvelope2D.__init__(self, ncols, nrows, xll, yll, cellsize, cellsize);
            return True;
        else:    
            # Open the file
            if os.path.exists(self.folder + os.path.sep + self.name):            
                self.datafile = open(self.folder + os.path.sep + self.name, mode[0] + 'b'); 
                if (mode[0] == 'w'):
                    # Assign the data attributes 
                    self.ncols = ncols;
                    self.nrows = nrows;                    
                    self.xll = xll;
                    self.yll = yll;
                    self.cellsize = cellsize;
                    self.nodatavalue = nodatavalue;
                    self.byteorder = byteorder;
                    self.writeheader();
                else: 
                    # Retrieve the data attributes from the header file
                    self.readheader();
                self.__envelope = GridEnvelope2D.__init__(self, self.ncols, self.nrows, self.xll, self.yll, self.cellsize, self.cellsize);
                return True;
            else: return False; 
          
    
    def readheader(self):
89
90
91
92
        # Read header file and assign all attributes
        pos1 = str.rfind(str(self.name), "." + self._const.DATAFILEXT)
        pos2 = str.rfind(str(self.name), "." + self._const.DATAFILEXTALT)
        pos = max(pos1, pos2)
Hoek, Steven's avatar
Hoek, Steven committed
93
94
95
        if pos != -1: hdrFilename = self.name[0:pos] + "." + const.HEADEREXT
        else: raise ValueError("Invalid file name: " + self.name);
        if os.path.exists(self.folder + os.path.sep + hdrFilename):
96
97
98
99
            fileinfo = os.stat(os.path.join(self.folder, self.name))
            filesize = fileinfo[stat.ST_SIZE]
            if filesize == 0:
                raise RuntimeError("Empty header file found!")
Hoek, Steven's avatar
Hoek, Steven committed
100
101
102
103
104
105
106
107
108
109
110
111
            hf = open(self.folder + os.path.sep + hdrFilename, 'r');
            hl = hf.readline();
            self.ncols = int(hl.replace('ncols', '').strip());
            hl = hf.readline();
            self.nrows = int(hl.replace('nrows', '').strip());
            hl = hf.readline();
            self.xll = float(hl.replace('xllcorner', '').strip());        
            hl = hf.readline();
            self.yll = float(hl.replace('yllcorner', '').strip());        
            hl = hf.readline();
            self.cellsize = float(hl.replace('cellsize', '').strip());        
            hl = hf.readline();
112
            if (self.datatype == const.INTEGER): 
Hoek, Steven's avatar
Hoek, Steven committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
                self.nodatavalue = int(hl.replace('NODATA_value', '').strip());
            else: 
                self.nodatavalue = float(hl.replace('NODATA_value', '').strip());
            hl = hf.readline();
            self.byteorder = hl.replace('byteorder', '');         
            hf.close();
        else: 
            msg = "Header file " + hdrFilename + " not found in folder " + self.folder;
            raise IOError(msg);
        
    def next(self):
        # Read the next row if possible, otherwise generate StopIteration
        try:
            self.currow += 1;
            if (self.currow > self.nrows): raise StopIteration;
128
129
            result = self.datafile.read(self.ncols * self._const.BYTESPERCELL);  
            return array(self.datatype, result);      
Hoek, Steven's avatar
Hoek, Steven committed
130
131
132
133
        except:
            raise StopIteration;       
        
    @staticmethod
134
135
    def getDataFileExt(self):
        return self._const.DATAFILEXT;
Hoek, Steven's avatar
Hoek, Steven committed
136
137
    
    @staticmethod
138
139
    def getHeaderFileExt(self):
        return self._const.HEADEREXT;    
Hoek, Steven's avatar
Hoek, Steven committed
140
141
    
    @staticmethod
142
143
    def getBytesPerCell(self):
        return self._const.BYTESPERCELL;
Hoek, Steven's avatar
Hoek, Steven committed
144
145
146
    
    def writeheader(self):
        # Write header file with all attributes 
147
148
149
        pos1 = str.rfind(str(self.name), "." + self._const.DATAFILEXT)
        pos2 = str.rfind(str(self.name), "." + self._const.DATAFILEXTALT)
        pos = max(pos1, pos2)
Hoek, Steven's avatar
Hoek, Steven committed
150
151
152
153
        if pos != -1: hdrFilename = self.name[0:pos] + "." + const.HEADEREXT
        else: raise ValueError("Invalid file name: " + self.name);
        try:
            # Open the file if it exists, otherwise create it
154
            hf = open(self.folder + os.path.sep + hdrFilename, 'w');
Hoek, Steven's avatar
Hoek, Steven committed
155
156
157
158
159
160
161
162
163
   
            # Now write all the attributes
            hf.write("ncols         " + str(self.ncols) + "\n");
            hf.write("nrows         " + str(self.nrows) + "\n");
            hf.write("xllcorner     " + str(self.xll) + "\n");
            hf.write("yllcorner     " + str(self.yll) + "\n");
            hf.write("cellsize      " + str(self.cellsize) + "\n");
            hf.write("NODATA_value  " + str(self.nodatavalue) + "\n");
            hf.write("byteorder     " + self.byteorder + "\n");
164
        except Exception as e:
Hoek, Steven's avatar
Hoek, Steven committed
165
166
167
168
169
170
171
172
            msg = "Header file " + hdrFilename + " could not be written in folder " + self.folder;
            raise IOError(msg + "(" + str(e) + ")");
        
    def writenext(self, sequence_with_data):
        # Write the next data if possible, otherwise generate StopIteration
        # We cannot know whether exactly 1 row is included or not.
        try:          
            return self.datafile.write(sequence_with_data);
173
        except Exception as e:
Hoek, Steven's avatar
Hoek, Steven committed
174
175
176
177
178
179
180
            raise IOError(str(e));            
            raise StopIteration;       
                
    def reset(self):
        self.datafile.seek(0);
        super(FloatingPointRaster, self).reset()