Source code for smartbot_irl.data._data_logging
# data_logging.py
from dataclasses import dataclass, field
from datetime import datetime
from time import time
from types import SimpleNamespace
import pandas as pd
"""
This class should take a list of strings to make new columns for. Then it should
offer intellisense for these columns. This will make it so students can
configure the state object to have a dataframe in the way they want it. But they
don't need to look at any pandas stuff. But it is a subclass so theyn can still
use .to_csv and .plot().
Pandas unfortunately does not have a good way to add extra attributes outside of
the dataframe so we just shove them in with a class that wraps the dataframe
proper.
"""
[docs]
@dataclass
class State:
state_vec: pd.DataFrame = field(init=False)
next_index: int = field(default=0, init=False)
def __post_init__(self):
# Create an empty DataFrame
self.state_vec = pd.DataFrame()
# self.state_vec = pd.DataFrame(columns=[
# "t_epoch", "time", "t_prev", "t_elapsed", "turning",
# "x", "y" # if you want these to exist for plotting
# ])
# TODO init first row in student code.
seed = {
't_epoch': time(),
't': 0.0,
'time': 0.0,
't_prev': time(),
't_elapsed': 0.0,
'turning': False,
}
self.append_row(seed)
[docs]
def append_row(self, rowdict: dict):
# Build the row DataFrame
row_df = pd.DataFrame([rowdict])
# Concat first
self.state_vec = pd.concat([self.state_vec, row_df], ignore_index=True)
# Only after concat do we back-fill any missing columns
# (Pandas will align for new columns automatically)
for col in rowdict:
if col not in self.state_vec.columns:
self.state_vec[col] = pd.NA
@property
def last(self) -> SimpleNamespace:
return SimpleNamespace(**self.state_vec.iloc[-1].to_dict())
def __getattr__(self, name):
# Prevent recursion: if 'state_vec' is missing, raise
if name == 'state_vec':
raise AttributeError
return getattr(self.state_vec, name)
def __getitem__(self, key):
return self.state_vec[key]
def __setitem__(self, key, value):
self.state_vec[key] = value
[docs]
def timestamp():
return datetime.now().strftime('%Y-%m-%d_%H-%M-%S')