app: stacked_cores: plot what happens when one cascades an inverter into a buffer
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
# df = pd.DataFrame(data=dict(x=[1, 2, 3, 4], y=[1, 4, 9, 16]))
|
from math import floor
|
||||||
# fig = px.line(df, x="x", y="y", title="test")
|
|
||||||
# fig.show()
|
def extrema(arr):
|
||||||
|
arr = list(arr)
|
||||||
|
return min(arr), max(arr)
|
||||||
|
|
||||||
class Line:
|
class Line:
|
||||||
def __init__(self, from_, to):
|
def __init__(self, from_, to):
|
||||||
@@ -74,6 +76,14 @@ class Piecewise:
|
|||||||
(x, min(max_, max(min_, y))) for (x, y) in self.xy
|
(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:
|
def line_for(self, x: float) -> Line:
|
||||||
for first_lower in self.xy[:-1][::-1]:
|
for first_lower in self.xy[:-1][::-1]:
|
||||||
if first_lower[0] < x: break
|
if first_lower[0] < x: break
|
||||||
@@ -113,6 +123,9 @@ class Piecewise:
|
|||||||
def get_integral(self, x: float, n: int = 100) -> float:
|
def get_integral(self, x: float, n: int = 100) -> float:
|
||||||
return self.get_mean(x) * x
|
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:
|
def df_for(self, from_: float, to: float, points: int, f) -> DataFrame:
|
||||||
x_step = (to - from_) / (points - 1)
|
x_step = (to - from_) / (points - 1)
|
||||||
x = [from_ + x_step*x for x in range(points)]
|
x = [from_ + x_step*x for x in range(points)]
|
||||||
|
@@ -3,6 +3,20 @@
|
|||||||
from fake_cores_db import *
|
from fake_cores_db import *
|
||||||
from stacked_cores_40xx_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
|
# plot pre-40xx sims
|
||||||
for (name, curve) in [
|
for (name, curve) in [
|
||||||
@@ -118,18 +132,25 @@ of_interest += [(p, get_meas(p)) for p in
|
|||||||
|
|
||||||
|
|
||||||
# plot all viable inverters
|
# 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=4)
|
||||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=9)
|
# 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=2)
|
||||||
# of_interest += filter_meas(run="42", rad_um=400, couplings=6)
|
# of_interest += filter_meas(run="42", rad_um=400, couplings=6)
|
||||||
# of_interest += filter_meas(run="43")
|
# 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:
|
if not params.is_inverter:
|
||||||
curve = curve.logically_inverted()
|
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")
|
curve.plot_equilibrium(title = f"{params.human_name} equilibrium")
|
||||||
|
@@ -57,9 +57,9 @@ class SimParams:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def tuple(self):
|
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
|
all parameters are optional
|
||||||
"""
|
"""
|
||||||
@@ -68,6 +68,7 @@ class SimParams:
|
|||||||
self.um if rad_um is None else rad_um,
|
self.um if rad_um is None else rad_um,
|
||||||
self.couplings if couplings is None else couplings,
|
self.couplings if couplings is None else couplings,
|
||||||
self.wrappings if wrappings is None else wrappings,
|
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),
|
self.drive if drive is None else int(drive),
|
||||||
)
|
)
|
||||||
return self.tuple == match_tuple
|
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:
|
def matches(actual, expected) -> bool:
|
||||||
return expected == None or actual == expected
|
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.
|
return only that set of (SimParams, Piecewise) which matches the given criteria.
|
||||||
leave any option as `None` to not filter on it.
|
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(
|
return sorted(
|
||||||
[
|
[
|
||||||
(p, get_meas(p)) for (p, _, _) in sims
|
(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) \
|
||||||
and get_meas(p).num_pieces > 0 \
|
and get_meas(p).num_pieces > 0 \
|
||||||
and matches(p.ensure_inverter(get_meas(p)).is_viable_inverter(), viable_inverter)
|
and matches(p.ensure_inverter(get_meas(p)).is_viable_inverter(), viable_inverter)
|
||||||
|
Reference in New Issue
Block a user