YAXArrays.jl icon indicating copy to clipboard operation
YAXArrays.jl copied to clipboard

How to add/change metadata in a YAXArray or Dataset?

Open dpabon opened this issue 1 year ago • 10 comments

In this MWE:


lst = randn(200,200)

lst = (
Dim{:x}(1:size(lst)[1]),
Dim{:y}(1:size(lst)[2]),
)

lst_cube = YAXArray(axlist, lst)

if I try:

lst_cube.properties = Dict("dummy1" => 200)

I got:

ERROR: setfield!: immutable struct of type YAXArray cannot be changed
Stacktrace:
 [1] setproperty!(x::YAXArray{Float64, 2, Matrix{…}, Tuple{…}, Dict{…}}, f::Symbol, v::Dict{String, Int64})
   @ Base ./Base.jl:41
 [2] top-level scope
   @ REPL[33]:1
Some type information was truncated. Use `show(err)` to see complete types.

Thanks in advance for your help @felixcremer @meggart

dpabon avatar Aug 08 '24 12:08 dpabon

Ok, I found the solution:

using YAXArrayBase

push!(YAXArrayBase.getattributes(cube), "some" => "thing")

here:

#117

I will add this to the documentation (PR)

dpabon avatar Aug 08 '24 13:08 dpabon

Did you try something like :

ds = YAXArray(ds.axes, ds, Dict(["standard_name" => "air_temperature", "units" => "degC"]))

Balinus avatar Aug 08 '24 13:08 Balinus

Good, that you found a solution. It would be good to add that to the docs, but also handling metadata could be made easier. I am wondering whether we should have a setattributes function which would do this push in the background. So that your example above would be:

setattributes(cube, "some"=>"thing")

felixcremer avatar Aug 08 '24 13:08 felixcremer

I think it will be quite useful to have this function. Imagine the result of mapCube operation where you want to add metadata before saving it. But not sure how much time/effort is required.

dpabon avatar Aug 08 '24 13:08 dpabon

Did you try something like :

ds = YAXArray(ds.axes, ds, Dict(["standard_name" => "air_temperature", "units" => "degC"]))

Hi Balinus,

yes, , this is also possible, but not for objects that are already a YAXArray. e.g. after you use open_dataset or after some mapcube operation.

dpabon avatar Aug 08 '24 13:08 dpabon

With the current solution, if you do

push!(YAXArrayBase.getattributes(cube), "some" => "thing")

and have a second cube, e.g. cube2 and do:

YAXArrayBase.getattributes(cube2)

the result is:

Dict{String, Int64} with 1 entry:
  "some" => "thing"

I checked the methods of YAXArrayBase.getattributes and a new method was created:

methods(YAXArrayBase.getattributes)
# 4 methods for generic function "getattributes" from YAXArrayBase:
 [1] getattributes(x::YAXArray)
     @ YAXArrays.Cubes ~/.julia/packages/YAXArrays/b5XBB/src/Cubes/Cubes.jl:367
 [2] getattributes(x::YAXArrays.Cubes.YAXSlice)
     @ YAXArrays.Cubes ~/.julia/packages/YAXArrays/b5XBB/src/Cubes/Slices.jl:29
 [3] getattributes(x::DimArray)
     @ ~/.julia/packages/YAXArrayBase/R6Frw/src/axisarrays/dimensionaldata.jl:12
 [4] getattributes(lst_cube)
     @ Main REPL[61]:1

Maybe a bug? @felixcremer

dpabon avatar Aug 08 '24 13:08 dpabon

I can't reproduce this.

felixcremer avatar Aug 08 '24 13:08 felixcremer

You might have done:

YAXArrayBase.getattributes(tc) = Dict("some"=>"thing")

felixcremer avatar Aug 08 '24 13:08 felixcremer

If you only want to change single entries of the properties you can use this:

c.properties["some"] = "thing"

felixcremer avatar Aug 08 '24 13:08 felixcremer

You might have done:

YAXArrayBase.getattributes(tc) = Dict("some"=>"thing")

Yes, you are right XD

dpabon avatar Aug 08 '24 14:08 dpabon