Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple possible axis matches found - mapCube "time" axis error with >1 InDims("time") and OutDims("time") #60

Closed
noralinscheid opened this issue May 7, 2021 · 5 comments

Comments

@noralinscheid
Copy link

I am having issues with applying mapCube on several cubes, when specifying more than one (identical) input axis InDims("time") and an OutDims("time"). Each input cube contains one time axis and they are identical. When using "lon" or "lat" axes instead this issue does not occur. If OutDims is not "time", the function also runs through. Prescribing a new time axis in OutDims circumvents the problem. So it seems quite specific to converting two InDims("time") to a single OutDims("time").

c = Cube("/scratch/DataCube/v2.0.0/esdc-8d-0.25deg-184x90x90-2.0.0.zarr/")
cta = c[var="air_temperature_2m",time=2000:2005,lon=(10,11),lat=(50,51)]
cpr = c[var="precipitation",time=2000:2005,lon=(10,11),lat=(50,51)]

getAxis("time",cta) # works 
getAxis("time",cpr) # works
cta_masked = map(*,cta,cpr) # works

function f(xout,xin1,xin2)
    xout[:] .= mean(xin1./xin2)
end

cta_masked = mapCube(f,(cta,cpr); indims=(InDims("time"),InDims("time")),outdims=OutDims()) #works 

function f2(xout,xin1,xin2)
    xout[:] .= xin1./xin2
end

cta_masked = mapCube(f2,(cta,cpr);indims=(InDims("lat"),InDims("lat")),outdims=OutDims("lat")) #works 

cta.time == cpr.time # true
cta_masked = mapCube(f2,(cta,cpr);indims=(InDims("time"),InDims("time")),outdims=OutDims(cta.time)) #works
cta_masked = mapCube(f2,(cta,cpr);indims=(InDims("time"),InDims("time")),outdims=OutDims("time")) #error 

Error message:

Multiple possible axis matches found for YAXArrays.Cubes.Axes.ByName("time")

on
[90b8fcef] YAXArrayBase v0.2.1
[c21b50f5] YAXArrays v0.1.2
[30363a11] NetCDF v0.11.3
[359177bc] ESDL v0.9.0 https://github.com/esa-esdl/ESDL.jl.git#master

@noralinscheid noralinscheid changed the title Multiple possible axis matches found - "time" axis error with >1 InDims("time") and OutDims("time") Multiple possible axis matches found - mapCube "time" axis error with >1 InDims("time") and OutDims("time") May 7, 2021
@meggart
Copy link
Member

meggart commented May 7, 2021

The issue seems to be the following:

cta.time == cpr.time # Returns true
unique([cta.time, cpr.time]) # Returns a vector with both axes

so although both time axes are the same, a call to unique still returns both. It is probably related to the values of the axis being a vector (mutable) while the values of a lon or lat axis are ranges (immutable). @felixcremer do you have an idea what to do? Define isequal?

@felixcremer
Copy link
Member

I don't think, that defining an isequal method is going to change anything, because isequal(cta.time, cpr.time)is already true. I am confused why unique gives two values.
When you use renameaxis!(cta, "Time"=>cpr.time) the computation works.
This is a dirty workaround for now and we would need to find a proper fix for this problem.

@felixcremer
Copy link
Member

We would have to also implement a custom hash function because we already have the custom isequal function in Axes.jl 281.
According to the docs:

isequal is the comparison function used by hash tables (Dict). isequal(x,y) must imply that hash(x) == hash(y).

This typically means that types for which a custom == or isequal method exists must implement a corresponding hash method (and vice versa). Collections typically implement isequal by calling isequal recursively on all contents.

See this julia issue for a more in depth discussion
JuliaLang/julia#12198

@meggart
Copy link
Member

meggart commented May 7, 2021

I was about to suggest exactly the same right now...

@meggart
Copy link
Member

meggart commented May 7, 2021

After defining

Base.hash(ax::CubeAxis{<:Any,S}, h::UInt) where S = hash(S, hash(ax.values, h))

@noralinscheid s example works as expected. Does anyone want to make a PR or shall I do it?

@meggart meggart mentioned this issue May 11, 2021
@meggart meggart closed this as completed May 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants