CliMA / ClimaAnalysis.jl

An analysis library for ClimaDiagnostics (and, more generally, NetCDF files)
Apache License 2.0
9 stars 3 forks source link

Add `ClimaExplorer`, intearctive visualizer #51

Open Sbozzolo opened 3 months ago

Sbozzolo commented 3 months ago

Description to be written

- [x] Support extruded sphere
- [x] Support surfaces
- [ ] Support box
- [ ] Support column
- [x] Support specifying output path
- [x] Support selecting reduction/period
- [ ] Add sample data with different periods
- [x] Compatibility with `WGLMakie`
- [x] Design logo
- [x] Play button for time
- [x] Add logo to webpage
- [ ] Button to share colorbar limits across different snapshots/altitudes
- [x] Create Figure and Axis only once, outside of interaction
- [ ] Widget for 2D or 3D axis
- [ ] Fix labels: hidden behind figure, too many digits
- [ ] Ability to change units, using `Unitful.jl` and `UnitfulMoles.jl`
- [ ] Unit label, using `MakieTeX.jl`
- [ ] Diplay Time (slider, play) in other units (maybe dd/mm/yy HH)
- [ ] Make colorbar label digits constant
AlexisRenchon commented 3 months ago

I made a little minimal working example, not sure if it is helpful, but here it is:

using Bonito
using WGLMakie 

function MWE()
    fig = Figure() # defined only once
    ax = Axis(fig[1,1]) # defined only once
    slider = Bonito.Slider(0:0.1:1)

    data = Observable(Vec2f.(1.0, slider.value[]))
    scatter!(ax, data) # plot an observable

    on(slider.value) do val
        data[] = Vec2f.(1.0, val) # update the value of the observable
    end

    app = App() do session::Session
        return DOM.div(
                   DOM.div(slider, slider.value),
                   fig
                  )
    end
    return app
end

MWE()
Sbozzolo commented 3 months ago

I made a little minimal working example, not sure if it is helpful, but here it is:

using Bonito
using WGLMakie 

function MWE()
    fig = Figure() # defined only once
    ax = Axis(fig[1,1]) # defined only once
    slider = Bonito.Slider(0:0.1:1)

    data = Observable(Vec2f.(1.0, slider.value[]))
    scatter!(ax, data) # plot an observable

    on(slider.value) do val
        data[] = Vec2f.(1.0, val) # update the value of the observable
    end

    app = App() do session::Session
        return DOM.div(
                   DOM.div(slider, slider.value),
                   fig
                  )
    end
    return app
end

MWE()

We have to find a way to balance this with how ClimaAnalysis is used elsewhere. I think I add to create new Axis to make sure it would work out of the box. But I am sure that there are ways to fix this.

AlexisRenchon commented 3 months ago

I can work on it after I am done with ClimaDiagnostics (or outside of work hours) - or we can do a hackathon together!

I think the ClimaAnalysis code just need some refactor, same functionality, and it won't be too many big changes, just isolate things a bit more.

Anything can be an Observable, and anything can take Observable arguments via the @lift macro, to become in turn a new Observable function of another one e.g.,

x = Observable(1.0)
coordinates = @lift(Vec2f.(1.0, $x)) # any function would work here

Eventually, a Makie plot function (scatter, heatmap, ...) needs to take one or more observables in its arguments, e.g. scatter(coordinates), figures and axis can be created before and not updated.

So in ClimaAnalysis, we need to be able to retrieve arguments of plotting from a function

There are other ways, but useful to know are:

julia> x = Observable(1.0)
Observable(1.0)
julia> x[] = 2
2
julia> x_value = x[]
2.0
julia> typeof(x)
Observable{Float64}
julia> typeof(x_value)
Float64

I find useful:

julia> y = @lift(Vec2f.(2.0, $x)) # the @lift macro 
Observable(Float32[2.0, 2.0])

on(slider.value) do val  # on any widget update
    f(val)
end

map(menu2.value) do val # this works too
    f(val)
end