# How to show large number of lines using Julia, GLMakie

**URL:** <https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725>\
**Category:** General Usage\
**Tags:** package\
**Created:** [March 8, 2021, 11:51am UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725 "2021-03-08T11:51:34Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 11:51am UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/1 "2021-03-08T11:51:34Z")

</div>

I try to show the road network, which has over 400,000 segments. I first tried the package OpenStreetMapXPlot.jl. However, it takes very long time and cannot plot. Then, I tried to use GLMakie.jl

```julia
using Makie, GeometryTypes

scene = Scene()
for r in roads # over 400,000 roads
     xs = ...
     ys = ...
     lines!(scene, xs, ys, color = :blue, linewidth = 1)
end

```

It takes a long time to plot 10,000 road segments. It seems also impossible to show the large network.  
I use the software QGIS, which is developed using C++, to show the road network and it works very smooth.

Is GLMakie.jl the proper package to show the large road network? Or some other technology is better?  
Thanks!

---

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 1:03pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/2 "2021-03-08T13:03:50Z")

</div>

I tried similar code using `Plots.jl`. The running time for plotting 1000 roads is,

```julia
Makie: 6.929608583 s
Plots: 1.138019358 s

```

The package `Plots.jl` seems several times quicker. For 400k roads, `Plots` still takes very long time. Is there other method to show large amount of lines using Julia? Thanks!

---

<div class="post-metadata">

**Author:** ![briochemc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/briochemc/32/4209_2.png) [@briochemc](https://discourse.julialang.org/u/briochemc)\
**Post date:** [March 8, 2021, 1:17pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/3 "2021-03-08T13:17:54Z")

</div>

Maybe you can avoid the calls to the plotting functions inside the loop? Have you tried calling `lines!` only once on a large vector of `xs` and `ys`, potentially separated by `NaN`s?

For example, I get a 200x speed up doing that with Plots.jl on this example:

```julia
xs = [rand(100) for _ in 1:1000]
ys = [rand(100) for _ in 1:1000]

function plot1(xs, ys)
    plt = plot()
    for (x, y) in zip(xs, ys)
        plot!(plt, x, y)
    end
    plt
end

function plot2(xs, ys)
    plot(reduce(vcat, xs), reduce(vcat, ys))
end

@btime plot1($xs, $ys) ; # 431.335 ms (2231129 allocations: 121.87 MiB)
@btime plot2($xs, $ys) ; # 2.844 ms (2530 allocations: 3.20 MiB)
# BTW in this case a simple call to plot(xs, ys) works, but it slow for me:
@btime plot($xs, $ys) ; # 205.678 ms (1374088 allocations: 72.29 MiB)

```

---

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 2:36pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/4 "2021-03-08T14:36:33Z")

</div>

Thanks for your reply!  
`plot2()` is different from `plot1()`. `plot1()` draws 1000 separated lines, while `plot2()` draw one line, which links 1000 lines as one. This would be the reason while plot2() is much quicker.  
The following are figures of three lines by these two function.

plot1()

 ![image](https://global.discourse-cdn.com/julialang/original/3X/9/f/9f53d056065fb32a4ca48941f83a92c5b71622a5.png)

plot2()

 ![image](https://global.discourse-cdn.com/julialang/original/3X/8/f/8f9fd3fcf4693b7986be962de01c704302d4e57d.png)

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [March 8, 2021, 2:53pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/5 "2021-03-08T14:53:04Z")

</div>

I think if you do `reduce(hcat, ...)` instead, they will be plotted as separate series. Not sure how that affects timing, but might be worth trying

---

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 3:02pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/6 "2021-03-08T15:02:48Z")

</div>

> [@briochemc](#):
>
> `reduce(vcat, xs)`

Thank you so much! It plots the correct figure. However, the running time is only slight quicker, which is as follows.

```julia
  plot1() running time: 380.361 ms (2491155 allocations: 129.92 MiB)
  plot2() running time: 209.021 ms (1610075 allocations: 79.49 MiB)

```

QGIS, written in c++, can render this network smoothly. Is there other package to draw large network? There should be some method to draw using Julia.

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [March 8, 2021, 4:37pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/7 "2021-03-08T16:37:43Z")

</div>

you can try `using GR`

> <https://github.com/jheinen/GR.jl/blob/master/examples/shade_wav.jl>

with this you can plot millions of points [lines].

`shadelines`

is what you are looking for.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 8, 2021, 5:37pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/8 "2021-03-08T17:37:18Z")

</div>

I think GLMakie works well with this, as long as you plot everything as one line (use NaN points as gaps).

Here are random “roads” with 900,000 segments

```julia
using GLMakie

roads = [i % 10 == 0 ? Point2f0(NaN) : 0.1f0 * randn(Point2f0) .+ Point2f0(x, y) for x in 1:300 for y in 1:300 for i in 1:10]

lines(roads)

```

```julia
julia> @time lines(roads)
  0.022839 seconds (44.10 k allocations: 2.294 MiB)

```

[https://i.imgur.com/5lLA9yK.mp4](https://i.imgur.com/5lLA9yK.mp4)

---

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 6:27pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/9 "2021-03-08T18:27:18Z")

</div>

So amazing! It works! The large urban traffic network, with over 400,000 road segments, can be shown within 1 second!

```julia
415.336 ms (534413 allocations: 77.38 MiB)

```

Thank you so much!

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 8, 2021, 6:37pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/10 "2021-03-08T18:37:15Z")

</div>

Awesome! The general rule is to have as few high level plot objects as possible, so that the gpu receives only a couple of large arrays. Then it will be fast. 100000 line plot objects have too much overhead

---

<div class="post-metadata">

**Author:** ![briochemc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/briochemc/32/4209_2.png) [@briochemc](https://discourse.julialang.org/u/briochemc)\
**Post date:** [March 8, 2021, 10:12pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/11 "2021-03-08T22:12:19Z")

</div>

> [@zhangliye](#):
>
> `plot2()` is different from `plot1()` . `plot1()` draws 1000 separated lines, while `plot2()` draw one line, which links 1000 lines as one. This would be the reason while plot2() is much quicker.

No, it’s the single call to `plot` that makes it quicker. As others have also said, you just need to concatenate your roads in a single array and separate the segments that need separation by `NaN`s and it should be fast with Plots. (I did not do the part adding the `NaN`s in my example.)

* * *

[_ **EDIT** _] For example, to sort-of match the GLMakie one,

```julia
xs = [0.1f0 * randn() .+ x for x in 1:300 for y in 1:300 for i in 1:10]
ys = [0.1f0 * randn() .+ y for x in 1:300 for y in 1:300 for i in 1:10]
roads = [i % 10 == 0 for x in 1:300 for y in 1:300 for i in 1:10]
isnotroad = [i % 10 == 0 for x in 1:300 for y in 1:300 for i in 1:10]
xs[isnotroad] .= NaN
ys[isnotroad] .= NaN
@btime plot($xs, $ys) # 23.933 ms for me

```

and these show what you want as well:

```julia
plot(plot(xs, ys), plot(xs, ys, xlim=(100, 110), ylim=(120, 130)))

```

gives

 ![Screen Shot 2021-03-09 at 9.23.43 am](https://global.discourse-cdn.com/julialang/original/3X/b/6/b63cab612f169debe69051bf6f29fc21842fd023.jpeg)

---

<div class="post-metadata">

**Author:** ![zhangliye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zhangliye/32/3208_2.png) [@zhangliye](https://discourse.julialang.org/u/zhangliye)\
**Post date:** [March 8, 2021, 10:20pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/12 "2021-03-08T22:20:35Z")

</div>

Thank you so much! I will have a try. It would have similar speed as the Jules’s suggestion.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [March 8, 2021, 10:42pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/13 "2021-03-08T22:42:57Z")

</div>

I wonder if high-level plot objects can be automatically “rewritten” to this more efficient representation.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 9, 2021, 6:50pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/14 "2021-03-09T18:50:34Z")

</div>

For the record, the `inspectdr()` backend seems to plot at same speed as `gr()` in this case, while allowing interactive zooming in and out. However it is 30% slower here than Makie. Makie zoom is nicer as scales are updated, while inspectdr() provides the coordinates of the cursor.

```julia
using Plots; inspectdr(legend=false)
xs = [i % 10 == 0 ? NaN : 0.1f0 * randn() .+ x for x in 1:300 for y in 1:300 for i in 1:10]
ys = [i % 10 == 0 ? NaN : 0.1f0 * randn() .+ y for x in 1:300 for y in 1:300 for i in 1:10]
@btime Plots.plot($xs, $ys) # 18 ms (2436 allocations: 13.88 MiB)
# draw rectangle with RMB to zoom-in, CTRL+f to unzoom

```

---

<div class="post-metadata">

**Author:** ![Allen\_Mauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allen_mauer/32/33541_2.png) [@Allen\_Mauer](https://discourse.julialang.org/u/Allen_Mauer)\
**Post date:** [November 6, 2022, 3:59pm UTC](https://discourse.julialang.org/t/how-to-show-large-number-of-lines-using-julia-glmakie/56725/15 "2022-11-06T15:59:05Z")

</div>

This works very well. Thank you.
