Add flepimop2.axis module for realized axes#208
Conversation
| ... domain=(1e-9, 1e-3), | ||
| ... spacing="log", | ||
| ... ).points() | ||
| ... ) |
There was a problem hiding this comment.
The Notes block claims points are computed via np.linspace(…, endpoint=False) / np.geomspace(…, endpoint=False), but the implementation computes bin centroids from size + 1 edges — arithmetic midpoints for linear (0.5 * (edges[:-1] + edges[1:])), geometric means for log (np.sqrt(edges[:-1] * edges[1:])).
These produce different values. E.g. for domain=(0, 8), size=4:
linspace(0, 8, 4, endpoint=False)→(0.0, 2.0, 4.0, 6.0)- Bin midpoints (actual) →
(1.0, 3.0, 5.0, 7.0)
The implementation is the better choice (cell-centered points are standard for FVM-style discretization and align naturally with bins()), but the docstring should describe what the code does. Something like:
Points are the centroids of the bins returned by
bins(): arithmetic midpoints for linear spacing, geometric means for log spacing.
There was a problem hiding this comment.
Ah good catch, I had originally used linspace/geomspace but realized the behavior was not quite right and forgot to update the docstring accordingly. Fixed in https://github.com/ACCIDDA/flepimop2/compare/6bfe49d13e7d0f0a5bfe683775b5fb382226f867..64e0a2b2f99b46aff9ff73c953d236edd1ddaba8
6bfe49d to
64e0a2b
Compare
pearsonca
left a comment
There was a problem hiding this comment.
I think this may be fine for now, but copying my slack thoughts here:
- we have top level config specification axes - that basically says here are other dimensions that models must somehow implement (Categorical and Continuous), and that parameters may vary over. These are pydantic types for easy deserialization
- my understanding of this PR is that we are doing the first pass at expressing how systems & parameters might meet those specifications - so the high level axes would not use these realizations, but systems, parameters, etc would as part of their specification
- these don't seem to be pydantic types; what's the plan for how things that need realizations create them? If I'm a system or parameter module provider, how do I have my config approach "just work"?
- In terms of design: my mind jumps to thinking that the concrete axes for implementors would be subclasses of their overarching types - not insisting on that design, but am curious if y'all though thru that angle and hit some dead end? As in, might have
class ManualBinAxis(ContinuousAxis)vsLinearBinAxis,LogBinAxis,DensityBinned, etc. (Categorical is probably less interesting, but even there could have all categories distinct, some grouped, etc). - Mostly thinking about that from two angles - the concrete axes also need to do abstract axes tasks (e.g. report domain) along with ones that specification-axes don't (e. g. how is that domain divided). Second, if they work that way, then checking if concrete axes match specification axes becomes easy (e.g. is domain covered)
- I am somewhat ambivalent about not modularizing axis representation. This approach avoids modularizing, which differs from how we approach other features - but that's probably the only downside I see. I think that's fine as modularization seems complicated (like what's the API?), and i'm not sure what other implementations might be even vaguely interesting (so limited value to make it modular). Also seems we can do it later if need be.
As I said, fine for now, but might want to directionally shift in response to those concerns
| def _continuous_domain(self) -> tuple[float, float]: | ||
| """ | ||
| Validate Continuous Axis Metadata. | ||
|
|
||
| Ensure this axis can support continuous point and bin helpers. | ||
|
|
||
| Returns: | ||
| The continuous axis domain as `(lower, upper)`. | ||
|
|
||
| Raises: | ||
| TypeError: If this is not a continuous axis. | ||
| ValueError: If the continuous axis is missing domain or spacing | ||
| metadata. | ||
|
|
There was a problem hiding this comment.
feels like this should not raise a value error - rather, an error should occur at construction time?
6445e0f to
5594072
Compare
5594072 to
82fad6a
Compare
Added the `axis` module for realizing and manipulating axes from configuration. Includes: - `ResolvedShape` as a container for metadata about the shape of an object based on its axes. - `Axis` as a data class for a realized axis that objects which need axes can use to do their calculations. - `AxisCollection` as a mapping of `Axis` objects that simplify access when multiple axes are needed. - Dropped deprecation warning from using the `axes` attribute of `ConfigurationModel`. Follow up to #147, #164.
82fad6a to
769052b
Compare
So I think there are two lines of thinking in this comment:
|
Added the
axismodule for realizing and manipulating axes from configuration. Includes:ResolvedShapeas a container for metadata about the shape of an object based on its axes.Axisas a data class for a realized axis that objects which need axes can use to do their calculations.AxisCollectionas a mapping ofAxisobjects that simplify access when multiple axes are needed.axesattribute ofConfigurationModel.Follow up to #147, #164.