99Utils for manipulating h5db with accdb & pyalgo cases.
1010
1111used by many tests & notebooks.
12+
13+ * load_vehicle_accdb(vehnum=1): load inps & outs for AccDB
14+ * load_vehicle_pyalgo(vehnum=1): load outs for AccDB
1215"""
1316import io
1417import json
4346EPS = sys .float_info .epsilon
4447
4548
49+ H5DB = Union [str , Path , HDFStore ]
50+
51+ notebooks_dir = Path (__file__ ).parent / ".." / "Notebooks"
52+ AccDbPath = notebooks_dir / "VehData" / "WltpGS-msaccess.h5"
53+ PyAlgoPath = notebooks_dir / "VehData" / "WltpGS-pyalgo.h5"
54+
55+
4656def oneliner (s ) -> str :
4757 """Collapse any whitespace in stringified `s` into a single space. """
4858 return re .sub (r"[\n ]+" , " " , str (s ).strip ())
@@ -176,7 +186,7 @@ def provenance_info(*, files=(), repos=(), base=None) -> Dict[str, str]:
176186## HDF5
177187
178188
179- def openh5 (h5 : Union [ str , HDFStore ] , mode = "r" ):
189+ def openh5 (h5 : H5DB , mode = "r" ):
180190 """Open h5-fpath or reuse existing h5db instance."""
181191
182192 h5db = None
@@ -200,7 +210,7 @@ def openh5(h5: Union[str, HDFStore], mode="r"):
200210 return h5db
201211
202212
203- def do_h5 (h5 : Union [ str , HDFStore ] , func : callable , * args , ** kw ):
213+ def do_h5 (h5 : H5DB , func : callable , * args , ** kw ):
204214 """Open & close if `h5` is fname (string), do nothing if an opened db"""
205215 if isinstance (h5 , HDFStore ) and h5 .is_open :
206216 out = func (h5 , * args , ** kw )
@@ -211,17 +221,15 @@ def do_h5(h5: Union[str, HDFStore], func: callable, *args, **kw):
211221 return out
212222
213223
214- def print_nodes (h5 : Union [ str , HDFStore ] , displaywidth = 160 ):
224+ def print_nodes (h5 : H5DB , displaywidth = 160 ):
215225 from columnize import columnize
216226
217227 nodes = do_h5 (h5 , lambda h5db : sorted (h5db .keys ()))
218228
219229 print (columnize (nodes , displaywidth = displaywidth ))
220230
221231
222- def provenir_h5node (
223- h5 : Union [str , HDFStore ], node , * , title = None , files = (), repos = (), base = None
224- ):
232+ def provenir_h5node (h5 : H5DB , node , * , title = None , files = (), repos = (), base = None ):
225233 """Add provenance-infos to some existing H5 node.
226234
227235 For its API, see :func:`provenance_info`.
@@ -239,7 +247,7 @@ def func(h5db):
239247 return do_h5 (h5 , func )
240248
241249
242- def provenance_h5node (h5 : Union [ str , HDFStore ] , node ):
250+ def provenance_h5node (h5 : H5DB , node ):
243251 """Get provenance-infos from some existing H5 node."""
244252
245253 def func (h5db ):
@@ -252,9 +260,7 @@ def func(h5db):
252260 return do_h5 (h5 , func )
253261
254262
255- def collect_nodes (
256- h5 : Union [str , HDFStore ], predicate : Callable [[str ], Any ], start_in = "/"
257- ) -> List [str ]:
263+ def collect_nodes (h5 : H5DB , predicate : Callable [[str ], Any ], start_in = "/" ) -> List [str ]:
258264 """
259265 feed all groups into predicate and collect its truthy output
260266 """
@@ -465,8 +471,9 @@ def vehnode(vehnum=None, *suffix):
465471# assert vehnode(None, 'props') == '/vehicles/props'
466472# assert vehnode() == '/vehicles'
467473
468-
469- def load_vehicle_nodes (h5 : Union [str , HDFStore ], vehnum , * subnodes ) -> list :
474+ # TODO: rename load_vehicle_nodes --> load_h5_nodes()
475+ # TODO: rename load_vehicle_XXX move make `vehnum` 1st compulsory argument.
476+ def load_vehicle_nodes (h5 : H5DB , vehnum , * subnodes ) -> list :
470477 "return vehicle's groups listed in `subnodes`"
471478
472479 def func (h5db ):
@@ -488,8 +495,8 @@ class CaseData(NamedTuple):
488495 items : list
489496
490497
491- def load_vehicle_accdb (h5 , vehnum ) -> CaseData :
492- """return the typical input & output data for a vehicle in accdc: props, wot, n2vs"""
498+ def load_vehicle_accdb (h5 : H5DB = AccDbPath , vehnum = None ) -> CaseData :
499+ """return the typical inputs data (not outs) for a vehicle in accdc: props, wot, n2vs"""
493500
494501 def func (h5db ):
495502 props = load_vehicle_nodes (h5db , vehnum , "prop" )
@@ -502,13 +509,13 @@ def func(h5db):
502509 return res
503510
504511
505- def load_vehicle_pyalgo (h5 , vehnum ) -> CaseData :
506- """return the typical output data for a vehicle in pyalgo: oprops, cycle, wots_vmax"""
512+ def load_vehicle_pyalgo (
513+ h5 : H5DB = PyAlgoPath , vehnum = None , nodes = ("oprop" , "cycle" , "wots_vmax" )
514+ ) -> CaseData :
515+ """return the typical output data for a vehicle in pyalgo (see `node` defaults). """
507516
508517 def func (h5db ):
509- return CaseData (
510- * load_vehicle_nodes (h5db , vehnum , "oprop" , "cycle" , "wots_vmax" )
511- )
518+ return CaseData (* load_vehicle_nodes (h5db , vehnum , * nodes ))
512519
513520 res = do_h5 (h5 , func )
514521 return res
@@ -637,7 +644,7 @@ def run_pyalgo_on_accdb_vehicle(
637644
638645
639646def merge_db_vehicle_subgroups (
640- h5 : Union [ str , HDFStore ] , * vehicle_subgroups : str , veh_nums = None
647+ h5 : H5DB , * vehicle_subgroups : str , veh_nums = None
641648) -> Union [NDFrame , List [NDFrame ]]:
642649 """
643650 Merge HDF-subgroup(s) from all vehicles into an Indexed-DataFrame(s)
@@ -676,3 +683,22 @@ def func(h5db):
676683 ]
677684
678685 return index_dfs [0 ] if len (index_dfs ) == 1 else index_dfs
686+
687+
688+ def read_matlab_csv (fpath , ** csv_kw ):
689+ """Matlab data-files have spaces columns and are humanly indented. """
690+
691+ df = pd .read_csv (fpath , sep = " *, *" , engine = "python" , ** csv_kw ).convert_dtypes ()
692+ return df
693+
694+ def setup_octave ():
695+ """Setup `oct2py` library to execute wltp's MATLAB sources. """
696+ from oct2py import octave as oc
697+
698+ # See https://nbviewer.jupyter.org/github/blink1073/oct2py/blob/master/example/octavemagic_extension.ipynb?create=1
699+ # %load_ext oct2py.ipython
700+
701+ wltp_mat_sources_path = str (Path ("src" ).absolute ())
702+ mat_path = set (oc .path ().split (osp .pathsep ))
703+ if wltp_mat_sources_path not in mat_path :
704+ oc .addpath (wltp_mat_sources_path )
0 commit comments