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

[FR] Adding Histogram3d/Lego-Plot #3379

Open
briederer opened this issue Mar 25, 2021 · 2 comments
Open

[FR] Adding Histogram3d/Lego-Plot #3379

briederer opened this issue Mar 25, 2021 · 2 comments
Labels
extension new behaviour

Comments

@briederer
Copy link
Contributor

After trying to find a nice way of creating a 3D-Histogram it turned out that there is no such feature yet. (Although it is reported as possible :seriestype in the Docs/attribute_series)

So I came up with a very hacky way of doing it using wireframe() and I thought the Code may be useful in the future.

function histogram3d(x::AbstractArray{T,1}, y::AbstractArray{T,1}; xlims::Tuple{Number,Number}=(0,0), ylims::Tuple{Number,Number}=(0,0), bins::Int64, kws...) where {T}

    # input check, if not given take extrema
    if all(xlims == (0,0))
        xlims = extrema(x)
    end
    if all(ylims == (0,0))
        ylims = extrema(y)
    end

    # create the x-y-grid to check values
    xgrid = range(xlims[1],xlims[end],length=bins+1)
    ygrid = range(ylims[1],ylims[end],length=bins+1)

    # count all x-y-values within a specific x-y-grid-cell (histcount may be nicer)
    z = [sum(all(((x[i],y[i]).>=(xgrid[itx],ygrid[ity])) .& ((x[i],y[i]).<(xgrid[itx+1],ygrid[ity+1]))) for i in eachindex(x)) for ity = 1:bins, itx = 1:bins]

    # Helpers for nice bars
    xdat = repeateps(xgrid,inner=(2));
    ydat = repeateps(ygrid,inner=(2));

    zdat = zeros(length(xdat),length(ydat));
    zdat[2:end-1,2:end-1] .= repeat(z,inner=(2,2));

    wireframe(xdat,ydat,zdat,xlims=xlims,ylims=ylims;kws...)
end

repeateps(x;kws...) = repeat(x;kws...) .- [k%2 == 1 ? 1e-15 : 0 for k = 1:2*length(x)];

The code basically adds additional points for the wireframe such that the resulting graph contains something that looks like a bar.
However I tried this so far only with the GR- and the plotly-backend.
GR produced quite decent results (apart from the known issue #1911 which makes it hard to look at it from all angles) :
7-7-0 7-0 5_sig38normlego

Plotly however completely fails (somehow the vertical parts of the wireframe are missing)
7-7-0 7-0 5_sig38normlego_plotly

There are probably several other issues with this Code, however it may help someone who knows how to improve this ☺️
Also feel free to delete this post if it is not helpful at all 😉

@dorn-gerhard
Copy link

Haha so nice to see you here Bernd :D

We also struggled to find a way to find a 3D histogram and a student has tried two approaches - one as well using wireframe and one using surface to make them more colorful :)
I guess he will post his solution soon

@briederer
Copy link
Contributor Author

briederer commented Apr 15, 2021

As I said it needs a lot of work still though (;
Especially I found that the repeateps(x,kws...) doesn‘t work always. If the x values are large the hack with an abolute subtraction of 1e-15 is not working. Replaced it in my code now with:

repeateps(x;kws...) = repeat(x;kws...) .- [k%2 == 1 ? 10*eps(x[Int64((k+1)/2) : 0 for k = 1:2*length(x)];

which is still ugly but works now for arbitrary x-values (;

PS: also nice to see you here @dorn-gerhard 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension new behaviour
Projects
None yet
Development

No branches or pull requests

4 participants