source: trunk/anuga_core/source/anuga/damage_modelling/exposure.py @ 8125

Last change on this file since 8125 was 7765, checked in by hudson, 14 years ago

Refactoring - moved file conversion routines to file_conversion folder, moved file loading/saving functions to file module.

File size: 8.4 KB
Line 
1import csv
2
3from anuga.anuga_exceptions import TitleValueError, \
4                                    DataMissingValuesError
5
6from anuga.file.csv_file import load_csv_as_dict
7
8from anuga.geospatial_data.geospatial_data import Geospatial_data,\
9     ensure_absolute
10
11LAT_TITLE = 'LATITUDE'
12LONG_TITLE = 'LONGITUDE'
13X_TITLE = 'x'
14Y_TITLE = 'y'
15
16
17
18class Exposure:
19    '''
20    Class for National Exposure Database storage (NEXIS).
21    Returns a csv file handle
22    '''
23    def __init__(self,file_name, latitude_title=LAT_TITLE,
24                 longitude_title=LONG_TITLE, is_x_y_locations=None,
25                 x_title=X_TITLE, y_title=Y_TITLE,
26                 refine_polygon=None, title_check_list=None):
27        """
28        This class is for handling the exposure csv file.
29        It reads the file in and converts the lats and longs to a geospatial
30        data object.
31        Use the methods to read and write columns.
32
33        The format of the csv files it reads is;
34           The first row is a title row.
35           comma's are the delimiters
36           each column is a 'set' of data
37
38        Feel free to use/expand it to read other csv files.
39
40        It is not for adding and deleting rows
41
42        Can geospatial handle string attributes? It's not made for them.
43        Currently it can't load and save string att's.
44
45        So just use geospatial to hold the x, y and georef? Bad, since
46        different att's are in diferent structures.  Not so bad, the info
47        to write if the .csv file is saved is in attribute_dic
48
49        The location info is in the geospatial attribute.
50        """
51
52        self._file_name = file_name
53        self._geospatial = None #
54
55        # self._attribute_dic is a dictionary.
56        #The keys are the column titles.
57        #The values are lists of column data
58
59        # self._title_index_dic is a dictionary.
60        #The keys are the column titles.
61        #The values are the index positions of file columns.
62        self._attribute_dic, self._title_index_dic = \
63            load_csv_as_dict(self._file_name, \
64            title_check_list=title_check_list)
65        try:
66            #Have code here that handles caps or lower
67            lats = self._attribute_dic[latitude_title]
68            longs = self._attribute_dic[longitude_title]
69        except KeyError:
70            # maybe a warning..
71            #Let's see if this works..
72            if False != is_x_y_locations:
73                is_x_y_locations = True
74            pass
75        else:
76            self._geospatial = Geospatial_data(latitudes=lats,
77                                               longitudes=longs)
78
79        if is_x_y_locations is True:
80            if self._geospatial is not None:
81                pass #fixme throw an error
82            try:
83                xs = self._attribute_dic[x_title]
84                ys = self._attribute_dic[y_title]
85                points = [[float(i),float(j)] for i,j in map(None,xs,ys)]
86            except KeyError:
87                # maybe a warning..
88                msg = "Could not find location information."
89                raise TitleValueError, msg
90            else:
91                self._geospatial = Geospatial_data(data_points=points)
92
93        # create a list of points that are in the refining_polygon
94        # described by a list of indexes representing the points
95
96    ##
97    # @brief Create a comparison method.
98    # @param self This object.
99    # @param other The other object.
100    # @return True if objects are 'same'.
101    def __cmp__(self, other):
102        #check that 'other' is an instance of this class
103        if isinstance(self, type(other)):
104            result = cmp(self._attribute_dic, other._attribute_dic)
105            if result <> 0:
106                return result
107
108            # The order of the columns is important. Therefore..
109            result = cmp(self._title_index_dic, other._title_index_dic)
110            if result <> 0:
111                return result
112            for self_ls, other_ls in map(None, self._attribute_dic,
113                                         other._attribute_dic):
114                result = cmp(self._attribute_dic[self_ls],
115                             other._attribute_dic[other_ls])
116                if result <> 0:
117                    return result
118            return 0
119        else:
120            return 1
121
122    ##
123    # @brief Get a list of column values given a column name.
124    # @param column_name The name of the column to get values from.
125    # @param use_refind_polygon Unused??
126    def get_column(self, column_name, use_refind_polygon=False):
127        """
128        Given a column name return a list of the column values
129
130        Note, the type of the values will be String!
131        do this to change a list of strings to a list of floats
132        time = [float(x) for x in time]
133
134        Not implemented:
135        if use_refind_polygon is True, only return values in the
136        refined polygon
137        """
138
139        if not self._attribute_dic.has_key(column_name):
140            msg = 'There is no column called %s!' % column_name
141            raise TitleValueError, msg
142
143        return self._attribute_dic[column_name]
144
145    ##
146    # @brief ??
147    # @param value_column_name ??
148    # @param known_column_name ??
149    # @param known_values ??
150    # @param use_refind_polygon ??
151    def get_value(self, value_column_name, known_column_name,
152                  known_values, use_refind_polygon=False):
153        """
154        Do linear interpolation on the known_colum, using the known_value,
155        to return a value of the column_value_name.
156        """
157
158        pass
159
160    ##
161    # @brief Get a geospatial object that describes the locations.
162    # @param use_refind_polygon Unused??
163    def get_location(self, use_refind_polygon=False):
164        """
165        Return a geospatial object which describes the
166        locations of the location file.
167
168        Note, if there is not location info, this returns None.
169
170        Not implemented:
171        if use_refind_polygon is True, only return values in the
172        refined polygon
173        """
174
175        return self._geospatial
176
177    ##
178    # @brief Add column to 'end' of CSV data.
179    # @param column_name The new column name.
180    # @param column_values The new column values.
181    # @param overwrite If True, overwrites last column, doesn't add at end.
182    def set_column(self, column_name, column_values, overwrite=False):
183        """
184        Add a column to the 'end' (with the right most column being the end)
185        of the csv file.
186
187        Set overwrite to True if you want to overwrite a column.
188
189        Note, in column_name white space is removed and case is not checked.
190        Precondition
191        The column_name and column_values cannot have comma's in it.
192        """
193
194        # sanity checks
195        value_row_count = \
196                len(self._attribute_dic[self._title_index_dic.keys()[0]])
197        if len(column_values) <> value_row_count:
198            msg = 'The number of column values must equal the number of rows.'
199            raise DataMissingValuesError, msg
200
201        # check new column name isn't already used, and we aren't overwriting
202        if self._attribute_dic.has_key(column_name):
203            if not overwrite:
204                msg = 'Column name %s already in use!' % column_name
205                raise TitleValueError, msg
206        else:
207            # New title.  Add it to the title index.
208            self._title_index_dic[column_name] = len(self._title_index_dic)
209
210        self._attribute_dic[column_name] = column_values
211
212    ##
213    # @brief Save the exposure CSV  file.
214    # @param file_name If supplied, use this filename, not original.
215    def save(self, file_name=None):
216        """
217        Save the exposure csv file
218        """
219
220        if file_name is None:
221            file_name = self._file_name
222
223        fd = open(file_name, 'wb')
224        writer = csv.writer(fd)
225
226        #Write the title to a cvs file
227        line = [None] * len(self._title_index_dic)
228        for title in self._title_index_dic.iterkeys():
229            line[self._title_index_dic[title]] = title
230        writer.writerow(line)
231
232        # Write the values to a cvs file
233        value_row_count = \
234                len(self._attribute_dic[self._title_index_dic.keys()[0]])
235        for row_i in range(value_row_count):
236            line = [None] * len(self._title_index_dic)
237            for title in self._title_index_dic.iterkeys():
238                line[self._title_index_dic[title]] = \
239                     self._attribute_dic[title][row_i]
240            writer.writerow(line)
241
Note: See TracBrowser for help on using the repository browser.