sequences.py 3.61 KiB
from __future__ import annotations
from lib.structures import *
import matplotlib.pyplot as pp
import lib.plotdefs as pd
import copy
"""
Builds on abstractions defined in lib.structures.
"""
def _titlecase(s: str) -> str:
return " ".join(_s[:1].upper() + _s[1:]
for _s in s.replace(" ", "_").split("_"))
class SuperSequence:
"""
Sequence of labeled Sequences. Mostly for visualization purposes.
Fields
------
sequences : dict[str, Sequence]
"""
def __init__(self, sequences: dict[str, Sequence]=None):
"""
Constructor.
Parameters
----------
sequences : dict[str, Sequence]
"""
self.sequences = dict() if sequences is None else sequences
def __getitem__(self, key: str) -> Sequence:
assert isinstance(key, str)
return self.sequences[key]
def __setitem__(self, key: str, seq: Sequence):
assert isinstance(key, str)
assert isinstance(seq, Sequence)
self.sequences[key] = seq
def get(self, key, default) -> Sequence:
return self.sequences.get(key, default)
def keys(self):
return self.sequences.keys()
def items(self):
return self.sequences.items()
def update(self, other):
self.sequences.update(other)
return self
def __add__(self, other):
sequences = copy.deepcopy(self.sequences)
return SuperSequence(sequences).update(other)
def __iadd__(self, other):
return self.update(other)
def by_times(self) -> list[Sequence]:
"""
Return Sequences in a list ordered by earliest Event.
"""
return sorted(
self.sequences.values(),
key=lambda e: e.min_time()
)
def to_sequence(self) -> Sequence:
"""
Condense to a single Sequence to pass to the computer.
"""
seq = Sequence()
for S in self.by_times():
seq = seq + S
return seq
@staticmethod
def _gen_timeline(detailed=False, layout=(1, 4, 32, 1, 32, -10, 10)) \
-> pd.Plotter:
FS = pp.rcParams["font.size"]
pp.rcParams["font.size"] = 3
P = pd.Plotter()
P.set_yticks([]).set_yticklabels([]).ggrid(True)
pp.rcParams["font.size"] = FS
return P
def draw_simple(self) -> pd.Plotter:
P = SuperSequence._gen_timeline(detailed=False)
FS = pp.rcParams["font.size"]
pp.rcParams["font.size"] = 3
H = 0.2
c = 0
tl_level = 0
tl_max = 0
t1_last = dict()
Tmin = 0
Tmax = 0
for i, (s, S) in enumerate(self.items()):
tmin, tmax = S.when()
Tmin = min(Tmin, tmin)
Tmax = max(Tmax, tmax)
k = 0
while tmin < t1_last.get(k, tmin):
k += 1
tl_level = k
tl_max = max(tl_max, tl_level)
P.ax.add_patch(
pp.Rectangle(
(tmin, tl_level * H), tmax - tmin, H / 2,
edgecolor="k", facecolor=f"C{c}",
zorder=100
)
)
P.ax.text(tmin, tl_level * H - H / 15, _titlecase(s),
horizontalalignment="left", verticalalignment="top")
c = (c + 1) % 10
t1_last[tl_level] = tmax
P.set_xlim(Tmin - (Tmax - Tmin) / 20, Tmax + (Tmax - Tmin) / 20)
P.set_ylim(-H / 2, (tl_max + 1) * H)
P.set_xlabel("Time [s]")
pp.rcParams["font.size"] = FS
return P
def draw_detailed(self) -> pd.Plotter:
P = SuperSequence._gen_timeline(detailed=True)
pass