Skip to content

Commit f50ecd5

Browse files
committed
[1.3.72] 2026-05-06
- Added `Context::deleteTimeseriesVariable()` to delete a single timeseries variable and all of its data points, identified by label. Issues a non-fatal warning if the variable does not exist; complements the existing `clearTimeseriesData()` (which removes all variables) and `updateTimeseriesData()` (which modifies a single point). - Added leaf-to-fruit nitrogen translocation in `removeFruitNitrogen()`. Per-plant fruit demand is now aggregated across all fruiting buds and first satisfied from the available pool; any remaining shortfall is drawn from leaves, with old leaves (age ≥ `remobilization_age_threshold`) donating first and young leaves serving as a fallback. Per-leaf availability uses the same `(current_N_area − minimum_leaf_N_area) × leaf_remobilization_efficiency` reserve as leaf-to-leaf remobilization, distributed proportionally across source leaves; no stress-acceleration multiplier is applied because withdrawal is governed by fruit demand rather than stress signaling. Residual demand that even leaves cannot cover is silently absorbed, preserving the preexisting fail-soft accounting. - Petiole geometry is now suppressed when either `petiole.radius` or `petiole.length` is zero (previously only radius=0 suppressed it); in that case no petiole tube object is created and leaves attach directly at the internode tip. Vertices are still computed so leaf orientation is well-defined. - Added `Phytomer::rotatePetiole(petiole_index, AxisRotation)` for solid-body rotation of a petiole and all leaves anchored to it (the terminal floral bud and its peduncle/inflorescence, anchored to the internode, are unaffected). Pitch rotates about the stored `petiole_rotation_axis` using the construction-time `abs(pitch)` convention, yaw rotates about the internode axis, and roll rotates about the petiole's current length axis. Used internally by the sorghum flag-leaf rule, which now sets the terminal phytomer petiole pitch to a small non-zero value (5°) to keep the rotation axis well-defined and applies an additional +25° solid-body petiole rotation so the flag leaf clears the panicle. - Reworked leaf orientation on curved stems: the legacy roll term `(acos(internode_axis.z) − roll)` is removed and replaced by a curvature-aware blade-up correction applied after the pitch/yaw chain. The leaf is rolled about its own length axis (the petiole tip axis) by an angle scaled by `min(petiole_length / leaf_size, 1)` and clamped below 90°, so leaves on long petioles hang at their natural angle while leaves that hug the stem follow stem curvature. Also fixed leaf-wave vertex displacement to be applied along the post-rotation surface normal rather than along world Z, so wave bumps no longer flatten visually past the buckle. - Tightened maize and sorghum library parameters: widened phyllotactic angle (170–190° → 155–205°), increased leaf buckle angles, increased sorghum wave amplitude, lengthened maize wave period (0.1 → 0.15), and relaxed sorghum gravitropic curvature (−1000…−400 → −800…−200) for less-extreme stem droop. - Added Fluspect-B SIF parameters `V2Z` (violaxanthin↔zeaxanthin de-epoxidation state) and `fqe` (intrinsic fluorescence quantum efficiency scalar) to `LeafOpticsProperties` and `LeafOpticsProperties_Nauto`. They are ignored by the PROSPECT reflectance/transmittance calculation; on every `LeafOptics::run()` call (and per-bin in the nitrogen-auto path), Helios now writes an 11-element `fluspect_biochem_<label>` global-data vector containing `[Cab, Cca, Cw, Cdm, Cs, Cant, Cp, Cbc, N, V2Z, fqe]` and stamps the primitive data label `fluspect_spectrum` on processed UUIDs so the radiation plug-in's SIF pipeline can identify fluorescing leaves and look up their biochemistry by label. - Added an implementation of the von Caemmerer (2021) steady-state C4 photosynthesis model, exposed via `setModelType_C4()` and a new `C4ModelCoefficients` struct that mirrors the C3 Farquhar API (four temperature-response setter overloads per rate parameter `Vpmax`/`Vcmax`/`Jmax`/`Rd`/`gm`, plus directly-editable kinetic constants and structural scalars). Includes a fail-fast species library (`SetariaViridis_vC2021`, `GenericC4_vC2000`, `Maize_Massad2007`) accessed via `setC4CoefficientsFromLibrary()`, per-UUID and per-material coefficient assignment with full material-data serialization, a `setCm()` override for direct mesophyll-CO2 prescription (testing/validation against the paper's reference spreadsheet), and new optional output primitive data `Cm` (mesophyll cytosolic CO2) and `Vp` (PEP carboxylation rate). The `limitation_state` output uses 1 = enzyme-limited and 2 = electron-transport-limited for the C4 model. - Added mesophyll conductance `gm` to the Farquhar C3 model via four `setMesophyllConductance_gm()` overloads on `FarquharModelCoefficients` (constant / Arrhenius / peaked / peaked+dHd) with the same temperature-response framework as the other rate parameters. When `gm` is finite, net assimilation is obtained by solving the Ethier & Livingston (2004) / Sharkey et al. (2007) quadratics derived from `Cc = Ci - A/gm` for the Rubisco- and electron-transport-limited branches; the default value is +infinity, which short-circuits to the legacy `Cc ≡ Ci` path and reproduces the original Farquhar `A` bit-for-bit so existing code and parameter libraries that do not set `gm` are unaffected. - Added a solar-induced chlorophyll fluorescence (SIF) modelling pipeline to `RadiationModel`, exposed through a new SIF camera type. Users add a camera via `addSIFCamera()` (taking a list of user-defined emission bands, a `SIFCameraProperties` struct with `excitation_bin_width_nm` and `excitation_scattering_depth`, and standard camera geometry); `isSIFCamera()` queries whether a label was registered as SIF. Helios auto-creates internal excitation bands spanning 400–750 nm at the requested bin width, ray-traces them to populate per-leaf APAR (with optional inter-leaf scattering when the user wants accurate NIR APAR), evaluates a per-leaf Fluspect-B excitation→emission kernel (Vilfan 2016, ported in `FluspectB.cpp`) cached by biochemistry label + bin width, scales by the van der Tol (2014) rate-coefficient quantum yield Φ_F (read from `electron_transport_ratio` and `temperature` primitive data), integrates per emission-band wavelength range, and injects the resulting per-leaf top/bottom source flux (Mf/Mb) into the standard `runBand()` emission loop so escape and reabsorption are 3D-faithful. Excitation bands are piggy-backed onto regular non-SIF dispatches when present, and cached APAR is invalidated when radiative properties change. SIF-flagged emission bands bypass the Stefan-Boltzmann ε+ρ+τ=1 check (still enforcing ρ+τ ≤ 1) and skip the broadband σ·ε·T⁴ fallback for primitives without an SIF source flux, so non-emitting primitives (ground, sensors) do not inject thermal energy into visible/red SIF bands. Each emission band is locked to one excitation bin width — re-flagging it from a second camera with a different width is an error. - CMake now disables the Vulkan radiation backend (rather than emitting an unresolvable `-lvulkan` linker flag that broke downstream linking) when no Vulkan loader is installed on Linux/macOS, with a status message pointing at the appropriate install command. - `VulkanComputeBackend::copyScatterToRadiation()` now sizes the scatter→radiation memcpy by `launch_band_count` rather than the global `band_count`, fixing an OOB read crash whenever a `runBand` dispatch is a strict subset of all bands (e.g., a SIF emission-only dispatch following an excitation-band dispatch that raised the global band count). - `addRadiationCamera()` now warns once per camera (aggregated across all bound bands) when a camera is bound to a band with `scatteringDepth == 0`, since camera pixels for that band would otherwise read as zero with no diagnostic. - Spectral-camera auto-exposure now anchors to the 95th percentile mapped to ~0.7 instead of the median mapped to 0.18, so narrow scientific bands (fluorescence, thermal IR, Fraunhofer-line retrievals) where most of the frame reads near zero no longer drive the gain to astronomical values and saturate the subject. - `runBand()` now skips cameras whose bound bands don't intersect the current dispatch, avoiding wasted full-camera launches when (e.g.) running PAR with a SIF camera registered. - BVH traversal kernels (`traverse_bvh`, `traverse_cwbvh`) drop the unused `hit_prim_type` and `hit_uv` outputs and the corresponding leaf-data load in cwBVH, removing dead reads from every camera/diffuse/direct/pixel-label raygen path. - Fixed `colorContextPrimitivesByObjectData()` (no-arg overload) so that orphan primitives (those with no parent compound object) are colored by the colormap at value 0 — matching the existing behaviour for compound-object primitives whose parent object lacks the data label, and matching the behaviour of `colorContextPrimitivesByData()` for primitives without primitive data. Previously orphans were rendered with their base RGBA, which left ground tiles and other standalone primitives showing through as their default color (e.g., the green from `Context::addTile`) instead of participating in the colormap. - Colorbar ticks are now filtered to the colorbar's `[cmin, cmax]` range (with a small epsilon) before placement, so a fixed-range colorbar no longer shows orphan labels at "nice" tick values that `generateNiceTicks()` extends past the data range.
1 parent c710cdf commit f50ecd5

65 files changed

Lines changed: 30901 additions & 686 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/include/Context.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6838,6 +6838,14 @@ namespace helios {
68386838
/** Removes all timeseries variables and their associated date/time values. */
68396839
void clearTimeseriesData();
68406840

6841+
//! Delete an entire timeseries variable and all of its data points
6842+
/**
6843+
* \param[in] label Name of the timeseries variable to delete.
6844+
* \note If the variable does not exist, a non-fatal warning is issued to stderr and the call is otherwise a no-op.
6845+
* \ingroup timeseries
6846+
*/
6847+
void deleteTimeseriesVariable(const char *label);
6848+
68416849
//! Load tabular weather data from text file into timeseries
68426850
/**
68436851
* \param[in] data_file Path to the text file containing the tabular weather data.

core/src/Context.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,16 @@ void Context::clearTimeseriesData() {
826826
timeseries_datevalue.clear();
827827
}
828828

829+
void Context::deleteTimeseriesVariable(const char *label) {
830+
auto it = timeseries_data.find(label);
831+
if (it == timeseries_data.end()) {
832+
std::cerr << "WARNING (Context::deleteTimeseriesVariable): Timeseries variable '" << label << "' does not exist. Nothing to delete." << std::endl;
833+
return;
834+
}
835+
timeseries_data.erase(it);
836+
timeseries_datevalue.erase(label);
837+
}
838+
829839
void Context::getDomainBoundingBox(vec2 &xbounds, vec2 &ybounds, vec2 &zbounds) const {
830840
getDomainBoundingBox(getAllUUIDs(), xbounds, ybounds, zbounds);
831841
}

core/tests/Test_context.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,6 +2122,41 @@ TEST_CASE("Missing Data and State Functions") {
21222122
DOCTEST_CHECK(ctx.listTimeseriesVariables().empty());
21232123
}
21242124

2125+
SUBCASE("deleteTimeseriesVariable") {
2126+
Context ctx;
2127+
Date date = make_Date(1, 1, 2025);
2128+
Time time0 = make_Time(0, 0, 12);
2129+
Time time1 = make_Time(1, 0, 12);
2130+
2131+
ctx.addTimeseriesData("temp", 25.5f, date, time0);
2132+
ctx.addTimeseriesData("temp", 26.5f, date, time1);
2133+
ctx.addTimeseriesData("humidity", 60.0f, date, time0);
2134+
DOCTEST_CHECK(ctx.listTimeseriesVariables().size() == 2);
2135+
2136+
// Delete one variable; the other must remain intact and queryable.
2137+
ctx.deleteTimeseriesVariable("temp");
2138+
DOCTEST_CHECK_FALSE(ctx.doesTimeseriesVariableExist("temp"));
2139+
DOCTEST_CHECK(ctx.doesTimeseriesVariableExist("humidity"));
2140+
DOCTEST_CHECK(ctx.getTimeseriesLength("humidity") == 1);
2141+
DOCTEST_CHECK(ctx.queryTimeseriesData("humidity", 0) == doctest::Approx(60.0f));
2142+
2143+
// Re-adding the same label after deletion creates a fresh series.
2144+
ctx.addTimeseriesData("temp", 99.9f, date, time0);
2145+
DOCTEST_CHECK(ctx.doesTimeseriesVariableExist("temp"));
2146+
DOCTEST_CHECK(ctx.getTimeseriesLength("temp") == 1);
2147+
DOCTEST_CHECK(ctx.queryTimeseriesData("temp", 0) == doctest::Approx(99.9f));
2148+
2149+
// Deleting a non-existent variable warns but does not throw.
2150+
std::string captured;
2151+
{
2152+
capture_cerr cerr_buffer;
2153+
DOCTEST_CHECK_NOTHROW(ctx.deleteTimeseriesVariable("nonexistent"));
2154+
captured = cerr_buffer.get_captured_output();
2155+
}
2156+
DOCTEST_CHECK(captured.find("WARNING") != std::string::npos);
2157+
DOCTEST_CHECK(captured.find("nonexistent") != std::string::npos);
2158+
}
2159+
21252160
SUBCASE("getUniquePrimitiveParentObjectIDs") {
21262161
Context ctx;
21272162
uint obj1 = ctx.addBoxObject(make_vec3(0, 0, 0), make_vec3(1, 1, 1), make_int3(1, 1, 1));

doc/CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
# Changelog
22

3+
# [1.3.72] 2026-05-06
4+
5+
## Core
6+
- Added `Context::deleteTimeseriesVariable()` to delete a single timeseries variable and all of its data points, identified by label. Issues a non-fatal warning if the variable does not exist; complements the existing `clearTimeseriesData()` (which removes all variables) and `updateTimeseriesData()` (which modifies a single point).
7+
8+
## Plant Architecture
9+
- Added leaf-to-fruit nitrogen translocation in `removeFruitNitrogen()`. Per-plant fruit demand is now aggregated across all fruiting buds and first satisfied from the available pool; any remaining shortfall is drawn from leaves, with old leaves (age ≥ `remobilization_age_threshold`) donating first and young leaves serving as a fallback. Per-leaf availability uses the same `(current_N_area − minimum_leaf_N_area) × leaf_remobilization_efficiency` reserve as leaf-to-leaf remobilization, distributed proportionally across source leaves; no stress-acceleration multiplier is applied because withdrawal is governed by fruit demand rather than stress signaling. Residual demand that even leaves cannot cover is silently absorbed, preserving the preexisting fail-soft accounting.
10+
- Petiole geometry is now suppressed when either `petiole.radius` or `petiole.length` is zero (previously only radius=0 suppressed it); in that case no petiole tube object is created and leaves attach directly at the internode tip. Vertices are still computed so leaf orientation is well-defined.
11+
- Added `Phytomer::rotatePetiole(petiole_index, AxisRotation)` for solid-body rotation of a petiole and all leaves anchored to it (the terminal floral bud and its peduncle/inflorescence, anchored to the internode, are unaffected). Pitch rotates about the stored `petiole_rotation_axis` using the construction-time `abs(pitch)` convention, yaw rotates about the internode axis, and roll rotates about the petiole's current length axis. Used internally by the sorghum flag-leaf rule, which now sets the terminal phytomer petiole pitch to a small non-zero value (5°) to keep the rotation axis well-defined and applies an additional +25° solid-body petiole rotation so the flag leaf clears the panicle.
12+
- Reworked leaf orientation on curved stems: the legacy roll term `(acos(internode_axis.z) − roll)` is removed and replaced by a curvature-aware blade-up correction applied after the pitch/yaw chain. The leaf is rolled about its own length axis (the petiole tip axis) by an angle scaled by `min(petiole_length / leaf_size, 1)` and clamped below 90°, so leaves on long petioles hang at their natural angle while leaves that hug the stem follow stem curvature. Also fixed leaf-wave vertex displacement to be applied along the post-rotation surface normal rather than along world Z, so wave bumps no longer flatten visually past the buckle.
13+
- Tightened maize and sorghum library parameters: widened phyllotactic angle (170–190° → 155–205°), increased leaf buckle angles, increased sorghum wave amplitude, lengthened maize wave period (0.1 → 0.15), and relaxed sorghum gravitropic curvature (−1000…−400 → −800…−200) for less-extreme stem droop.
14+
15+
## Leaf Optics
16+
- Added Fluspect-B SIF parameters `V2Z` (violaxanthin↔zeaxanthin de-epoxidation state) and `fqe` (intrinsic fluorescence quantum efficiency scalar) to `LeafOpticsProperties` and `LeafOpticsProperties_Nauto`. They are ignored by the PROSPECT reflectance/transmittance calculation; on every `LeafOptics::run()` call (and per-bin in the nitrogen-auto path), Helios now writes an 11-element `fluspect_biochem_<label>` global-data vector containing `[Cab, Cca, Cw, Cdm, Cs, Cant, Cp, Cbc, N, V2Z, fqe]` and stamps the primitive data label `fluspect_spectrum` on processed UUIDs so the radiation plug-in's SIF pipeline can identify fluorescing leaves and look up their biochemistry by label.
17+
18+
## Photosynthesis
19+
- Added an implementation of the von Caemmerer (2021) steady-state C4 photosynthesis model, exposed via `setModelType_C4()` and a new `C4ModelCoefficients` struct that mirrors the C3 Farquhar API (four temperature-response setter overloads per rate parameter `Vpmax`/`Vcmax`/`Jmax`/`Rd`/`gm`, plus directly-editable kinetic constants and structural scalars). Includes a fail-fast species library (`SetariaViridis_vC2021`, `GenericC4_vC2000`, `Maize_Massad2007`) accessed via `setC4CoefficientsFromLibrary()`, per-UUID and per-material coefficient assignment with full material-data serialization, a `setCm()` override for direct mesophyll-CO2 prescription (testing/validation against the paper's reference spreadsheet), and new optional output primitive data `Cm` (mesophyll cytosolic CO2) and `Vp` (PEP carboxylation rate). The `limitation_state` output uses 1 = enzyme-limited and 2 = electron-transport-limited for the C4 model.
20+
- Added mesophyll conductance `gm` to the Farquhar C3 model via four `setMesophyllConductance_gm()` overloads on `FarquharModelCoefficients` (constant / Arrhenius / peaked / peaked+dHd) with the same temperature-response framework as the other rate parameters. When `gm` is finite, net assimilation is obtained by solving the Ethier & Livingston (2004) / Sharkey et al. (2007) quadratics derived from `Cc = Ci - A/gm` for the Rubisco- and electron-transport-limited branches; the default value is +infinity, which short-circuits to the legacy `Cc ≡ Ci` path and reproduces the original Farquhar `A` bit-for-bit so existing code and parameter libraries that do not set `gm` are unaffected.
21+
22+
## Radiation
23+
- Added a solar-induced chlorophyll fluorescence (SIF) modelling pipeline to `RadiationModel`, exposed through a new SIF camera type. Users add a camera via `addSIFCamera()` (taking a list of user-defined emission bands, a `SIFCameraProperties` struct with `excitation_bin_width_nm` and `excitation_scattering_depth`, and standard camera geometry); `isSIFCamera()` queries whether a label was registered as SIF. Helios auto-creates internal excitation bands spanning 400–750 nm at the requested bin width, ray-traces them to populate per-leaf APAR (with optional inter-leaf scattering when the user wants accurate NIR APAR), evaluates a per-leaf Fluspect-B excitation→emission kernel (Vilfan 2016, ported in `FluspectB.cpp`) cached by biochemistry label + bin width, scales by the van der Tol (2014) rate-coefficient quantum yield Φ_F (read from `electron_transport_ratio` and `temperature` primitive data), integrates per emission-band wavelength range, and injects the resulting per-leaf top/bottom source flux (Mf/Mb) into the standard `runBand()` emission loop so escape and reabsorption are 3D-faithful. Excitation bands are piggy-backed onto regular non-SIF dispatches when present, and cached APAR is invalidated when radiative properties change. SIF-flagged emission bands bypass the Stefan-Boltzmann ε+ρ+τ=1 check (still enforcing ρ+τ ≤ 1) and skip the broadband σ·ε·T⁴ fallback for primitives without an SIF source flux, so non-emitting primitives (ground, sensors) do not inject thermal energy into visible/red SIF bands. Each emission band is locked to one excitation bin width — re-flagging it from a second camera with a different width is an error.
24+
- CMake now disables the Vulkan radiation backend (rather than emitting an unresolvable `-lvulkan` linker flag that broke downstream linking) when no Vulkan loader is installed on Linux/macOS, with a status message pointing at the appropriate install command.
25+
- `VulkanComputeBackend::copyScatterToRadiation()` now sizes the scatter→radiation memcpy by `launch_band_count` rather than the global `band_count`, fixing an OOB read crash whenever a `runBand` dispatch is a strict subset of all bands (e.g., a SIF emission-only dispatch following an excitation-band dispatch that raised the global band count).
26+
- `addRadiationCamera()` now warns once per camera (aggregated across all bound bands) when a camera is bound to a band with `scatteringDepth == 0`, since camera pixels for that band would otherwise read as zero with no diagnostic.
27+
- Spectral-camera auto-exposure now anchors to the 95th percentile mapped to ~0.7 instead of the median mapped to 0.18, so narrow scientific bands (fluorescence, thermal IR, Fraunhofer-line retrievals) where most of the frame reads near zero no longer drive the gain to astronomical values and saturate the subject.
28+
- `runBand()` now skips cameras whose bound bands don't intersect the current dispatch, avoiding wasted full-camera launches when (e.g.) running PAR with a SIF camera registered.
29+
- BVH traversal kernels (`traverse_bvh`, `traverse_cwbvh`) drop the unused `hit_prim_type` and `hit_uv` outputs and the corresponding leaf-data load in cwBVH, removing dead reads from every camera/diffuse/direct/pixel-label raygen path.
30+
31+
## Visualizer
32+
- Fixed `colorContextPrimitivesByObjectData()` (no-arg overload) so that orphan primitives (those with no parent compound object) are colored by the colormap at value 0 — matching the existing behaviour for compound-object primitives whose parent object lacks the data label, and matching the behaviour of `colorContextPrimitivesByData()` for primitives without primitive data. Previously orphans were rendered with their base RGBA, which left ground tiles and other standalone primitives showing through as their default color (e.g., the green from `Context::addTile`) instead of participating in the colormap.
33+
- Colorbar ticks are now filtered to the colorbar's `[cmin, cmax]` range (with a small epsilon) before placement, so a fixed-range colorbar no longer shows orphan labels at "nice" tick values that `generateNiceTicks()` extends past the data range.
34+
335
# [1.3.71] 2026-04-14
436

537
## Core

doc/DoxygenLayout.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
<tab type="user" visible="yes" url="@ref radiation_basics_tutorial" title="Tutorial 10: Tree light interception"/>
4242
<tab type="user" visible="yes" url="@ref radiation_BeersLaw_tutorial" title="Tutorial 11: Light interception for a homogeneous canopy"/>
4343
<tab type="user" visible="yes" url="@ref radiation_segmentation_tutorial" title="Tutorial 12: Radaition camera and image annotation"/>
44-
<tab type="user" visible="yes" url="@ref canopy_WUE_tutorial" title="Tutorial 13: Water-use efficiency for a canopy of spherical crowns"/>
44+
<tab type="user" visible="yes" url="@ref radiation_SIF_tutorial" title="Tutorial 13: Imaging solar-induced chlorophyll fluorescence (SIF)"/>
45+
<tab type="user" visible="yes" url="@ref canopy_WUE_tutorial" title="Tutorial 14: Water-use efficiency for a canopy of spherical crowns"/>
4546
</tab>
4647
<tab type="usergroup" visible="yes" url="@ref Benchmarks" title="Benchmarks">
4748
<tab type="user" visible="yes" url="@ref RadCanopyBenchmark" title="Homogeneous Canopy Radiation"/>

doc/Tutorials.dox

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ The following provides a several tutorials to help in getting started with the c
2626
- \subpage radiation_basics_tutorial "Tutorial 10: Radiation model basics - tree light interception"
2727
- \subpage radiation_BeersLaw_tutorial "Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy"
2828
- \subpage radiation_segmentation_tutorial "Tutorial 12: Image segmentation and object detection using the radiation camera"
29+
- \subpage radiation_SIF_tutorial "Tutorial 13: Imaging solar-induced chlorophyll fluorescence (SIF) of a plant"
2930

3031
\section WUETuts Canopy Water-Use Efficiency
31-
- \subpage canopy_WUE_tutorial "Tutorial 13: Canopy water-use efficiency - integrates many plug-ins, including radiation, energy balance, stomatal conductance, photosynthesis, etc.
32+
- \subpage canopy_WUE_tutorial "Tutorial 14: Canopy water-use efficiency - integrates many plug-ins, including radiation, energy balance, stomatal conductance, photosynthesis, etc.
3233

3334

3435
*/

doc/UserGuide.dox

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,12 @@ This will first rotate the patch by 0.25\f$\pi\f$ rad about the x-axis such that
15881588
time = make_Time( 13, 15, 00 );
15891589
context.updateTimeseriesData( "temperature", date, time, 302.10 ); // replaces the value at index #1
15901590
~~~~~~
1591+
1592+
An entire timeseries variable (with all of its time points) can be removed using \ref helios::Context::deleteTimeseriesVariable() "deleteTimeseriesVariable()". If the variable does not exist a non-fatal warning is issued and the call is otherwise a no-op. To wipe every timeseries variable at once, use \ref helios::Context::clearTimeseriesData() "clearTimeseriesData()" instead.
1593+
1594+
~~~~~~{.cpp}
1595+
context.deleteTimeseriesVariable( "temperature" ); // removes the variable and all of its data points
1596+
~~~~~~
15911597

15921598

15931599
*/

doc/tutorials/tutorial_03.dox

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ Tabular CSV files can also be read with
4242

4343
Indices may be accessed directly with \ref helios::Context::setCurrentTimeseriesPoint() "setCurrentTimeseriesPoint()" when iterating over a dataset.
4444

45-
A complete example of using timeseries data can be found in \subpage canopy_WUE_tutorial "Tutorial 13".
45+
A complete example of using timeseries data can be found in \subpage canopy_WUE_tutorial "Tutorial 14".
4646

4747
*/

0 commit comments

Comments
 (0)