plot some datapoints about the stacked_cores inverters
This commit is contained in:
141
crates/post/scripts/inverter_characteristics.py
Executable file
141
crates/post/scripts/inverter_characteristics.py
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env python3
|
||||
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()
|
||||
|
||||
class Line:
|
||||
def __init__(self, from_, to):
|
||||
self.from_ = from_
|
||||
self.to = to
|
||||
|
||||
def slope(self) -> float:
|
||||
return (self.to[1] - self.from_[1]) / (self.to[0] - self.from_[0])
|
||||
|
||||
def get(self, x: float) -> float:
|
||||
from_x, from_y = self.from_
|
||||
to_x, to_y = self.to
|
||||
tween = (x - from_x) / (to_x - from_x)
|
||||
return tween * to_y + (1-tween) * from_y
|
||||
|
||||
|
||||
class Piecewise:
|
||||
def __init__(self, xy: list):
|
||||
""" xy is a list of (x, y) pairs """
|
||||
self.xy = list(xy)
|
||||
|
||||
def normalized(self, prev_max: float) -> 'Piecewise':
|
||||
""" map every coordinate from [-prev_max, prev_max] to [0, 1] """
|
||||
p = prev_max
|
||||
r = 2*prev_max
|
||||
s = 1.0/r
|
||||
return Piecewise([
|
||||
(s*(x + p), s*(y + p)) for (x, y) in self.xy
|
||||
])
|
||||
|
||||
def logically_inverted(self) -> 'Piecewise':
|
||||
""" return a Piecewise that evaluates to 1-y """
|
||||
return Piecewise([
|
||||
(x, 1-y) for (x, y) in self.xy
|
||||
])
|
||||
|
||||
def line_for(self, x: float) -> Line:
|
||||
for first_lower in self.xy[:-1][::-1]:
|
||||
if first_lower[0] < x: break
|
||||
for first_upper in self.xy[1:]:
|
||||
if first_upper[0] > x: break
|
||||
|
||||
return Line(first_lower, first_upper)
|
||||
|
||||
def get(self, x: float) -> float:
|
||||
"""
|
||||
evaluate the piecewise function at the provided x value.
|
||||
OOB points are just extrapolated from the nearest piece.
|
||||
"""
|
||||
return self.line_for(x).get(x)
|
||||
|
||||
def get_slope(self, x: float) -> float:
|
||||
return self.line_for(x).slope()
|
||||
|
||||
def get_repeated(self, x: float, n: int = 63) -> float:
|
||||
for _ in range(n):
|
||||
x = self.get(x)
|
||||
return x
|
||||
|
||||
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)]
|
||||
y = [f(xi) for xi in x]
|
||||
return DataFrame(data=dict(x=x, y=y))
|
||||
|
||||
def df(self, from_: float = 0.0, to: float = 1.0, points: int = 101) -> DataFrame:
|
||||
return self.df_for(from_, to, points, self.get)
|
||||
|
||||
def slope_df(self, from_: float = 0.0, to: float = 1.0, points: int = 101) -> DataFrame:
|
||||
return self.df_for(from_, to, points, self.get_slope)
|
||||
|
||||
def plot_for(self, from_: float, to: float, title: str, f):
|
||||
df = self.df_for(from_, to, points=101, f=f)
|
||||
fig = px.line(df, x="x", y="y", title=title)
|
||||
fig.show()
|
||||
|
||||
def plot(self, from_: float = 0.0, to: float = 1.0, title: str = "Piecewise"):
|
||||
self.plot_for(from_, to, title, self.get)
|
||||
|
||||
def plot_slope(self, from_: float = 0.0, to: float = 1.0, title: str = "Piecewise"):
|
||||
self.plot_for(from_, to, title, self.get_slope)
|
||||
|
||||
def plot_equilibrium(self, from_: float = 0.0, to: float = 1.0, title: str = "Piecewise"):
|
||||
self.plot_for(from_, to, title, self.get_repeated)
|
||||
|
||||
|
||||
fwd_26 = Piecewise(
|
||||
[
|
||||
[ -14687, -7326 ],
|
||||
[ -13049, -6503 ],
|
||||
[ -11785, -5833 ],
|
||||
[ -4649, -1447 ],
|
||||
[ 4961, 7059 ],
|
||||
[ 11283, 11147 ],
|
||||
]
|
||||
).normalized(17000)
|
||||
|
||||
# fwd_26.plot(title = "26 forward")
|
||||
# fwd_26.logically_inverted().plot(title = "26 inverted")
|
||||
# fwd_26.plot_slope(title = "26 slope")
|
||||
# fwd_26.logically_inverted().plot_equilibrium(title = "26 equilibrium")
|
||||
|
||||
|
||||
fwd_38_2_0 = Piecewise(
|
||||
[
|
||||
[ (-13745 + -13012)/2, -6222 ],
|
||||
[ (-4969 + -4744)/2, 2373 ],
|
||||
[ (1772 + 2070)/2, 10467 ],
|
||||
[ (4472 + 4114)/2, 12921 ],
|
||||
[ (7221 + 6291)/2, 14530 ],
|
||||
[ (11159 + 10397)/2, 15865 ],
|
||||
[ (12430 + 15653)/2, 16202 ],
|
||||
]
|
||||
).normalized(17000)
|
||||
fwd_38_2_0.plot(title = "38 2:0 forward")
|
||||
fwd_38_2_0.logically_inverted().plot(title = "38 2:0 inverted")
|
||||
fwd_38_2_0.plot_slope(title = "38 2:0 slope")
|
||||
fwd_38_2_0.logically_inverted().plot_equilibrium(title = "38 2:0 equilibrium")
|
||||
|
||||
fwd_38_3_0 = Piecewise(
|
||||
[
|
||||
[ (-13956 + -13890 + -13077)/3, -5203],
|
||||
[ (-4979 + -4885 + -4717)/3, 5051],
|
||||
[ (1531 + 503 + 1006)/3, 12509],
|
||||
[ (4180 + 1821 + 2239)/3, 14386],
|
||||
[ (6986 + 3436 + 3701)/3, 15451],
|
||||
[ (10482 + 6644 + 7735)/3, 16081],
|
||||
[ (11436 + 13343 + 14411)/3, 16380],
|
||||
]
|
||||
).normalized(17000)
|
||||
fwd_38_3_0.plot(title = "38 3:0 forward")
|
||||
fwd_38_3_0.logically_inverted().plot(title = "38 3:0 inverted")
|
||||
fwd_38_3_0.plot_slope(title = "38 3:0 slope")
|
||||
fwd_38_3_0.logically_inverted().plot_equilibrium(title = "38 3:0 equilibrium")
|
@@ -14,6 +14,11 @@
|
||||
overlays = [ rust-overlay.overlays.default ];
|
||||
};
|
||||
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
|
||||
python-packages = pypkg: with pypkg; [
|
||||
pandas
|
||||
plotly
|
||||
];
|
||||
python3 = pkgs.python3.withPackages python-packages;
|
||||
in
|
||||
rec {
|
||||
packages = {
|
||||
@@ -51,7 +56,7 @@
|
||||
# Allow cargo to download crates.
|
||||
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
buildInputs = [ rust-toolchain ];
|
||||
buildInputs = [ rust-toolchain python3 ];
|
||||
|
||||
# Runtime dependencies.
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.vulkan-loader ];
|
||||
|
Reference in New Issue
Block a user