Replies: 2 comments 4 replies
-
It currently kind-of means that. There's four things to note:
from typing import TypeAlias # or from typing_extensions for older python
from cosmology.api import BackgroundCosmology
from dask import Array
DaskCosmo: TypeAlias = BackgroundCosmology[Array]
...
Just a note that the above discussion of But more generally, I think this function is actually a good example why we DO want type vars. This function is missing a return type annotation; filling this in... T = TypeVar('T')
def myfunction(cosmo: Cosmology[T]) -> T:
... If
This is true, but we couldn't use this function as intended inside of dask_cosmo = SomeCosmology(H0=dask.Array(70))
def myfunction(cosmo: Cosmology[NO TYPE], z: T) -> T:
return mycosmo.H * cosmo.scale_factor(z)
myfunction(dask_cosmo, np.array([1, 2, 3]) # THIS IS WRONG! does it return a dask or numpy array?
I think this is the real crux of the issue. We need to expand the API to permit float inputs! I think Array outputs is fine since that's up to the library implementor, but yes, float inputs should be allowed.
It's not just the constants like This didn't fit into the above discussion, but I think it's very important to make the Cosmology API work well in ML and high precision contexts. We should be able to have |
Beta Was this translation helpful? Give feedback.
-
Ok, if I understand it correctly, the interface is saying that a cosmology object of type Taking CAMB as an example, which computes everything in Fortran via an interface using numpy arrays, it then makes sense that the But where before I thought they would all have to individually make their inputs compatible, actually the current interface makes our life easier, because we would only have to write e.g. a single "dask adapter" cosmology that takes dask chunks and feeds them to a For the constants, I agree that having them be 0D arrays is a good idea, if there is scope for supporting arrays of parameters. Running a whole MCMC chain via dask parameter arrays is definitely something that should be written down under the "vision" of the interface! Lastly, for the scalar vs 0d array input, would it not suffice to define all functions like this: from numbers import Number
from array_api import Array
...
NumericT = TypeVar('NumericT', bound=Number|Array)
class Cosmology(...):
...
def scale_factor(self: Self, z: NumericT) -> NumericT:
... |
Beta Was this translation helpful? Give feedback.
-
As far as I can tell, the definition
means that I need to explicitly pass the array type when specifying the type hint for a function. I find that quite awkward, particularly if it means I have to declare and pass another type var to support arbitrary cosmology classes:
However, if we let
ArrayT
be a type var in the individual functions instead, we don't really need the Generic class there:Having the type var at the method level also results in correct behaviour when floats are passed to the function. That's good because, realistically, no one will explicitly convert their floats to 0-dim arrays before calling these functions, so no one will ever strictly adhere to the API as it stands.
I understand that the generic class definition is necessary for hinting the properties of the cosmological constants, but that is such a minor part of the interface that I think they could simply be
float
, or maybeArray
if we want support for arrays of values.Beta Was this translation helpful? Give feedback.
All reactions