# Cartographic projections using RecipesBase

**URL:** <https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421>\
**Category:** Visualization\
**Tags:** recipe\
**Created:** [March 3, 2019, 6:57am UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421 "2019-03-03T06:57:23Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)\
**Post date:** [March 3, 2019, 6:57am UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/1 "2019-03-03T06:57:24Z")

</div>

Hi to everybody,

In the past years, I have developed a library that implements [Healpix](https://healpix.jpl.nasa.gov/) projection functions: [GitHub - ziotom78/Healpix.jl: Healpix library written in Julia](https://github.com/ziotom78/Healpix.jl). Unlike Michael Eastwood’s [Libhealpix.jl](https://github.com/mweastwood/LibHealpix.jl), this library is 100% pure Julia, because I needed to make it run under Windows as well (Libhealpix is a wrapper to the C++ Healpix library, which does not support Windows yet).

So far, I have managed to produce cartographic projections [using Cairo](https://github.com/ziotom78/Healpix.jl/blob/b0cbb89adb60c80ad7fcf1428bf12c44d7d5b180/src/projections.jl) to create RGB bitmaps, which look nice in Jupyter but are not shown in the REPL. As the dependency on Cairo, Images, and ImageMagick is quite heavy and does not work well for those applications that need to run on clusters, I would like to move to [RecipesBase](http://docs.juliaplots.org/latest/recipes/).

Using Cairo has allowed me to render images similar to the one here:

 ![](https://global.discourse-cdn.com/julialang/original/3X/d/5/d54e882bb392935b2c2ff9aa6931534702e5b154.png)

This is a Mollweide projection of the celestial sphere, where pixels along the Galactic plane have been masked and are shown in gray.

My question is: how am I supposed to produce this kind of images using RecipesBase? My understanding is that I should write a `@recipe` returning a matrix containing the 2D projection of the map, using `missing` for the pixels outside the ellipse. This matrix should contain floating-point values, which would be mapped to colors by a user-specified color scale, like the ones defined in [ColorSchemes.jl](https://github.com/JuliaGraphics/ColorSchemes.jl). But how could I specify that «masked» pixels must be painted using a dedicated color?

The Python bindings to Healpix use Matplotlib’s features to provide custom axis that take care of the projection ([healpy/projaxes.py#L719](https://github.com/healpy/healpy/blob/785e076a55fb8b5cad7952cca80ca10578e01a20/healpy/projaxes.py#L719)); from my understanding, in this case pixels get a gray color if they map to some special values (like `numpy.NaN`), and pixels outside the ellipse are never painted at all.

The best solution would allow to add layers of vector elements: the most common case is a graticule showing parallels and meridians, and points and lines indicating sky sources and regions.  
(P.S. I have made the case of Mollweide projections, but the library should provide other projections as well, of corse. So I am looking for some _general_ way to implement this, which does not assume that the pixels will be always plotted within an ellipse.)

Thanks a lot!  
Maurizio.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 3, 2019, 9:13am UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/2 "2019-03-03T09:13:56Z")

</div>

It’d be a lot easier to answer with some specific code examples. But yes, briefly, you’l make a heatmap of a 2-d Matrix{Float64} with NaNs as transparent fields. Masking and adding graticules etc is easiest done by adding additional `@series` where `primary = false` (so they don’t show up in your color legend).

---

<div class="post-metadata">

**Author:** ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)\
**Post date:** [March 5, 2019, 7:11am UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/3 "2019-03-05T07:11:31Z")

</div>

Many thanks @mkborregaard, the reason why I did not submit any code (as I usually do) is that I’m actually in the planning stage and have yet to write anything. Your idea to use `@series` is perfect, many thanks!

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 5, 2019, 10:11pm UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/4 "2019-03-05T22:11:11Z")

</div>

Great - you’re welcome to post code for comments once you get to that stage.

---

<div class="post-metadata">

**Author:** ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)\
**Post date:** [March 12, 2019, 10:55am UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/5 "2019-03-12T10:55:19Z")

</div>

After a few trials, I have been able to produce something really close to what I want. But I am struggling to understand how to properly implement masks.

This short script reproduces the problem:

```julia
using RecipesBase

# This type represents the map
struct T end

# Very silly, "cross-like" projection. The function
# returns the bitmap to display and a 2D bitmap
# marking the position of masked pixels (to be
# shown using a uniform gray shade)
function projection()
    # NaN marks the pixels outside the map area
    img = [[NaN 1. NaN];
            [2. 2. 2.];
            [NaN 3. NaN]]

    # NaN means "unmasked" (default), 0 means "masked"
    # Only the pixel at the center of the cross should be masked
    mask = [[NaN NaN NaN];
            [NaN 0. NaN];
            [NaN NaN NaN]]

    (img, mask)
end

@recipe function plot(::T)
    seriestype := :heatmap
    aspect_ratio := 1
    colorbar := :bottom
    framestyle := :none
    
    img, mask = projection()

    @series begin
        seriestype := :heatmap
        primary := false
        color_palette := [:gray] # Masked pixels should be gray
        mask
    end
    
    img
end

using Plots
gr()

plot(T())

```

The result is the following:

![cross](https://global.discourse-cdn.com/julialang/original/3X/5/3/53946b810a7b10332bf99191e95b59f1852f384e.png)

The shape of the cross and the shades look as expected, but the center of the cross has not been painted with gray. I don’t understand if the mask is being ignored, or if it has been drawn _below_ the map itself.

May you provide me some tip to debug this issue, please?

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 12, 2019, 2:58pm UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/6 "2019-03-12T14:58:23Z")

</div>

It’s plotting below, yes, but unfortunately it seems Plots has issues with overplotting different heatmaps with different color gradients ☹

You could implement your own seriestype that draws the mask as a polygon…

---

<div class="post-metadata">

**Author:** ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)\
**Post date:** [March 12, 2019, 3:09pm UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/7 "2019-03-12T15:09:11Z")

</div>

> unfortunately it seems Plots has issues with overplotting different heatmaps

That’s a pity to hear. I have looked for an issue of this kind in [Issues · JuliaPlots/Plots.jl · GitHub](https://github.com/JuliaPlots/Plots.jl/issues), but I found nothing. Should I report this somewhere?

In the meantime, I will try to follow the polygon route…

---

<div class="post-metadata">

**Author:** ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)\
**Post date:** [March 15, 2019, 3:18pm UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/8 "2019-03-15T15:18:45Z")

</div>

Fantastic, I have been able to put together a solution that works pretty well. Have a look at this:

 ![masked_map](https://global.discourse-cdn.com/julialang/original/3X/d/4/d4a504f1cdb66fd83219b3ee62431652f44e113e.png)

If you are curious, the implementation of the recipe is in file [src/projections.jl](https://github.com/ziotom78/Healpix.jl/blob/95c913c898410c259bb300c76588f8d8583dcd08/src/projections.jl#L212), and a quite sketchy documentation is [here](http://ziotom78.github.io/Healpix.jl/latest/visualization/).

Using polygons was easier than I thought. Many thanks, @mkborregaard, I would have never been able to do this without your suggestions!

---

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [March 22, 2019, 6:45pm UTC](https://discourse.julialang.org/t/cartographic-projections-using-recipesbase/21421/9 "2019-03-22T18:45:26Z")

</div>

Very nice!
