Skip to content

MagNIMBUS Gradiometer Distance Depth Weight Estimation Script

AndriksonsM edited this page Mar 18, 2026 · 1 revision
image

This document describes a method for estimating the distance, depth, and approximate weight of magnetic targets using a MagNIMBUS two-sensor vertical gradiometer system.

The approach is based on the physical assumption that a magnetic source behaves like a point dipole, where the magnetic field strength decreases with distance according to an inverse-cube law. By comparing measurements from a lower and upper sensor, the method derives the relative distance to the source without requiring prior knowledge of its exact properties.

What this method provides

  • Distance to target from the lower sensor
  • Estimated depth below ground surface
  • Approximate target weight, based on empirical models

Why it is used

This method is particularly useful in applications such as:

  • Detection of buried metallic objects, for example, UXO's (unexploded ordnance)
  • Environmental and geophysical investigations
  • Rapid field estimation where full inversion modelling is not practical

It enables fast, automated interpretation of magnetic anomalies directly from survey data, making it well-suited for pipeline processing (e.g. MagNIMBUS workflows). The following sections describe the input requirements, physical model, algorithm, and output structure in detail.


1. Prerequisites and Input Requirements

1.1 Prior Steps

  • Anomalies must be marked in the data file before running this script (Mark = 1). More information about setting marks can be found here and here.
  • The script exits with a message if no marked rows are found.

1.2 Input File Format

Standard MagNIMBUS CSV file with the following required columns:

Column Default name Description
Lower sensor field TMI_LPF Total magnetic intensity at the lower (closer-to-ground) sensor (nT)
Upper sensor field TMI_S_LPF Total magnetic intensity at the upper sensor (nT)
Altitude AGL Altitude AGL Height of the altimeter above ground level (metres)
Mark Mark Anomaly mark (1 = marked row)

All column names are configurable via command-line arguments (see Section 6).

1.3 Background Estimation

No per-flight-line spatial filtering is applied. Instead, the background field is estimated globally as the median of the upper-sensor column (TMI_S_LPF) across the entire file. The upper sensor is used because its greater height above ground makes it less sensitive to near-surface magnetic anomalies, yielding a more representative ambient field value.

No pre-processing of the background field is required before running this script. If a pre-filtered column (e.g. TMI_LPF) is supplied as the lower-sensor column, the anomaly computed in Step 2 will reflect the residual after that external filter — this is the intended workflow in the MagNIMBUS pipeline.


2. Physical Model and Assumptions

2.1 Source Model

The magnetic source is modelled as a point magnetic dipole (compact object, dimensions much smaller than depth). Under this model, the total field anomaly at distance $D$ from the source scales as $D^{-3}$.

2.2 Two-Sensor Gradiometer Principle

When the two sensors are positioned vertically with a known separation $s$ (metres), and both are directly above the source, the ratio of their respective anomalies encodes the relative distances to the source via the inverse-cube law:

$$ \frac{\Delta B_{\mathrm{lower}}}{\Delta B_{\mathrm{upper}}} = \left(\frac{D_{\mathrm{upper}}}{D_{\mathrm{lower}}}\right)^3 $$

Since $D_{\mathrm{upper}} = D_{\mathrm{lower}} + s$:

$$ \frac{\Delta B_{\mathrm{lower}}}{\Delta B_{\mathrm{upper}}} = \left(\frac{D_{\mathrm{lower}} + s}{D_{\mathrm{lower}}}\right)^3 = \left(1 + \frac{s}{D_{\mathrm{lower}}}\right)^3 $$

Taking the cube root of both sides and solving for $D_{\mathrm{lower}}$:

$$ D_{\mathrm{lower}} = \frac{s}{\left(\frac{\Delta B_{\mathrm{lower}}}{\Delta B_{\mathrm{upper}}}\right)^{1/3} - 1} $$

This gives the sensor-to-source distance measured from the lower sensor.

2.3 Anomaly Computation

The background is subtracted from each sensor reading independently using the global median of the upper sensor as a proxy for the ambient field:

$$ \Delta B_{\mathrm{lower}} = B_{\mathrm{lower}} - B_{\mathrm{background}} $$

$$ \Delta B_{\mathrm{upper}} = B_{\mathrm{upper}} - B_{\mathrm{background}} $$

2.4 Distance Estimation

$$ D_{\mathrm{lower}} = \frac{s}{\left(\frac{\Delta B_{\mathrm{lower}}}{\Delta B_{\mathrm{upper}}}\right)^{1/3} - 1} $$

If $D_{\mathrm{lower}}$ evaluates to a negative value (which can arise from numerical edge cases near the singularity), its absolute value is taken.

2.5 Depth Below Ground Surface

$$ d_{\mathrm{ground}} = D_{\mathrm{lower}} - h_{\mathrm{AGL}} + \delta_{\mathrm{offset}} $$

where:

  • $h_{\mathrm{AGL}}$ is the altitude AGL at the marked row,
  • $\delta_{\mathrm{offset}}$ (altimeter-lower-offset) is the vertical distance between the altimeter and the lower sensor (metres; default 0.5 m), correcting for the fact that the altimeter and sensor are not co-located.

If $d_{\mathrm{ground}} < 0$, the value is clipped to 0.

If altitude AGL data is not present in the file, depth is not computed and Estimated_Depth is left empty. The script prints an informational message in this case.

2.6 Weight Estimation Model

Weight is estimated from two independent empirical models; the more conservative (smaller) result is reported.

All distances are converted to feet for the weight formulae, consistent with the original empirical calibration:

$$ D_{\mathrm{ft}} = D_{\mathrm{lower}} / 0.3048 $$

Model 1 — Dipole Scaling (upper bound for large distances)

$$ W_{\mathrm{dipole}} = \frac{|\Delta B_{\mathrm{lower}}| \cdot D_{\mathrm{ft}}^3}{1000} \times 0.453592 \quad [\mathrm{kg}] $$

This is analogous to the dipole-moment inversion $m \propto |B| \cdot D^3$, empirically calibrated to produce a weight estimate in kg via a fixed proportionality.

Model 2 — Inverse Power (upper bound for shallow targets)

$$ W_{\mathrm{inv}} = \frac{|\Delta B_{\mathrm{lower}}|}{D_{\mathrm{ft}}^{1.5}} \quad [\mathrm{kg}] $$

This model decays more slowly with distance and dominates (produces a smaller estimate) for shallow, high-field anomalies where the dipole model can overestimate.

Selected Weight

$$ W = \min(W_{\mathrm{dipole}},\ W_{\mathrm{inv}}) $$

The minimum is taken as a conservative estimate; using the smaller of the two models reduces the risk of overestimating the weight of a shallow strong target.


3. Algorithm

Step 1 — Load and validate

  • Read input CSV.
  • Verify that the lower-sensor column and upper-sensor column exist and are numeric.
  • Verify that the Mark column exists.
  • Print an informational message if the altitude AGL column is absent (depth will not be computed).
  • Exit cleanly if no marked rows (Mark = 1) are found.

Step 2 — Compute global background

$$ B_{\mathrm{background}} = \mathrm{median}(B_{\mathrm{upper}}) $$

The upper-sensor column is used in its entirety (all rows, not just unmarked rows).

Step 3 — Identify marked rows

Convert the Mark column to numeric (coercing non-numeric values to 0). Collect the integer row indices where Mark = 1.

Step 4 — Process each marked row

For each marked index $i$:

  1. Read sensor values: $B_{\mathrm{lower},i}$ and $B_{\mathrm{upper},i}$. If either is NaN, skip with a warning.

  2. Compute anomalies:

    $\Delta B_{\mathrm{lower}} = B_{\mathrm{lower},i} - B_{\mathrm{background}}, \quad \Delta B_{\mathrm{upper}} = B_{\mathrm{upper},i} - B_{\mathrm{background}}$

  3. Guard — zero upper anomaly: if $\Delta B_{\mathrm{upper}} = 0$, skip with a warning.

  4. Compute anomaly ratio: $r = \Delta B_{\mathrm{lower}} / \Delta B_{\mathrm{upper}}$.

  5. Guard — negative ratio: if $r < 0$ (opposite-sign anomalies, indicating the sensors are on opposite sides of a dipole lobe), skip with a warning.

  6. Cube root: $r^{1/3} = r^{0.333\ldots}$

  7. Guard — unit denominator: if $r^{1/3} = 1$ (ratio equals 1, denominator is zero, distance is undefined), skip with a warning.

  8. Distance:

    $D_{\mathrm{lower}} = s / (r^{1/3} - 1)$ If negative, take the absolute value. Round to 4 decimal places.

  9. Guard — zero distance: if $D_{\mathrm{lower}} = 0$ after rounding, skip with a warning.

  10. Depth (if altitude AGL is available):

    $d_{\mathrm{ground}} = D_{\mathrm{lower}} - h_{\mathrm{AGL},i} + \delta_{\mathrm{offset}}$ Clip to 0 if negative. Round to 4 decimal places.

  11. Weight:

    $D_{\mathrm{ft}} = D_{\mathrm{lower}} / 0.3048$ $W = \min!\left(\frac{|\Delta B_{\mathrm{lower}}| \cdot D_{\mathrm{ft}}^3}{1000} \times 0.453592,\ \frac{|\Delta B_{\mathrm{lower}}|}{D_{\mathrm{ft}}^{1.5}}\right)$ Round to 6 decimal places.

Step 5 — Write outputs

  • Add three new columns to the original data: Estimated_Distance, Estimated_Depth, Estimated_Weight. All rows are initialised to empty string "".
  • For each successfully processed marked row, write the computed values. Rows that were skipped retain "".
  • Overwrite the input CSV with the updated data.
  • Write a targets CSV containing only the marked rows (see Section 4.2).

4. Outputs

4.1 Additional Columns Added to Source CSV

Column Description Unit
Estimated_Distance Sensor-to-source distance from the lower sensor ($D_{\mathrm{lower}}$) m
Estimated_Depth Estimated depth below ground surface ($D_{\mathrm{lower}} - h_{\mathrm{AGL}} + \delta_{\mathrm{offset}}$), clipped to 0; empty if altitude AGL is unavailable m
Estimated_Weight Conservative weight estimate:$\min(W_{\mathrm{dipole}},\ W_{\mathrm{inv}})$ kg

All three columns are empty ("") for rows where Mark ≠ 1 or where processing was skipped due to a guard condition.

4.2 Targets CSV ({stem}-targets.csv)

One row per marked row. Contains all original source CSV columns plus the three output columns listed in Section 4.1. Written to output-dir if specified, otherwise to the same directory as the input file.


5. Internal Constants

Not exposed as CLI arguments; edit the script to change them.

Constant Value Description
LBS_TO_KG 0.453592 Conversion factor applied in the dipole weight model

All other tunable quantities (sensor separation, altimeter offset, column names) are exposed as command-line parameters.


6. Command-Line Parameters

Argument Default Description
file_path (required) Input CSV file path
--lower-sensor-column TMI_LPF Column name for the lower (closer-to-ground) sensor
--upper-sensor-column TMI_S_LPF Column name for the upper sensor
--altitude-column Altitude AGL Column name for altitude AGL; if absent from file, depth is not computed
--sensor-separation 1.5 Vertical distance between the two sensors (metres)
--altimeter-lower-offset 0.5 Vertical distance between the altimeter and the lower sensor (metres)
--output-dir (same as input) Directory for the targets CSV

Clone this wiki locally