@@ -51,6 +51,31 @@ class Exposures():
5151 centroid(s) affecting each exposure. Filled in 'assign' method.
5252 """
5353
54+ vars_oblig = {'tag' ,
55+ 'ref_year' ,
56+ 'value_unit' ,
57+ '_coord' ,
58+ 'value' ,
59+ 'impact_id' ,
60+ 'id'
61+ }
62+ """Name of the variables needed to compute the impact. Types: scalar, str,
63+ list, 1dim np.array of size num_exposures, GridPoints and Tag."""
64+
65+ vars_def = {'assigned'
66+ }
67+ """Name of the variables used in impact calculation whose value is
68+ descriptive or can be recomputed. Types: dict.
69+ """
70+
71+ vars_opt = {'deductible' ,
72+ 'cover' ,
73+ 'category_id' ,
74+ 'region_id'
75+ }
76+ """Name of the variables that aren't need to compute the impact. Types:
77+ scalar, string, list, 1dim np.array of size num_exposures."""
78+
5479 def __init__ (self , file_name = '' , description = '' ):
5580 """Fill values from file, if provided.
5681
@@ -73,20 +98,13 @@ def __init__(self, file_name='', description=''):
7398 >>> exp_city.id = np.array([11, 12, 13])
7499 >>> exp_city.check()
75100
76- Read exposures from Zurich.mat and checks consistency data.
101+ Read exposures from ENT_TEMPLATE_XLS and checks consistency data.
77102
78103 >>> exp_city = Exposures(ENT_TEMPLATE_XLS)
79104 """
80- self .clear ()
81- if file_name != '' :
82- self .read (file_name , description )
83-
84- def clear (self ):
85- """Reinitialize attributes."""
86- # Optional variables
87105 self .tag = Tag ()
88106 self .ref_year = CONFIG ['entity' ]['present_ref_year' ]
89- self .value_unit = 'NA '
107+ self .value_unit = ''
90108 # Following values defined for each exposure
91109 # Obligatory variables
92110 self .coord = GridPoints ()
@@ -100,9 +118,21 @@ def clear(self):
100118 self .region_id = np .array ([], int )
101119 self .assigned = dict ()
102120
121+ if file_name != '' :
122+ self .read (file_name , description )
123+
124+ def clear (self ):
125+ """Reinitialize attributes."""
126+ for (var_name , var_val ) in self .__dict__ .items ():
127+ if isinstance (var_val , np .ndarray ) and var_val .ndim == 1 :
128+ setattr (self , var_name , np .array ([]))
129+ else :
130+ setattr (self , var_name , var_val .__class__ ())
131+ self .ref_year = CONFIG ['entity' ]['present_ref_year' ]
132+
103133 def assign (self , hazard ):
104- """Compute the hazard centroids affecting to each exposure. The
105- position of the centroids are provided , not their ids.
134+ """Compute the hazard centroids affecting to each exposure. Returns the
135+ position of the centroids, not their ids.
106136
107137 Parameters:
108138 hazard (subclass Hazard): one hazard
@@ -123,8 +153,18 @@ def check(self):
123153 if np .unique (self .id ).size != num_exp :
124154 LOGGER .error ("There are exposures with the same identifier." )
125155 raise ValueError
126- self ._check_obligatories (num_exp )
127- self ._check_optionals (num_exp )
156+
157+ check .check_oligatories (self .__dict__ , self .vars_oblig , 'Exposures.' ,
158+ num_exp , num_exp , 2 )
159+ check .check_optionals (self .__dict__ , self .vars_opt , 'Exposures.' , num_exp )
160+
161+ check .empty_optional (self .assigned , "Exposures.assigned" )
162+ for (ass_haz , ass ) in self .assigned .items ():
163+ if not ass_haz :
164+ LOGGER .warning ('Exposures.assigned: assigned hazard type ' \
165+ 'not set.' )
166+ check .array_optional (num_exp , ass , 'Exposures.assigned' )
167+
128168
129169 def plot (self , ignore_zero = True , pop_name = True , buffer_deg = 1.0 ,
130170 extend = 'neither' , ** kwargs ):
@@ -192,18 +232,17 @@ def remove(self, exp_id):
192232 except IndexError :
193233 LOGGER .info ('No exposure with id %s.' , exp_id )
194234 return
195- self .coord = np .delete (self .coord , pos_del , axis = 0 )
196- self .value = np .delete (self .value , pos_del )
197- self .impact_id = np .delete (self .impact_id , pos_del )
198- self .id = np .delete (self .id , pos_del )
199- if self .deductible .size :
200- self .deductible = np .delete (self .deductible , pos_del )
201- if self .cover .size :
202- self .cover = np .delete (self .cover , pos_del )
203- if self .category_id .size :
204- self .category_id = np .delete (self .category_id , pos_del )
205- if self .region_id .size :
206- self .region_id = np .delete (self .region_id , pos_del )
235+
236+ for (var_name , var_val ) in self .__dict__ .items ():
237+ if var_name in self .vars_oblig :
238+ if isinstance (var_val , np .ndarray ) and var_val .ndim == 1 :
239+ setattr (self , var_name , np .delete (var_val , pos_del ))
240+ elif isinstance (var_val , np .ndarray ) and var_val .ndim == 2 :
241+ setattr (self , var_name , np .delete (var_val , pos_del , axis = 0 ))
242+ else :
243+ if isinstance (var_val , np .ndarray ) and var_val .size :
244+ setattr (self , var_name , np .delete (var_val , pos_del ))
245+
207246 old_assigned = self .assigned .copy ()
208247 for key , val in old_assigned .items ():
209248 self .assigned [key ] = np .delete (val , pos_del )
@@ -222,37 +261,37 @@ def append(self, exposures):
222261 self .__dict__ = exposures .__dict__ .copy ()
223262 return
224263
225- self .tag .append (exposures .tag )
226264 if self .ref_year != exposures .ref_year :
227265 LOGGER .error ("Append not possible. Different reference years." )
228266 raise ValueError
229- if ( self .value_unit == 'NA' ) and ( exposures .value_unit != 'NA' ) :
267+ if not self .value_unit and exposures .value_unit :
230268 self .value_unit = exposures .value_unit
231269 LOGGER .info ("Exposures units set to %s." , self .value_unit )
232- elif exposures .value_unit == 'NA' :
270+ elif not exposures .value_unit :
233271 LOGGER .info ("Exposures units set to %s." , self .value_unit )
234272 elif self .value_unit != exposures .value_unit :
235273 LOGGER .error ("Append not possible. Different units: %s != %s." , \
236274 self .value_unit , exposures .value_unit )
237275 raise ValueError
276+ self .tag .append (exposures .tag )
277+
278+ # append all 1-dim variables and 2-dim coordinate variable
279+ for (var_name , var_val ), haz_val in zip (self .__dict__ .items (),
280+ exposures .__dict__ .values ()):
281+ if isinstance (var_val , np .ndarray ) and var_val .ndim == 1 \
282+ and var_val .size :
283+ setattr (self , var_name , np .append (var_val , haz_val ). \
284+ astype (var_val .dtype , copy = False ))
285+ elif isinstance (var_val , np .ndarray ) and var_val .ndim == 2 :
286+ setattr (self , var_name , np .append (var_val , haz_val , axis = 0 ). \
287+ astype (var_val .dtype , copy = False ))
288+ elif isinstance (var_val , list ) and len (var_val ):
289+ setattr (self , var_name , var_val + haz_val )
238290
239- self .coord = np .append (self .coord , exposures .coord , axis = 0 )
240- self .value = np .append (self .value , exposures .value )
241- self .impact_id = np .append (self .impact_id , exposures .impact_id )
242- self .id = np .append (self .id , exposures .id )
243- self .deductible = self ._append_optional (self .deductible ,
244- exposures .deductible )
245- self .cover = self ._append_optional (self .cover , exposures .cover )
246- self .category_id = self ._append_optional (self .category_id , \
247- exposures .category_id )
248- self .region_id = self ._append_optional (self .region_id , \
249- exposures .region_id )
250291 for (ass_haz , ass ) in exposures .assigned .items ():
251- if ass_haz not in self .assigned :
252- self .assigned [ass_haz ] = ass
253- else :
254- self .assigned [ass_haz ] = self ._append_optional ( \
255- self .assigned [ass_haz ], ass )
292+ if ass_haz in self .assigned :
293+ self .assigned [ass_haz ] = np .append (
294+ self .assigned [ass_haz ], ass ).astype (ass .dtype , copy = False )
256295
257296 # provide new ids to repeated ones
258297 _ , indices = np .unique (self .id , return_index = True )
@@ -278,24 +317,16 @@ def select(self, reg_id):
278317 return None
279318
280319 sel_exp = self .__class__ ()
281- sel_exp .tag .file_name = self .tag .file_name
282- sel_exp .tag .description = 'Region ' + str (reg_id )
283- sel_exp .ref_year = self .ref_year
284- sel_exp .value_unit = self .value_unit
285- # Obligatory variables
286- sel_exp .coord = self .coord [sel_idx , :]
287- sel_exp .value = self .value [sel_idx ]
288- sel_exp .impact_id = self .impact_id [sel_idx ]
289- sel_exp .id = self .id [sel_idx ]
290- # Optional variables.
291- if self .deductible .size :
292- sel_exp .deductible = self .deductible [sel_idx ]
293- if self .cover .size :
294- sel_exp .cover = self .cover [sel_idx ]
295- if self .category_id .size :
296- sel_exp .category_id = self .category_id [sel_idx ]
297- if self .region_id .size :
298- sel_exp .region_id = self .region_id [sel_idx ]
320+ for (var_name , var_val ) in self .__dict__ .items ():
321+ if isinstance (var_val , np .ndarray ) and var_val .ndim == 1 and \
322+ var_val .size :
323+ setattr (sel_exp , var_name , var_val [sel_idx ])
324+ elif isinstance (var_val , np .ndarray ) and var_val .ndim == 2 :
325+ setattr (sel_exp , var_name , var_val [sel_idx , :])
326+ elif isinstance (var_val , list ) and var_val :
327+ setattr (sel_exp , var_name , [var_val [idx ] for idx in sel_idx ])
328+ else :
329+ setattr (sel_exp , var_name , var_val )
299330
300331 sel_exp .assigned = dict ()
301332 for key , value in self .assigned .items ():
@@ -359,8 +390,8 @@ def size(self):
359390 self .check ()
360391 return self .value .size
361392
362- @staticmethod
363- def _read_one (file_name , description = '' , var_names = None ):
393+ @classmethod
394+ def _read_one (cls , file_name , description = '' , var_names = None ):
364395 """Read one file and fill attributes.
365396
366397 Parameters:
@@ -375,7 +406,7 @@ def _read_one(file_name, description='', var_names=None):
375406 Exposures
376407 """
377408 LOGGER .info ('Reading file: %s' , file_name )
378- new_exp = Exposures ()
409+ new_exp = cls ()
379410 new_exp .tag = Tag (file_name , description )
380411
381412 extension = os .path .splitext (file_name )[1 ]
@@ -388,36 +419,6 @@ def _read_one(file_name, description='', var_names=None):
388419
389420 return new_exp
390421
391- @staticmethod
392- def _append_optional (ini , to_add ):
393- """Append variable only if both are filled."""
394- if (ini .size != 0 ) and (to_add .size != 0 ):
395- ini = np .append (ini , to_add )
396- else :
397- ini = np .array ([], float )
398- return ini
399-
400- def _check_obligatories (self , num_exp ):
401- """Check coherence obligatory variables."""
402- check .size (num_exp , self .value , 'Exposures.value' )
403- check .size (num_exp , self .impact_id , 'Exposures.impact_id' )
404- check .shape (num_exp , 2 , self .coord , 'Exposures.coord' )
405-
406- def _check_optionals (self , num_exp ):
407- """Check coherence optional variables. Warn if empty."""
408- check .array_optional (num_exp , self .category_id , \
409- 'Exposures.category_id' )
410- check .array_optional (num_exp , self .region_id , \
411- 'Exposures.region_id' )
412- check .empty_optional (self .assigned , "Exposures.assigned" )
413- check .array_optional (num_exp , self .deductible , 'Exposures.deductible' )
414- check .array_optional (num_exp , self .cover , 'Exposures.cover' )
415- for (ass_haz , ass ) in self .assigned .items ():
416- if ass_haz == 'NA' :
417- LOGGER .warning ('Exposures.assigned: assigned hazard type ' \
418- 'not set.' )
419- check .array_optional (num_exp , ass , 'Exposures.assigned' )
420-
421422 def __str__ (self ):
422423 return self .tag .__str__ ()
423424
0 commit comments