You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One thing that bother me alot is that pandas lacks good unit support (e.g. quantities, pint, ...)
Is there a chance that xray will support it?
Reacted by Gerrit Holl, Orso Meneghini, Sterling Smith, Shaun Read, Tom Nicholas, Nick Murphy, Miguel Raz Guzmán Macedo, Wei Ji, Florian R. Hölzlwimmer and David Stansby
Unfortunately, doing this in a feasible and maintainable way will probably require upstream fixes in NumPy. In particular, better support for duck-array types (numpy/numpy#4164) and/or the ability to write units as a custom NumPy dtypes. Both of these are on the NumPy roadmap, though they don't have a timeframe for when that will happen.
Unfortunately, the astropy approach uses a numpy.ndarray subclass, which means it's mutually exclusive with dask.array. Otherwise, it does look very nice, though.
@shoyer - as one who thinks unit support is probably the single best thing astropy has (and is co-maintainer of astropy.units), I thought I'd pipe in: why would it be a problem that astropy's Quantity is an ndarray subclass? I must admit not having used dask arrays, but since they use ndarray internally for the pieces, shouldn't the fact that Quantity has the same interface/methods, make it relatively easy to swap ndarray for Quantity internally? I'd be quite happy to help think about this (surely it cannot be as bad as it is for MaskedArray ;-).
Alternatively, maybe it is easier to tag on the outside rather than the inside. This would also not seem to be that hard, given that astropy's Quantity is really just a wrapper around ndarray that carries a Unit instance. I think the parts that truly wrap might be separated from those that override ndarray methods, and would be willing to implement that if there is a good reason (like making dask quantities possible...). It may be that in this case one would not use Quantity proper, but rather just the parts of units where the real magic happens: in the Unit class (which does the unit conversion) and in quantity_helpers.py (which tells what unit conversion is necessary for a given operation/function).
@mhvk It would certainly be possible to extend dask.array to handle units, in either of the ways you suggest.
Although you could allow Quantity objects inside dask.arrays, I don't like that approach, because static checks like units really should be done only once when arrays are constructed (akin to dtype checks) rather than at evaluation time, and for every chunk. This suggests that tagging on the outside is the better approach.
So far, so good -- but with the current state of duck array typing in NumPy, it's really hard to be happy with this. Until __numpy_ufunc__ lands, we can't override operations like np.sqrt in a way that is remotely feasible for dask.arrays (we can't afford to load big arrays into memory). Likewise, we need overrides for standard numpy array utility functions like concatenate. But the worst part is that the lack of standard interfaces means that we lose the possibility of composing different arrays backends with your Quantity type -- it will only be able to wrap dask or numpy arrays, not sparse matrices or bolt arrays or some other type yet to be invented.
Once we have all that duck-array stuff, then yes, you certainly could write all a duck-array Quantity type that can wrap generic duck-arrays. But something like Quantity really only needs to override compute operations so that they can propagate dtypes -- there shouldn't be a need to override methods like concatenate. If you had an actual (parametric) dtype for units (e.g., Quantity[float64, 'meters']), then you would get all those dtype agnostic methods for free, which would make your life as an implementer much easier. Hence why I think custom dtypes would really be the ideal solution.
@shoyer - fair enough, and sad we don't have __numpy_ufunc__ yet... I agree that with Quantity inside, one would end up duplicating work for every chunk, which makes it less than ideal even though it would probably be the easier approach to implement.
For the outside method, from the dask perspective, it would indeed be easiest if units were done as a dtype, since then you can punt all the decisions to helper routines. My guess, though, is that it will be a while before numpy will include what is required to tell, e.g., that if I add something in m to something in cm, the second argument has to be multiplied by 0.01. But astropy does provide something just like that: quantity_helpers exposes a dict keyed by operation, which holds functions that return the required converters given the units. E.g., in the above example, internally what happens is
In dask, you could run the converters on your individual chunks, though obviously I don't know how easy it is to add an extra step like this without slowing down other aspects too much.
p.s. For concatenate, you need unit conversion as well, so sadly Quantity does need to override that too (and currently cannot, which is rather annoying).
I am one of the authors of Pint and I was just pointed here by @arsenovic
Pint does not subclass ndarray, it rathers wrap any numerical type dispatching to the wrapped value any attribute access that does not understand. By defining __array_prepare__ and __array_wraps__ most numpy functions and array attributes work as expected without monkey patching or having a specialized math module. For example:
>>>importnumpyasnp>>>importpint>>>ureg=pint.UnitRegistry()
>>> [1., 4., 9.] *ureg.meter# a list is interpreted as an ndarray<Quantity([1.4.9.], 'meter')>>>>np.sqrt(_)
<Quantity([ 1.2.3.], 'meter ** 0.5')>>>>_.sum()
<Quantity(6.0, 'meter ** 0.5')>
@hgrecco - for astropy's Quantity, we currently also rely on __array_prepare__ and __array_wrap__. The main annoyances are (1) one cannot change the input before a numpy ufunc is called, and therefore often has no choice but to let a wrong calculation proceed; (2) proper recognition in non-ufunc functions is sparse (e.g., np.dot, etc.; see http://docs.astropy.org/en/latest/known_issues.html#quantity-issues)
Aside: at some point I'd hope to get the various implementations of units to talk together: it would be good to have an API that works such that units are inter-operable.
@hgrecco Are you suggesting that pint could wrap xarray objects, or that xarray could wrap pint? Either is certainly possible, though I'm a bit pessimistic that we can come up with a complete solution without the numpy fixes we've been discussing.
Also, just to note, xarray contains a Dataset type for representing collections of variables that often have different units (e.g., temperature and pressure). That suggests to me that it could make more sense to put pint and/or astropy.Quantity objects inside xarray arrays rather than the other way around.
id just like to chime in and say that this feature would really be sweet. i always find myself doing a lot work to handle/convert different units.
it seems that adding units to labeled axes does a lot to describe a set of data.
@shoyer When we prototyped Pint we tried putting Quantity objects inside numpy array. It was was working fine but the performance and memory hit was too large. We were convinced that our current design was right when we wrote the first code using it. The case might be different with xarray. It would be nice to see some code using xarray and units (as if this was an already implemented feature).
@mhvk I do agree with your views. We also mention these limitations in the Pint documentation. Wrapping (instead of subclassing) adds another issue: some Numpy functions do not recognize a Quantity object as an array. Therefore any function that call numpy.asanyarray will erase the information that this is a quantity (See my issue here numpy/numpy#4072).
In any case, as was mentioned before in the thread Custom dtypes and Duck typing will be great for this.
In spite of this limitations, we chose wrapping because we want to support quantities even if NumPy is not installed. It has worked really nice for us, working in most of the common cases even for numpy arrays.
Regarding interoperating, it will be great. It will be even better if we can move into one, blessed, solution under the pydata umbrella (or similar).
If anyone is excited about working on the NumPy improvement we need to make this more feasible (namely, custom dtypes and duck typing) at BIDS, you should talk to @njsmith.
With the units attribute, I was presuming based on the past comments that DataArray.units would be a new property; I forgot that DataArray.<attrname> passes along to DataArray.attrs.<attrname>, so that implementing something new for DataArray.units would be a breaking change!
I think the new property is still an option, even if we want to preserve accessing "units" from attrs, e.g.,
@propertydefunits(self):
ifhasattr(self.data, 'units'):
# data is an array with unitsreturnself.data.unitselif'units'inself.attrs:
# consider issuing a FutureWarning here?returnself.attrs['units']
else:
raiseAttributeError('units')
Oh, okay, having the fallback like that was how I thought about implementing it. (I'm sorry that I didn't describe that in my initial comment.)
So would the way forward be to implement DataArray.units_convert()/DataArray.units_to() and DataArray.units as you described right now, but wait for and/or delegate IO integration? Or, should there also be a fully-backwards-compatible IO integration implemented now (such as an optional kwarg on open_dataset and to_netcdf)?
That said, I agree that the dedicated accessor is a pretty good interface, especially if you want more methods/property than units and to. Even then array.pint.units and array.pint.to() is pretty readable. This could make sense if we are concerned about different interfaces for different unit libraries.
The accessor route is also definitely more conservative than putting first-class unit support in xarray proper, which I like.
As for where to put it, that's sort of up to you. I think it's probably going to get complicated enough that it should into a library that can be installed, rather than being a boilerplate example in xarray's docs. It could be in xarray if it's going to be very minimal (e.g., only one method + one property) but if you want more than that -- and judging by pint-pandas I would guess you do -- then it should probably go into pint or a dedicated package, e.g., pint-xarray.
I would not write a general purpose xarray+units library unless you're particularly excited about doing that for some reason -- it's much better to start with a particular integration that works well than to make a half-hearted effort at something general purpose without well-motivated use-cases.
@shoyer I agree, the accessor interface makes a lot of sense for this: it's more conservative on the xarray side, while also giving the most flexibility for the pint + xarray integration.
Based on your feedback and what I'd hope to see out of the pint + xarray integration, I'm thinking a pint-adjacent package like pint-xarray may be the best route forward. I'll create an issue on pint to inquire about that possibility. See hgrecco/pint#849.
The other virtue of the separate package is a faster release cycle. We can (and should!) still put a full example in the xarray docs.
For IO integration, I think the simplest choice would be to write utility functions for going to pint arrays from unit-free arrays with string “units” in attrs (and back). That will be easily composable with xarray’s existing IO functionality.
Based the points raised by @crusaderky in hgrecco/pint#878 (comment) about how much special case handling xarray has for dask arrays, I was thinking recently about what it might take for the xarray > pint > dask.array wrapping discussed here and elsewhere to work as fluidly as xarray > dask.array currently does.
Would it help for this integration to have pint Quanitites implement the dask custom collections interface for when it wraps a dask array? I would think that this would allow a pint Quanitity to behave in a "dask-array-like" way rather than just an "array-like" way. Then, instead of xarray checking for isinstance(dask_array_type), it could for check for "duck dask arrays" (e.g., those with both __array_function__ and __dask_graph__)? There are almost certainly some subtle implementation details that would need to be worked out, but I'm guessing that this could take care of the bulk of the integration.
Also, if I'm incorrect with this line of thought, or there is a better way forward for implementing this wrapping pattern, please do let me know!
Would it help for this integration to have pint Quanitites implement the dask custom collections interface for when it wraps a dask array? ... Then, instead of xarray checking for isinstance(dask_array_type), it could for check for "duck dask arrays" (e.g., those with both __array_function__ and __dask_graph__)?
Hi all, I was just pointed at this by someone who went to the NumFOCUS summit. I'm the lead developer for unyt, which I see has come up a little bit. If anyone wants to chat with me about adding support for unyt along with Pint I'd be happy to discuss.
sorry for the late reply, @ngoldbaum. For xarray to support unyt, it would have to implement NEP-18 (i.e. __array_function__) which I think it does not yet? I would expect to have unyt support come for free once pint support works so I would focus on that first (see #3594 for the current progress). Extending the tests to also test unyt would be possible but I'm thinking it would be better to put that into the accessor package (as discussed above for a possible pint accessor)?
There were a few unresolved design questions with how unit libraries should implement certain numpy functions (e.g. how where should behave when receiving array(nan) and array(0) which xarray uses to implement nanops, or which unit the result of full_like should have): see hgrecco/pint#905. Any supported unit library would have to behave the same way so I think it would be good to coordinate that. Thoughts?
Hi! I'm just popping in as a very interested user of both xarray and unit packages to ask: since there's been some awesome progress made here and pint-xarray is now enough of A Thing to have documentation, though obviously experimental - how much work would you expect a corresponding package for astropy's Quantities to take, given the current state of things?
Are there any limitations that would prevent that? I saw the discussion above about Quantities being more problematic due to taking the subclass-from-numpy-arrays route, but I'm not sure how much of a roadblock that still is. I would suspect the API could be shared with pint-xarray (which, obviously, is experimental for now).
I saw the discussion above about Quantities being more problematic
I would expect astropy quantities to work just fine as long as they are duck arrays. Also, the only limitation I would expect them to have is that they can't "wrap" anything other than numpy arrays. dask arrays are an exception since they can wrap quantities using the _meta attribute (which is something we try to avoid with pint, though).
For reference, the currently remaining issues for all duck arrays (except obviously dask) are documented here
I would expect astropy quantities to work just fine as long as they are duck arrays
actually, that turns out to be wrong. Since isinstance(data, np.ndarray) returns true for astropy.units.Quantity, it is cast to ndarray using np.asarray:
"__array_function__ protocol but NEP18 is not enabled. "
"Check that numpy >= v1.16 and that the environment "
'variable "NUMPY_EXPERIMENTAL_ARRAY_FUNCTION" is set to '
'"1"'
)
# validate whether the data is valid data types.
data=np.asarray(data)
Adding or issubclass(type(data), np.ndarray)or type(data) != np.ndarray does allow wrapping a astropy.units quantity in Dataset / DataArray objects but it breaks a few tests. Also, unless we modify the testsuite in xarray/tests/test_units.py to run with astropy.units instead of pint I can't really tell which features of xarray strip the units (in addition to the ones documented for pint). For that, we probably need to somehow create a generalization of the tests for duck arrays.
# validate whether the data is valid data types. Also, explicitly cast `numpy`
# subclasses and `numpy` scalars to `numpy.ndarray`
data=np.asarray(data)
@keewis it looks like adding an if block before line 323 would allow astropy quantities to be wrapped as you said, i.e.,
if isinstance(data, u.Quantity):
return cast("T_DuckArray", data)
what else is needed to make this happen? I'd love to make some progress towards xarray wrapping astropy.units. Should #7799 be picked up again since @dstansby can't work on it anymore?
We've since made some progress with the automatic generation of tests for arbitrary duck arrays in xarray-array-testing, so it might be better to work on that instead of trying to generalize the massive (and probably stale) testsuite for testing unit support with pint.
That said, that's for testing the support, not the support itself. Implementing that should be fairly easy, we should just make sure to continue banning numpy.matrix and numpy.ma.masked_array (I think those were the ones we explicitly wanted to convert to numpy.ndarray in #2956). Either way, feel free to open a dedicated issue to track astropy.units support.
Edit: actually, numpy.ma.MaskedArray is special-cased immediately above the block for duck arrays, so I believe the only thing we have to make sure is to not pass through numpy.matrix instances.
Activity
shoyer commentedon Aug 12, 2015
Eventually, I hope so!
Unfortunately, doing this in a feasible and maintainable way will probably require upstream fixes in NumPy. In particular, better support for duck-array types (numpy/numpy#4164) and/or the ability to write units as a custom NumPy dtypes. Both of these are on the NumPy roadmap, though they don't have a timeframe for when that will happen.
rabernat commentedon Aug 17, 2015
Astropy has pretty good units support:
http://astropy.readthedocs.org/en/latest/units/
Would it be possible to copy what they do?
shoyer commentedon Aug 17, 2015
Unfortunately, the astropy approach uses a numpy.ndarray subclass, which means it's mutually exclusive with dask.array. Otherwise, it does look very nice, though.
On Mon, Aug 17, 2015 at 8:38 AM, Ryan Abernathey notifications@github.com
wrote:
mhvk commentedon Sep 19, 2015
@shoyer - as one who thinks unit support is probably the single best thing astropy has (and is co-maintainer of
astropy.units), I thought I'd pipe in: why would it be a problem that astropy'sQuantityis anndarraysubclass? I must admit not having used dask arrays, but since they usendarrayinternally for the pieces, shouldn't the fact thatQuantityhas the same interface/methods, make it relatively easy to swapndarrayforQuantityinternally? I'd be quite happy to help think about this (surely it cannot be as bad as it is forMaskedArray;-).Alternatively, maybe it is easier to tag on the outside rather than the inside. This would also not seem to be that hard, given that astropy's
Quantityis really just a wrapper aroundndarraythat carries aUnitinstance. I think the parts that truly wrap might be separated from those that overridendarraymethods, and would be willing to implement that if there is a good reason (like making dask quantities possible...). It may be that in this case one would not useQuantityproper, but rather just the parts ofunitswhere the real magic happens: in theUnitclass (which does the unit conversion) and inquantity_helpers.py(which tells what unit conversion is necessary for a given operation/function).shoyer commentedon Sep 21, 2015
@mhvk It would certainly be possible to extend dask.array to handle units, in either of the ways you suggest.
Although you could allow
Quantityobjects inside dask.arrays, I don't like that approach, because static checks like units really should be done only once when arrays are constructed (akin to dtype checks) rather than at evaluation time, and for every chunk. This suggests that tagging on the outside is the better approach.So far, so good -- but with the current state of duck array typing in NumPy, it's really hard to be happy with this. Until
__numpy_ufunc__lands, we can't override operations likenp.sqrtin a way that is remotely feasible for dask.arrays (we can't afford to load big arrays into memory). Likewise, we need overrides for standard numpy array utility functions likeconcatenate. But the worst part is that the lack of standard interfaces means that we lose the possibility of composing different arrays backends with yourQuantitytype -- it will only be able to wrap dask or numpy arrays, not sparse matrices or bolt arrays or some other type yet to be invented.Once we have all that duck-array stuff, then yes, you certainly could write all a duck-array
Quantitytype that can wrap generic duck-arrays. But something likeQuantityreally only needs to override compute operations so that they can propagate dtypes -- there shouldn't be a need to override methods likeconcatenate. If you had an actual (parametric) dtype for units (e.g.,Quantity[float64, 'meters']), then you would get all those dtype agnostic methods for free, which would make your life as an implementer much easier. Hence why I think custom dtypes would really be the ideal solution.mhvk commentedon Sep 21, 2015
@shoyer - fair enough, and sad we don't have
__numpy_ufunc__yet... I agree that with Quantity inside, one would end up duplicating work for every chunk, which makes it less than ideal even though it would probably be the easier approach to implement.For the outside method, from the dask perspective, it would indeed be easiest if units were done as a dtype, since then you can punt all the decisions to helper routines. My guess, though, is that it will be a while before numpy will include what is required to tell, e.g., that if I add something in
mto something incm, the second argument has to be multiplied by0.01. But astropy does provide something just like that:quantity_helpersexposes a dict keyed by operation, which holds functions that return the required converters given the units. E.g., in the above example, internally what happens isIn
dask, you could run the converters on your individual chunks, though obviously I don't know how easy it is to add an extra step like this without slowing down other aspects too much.mhvk commentedon Sep 21, 2015
p.s. For
concatenate, you need unit conversion as well, so sadlyQuantitydoes need to override that too (and currently cannot, which is rather annoying).hgrecco commentedon Feb 8, 2016
I am one of the authors of Pint and I was just pointed here by @arsenovic
Pint does not subclass ndarray, it rathers wrap any numerical type dispatching to the wrapped value any attribute access that does not understand. By defining
__array_prepare__and__array_wraps__most numpy functions and array attributes work as expected without monkey patching or having a specialized math module. For example:I think something similar can be done for xarray.
mhvk commentedon Feb 9, 2016
@hgrecco - for astropy's
Quantity, we currently also rely on__array_prepare__and__array_wrap__. The main annoyances are (1) one cannot change the input before a numpy ufunc is called, and therefore often has no choice but to let a wrong calculation proceed; (2) proper recognition in non-ufunc functions is sparse (e.g.,np.dot, etc.; see http://docs.astropy.org/en/latest/known_issues.html#quantity-issues)Aside: at some point I'd hope to get the various implementations of units to talk together: it would be good to have an API that works such that units are inter-operable.
shoyer commentedon Feb 9, 2016
@hgrecco Are you suggesting that pint could wrap xarray objects, or that xarray could wrap pint? Either is certainly possible, though I'm a bit pessimistic that we can come up with a complete solution without the numpy fixes we've been discussing.
Also, just to note, xarray contains a
Datasettype for representing collections of variables that often have different units (e.g., temperature and pressure). That suggests to me that it could make more sense to put pint and/or astropy.Quantity objects inside xarray arrays rather than the other way around.arsenovic commentedon Feb 9, 2016
id just like to chime in and say that this feature would really be sweet. i always find myself doing a lot work to handle/convert different units.
it seems that adding units to labeled axes does a lot to describe a set of data.
hgrecco commentedon Feb 10, 2016
@shoyer When we prototyped Pint we tried putting Quantity objects inside numpy array. It was was working fine but the performance and memory hit was too large. We were convinced that our current design was right when we wrote the first code using it. The case might be different with xarray. It would be nice to see some code using xarray and units (as if this was an already implemented feature).
@mhvk I do agree with your views. We also mention these limitations in the Pint documentation. Wrapping (instead of subclassing) adds another issue: some Numpy functions do not recognize a Quantity object as an array. Therefore any function that call
numpy.asanyarraywill erase the information that this is a quantity (See my issue here numpy/numpy#4072).In any case, as was mentioned before in the thread Custom dtypes and Duck typing will be great for this.
In spite of this limitations, we chose wrapping because we want to support quantities even if NumPy is not installed. It has worked really nice for us, working in most of the common cases even for numpy arrays.
Regarding interoperating, it will be great. It will be even better if we can move into one, blessed, solution under the pydata umbrella (or similar).
spencerahill commentedon Feb 10, 2016
Not to be pedantic, but just one more 👍 on ultimately implementing units support within xarray -- that would be huge.
shoyer commentedon Feb 11, 2016
If anyone is excited about working on the NumPy improvement we need to make this more feasible (namely, custom dtypes and duck typing) at BIDS, you should talk to @njsmith.
39 remaining items
shoyer commentedon Aug 24, 2019
I think the new property is still an option, even if we want to preserve accessing
"units"fromattrs, e.g.,jthielen commentedon Aug 24, 2019
Oh, okay, having the fallback like that was how I thought about implementing it. (I'm sorry that I didn't describe that in my initial comment.)
So would the way forward be to implement
DataArray.units_convert()/DataArray.units_to()andDataArray.unitsas you described right now, but wait for and/or delegate IO integration? Or, should there also be a fully-backwards-compatible IO integration implemented now (such as an optional kwarg onopen_datasetandto_netcdf)?shoyer commentedon Aug 24, 2019
That said, I agree that the dedicated accessor is a pretty good interface, especially if you want more methods/property than
unitsandto. Even thenarray.pint.unitsandarray.pint.to()is pretty readable. This could make sense if we are concerned about different interfaces for different unit libraries.The accessor route is also definitely more conservative than putting first-class unit support in xarray proper, which I like.
As for where to put it, that's sort of up to you. I think it's probably going to get complicated enough that it should into a library that can be installed, rather than being a boilerplate example in xarray's docs. It could be in xarray if it's going to be very minimal (e.g., only one method + one property) but if you want more than that -- and judging by pint-pandas I would guess you do -- then it should probably go into pint or a dedicated package, e.g., pint-xarray.
I would not write a general purpose xarray+units library unless you're particularly excited about doing that for some reason -- it's much better to start with a particular integration that works well than to make a half-hearted effort at something general purpose without well-motivated use-cases.
jthielen commentedon Aug 24, 2019
@shoyer I agree, the accessor interface makes a lot of sense for this: it's more conservative on the xarray side, while also giving the most flexibility for the pint + xarray integration.
Based on your feedback and what I'd hope to see out of the pint + xarray integration, I'm thinking a pint-adjacent package like pint-xarray may be the best route forward.
I'll create an issue on pint to inquire about that possibility.See hgrecco/pint#849.shoyer commentedon Aug 24, 2019
The other virtue of the separate package is a faster release cycle. We can (and should!) still put a full example in the xarray docs.
For IO integration, I think the simplest choice would be to write utility functions for going to pint arrays from unit-free arrays with string “units” in attrs (and back). That will be easily composable with xarray’s existing IO functionality.
jthielen commentedon Sep 15, 2019
Based the points raised by @crusaderky in hgrecco/pint#878 (comment) about how much special case handling xarray has for dask arrays, I was thinking recently about what it might take for the xarray > pint > dask.array wrapping discussed here and elsewhere to work as fluidly as xarray > dask.array currently does.
Would it help for this integration to have pint Quanitites implement the dask custom collections interface for when it wraps a dask array? I would think that this would allow a pint Quanitity to behave in a "dask-array-like" way rather than just an "array-like" way. Then, instead of xarray checking for
isinstance(dask_array_type), it could for check for "duck dask arrays" (e.g., those with both__array_function__and__dask_graph__)? There are almost certainly some subtle implementation details that would need to be worked out, but I'm guessing that this could take care of the bulk of the integration.Also, if I'm incorrect with this line of thought, or there is a better way forward for implementing this wrapping pattern, please do let me know!
shoyer commentedon Sep 15, 2019
Yes, great idea!
ngoldbaum commentedon Nov 13, 2019
Hi all, I was just pointed at this by someone who went to the NumFOCUS summit. I'm the lead developer for
unyt, which I see has come up a little bit. If anyone wants to chat with me about adding support forunytalong withPintI'd be happy to discuss.keewis commentedon Dec 8, 2019
sorry for the late reply, @ngoldbaum. For
xarrayto supportunyt, it would have to implement NEP-18 (i.e.__array_function__) which I think it does not yet? I would expect to haveunytsupport come for free oncepintsupport works so I would focus on that first (see #3594 for the current progress). Extending the tests to also testunytwould be possible but I'm thinking it would be better to put that into the accessor package (as discussed above for a possiblepintaccessor)?There were a few unresolved design questions with how unit libraries should implement certain
numpyfunctions (e.g. howwhereshould behave when receivingarray(nan)andarray(0)whichxarrayuses to implement nanops, or which unit the result offull_likeshould have): see hgrecco/pint#905. Any supported unit library would have to behave the same way so I think it would be good to coordinate that. Thoughts?StanczakDominik commentedon Nov 25, 2020
Hi! I'm just popping in as a very interested user of both xarray and unit packages to ask: since there's been some awesome progress made here and pint-xarray is now enough of A Thing to have documentation, though obviously experimental - how much work would you expect a corresponding package for astropy's Quantities to take, given the current state of things?
Are there any limitations that would prevent that? I saw the discussion above about Quantities being more problematic due to taking the subclass-from-numpy-arrays route, but I'm not sure how much of a roadblock that still is. I would suspect the API could be shared with pint-xarray (which, obviously, is experimental for now).
keewis commentedon Nov 25, 2020
I would expect
astropyquantities to work just fine as long as they are duck arrays. Also, the only limitation I would expect them to have is that they can't "wrap" anything other thannumpyarrays.daskarrays are an exception since they can wrap quantities using the_metaattribute (which is something we try to avoid withpint, though).For reference, the currently remaining issues for all duck arrays (except obviously
dask) are documented herekeewis commentedon Jan 19, 2021
actually, that turns out to be wrong. Since
isinstance(data, np.ndarray)returns true forastropy.units.Quantity, it is cast tondarrayusingnp.asarray:xarray/xarray/core/variable.py
Lines 231 to 245 in 7dbbdca
Adding
or issubclass(type(data), np.ndarray)or type(data) != np.ndarraydoes allow wrapping aastropy.unitsquantity inDataset/DataArrayobjectsbut it breaks a few tests. Also, unless we modify the testsuite inxarray/tests/test_units.pyto run withastropy.unitsinstead ofpintI can't really tell which features ofxarraystrip the units (in addition to the ones documented forpint). For that, we probably need to somehow create a generalization of the tests for duck arrays.riley-brady commentedon Oct 6, 2022
I believe this can be closed via #5734 @andersy005?
tien-vo commentedon Nov 2, 2024
xarray/xarray/core/variable.py
Lines 294 to 331 in 5fd50c5
@keewis it looks like adding an if block before line 323 would allow astropy quantities to be wrapped as you said, i.e.,
what else is needed to make this happen? I'd love to make some progress towards
xarraywrappingastropy.units. Should #7799 be picked up again since @dstansby can't work on it anymore?keewis commentedon Nov 2, 2024
We've since made some progress with the automatic generation of tests for arbitrary duck arrays in xarray-array-testing, so it might be better to work on that instead of trying to generalize the massive (and probably stale) testsuite for testing unit support with
pint.That said, that's for testing the support, not the support itself. Implementing that should be fairly easy, we should just make sure to continue banning
numpy.matrixandnumpy.ma.masked_array(I think those were the ones we explicitly wanted to convert tonumpy.ndarrayin #2956). Either way, feel free to open a dedicated issue to trackastropy.unitssupport.Edit: actually,
numpy.ma.MaskedArrayis special-cased immediately above the block for duck arrays, so I believe the only thing we have to make sure is to not pass throughnumpy.matrixinstances.