app: stacked_cores: plot what happens when one cascades an inverter into a buffer
This commit is contained in:
parent
d03818b58e
commit
33b0b76278
|
@ -1,9 +1,11 @@
|
|||
import plotly.express as px
|
||||
from pandas import DataFrame
|
||||
|
||||
# df = pd.DataFrame(data=dict(x=[1, 2, 3, 4], y=[1, 4, 9, 16]))
|
||||
# fig = px.line(df, x="x", y="y", title="test")
|
||||
# fig.show()
|
||||
from math import floor
|
||||
|
||||
def extrema(arr):
|
||||
arr = list(arr)
|
||||
return min(arr), max(arr)
|
||||
|
||||
class Line:
|
||||
def __init__(self, from_, to):
|
||||
|
@ -74,6 +76,14 @@ class Piecewise:
|
|||
(x, min(max_, max(min_, y))) for (x, y) in self.xy
|
||||
])
|
||||
|
||||
def cascaded(self, second: 'Piecewise') -> 'Piecewise':
|
||||
""" return a function equivalent to y = second(self(x)) """
|
||||
b_min, b_max = extrema(x for (x, y) in self.xy)
|
||||
bounds = [ int(floor(b_min * 100)), 1 + int(floor(b_max * 100)) ]
|
||||
return Piecewise([
|
||||
(0.01 * x, second.get(self.get(0.01 * x))) for x in range(*bounds)
|
||||
])
|
||||
|
||||
def line_for(self, x: float) -> Line:
|
||||
for first_lower in self.xy[:-1][::-1]:
|
||||
if first_lower[0] < x: break
|
||||
|
@ -113,6 +123,9 @@ class Piecewise:
|
|||
def get_integral(self, x: float, n: int = 100) -> float:
|
||||
return self.get_mean(x) * x
|
||||
|
||||
def get_range(self, xmin: float = 0.0, xmax: float = 1.0) -> float:
|
||||
return abs(self.get(xmax) - self.get(xmin))
|
||||
|
||||
def df_for(self, from_: float, to: float, points: int, f) -> DataFrame:
|
||||
x_step = (to - from_) / (points - 1)
|
||||
x = [from_ + x_step*x for x in range(points)]
|
||||
|
|
|
@ -3,6 +3,20 @@
|
|||
from fake_cores_db import *
|
||||
from stacked_cores_40xx_db import *
|
||||
|
||||
class SimParamsCascaded(SimParams):
|
||||
def __init__(self, p1: SimParams, p2: SimParams):
|
||||
super().__init__(p1.couplings, p1.wrappings_spec, p1.um, p1.drive_str)
|
||||
self.p1 = p1
|
||||
self.p2 = p2
|
||||
|
||||
@property
|
||||
def is_inverter(self) -> bool:
|
||||
return self.p1.is_inverter ^ self.p2.is_inverter
|
||||
|
||||
@property
|
||||
def human_name(self) -> str:
|
||||
return f"Cascade: {self.p1.human_name} -> {self.p2.human_name}"
|
||||
|
||||
|
||||
# plot pre-40xx sims
|
||||
for (name, curve) in [
|
||||
|
@ -118,18 +132,25 @@ of_interest += [(p, get_meas(p)) for p in
|
|||
|
||||
|
||||
# plot all viable inverters
|
||||
of_interest += filter_meas(run="41", viable_inverter=True)
|
||||
# of_interest += filter_meas(run="41", viable_inverter=True)
|
||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=4)
|
||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=9)
|
||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=2)
|
||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=6)
|
||||
# of_interest += filter_meas(run="43")
|
||||
|
||||
of_interest.sort(key=lambda i: -i[1].max_abs_slope())
|
||||
for (inv_p, inv_curve) in filter_meas(is_inverter=True):
|
||||
for (fwd_p, fwd_curve) in filter_meas(rad_um=400, is_inverter=False):
|
||||
of_interest += [ (SimParamsCascaded(inv_p, fwd_p), inv_curve.cascaded(fwd_curve)) ]
|
||||
|
||||
for (params, curve) in of_interest:
|
||||
|
||||
# of_interest.sort(key = lambda i: -i[1].max_abs_slope())
|
||||
# of_interest.sort(key = lambda i: -i[1].get_range())
|
||||
of_interest.sort(key = lambda i: i[1].get_repeated(1.0) - i[1].get_repeated(0.0)) # inverter strength
|
||||
|
||||
for (params, curve) in of_interest[:5]:
|
||||
curve.plot(title = f"{params.human_name} mapping")
|
||||
curve.plot_slope(title = f"{params.human_name} slope")
|
||||
if not params.is_inverter:
|
||||
curve = curve.logically_inverted()
|
||||
curve.plot(title = f"{params.human_name} mapping")
|
||||
curve.logically_inverted().plot_slope(title = f"{params.human_name} slope")
|
||||
curve.plot_equilibrium(title = f"{params.human_name} equilibrium")
|
||||
|
|
|
@ -57,9 +57,9 @@ class SimParams:
|
|||
|
||||
@property
|
||||
def tuple(self):
|
||||
return (self.run, self.um, self.couplings, self.wrappings, self.drive)
|
||||
return (self.run, self.um, self.couplings, self.wrappings, self.is_inverter, self.drive)
|
||||
|
||||
def matches(self, run: str, rad_um: int, drive: float, couplings: int, wrappings: int) -> bool:
|
||||
def matches(self, run: str, rad_um: int, drive: float, couplings: int, wrappings: int, is_inverter: bool) -> bool:
|
||||
"""
|
||||
all parameters are optional
|
||||
"""
|
||||
|
@ -68,6 +68,7 @@ class SimParams:
|
|||
self.um if rad_um is None else rad_um,
|
||||
self.couplings if couplings is None else couplings,
|
||||
self.wrappings if wrappings is None else wrappings,
|
||||
self.is_inverter if is_inverter is None else is_inverter,
|
||||
self.drive if drive is None else int(drive),
|
||||
)
|
||||
return self.tuple == match_tuple
|
||||
|
@ -253,7 +254,15 @@ measurements = { real.machine_name: [human, norm, None, None] for (real, human,
|
|||
def matches(actual, expected) -> bool:
|
||||
return expected == None or actual == expected
|
||||
|
||||
def filter_meas(run: str = None, rad_um: int = None, drive: float = None, couplings: int = None, wrappings: int = None, viable_inverter = None) -> list:
|
||||
def filter_meas(
|
||||
run: str = None,
|
||||
rad_um: int = None,
|
||||
drive: float = None,
|
||||
couplings: int = None,
|
||||
wrappings: int = None,
|
||||
viable_inverter = None,
|
||||
is_inverter = None,
|
||||
) -> list:
|
||||
"""
|
||||
return only that set of (SimParams, Piecewise) which matches the given criteria.
|
||||
leave any option as `None` to not filter on it.
|
||||
|
@ -262,7 +271,7 @@ def filter_meas(run: str = None, rad_um: int = None, drive: float = None, coupli
|
|||
return sorted(
|
||||
[
|
||||
(p, get_meas(p)) for (p, _, _) in sims
|
||||
if p.matches(run, rad_um, drive, couplings, wrappings) \
|
||||
if p.matches(run, rad_um, drive, couplings, wrappings, is_inverter) \
|
||||
and get_meas(p) \
|
||||
and get_meas(p).num_pieces > 0 \
|
||||
and matches(p.ensure_inverter(get_meas(p)).is_viable_inverter(), viable_inverter)
|
||||
|
|
Loading…
Reference in New Issue