243 add map view visualization - #244
Conversation
…Add stubs in Visualization and VisualizationExt.
Removed WGLMakie dependency from Project.toml
jhidding
left a comment
There was a problem hiding this comment.
Hi Lucy,
These plots look really useful, but I do have some questions. To plot the correct values for a certain time, we need to search for the most recent sediment at a certain time. From the current code I can't see where this happens, so the code should be refactored to reveal this. If the last sedimentation event was very small, this search will give noisy results, especially when plotting facies fractions.
To rephrase this slightly: most of the code should be doing data manipulation to retrieve the input for heatmap!. This data mangling should be separated from the actual plotting code.
I would propose a more robust method. We can reuse the SedimentBuffer code. Push sediment until the target time to the sediment buffer, then pop a layer of a given thickness and use that for plotting.
Let me know if this helps!
Cheers, Johan
|
|
||
| Example 3 shows how to plot map views directly from memory. Run it immediately after running the model. | ||
|
|
||
| ```{.julia .task file=examples/visualization/map_view.jl} |
There was a problem hiding this comment.
These examples need to be split, so we get one image and then the corresponding code each. You can use entangled quotations to still put the actual script in a single file.
| Script.from_file_categorical() | ||
| ``` | ||
|
|
||
| ### Implementation |
There was a problem hiding this comment.
The implementation needs better motivation. As it stands now, I can't see why you made certain choices.
| _colormax(d::AbstractArray) = getindex.(argmax(d; dims=1)[1, :, :], 1) | ||
|
|
||
| #Calculate a given facies' proportion relative to the others in a specific location. | ||
| function _facies_fraction(d::AbstractArray, facies::Integer) |
There was a problem hiding this comment.
Use the ifelse function. Then this function becomes a one-liner. I think something like ifelse.(iszero.(total), missing, ustrip.(selected ./ total)) should work.
| return fraction | ||
| end | ||
|
|
||
| # Resolve a stratigraphic position into an index along the (write-interval |
There was a problem hiding this comment.
You can use Entangled literate programming to put these important comments into the text.
|
Hi Johan,
I hope you are well, thank you for your feedback.
I am happy to follow your lead on this, it seems both robust and simpler.
Best regards,
Lucy
Lucy SALMON
Junior Geoscientist
Chemin des Vergers 4 | 1208Geneva | Switzerland
***@***.***
Landline
+41 22 342 15 00
www.adterra.com
www.adterraconsultancy.com
This email and its attachments may be confidential and are intended solely for the use of the intended recipient. If you are not the intended recipient of this email and its attachments, you must take no action based upon them, nor must you copy or show them to anyone. Please notify the sender immediately by email if you have received this email in error and delete this email from your system.
________________________________
From: Johannes Hidding ***@***.***>
Sent: Tuesday, July 14, 2026 15:01
To: MindTheGap-ERC/CarboKitten.jl ***@***.***>
Cc: Lucy Salmon ***@***.***>; Author ***@***.***>
Subject: Re: [MindTheGap-ERC/CarboKitten.jl] 243 add map view visualization (PR #244)
Warning - External Sender
@jhidding requested changes on this pull request.
Hi Lucy,
These plots look really useful, but I do have some questions. To plot the correct values for a certain time, we need to search for the most recent sediment at a certain time. From the current code I can't see where this happens, so the code should be refactored to reveal this. If the last sedimentation event was very small, this search will give noisy results, especially when plotting facies fractions.
To rephrase this slightly: most of the code should be doing data manipulation to retrieve the input for heatmap!. This data mangling should be separated from the actual plotting code.
I would propose a more robust method. We can reuse the SedimentBuffer code. Push sediment until the target time to the sediment buffer, then pop a layer of a given thickness and use that for plotting.
Let me know if this helps!
Cheers, Johan
________________________________
In docs/src/visualization/map-view.md<https://url.avanan.click/v2/r02/___https://github.com/RnsiYmjLfu-JWHdHfwgtPnyyjs.oqduzqqd799e78inxhzxxnts_w8/abc99*~*cb___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6ZTM1ZDo4ZGZiOGNlOWJhYjg1ZGE3NjgwMGFkZDYyZjA5MDVhMTU2NTU5YjNjODliZjA5YmUyZWQzMGRjOTQ5M2YyMWMwOmg6VDpU>:
+
+The map-view visualization routine allows users to plot model output at selected stratigraphic positions or depths. This makes it possible to inspect 2D facies patterns, sediment distribution, and lateral organization across the platform at different stratigraphic levels.
+The user can select the stratigraphic position or depth to visualize, and the routine returns a horizontal map-view of the facies distribution. Maps can be coloured either categorically, by dominant facies, or continuously, by the proportion of one selected facies relative to the total sediment in each cell.
+
+
+
+
+### Test
+
+Example 1 reproduces the map-view figure from `alcap-example.h5` using categorical facies colouring. Each colour corresponds to the dominant facies in a cell, and the colourbar is labelled by facies index.
+
+Example 2 reproduces the same map views using continuous proportional colouring. In this mode, the colour scale represents the proportion of one selected facies relative to the total sediment in each cell.
+
+Example 3 shows how to plot map views directly from memory. Run it immediately after running the model.
+
+```{.julia .task file=examples/visualization/map_view.jl}
These examples need to be split, so we get one image and then the corresponding code each. You can use entangled quotations to still put the actual script in a single file.
________________________________
In docs/src/visualization/map-view.md<https://url.avanan.click/v2/r02/___https://github.com/RnsiYmjLfu-JWHdHfwgtPnyyjs.oqduzqqd799e78inxhzxxnts_w8/abca8896___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6OTRiMDplMmU1NTIxNWZkYjljNzc5NmQ2MWRlNzg3ZGQ2NTFjMDMxZGVmOWI3NGRmY2UxMjFjYTdhM2UwNWViZTc4ZGRkOmg6VDpU>:
+ idx_pick = [div(n_frames, 4), div(n_frames, 2), n_frames]
+
+ fig = map_view(header, volume;
+ times = idx_pick,
+ show = :preserved,
+ layout = :row,
+ color_by = :facies)
+ return fig
+end
+
+end # module Script
+
+Script.from_file_categorical()
+```
+
+### Implementation
The implementation needs better motivation. As it stands now, I can't see why you made certain choices.
________________________________
In docs/src/visualization/map-view.md<https://url.avanan.click/v2/r02/___https://github.com/RnsiYmjLfu-JWHdHfwgtPnyyjs.oqduzqqd799e78inxhzxxnts_w8/abcc78cb___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6ODcxMzo1OGZlMGM0NDA1NjZhMTM2ZDQ3OTc4Y2ZjMzZiMjlmZmU4Mjg2ZDQyNmI4MWQ0NWFjNDFkYTBhMWNiMTkxNWJiOmg6VDpU>:
+using CarboKitten.Utility: in_units_of
+using CarboKitten.Export: Header, Data, DataVolume, read_volume
+using CarboKitten.Output.Abstract: stratigraphic_column, water_depth
+
+using Makie
+using Unitful
+
+const Time = typeof(1.0u"Myr")
+
+# Pulled verbatim from WheelerDiagram.dominant_facies! — works on
+# any array whose first axis is facies. For a DataVolume snapshot the input is
+# (n_facies, n_x, n_y) and the output is (n_x, n_y) Int.
+_colormax(d::AbstractArray) = getindex.(argmax(d; dims=1)[1, :, :], 1)
+
+#Calculate a given facies' proportion relative to the others in a specific location.
+function _facies_fraction(d::AbstractArray, facies::Integer)
Use the ifelse function. Then this function becomes a one-liner. I think something like ifelse.(iszero.(total), missing, ustrip.(selected ./ total)) should work.
________________________________
In docs/src/visualization/map-view.md<https://url.avanan.click/v2/r02/___https://github.com/RnsiYmjLfu-JWHdHfwgtPnyyjs.oqduzqqd799e78inxhzxxnts_w8/abcccabb___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6ZmNlZDozMWI5MGY3NjdjZThhNDNiN2ZlNDgwZjk5YmY0YmM0MjU2NjI3MmI4OWU3ODlmNGMwYWU2OWE4YzljMTQxZDQ4Omg6VDpU>:
+ selected = d[facies, :, :]
+
+ fraction = Matrix{Union{Missing,Float64}}(undef, Base.size(total))
+
+ for I in eachindex(total)
+ if iszero(total[I])
+ fraction[I] = missing
+ else
+ fraction[I] = Float64(ustrip(selected[I] / total[I]))
+ end
+ end
+
+ return fraction
+end
+
+# Resolve a stratigraphic position into an index along the (write-interval
You can use Entangled literate programming to put these important comments into the text.
—
Reply to this email directly, view it on GitHub<https://url.avanan.click/v2/r02/___https://github.com/RnsiYmjLfu-JWHdHfwgtPnyyjs.oqduzqqd799?jrfnq_xtzwhj=stynknhfyntsx&fru;jrfnq_ytpjs=HHTLN2VQG3WVaXHS9YFGL/8/J30OMF/HSKXSZFGPR/Z1NTWUK/Y1X/GSSG71JQ7VT01L3ZYKTK71P98ZPOX2R7QKT92YNSW4LV4ILTG4LJ77R9YKRK41*~*80LRK72N7IUTPX1P/YKS47P34YUS/7LP9XaRS1LX38Qe78uzqqwjvzjxywjAnjB-9*~*c978bc6/___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6ZTBhMTpmMmIxNmM1ZDk2NGE2MmEyMjQ4ZDNhODczNzdkOGE2M2Q0NTU2NDc4YWQ0OWZmOGZiMWM2YWU5M2E3MjNkZWM5Omg6VDpU>, or unsubscribe<https://url.avanan.click/v2/r02/___https://github.com/stynknhfyntsxdzsxzgxhwngj-fzymdHHTLN2XKVUSV*~*2aRTGX29GY/J30OMF0HSKXSZFGKPOX2F88YSK7L*~*9Y4MR8IVSG1LF9YTTOVMSJ2L980RZ/YNSOYMJ9IXS42MF47H/VH___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6MDkyZjowYTlmNGRlZTlmY2I0NjEwNzhhM2I5NzZhNzg4NDUzMDQ4NDZkNDgyYWVlZTI1NGE3YTBkZTQxZmFhNDgxNTBmOmg6VDpU>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://url.avanan.click/v2/r02/___https://github.com/stynknhfyntsxdrtgnqjdntxdHHTLN2VN72OLQJ7LOVWVYGY/J30OMF/HSKXSZFGPR/Z1NTWUK/Y1X/GSSG71JQ7VT01L3ZYKTK71P98ZPOX2R7QKT92YNSW4LV4ILTG4LJ77R9YKRK41*~*80LRK72N7IUTPX1P/YKS47PZ4YUS/7LP9XaSK22L___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6MjkyNDo1Zjc2ODM3ZjE0MmZlNGUyODZkNzg2NTkzN2M1MGQxZDNiMDc4OGJiNTkxODNiNDg1ZjgzOWUxNjE2N2E1OGRiOmg6VDpU> and Android<https://url.avanan.click/v2/r02/___https://github.com/stynknhfyntsxdrtgnqjdfsiwtnidHHTLN2XKXRT2LONYJ9NXR/Y/J30OMF/HSKXSZFGPR/Z1NTWUK/Y1X/GSSG71JQ7VT01L3ZYKTK71P98ZPOX2R7QKT92YNSW4LV4ILTG4LJ77R9YKRK41*~*80LRK72N7IUTPX1P/YKS47P94YUS/7LP9XaRK2LN9YUSKXF___.YXAxZTplbi1hZHQ6YTpvOjkzODlmMzA1ZmJiMDFiZmJkOGFhNDIwNmU2OWJkNmQ0Ojc6YWVmNzpiZDE2NWU2ZWM2ZTExZWY5NmYyNDZlNjBkYjU4Y2RjMzQyOTJlY2U3ODc3NTY5ZjA5OTYxMTg1MGYyZmEyOGY2Omg6VDpU>. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
…indTheGap-ERC/CarboKitten.jl into 243-Add-map-view-visualization
…cut through the platform, instead of only what got deposited at a specific timeframe. Added the timeframe behaviour to the examples as well as figures and example command line to the documentation file.
|
The current implementation is very complex. We need to incorporate the time-based slicing (both preserved and deposited modes, as suggested using the sediment buffer interface) and then implement the visualisation separately in two PRs. This would divert from the current PR so much that it is better to close this for now. |
CarboKitten currently provides several visualization options for model output, including topographic views and vertical profile views. However, while the platform can be inspected through vertical sections, there is currently no straightforward way to visualize model output as horizontal stratigraphic slices. This makes it difficult to examine lateral facies organization, spatial facies patterns, and how these patterns vary through the stratigraphic succession.
This PR adds a map-view visualization routine that allows users to plot model output at selected stratigraphic positions at various time steps. The new routine makes it possible to inspect 2D facies patterns, sediment distribution, and lateral organization across the platform at different stratigraphic levels.
The user can choose whether to visualize the facies being deposited at a given frame, the facies preserved in the stratigraphic column, or both, with the modelled facies shown as a translucent layer beneath the preserved record. The routine also supports optional shoreline plotting and allows emerged cells to be either masked or displayed.
Map-view stratigraphic visualizations are commonly available in industrial geomodelling and stratigraphic modelling software. Adding this functionality to CarboKitten makes model outputs easier to inspect, compare, and communicate, and helps make the package more comparable to applied or industry-facing modelling tools.