4848
4949"""
5050
51- from .base import *
52- from .file_io import *
53- from .model import *
51+ import json
52+ from datetime import datetime
53+ from . import base
54+ from . import file_io
55+ from . import model
56+ from .__init__ import __version__ as pelicun_version
5457
55- class Assessment (object ):
58+
59+ class Assessment :
5660 """
5761 Assessment objects manage the models, data, and calculations in pelicun.
5862
@@ -68,79 +72,86 @@ class Assessment(object):
6872 ...
6973 stories: int
7074 Number of stories.
75+ options: Options
76+ Options object.
7177 """
7278
7379 def __init__ (self , config_options = None ):
7480
75- load_default_options ()
7681
77- set_options (merge_default_config (config_options ))
82+ self .stories = None
83+ self .options = base .Options (self )
84+
85+ file_io .load_default_options (self .options )
7886
79- log_msg (f'pelicun { pelicun_version } | \n ' ,
80- prepend_timestamp = False , prepend_blank_space = False )
87+ self .options .set_options (file_io .merge_default_config (
88+ config_options , self .options ))
89+ self .unit_conversion_factors = file_io .parse_units (
90+ self .options .units_file )
8191
82- print_system_info ()
92+ self .log_msg (f'pelicun { pelicun_version } | \n ' ,
93+ prepend_timestamp = False , prepend_blank_space = False )
8394
84- log_div ()
85- log_msg ('Assessement Started' )
95+ base .print_system_info (self )
8696
87- self .stories = None
97+ self .log_div ()
98+ self .log_msg ('Assessement Started' )
8899
89100 @property
90101 def demand (self ):
91102 """
92103 Return a DemandModel object that manages the demand information.
93104
94105 """
106+ # pylint: disable = access-member-before-definition
95107
96108 if hasattr (self , '_demand' ):
97109 return self ._demand
98110
99- else :
100- self ._demand = DemandModel ()
101- return self .demand
111+ self ._demand = model .DemandModel (self )
112+ return self .demand
102113
103114 @property
104115 def asset (self ):
105116 """
106117 Return an AssetModel object that manages the asset information.
107118
108119 """
120+ # pylint: disable = access-member-before-definition
109121
110122 if hasattr (self , '_asset' ):
111123 return self ._asset
112124
113- else :
114- self ._asset = AssetModel (self )
115- return self .asset
125+ self ._asset = model .AssetModel (self )
126+ return self .asset
116127
117128 @property
118129 def damage (self ):
119130 """
120131 Return an DamageModel object that manages the damage information.
121132
122133 """
134+ # pylint: disable = access-member-before-definition
123135
124136 if hasattr (self , '_damage' ):
125137 return self ._damage
126138
127- else :
128- self ._damage = DamageModel (self )
129- return self .damage
139+ self ._damage = model .DamageModel (self )
140+ return self .damage
130141
131142 @property
132143 def bldg_repair (self ):
133144 """
134145 Return an BldgRepairModel object that manages the repair information.
135146
136147 """
148+ # pylint: disable = access-member-before-definition
137149
138150 if hasattr (self , '_bldg_repair' ):
139151 return self ._bldg_repair
140152
141- else :
142- self ._bldg_repair = BldgRepairModel (self )
143- return self .bldg_repair
153+ self ._bldg_repair = model .BldgRepairModel (self )
154+ return self .bldg_repair
144155
145156 def get_default_data (self , data_name ):
146157 """
@@ -153,10 +164,11 @@ def get_default_data(self, data_name):
153164
154165 """
155166
156- data_path = str (pelicun_path )+ '/resources/' + data_name + '.csv'
157-
158- return load_data (data_path , orientation = 1 , reindex = False , convert = [])
167+ data_path = str (base .pelicun_path )+ '/resources/' + data_name + '.csv'
159168
169+ return file_io .load_data (
170+ data_path , self .unit_conversion_factors ,
171+ orientation = 1 , reindex = False , convert = [])
160172
161173 def get_default_metadata (self , data_name ):
162174 """
@@ -169,9 +181,116 @@ def get_default_metadata(self, data_name):
169181
170182 """
171183
172- data_path = str (pelicun_path ) + '/resources/' + data_name + '.json'
184+ data_path = str (base . pelicun_path ) + '/resources/' + data_name + '.json'
173185
174- with open (data_path , 'r' ) as f :
186+ with open (data_path , 'r' , encoding = 'utf-8' ) as f :
175187 data = json .load (f )
176188
177- return data
189+ return data
190+
191+ def log_div (self , prepend_timestamp = False ):
192+ """
193+ Print a divider line to the log file
194+
195+ """
196+
197+ if prepend_timestamp :
198+ msg = self .options .log_div
199+
200+ else :
201+ msg = '-' * 80
202+
203+ self .log_msg (msg , prepend_timestamp = prepend_timestamp )
204+
205+
206+ def log_msg (self , msg = '' , prepend_timestamp = True , prepend_blank_space = True ):
207+ """
208+ Print a message to the screen with the current time as prefix
209+
210+ The time is in ISO-8601 format, e.g. 2018-06-16T20:24:04Z
211+
212+ Parameters
213+ ----------
214+ msg: string
215+ Message to print.
216+
217+ """
218+
219+ # pylint: disable = consider-using-f-string
220+ msg_lines = msg .split ('\n ' )
221+
222+ for msg_i , msg_line in enumerate (msg_lines ):
223+
224+ if (prepend_timestamp and (msg_i == 0 )):
225+ formatted_msg = '{} {}' .format (
226+ datetime .now ().strftime (self .options .log_time_format ), msg_line )
227+ elif prepend_timestamp :
228+ formatted_msg = self .options .log_pref + msg_line
229+ elif prepend_blank_space :
230+ formatted_msg = self .options .log_pref + msg_line
231+ else :
232+ formatted_msg = msg_line
233+
234+ if self .options .print_log :
235+ print (formatted_msg )
236+
237+ if self .options .log_file is not None :
238+ with open (self .options .log_file , 'a' , encoding = 'utf-8' ) as f :
239+ f .write ('\n ' + formatted_msg )
240+
241+
242+ def calc_unit_scale_factor (self , unit ):
243+ """
244+ Determines the scale factor from input unit to the corresponding SI unit
245+
246+ Parameters
247+ ----------
248+ unit: str
249+ Either a unit name, or a quantity and a unit name separated by a space.
250+ For example: 'ft' or '100 ft'.
251+
252+ Returns
253+ -------
254+ scale_factor: float
255+ Scale factor that convert values from unit to SI unit
256+
257+ Raises
258+ ------
259+ KeyError:
260+ When an invalid unit is specified
261+ """
262+
263+ unit_lst = unit .strip ().split (' ' )
264+
265+ # check if there is a quantity specified; if yes, parse it
266+ if len (unit_lst ) > 1 :
267+ unit_count , unit_name = unit_lst
268+ unit_count = float (unit_count )
269+
270+ else :
271+ unit_count = 1
272+ unit_name = unit_lst [0 ]
273+
274+ try :
275+ scale_factor = unit_count * self .unit_conversion_factors [unit_name ]
276+
277+ except KeyError as exc :
278+ raise KeyError (f"Specified unit not recognized: "
279+ f"{ unit_count } { unit_name } " ) from exc
280+
281+ return scale_factor
282+
283+ def scale_factor (self , unit ):
284+
285+ if unit is not None :
286+
287+ if unit in self .unit_conversion_factors :
288+ scale_factor = self .unit_conversion_factors [unit ]
289+
290+ else :
291+ raise ValueError (f"Unknown unit: { unit } " )
292+ else :
293+ scale_factor = 1.0
294+
295+ return scale_factor
296+
0 commit comments