Massive boost.
Hard to quantify everything.
We're almost batch/inverse design!
- All units are now correct at realization (they weren't before), and
several operations were simply wrong.
- Near-optimal "flow narrowing", which globally minimizes `DataChanged`
even in the face of complex internal property dependencies.
- Sockets now cache `FlowKind` output themselves, with invalidation
provided for and flow narrowing happening before it even enters the
node flow.
- New FlowKind (`PreviewsFlow`) w/plotting, 3D, efficient caching, with
all previewed nodes already adapted.
- Drastically prettified plot output, due to seaborn theme integration,
dict-like data transport w/better labelling, etc. .
- Deep, reliable unit/unit dimension deduction and arithmetic for
`PhysicalType` deduction using dimensional analysis on arbitrary
expression operations.
- Fourier transform w/Nyquist limits as boundary conditions (preserving original shift).
- Vastly improved math node operation checks.
- Symbol constant node, integrating domain presumptions.
- Flow integration for ExprSocket, including for flow-dynamic capabilities and color.
- Viewer node got a big update, incl. live-display of sympy types (even
matrix) and a few Tidy3D types, as well as seperating deeper options
into a "Debug" mode
- Deeply streamlined symbolic flow, including
- **Differentiable Box structure**, w/generic lazy parameter support - only the start!
We implemented a node to load various kinds of data, notably `.npy`,
`.txt`, `.txt.gz`, and `.csv`. The `DataFileImporterNode` really should
expose some settings for setting name/mathtype/physical type/unit of
each unit, and/or treating a column from 2D data as index coordinates.
But the nuances of doing this in a manner general enough to deal with
!=2D data was a lot, and we needed similar abilities in the general math
system anyway.
So, we delved back into the `FilterMathNode` and a little into the
`TransformMathNode`. Fundamentally, a few difficult operations came out
of this:
- Filter:SliceIdx: Slice an array using the usual syntax, as baked into the
function.
- Filter:PinIdx: Pin an axis by its actual index.
- Filter:SetDim: Set the `InfoFlow` index coordinates of an axis to a specific,
loose-socket provided 1D array, and use a common symbol to set the
name+physical type (and allow specifying an appropriate unit).
- Transform:IntDimToComplex: Fold a last length-2 integer-indexed axis
into a real output type, which removes the dimension and produces a
complex output type. Essentially, this is equivalent to folding it as
a vector and treating the `R^2` numbers as real/imaginary, except this
is more explicit.
By combining all of these, we managed to process and constrain the medium data to
be a well-suited, unit-aware (**though not on the output (yet)**) `wl->C` tensor.
In particular, the slicing is nice for avoiding discontinuities.
Workflow-wise, we'll see how important these are / what else we might
want. Also, it turns out Blender's text editor is really quite nice for
light data-text viewing.
It's recommended to add license headers to all files in an AGPL project, in case a file is viewed outside the context of its main repository. We're using a `pre-commit` tool to manage this, to make sure it's consistently applied to all our Python files.
The performance difference isn't as clear cut as hoped.
However, the plotting procedure is enormously more straightforward, and
performance is more predictable.
So it's worth it.
We're managing to perfectly reuse figure/canvas/axis, but still hovering at around 70-80ms.
Mind you, the tested machine is an older laptop.
Still, things feel interactive enough, especially together with the
other modifications.
To really amp it up, we can look into blitting. It requires alterations
to the plotting methodology, but it offers a cached approach to drawing
only altered pixels (the bottleneck with `canvas.draw()` is that it
needs to render all the pixels, every time).
We can also try to lower the resolution if it's too slow.
The Viz node now detects the shape of the data, and presents compatible
plot options.
Not all are implemented, but a few quite important ones are.
Additionally, a number of dataflow-related bugs were investigated and
fixed. A few were truly damaging, but many simply resulted in gross
inefficiencies - we must be careful declaring BLFields that are updated
in hot loops!
Moreover, it is exceptionally easy to add more as needed, as we analyze
more and more sims.
The only limit is `matplotlib`, which is... well, yeah.
Due to the BLField work, the dynamicness of the Viz node is quite
under control, so there will not be any critical issues there.
The plotting lags (70ms total in the hot loop), but that's actually
entirely fixeable.
It's also entirely the `managed_bl_image`'s fault.
Fixing these inefficiencies will also make Tidy3D's builtin plots
near-realtime, incidentally.
We profiled the following currently:
- 25ms: Creating `fig = plt.subplots`. We can reuse fig per-managed
image.
- 43ms: The BytesIO roundtrip, including `savefig`. We can instead use
the Agg backend, `fig.canvas.draw()`, and a `np.frombuffer` to both
plot directly to the memory location,
- ~3ms: Actual plotting functions in `image_ops`. They are seriously fast.
- ~0ms: Blitting pixels to the Blender image - this was optimized in
4.1, and it shows; the time to copy the data over is essentially nothing.