cml, gauges = open_cml_sample(), open_gauge_sample()Interactive map visualization of CML vector data
Scroll wheel zoom is disabled in the documentation examples below to make page navigation easier. When you create maps yourself, scroll wheel zoom will be enabled by default.
Default map
Create a Folium map with multiple basemap options (OpenStreetMap, OpenTopoMap, Esri World Imagery), layer controls, fullscreen toggle, geocoder search, and measurement tools that will be used as a default for exploration.
setup_default_map
def setup_default_map(
m:Map=None, # Optional folium map to be setup with basemaps and controls
show:Literal='Esri.WorldGrayCanvas', # Basemap to show by default.
)->Map:
Create a default folium map with common basemaps, layers and controls.
m = setup_default_map()Visualize Gauges on an interactive map.
explore_gauges
def explore_gauges(
gauges:xarray.core.dataset.Dataset | xarray.core.dataarray.DataArray, # Gauges in pws OpenSense standard
default:Callable=setup_default_map, # Function to set up a default map including for example basemaps or controls
explore_kwargs:VAR_KEYWORD
)->Map:
Call self as a function.
m = explore_gauges(gauges)Code
m.options['scrollWheelZoom'] = False
mVisualize CML links on an interactive map.
Each link is drawn as a line between its two antenna sites. Includes a search control to find links by ID. It also includes right-click to copy cml_id to clipboard. Then you only need to paste it wherever you require.
explore_links
def explore_links(
cml:xarray.core.dataset.Dataset | xarray.core.dataarray.DataArray, # CML in OpenSense standard
default:Callable=setup_default_map, # Function to set up a default map including for example basemaps or controls
cp_cml_id_on_rclick:bool=True, # Enable copying cml_id to clipboard when right clicking on a link
explore_kwargs:VAR_KEYWORD
)->Map:
Geopandas explore wrapper to visualize CML link structure
m = explore_links(cml)Code
m.options['scrollWheelZoom'] = False
mVisualize link-gauge groups
Links and gauges are grouped by colours. As before right clicking on any link will return the cml_id.
explore_link_gauge_groups
def explore_link_gauge_groups(
cml:xarray.core.dataset.Dataset | xarray.core.dataarray.DataArray, # CML data containing the id of the assigned (e.g. nearest) gauge
gauges:xarray.core.dataset.Dataset | xarray.core.dataarray.DataArray, # Gauges data with the same id as in CML
default:Callable=setup_default_map, # Function to set up a default map including for example basemaps or controls
id_to_color:Union=None, # Function or dict that allows to map gauge id to a color
cp_cml_id_on_rclick:bool=True, # Enable copying cml_id to clipboard when right clicking on a link
explore_kwargs:VAR_KEYWORD
)->Map:
Call self as a function.
We will start by opening a sample that contains the nearest gauge to each link based on the distance to its center. You can check how this sample was created on the merging doc.
cml_with_gauges = open_cml_sample("with_nearest_gauge")m = explore_link_gauge_groups(cml_with_gauges, gauges)Code
m.options['scrollWheelZoom'] = False
mGeopandas explore will assign colors automatically which is very useful. However in some cases we might want to add custom colors.
color_mapper = {
'Campus_2_Universite': '#1f77b4',
'Ecole_Saint_Andre_PK11': '#ff7f0e',
'Eglise_Pie_X_PK14': '#2ca02c',
'Hopital_des_Soeurs_Logpom': '#d62728',
'Lycee_NYALLA': '#9467bd',
'Meteo_IUT': '#8c564b',
'Piscine_CITE_SIC': '#e377c2',
'SOCATUR': '#ffd000ff'
}
m = explore_link_gauge_groups(cml_with_gauges, gauges, id_to_color=color_mapper)Code
m.options['scrollWheelZoom'] = False
mVisualize CML sublinks
Sublinks are colored by frequency using the electromagnetic spectrum coloring (red for lowest frequencies to violet for highest). Sublinks within the same CML are slightly offset for visibility. Optionally shows transmission direction arrows It also supports right-click to copy IDs that can then be used to select the sublink of interest from the dataset (see the example at link visualization section).
explore_sublinks
def explore_sublinks(
cml:xarray.core.dataset.Dataset | xarray.core.dataarray.DataArray, # CML in OpenSense standard
default:Callable=setup_default_map, # Function to set up a default map including for example basemaps or controls
add_transmission_sense:bool=True, # If true it will overlay an arrow over each sublink showing the sense of the signal
cp_id_on_rclick:bool=True, # Enable copying cml_id and sublink_id when right clicking on a sublink
explore_kwargs:VAR_KEYWORD
)->Map:
Geopandas explore wrapper to visualize CML sublink structure by coloring on frequency
m = explore_sublinks(cml)Code
m.options['scrollWheelZoom'] = False
mVisualize sublinkwise data
explore_data
def explore_data(
cml:DataArray, # CML raw or derived data in OpenSense standard
vmin:float=None, # Minimum value for the colormap
vmax:float=None, # Maximum value for the colormap
cmap:ListedColormap=<matplotlib.colors.ListedColormap object at 0x7f525e0fb110>, # Matplotlib colormap
)->Map:
Call self as a function.
cml = open_cml_sample()If you are showing variables such as attenuation that will depend on several factors such as baseline, length, … remember to normalize the values. This step is not necessary when showing the rainfall.
For the sake of this example, we will normalise the variable based on data from two consecutive days. To avoid potential issues due to outliers, we will use quantiles 0.1 and 0.9.
cml = cml.sel(time=slice("2019-07-17T00:00", "2019-07-19T00:00"))
att = cml["tsl_max"] - cml["rsl_min"]
att.name = "att"
q = att.quantile([0.1, 0.9], dim="time")
att = (att - q.sel(quantile=0.1, drop=True)) / (q.sel(quantile=0.9, drop=True) - q.sel(quantile=0.1, drop=True))/opt/hostedtoolcache/Python/3.12.13/x64/lib/python3.12/site-packages/numpy/lib/_nanfunctions_impl.py:1593: RuntimeWarning: All-NaN slice encountered
return fnb._ureduce(a,
Given the current state of development, we recommend plotting a maximum of one day of data at 15-minute intervals (approximately 96 timesteps). You can use the Romulo plot to identify the periods of interest. Please remember to toggle the visibility of the metadata before playing to achieve a more fluid animation.
In this case, to avoid performance issues, we will only show few hours of data.
m = explore_data(att.sel(time=slice("2019-07-17T18:00", "2019-07-18T03:00")), vmin=0, vmax=1)Code
m.options['scrollWheelZoom'] = False
mHow to join visualizations?
Stacking layers together. Example of the sublink and gauge data
m = explore_sublinks(cml, default=None)
m = explore_gauges(gauges, default=None, m=m)
m = setup_default_map(m)Code
m.options['scrollWheelZoom'] = False
mVisualizing data side by side. Example of sublink metadata and link-gauge groups
We will import some helper functions
from raincell.maps._helpers import get_center, get_zoom_startm = folium.plugins.DualMap(zoom_start=get_zoom_start(cml), location=get_center(cml), tiles=None)
lm, rm = m.m1, m.m2
lm = explore_sublinks(cml, default=None, m=lm)
rm = explore_link_gauge_groups(cml_with_gauges, gauges, m=rm, default=None)
m = setup_default_map(m)Code
lm.options['scrollWheelZoom'] = False
rm.options['scrollWheelZoom'] = False
m