Bonner-sphere spectrometry¶
Neptoon has a standalone processing domain for multi-channel Bonner-sphere spectrometers.
It is deliberately separate from CRNSDataHub: a Bonner spectrometer must preserve every
sphere channel because each channel has its own neutron response. The Bonner workflow never
merges or sums configured sphere channels.
The first supported parameter sets are the NEMUS and HERMEIS Skyview fits (report version
0.8, 2025-03-21). Sphere size is not a sufficient scientific identifier. For example,
NEMUS 3-inch and HERMEIS 3-inch spheres have different response coefficients. Neptoon
therefore resolves a response by instrument model + sphere label. The user-facing channel
id is only a stable data label and may additionally distinguish repeated physical channels.
What is implemented¶
For every configured channel Neptoon can:
- preserve the raw channel independently;
- convert absolute counts to counts per hour using a channel-specific or common elapsed time;
- divide by a configured
reference_intensity_cphto obtain relative intensity; - evaluate/invert the published two-dimensional soil-moisture/air-humidity response;
- calculate W63 and W86 from a 10 Vol-% channel reference plus the published relative soil-moisture scaling, and interpolate the published soil-contact percentage; and
- optionally construct a radial proxy from a fixed Schrön-2017 reference shape scaled by that Bonner W86 response;
- evaluate the channel-specific published D86 depth fits, using the event-weighted range-integrated fit for ordinary time-series output; and
- evaluate the distance-dependent D86 fit or an explicitly labelled quantile-matched exponential layer-weight proxy through the Python API.
The response fits use soil moisture in Vol-% and absolute humidity in g/m3. Neptoon keeps volumetric soil moisture in its normal internal unit m3/m3 and performs the factor-100 conversion only at the Bonner response boundary. The reported fit domain is 1--90 Vol-% and 0--50 g/m3; Neptoon does not silently extrapolate beyond it.
The supplied Skyview reports do not define channel-specific pressure or incoming radiation corrections. Neptoon therefore does not reuse a CRNS correction merely because it is numerically available. Humidity is also not corrected a second time: it is already an independent variable in the published Bonner response model. Separate NEMUS/HERMEIS depth-fit reports provide the vertical D86 parameterisation described below.
NEMUS sphere 0 is registered for its published horizontal footprint, but the supplied
NEMUS response tables do not contain intensity-fit parameters for that channel. It can be
processed as a count channel when soil-moisture inversion is disabled, but Neptoon does not
invent an intensity response for it.
YAML configuration¶
Bonner processing uses its own strict configuration rather than extending the normal
sensor/process CRNS files:
config: bonner_sphere
spectrometer:
model: hermeis
identifier: HERMEIS01
parameter_set: hermeis_skyview_2025_v0_8
input:
path_to_data: HERMEIS.csv
delimiter: ","
datetime:
column: DateTime
format: "%Y-%m-%d %H:%M:%S"
timezone: UTC
# Use `cph` if the source columns already contain rates.
count_units: absolute_count
default_elapsed_time_seconds: 3600
meteo:
# Alternatively provide temperature_column + relative_humidity_column.
absolute_humidity_column: AbsoluteHumidity_g_m3
pressure_column: AirPressure_hPa
# Optional. If omitted, vertical D86 automatically uses the published
# event-weighted range-integrated fit. A direct range column can be mapped as:
spatial:
distance_column: Distance_m
channels:
- id: H3
sphere: "3"
count_column: BS3_Counts
reference_intensity_cph: 1234.5
- id: H3_5
sphere: "3.5"
count_column: BS3_5_Counts
elapsed_time_column: BS3_5_LiveTime_s
reference_intensity_cph: 987.2
- id: H7W
sphere: "7W"
count_column: BS7W_Counts
reference_intensity_cph: 456.7
processing:
soil_moisture:
enabled: true
out_of_domain: warn_nan
footprint:
effective_radii: true
radial_proxy: scaled_schroen_2017
vertical:
enabled: true
# D86 is natively g/cm2. Set bulk density only when a cm output is needed.
bulk_density_g_cm3: 1.4
output:
save_path: HERMEIS_processed.csv
reference_intensity_cph is intentionally explicit per channel. The Skyview reports define
relative response functions but do not specify how a particular field instrument's absolute
count rate should be normalised. A future validated calibration method can supply this value,
but the current workflow does not equate it with the ordinary CRNS N0 parameter.
Relative paths are resolved against the Bonner YAML file.
Python API¶
from neptoon.spectrometry.bonner_sphere import BonnerSphereProcessor
processor = BonnerSphereProcessor.from_yaml("hermeis.yaml")
data = processor.run()
Standardised channel outputs use the configured channel id:
bs_H3_raw
bs_H3_cph
bs_H3_relative_intensity
bs_H3_smv
bs_H3_w63_m
bs_H3_w86_m
bs_H3_soil_contact_percent
bs_H3_d86_g_cm2
bs_H3_d86_cm
Missing values remain channel-local. A missing H3 observation does not make H3.5 or H7W invalid at the same timestamp.
Response equations¶
The NEMUS parameter set contains two equation families. For the NEMUS 3, 3.5, 7, 8, 10, 12 and modified spheres the response is
For NEMUS 4, 4.5, 5 and 6 it is
HERMEIS uses
Here x is soil moisture in Vol-% and h is absolute humidity in g/m3. The complete
channel-specific coefficient sets live in the immutable Bonner registry rather than user
YAML, so a HERMEIS channel cannot accidentally use NEMUS coefficients.
Horizontal footprint¶
The published W63 and W86 tables are represented as a reference footprint plus a dimensionless soil-moisture response. The current Skyview parameter sets use 10 Vol-% as the reference point for every channel:
and
W63 is represented in the same way. Neptoon linearly interpolates the dimensionless scaling factors between the reported 1, 3, 6, 10, 12, 15, 20, 25, 30, 40, 50 and 90 Vol-% simulation points and returns NaN outside that interval. Multiplication by the channel reference radius exactly reconstructs the published table values. Soil-contact percentages remain a directly interpolated published diagnostic. Pure-water values are available separately through the Python API.
The optional scaled_schroen_2017 model is a deliberately labelled proxy. The Skyview
reports provide containment radii rather than a complete radial probability law. Neptoon
therefore takes one Schrön-2017 radial shape at the common 10 Vol-% reference soil moisture
and at the report-specific footprint humidity (1 g/m3 for NEMUS, 0 g/m3 for HERMEIS).
That fixed reference shape is scaled once to the channel's reference W86. For another soil
moisture, only the Bonner-sphere relative response is applied:
Thus the radial proxy does not inherit an additional CRNS soil-moisture dependence from the Schrön model. Its W86 reproduces the Bonner value by construction. The published W63 is retained in metadata as a diagnostic and is not claimed to be a directly simulated Bonner radial law.
Vertical D86 depth weighting¶
The NEMUS and HERMEIS depth-fit reports use the 86 % depth quantile and publish two different models. Their native quantity is dry-soil mass depth in g/cm2, not geometric depth in centimetres.
With horizontal distance information the channel-specific fit is
where theta is volumetric soil moisture as a fraction (for example 0.10 for 10 Vol-%)
and r is detector distance in metres. This model is available through
calculate_range_dependent_d86(...) and BonnerSphereProcessor.calculate_vertical_depth(...)
when a distance is supplied.
For the no-distance case the reports first combine the simulated depth distributions of all radial rings using their simulated event fractions,
and then fit the resulting quantile depth as
For time-series processing Neptoon selects between these two published models from the
available geometry. If no distance or coordinate mapping is configured, the entire series
uses the event-weighted range-integrated D86(theta) fit. If range information is available,
rows with a finite detector distance use D86(theta,r). Rows whose distance or coordinates
are empty/NA automatically fall back to D86(theta) rather than producing a missing depth.
The selected mode is recorded in bonner_vertical_d86_mode as range_dependent or
range_integrated, and any derived distance is published as bonner_distance_m.
Three geometry inputs are supported under input.spatial: a direct distance_column in
metres; local Cartesian x_column/y_column together with the detector x/y coordinates; or
WGS84 latitude_column/longitude_column together with spectrometer.latitude and
spectrometer.longitude. Geometry is never guessed from arbitrary column names. Omitting
input.spatial is therefore the explicit no-range case.
Neptoon does not numerically average D86(theta,r) with the optional scaled-Schrön radial
proxy. The depth report already supplies an event-weighted no-distance fit, whereas the
Schrön shape is only an approximation to the unknown full Bonner radial probability law.
When processing.footprint.vertical.enabled: true, Neptoon writes
bs_<id>_d86_g_cm2 from the automatically selected published fit. If
bulk_density_g_cm3 is configured, it also writes
Neptoon keeps the mass-depth value as the primary product because it is what the supplied
fits actually parameterise. The simple division is appropriate for the scalar/uniform bulk
density configured in the time-series workflow. The low-level layer-weight helper supports
layer-specific bulk density directly in cumulative mass-depth coordinates. If the supplied
layer column does not contain enough dry-soil mass to reach D86, its physical d86_cm
diagnostic remains NaN rather than extrapolating an unknown deeper bulk density.
The depth reports do not publish an analytic full vertical probability-density law; they
publish D86 fits derived from simulated distributions. Consequently
calculate_exponential_vertical_weights_proxy(...) is deliberately a proxy, not a
claim to reconstruct the original simulated W(z). It uses an exponential in dry-mass
depth with rate
so its untruncated cumulative probability is exactly 0.86 at the published D86. The helper
integrates this proxy analytically over user-supplied soil layers and normalises the weights
over the supplied finite column. Omitting distance uses the event-weighted no-distance D86;
supplying distance_m uses the range-dependent fit. The standalone processor applies the
same rule automatically to time-series geometry, including row-wise no-range fallback.
The depth-fit reports also warn that formal covariance errors do not fully represent systematic model mismatch when chi2/ndf is large. Neptoon retains RMSE, R2 and chi2/ndf in the immutable channel registry for diagnostics, but does not currently promote the formal coefficient errors into a physical D86 uncertainty product.