fym.logging module¶
There are several way to save a experimental data in fym.
The Logger class provides several convient features to record a numerical
data into a HDF5 format file
using h5py module.
Inner logger¶
Basic usage¶
As long as a Logger instance is registered with the BaseEnv
instance as a logger attribute, the Logger instance becomes the inner
logger, and is ready to record the inner states.
env = Env()
env.logger = fym.Logger(path="data.h5")
"""..."""
env.close()
Note that you should BaseEnv.close the BaseEnv to ensure all the data is
properly recorded into the file.
There are three ways to record BaseEnv’s inner states.
Simply do nothing. The inner logger automatically records the time and all the inner states.
Define the
BaseEnv.logger_callbackmethod that returns adict, or makeBaseEnv.set_dotmethod return adict. The returned dict will be recorded.Make both in 2. The two
dictis going to be merged whereBaseEnv.logger_callbackhas priority. (i.e.,set_dot_returned.update(logger_callback_returned))
BaseEnv.logger_callback¶
Sometimes, the data users want to record can be simply state variables within
the BaseEnv and/or BaseSystem and data derived from them (i.e.
control inputs). When using fym, there is one major BaseEnv that runs
the simulation with BaseEnv.update method. The
BaseEnv.logger_callback method defines information to be recorded in
every time step when the environment updates. See the example below.
from fym.core import BaseEnv, BaseSystem
import fym.logging
class Env(BaseEnv):
"""Other methods"""
def logger_callback(self, t):
ud = self.controller.get(self.plant)
return dict(t=t, **self.observe_dict(), ud=ud)
class Controller(BaseSystem):
"""Other methods"""
def get(self, plant):
x = plant.state
k = self.state
return - k * x[0]
env = Env()
env.logger = fym.logging.Logger("data.h5")
env.reset()
while True:
env.render()
done = env.step()
if done:
break
env.close()
data = fym.logging.load("data.h5")
print(data)
BaseEnv.set_dot¶
If all the variables to be recorded is already calculated in BaseEnv.set_dot,
simply return a dictionary of them is going to be recorded automatically. It
would reduce several lines of code and saves time. For this, you must remove
the BaseEnv.logger_callback method as follows.
class Env(BaseEnv):
"""Other methods without logger_callback"""
def set_dot(self, t):
x = self.plant.state
u = self.actuator.state
ud = self.controller.get(self.plant)
self.plant.dot = - x
self.actuator.dot = - (u - ud)
self.controller.set_dot()
return dict(t=t, **self.observe_dict(), ud=ud)
When both returns are defined¶
BaseEnv.set_dothas returned value +BaseEnv.logger_callbackis defined: record both (priority check:dict.update(set_dot, logger_callback))BaseEnv.set_dotdoesn’t have returned value +BaseEnv.logger_callbackis defined: recordBaseEnv.logger_callbackBaseEnv.set_dothas returned value +BaseEnv.logger_callbackis not defined: recordBaseEnv.set_dotBaseEnv.set_dotdoesn’t have returned value +BaseEnv.logger_callbackis not defined: recordtandBaseEnv.observe_dict()