From 3755b62d4141781ff1d96a5e905c5b98d12b348f Mon Sep 17 00:00:00 2001 From: Robin Steuteville Date: Mon, 2 Dec 2024 12:54:06 -0700 Subject: [PATCH 1/2] creating to_pydict and from_pydict methods that work with RustVehicle --- python/fastsim/__init__.py | 43 +++++++++++++++++++++++++++++ python/fastsim/demos/pydict_demo.py | 22 +++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 python/fastsim/demos/pydict_demo.py diff --git a/python/fastsim/__init__.py b/python/fastsim/__init__.py index 70f17608..ff03cd9c 100644 --- a/python/fastsim/__init__.py +++ b/python/fastsim/__init__.py @@ -6,7 +6,10 @@ import logging import traceback from typing import Dict +from typing_extensions import Self +import inspect +import fastsim from fastsim import parameters as params from fastsim import utils from fastsim import simdrive, vehicle, cycle, calibration, tests @@ -55,3 +58,43 @@ def _as_numpy_array(self, *args, **kwargs): setattr(fsr.Pyo3ArrayU32, "__array__", _as_numpy_array) setattr(fsr.Pyo3ArrayBool, "__array__", _as_numpy_array) setattr(fsr.Pyo3VecF64, "__array__", _as_numpy_array) + +# creates a list of all python classes from rust structs that need to_pydict and +# from_pydict added as methods +ACCEPTED_RUST_STRUCTS = [attr for attr in fastsim.__dir__() if not\ + attr.startswith("__") and\ + isinstance(getattr(fastsim, attr), type) and\ + attr[0].isupper() and\ + ("fastsim" in str(inspect.getmodule(getattr(fastsim, attr))))] + +def to_pydict(self) -> Dict: + """ + Returns self converted to pure python dictionary with no nested Rust objects + """ + import json + try: + return json.loads(self.to_json()) + except: + import yaml + return yaml.loads(self.to_yaml()) + +@classmethod +def from_pydict(cls, pydict: Dict) -> Self: + """ + Instantiates Self from pure python dictionary + """ + import json + try: + return cls.from_json(json.dumps(pydict)) + except: + import yaml + return cls.from_yaml(yaml.dumps(pydict)) + +for item in ACCEPTED_RUST_STRUCTS: + setattr(getattr(fastsim, item), "to_pydict", to_pydict) + setattr(getattr(fastsim, item), "from_pydict", from_pydict) + +setattr(fsr.RustVehicle, "to_pydict", to_pydict) +setattr(fsr.RustVehicle, "from_pydict", from_pydict) +setattr(fastsim.vehicle.Vehicle, "to_pydict", to_pydict) +setattr(fastsim.vehicle.Vehicle, "from_pydict", from_pydict) diff --git a/python/fastsim/demos/pydict_demo.py b/python/fastsim/demos/pydict_demo.py new file mode 100644 index 00000000..4a2e8360 --- /dev/null +++ b/python/fastsim/demos/pydict_demo.py @@ -0,0 +1,22 @@ +""" +Script demonstrating how to use to_pydict() and from_pydict() for FASTSim +classes. +""" +import fastsim as fsim +from fastsim import fastsimrust as fsr + +# load 2012 Ford F-150 Ecoboost from file +veh = fsim.vehicle.Vehicle.from_file("2017_Ford_F-150_Ecoboost.csv").to_rust() +print(veh) + +# saving vehicle as pydict +veh_pydict = veh.to_pydict() +print(veh_pydict) + +# getting fastsim vehicle from pydict +from_pydict_veh = fsr.RustVehicle.from_pydict(veh_pydict) +print(from_pydict_veh) + +# spot checking to see if the pre-pydict and post-pydict Rust Vehicles are the same +assert(veh.scenario_name==from_pydict_veh.scenario_name) +assert(veh.drag_coef==from_pydict_veh.drag_coef) \ No newline at end of file From c997cb3740a3d37c05e4dc64f40127bc402717b6 Mon Sep 17 00:00:00 2001 From: Robin Steuteville Date: Mon, 2 Dec 2024 13:11:07 -0700 Subject: [PATCH 2/2] cleaning up the code --- python/fastsim/__init__.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/python/fastsim/__init__.py b/python/fastsim/__init__.py index ff03cd9c..3dd9afe0 100644 --- a/python/fastsim/__init__.py +++ b/python/fastsim/__init__.py @@ -72,11 +72,7 @@ def to_pydict(self) -> Dict: Returns self converted to pure python dictionary with no nested Rust objects """ import json - try: - return json.loads(self.to_json()) - except: - import yaml - return yaml.loads(self.to_yaml()) + return json.loads(self.to_json()) @classmethod def from_pydict(cls, pydict: Dict) -> Self: @@ -84,11 +80,7 @@ def from_pydict(cls, pydict: Dict) -> Self: Instantiates Self from pure python dictionary """ import json - try: - return cls.from_json(json.dumps(pydict)) - except: - import yaml - return cls.from_yaml(yaml.dumps(pydict)) + return cls.from_json(json.dumps(pydict)) for item in ACCEPTED_RUST_STRUCTS: setattr(getattr(fastsim, item), "to_pydict", to_pydict)