7. Calibration of single-ended measurement

A single-ended DTS measurement setup is a setup where the measurements are taken from one ending of the fiber, e.g., only one ending is connected to the DTS device. Opposed to double-ended setups, where measurements are taken from both endings of the fiber, the calibration of single-ended setups require the additional assumption that the losses (differential attenuation) is constant along the fiber. E.g., a sharp bend result additional losses and causes a false jump in the temperature. The estimation of the measurement uncertainty also assumes constant losses.

A single-ended calibration is performed where the unknown parameters are estimated using fiber sections that have a reference temperature. The parameters are estimated with a weighted least squares optimization using Stokes and anti-Stokes measurements from all timesteps. Thus Stokes and anti-Stokes measurements with a large signal to noise ratio contribute more towards estimating the optimal parameter set, but an estimate of the noise variance is required.

Single-ended calibration requires a few steps: 1. Read the raw data files loaded from your DTS machine 2. Define the reference sections: fiber sections that have a known temperature. 3. Estimate the variance of the noise in the Stokes and anti-Stokes measurements 4. Perform the parameter search and compute the temperature along the entire fiber. 5. Plot the temperature and uncertainty of the estimated temperature

Please have a look at [1] for more information.

[1]: des Tombe, B., Schilperoort, B., & Bakker, M. (2020). Estimation of Temperature and Associated Uncertainty from Fiber-Optic Raman-Spectrum Distributed Temperature Sensing. Sensors, 20(8), 2235. https://doi.org/10.3390/s20082235

[1]:
import os

from dtscalibration import read_silixa_files

# The following line introduces the .dts accessor for xarray datasets
import dtscalibration  # noqa: E401  # noqa: E401
from dtscalibration.variance_stokes import variance_stokes_constant
import matplotlib.pyplot as plt

Read the raw data files loaded from your DTS machine

Use read_silixa_files for reading files from a Silixa device. The following functions are available for reading files from other devices: read_sensortran_files, read_apsensing_files, and read_sensornet_files. See Notebook 1.

Calibration is performed on sections that have a known

[2]:
filepath = os.path.join("..", "..", "tests", "data", "single_ended")
ds = read_silixa_files(directory=filepath, timezone_netcdf="UTC", file_ext="*.xml")
3 files were found, each representing a single timestep
4 recorded vars were found: LAF, ST, AST, TMP
Recorded at 1461 points along the cable
The measurement is single ended
Reading the data from disk

Define the reference fiber sections that have a known temperature

As explained in Notebook 3. DTS devices come with temperature probes to measure the temperature of the water baths. These measurements are stored in the data that was loaded in the previous step and are loaded automatically. In the case you would like to use an external temperature sensor, have a look at notebook 09Import_timeseries to append those measurements to the ds before continuing with the calibration.

[3]:
ds = ds.sel(x=slice(-30, 101))  # dismiss parts of the fiber that are not interesting
sections = {
    "probe1Temperature": [slice(20, 25.5)],  # warm bath
    "probe2Temperature": [slice(5.5, 15.5)],  # cold bath
}

Estimate the variance of the noise in the Stokes and anti-Stokes measurements

First calculate the variance of the noise in the measured Stokes and anti-Stokes signals. See Notebook 4 for more information.

The Stokes and anti-Stokes signals should follow a smooth decaying exponential. This function fits a decaying exponential to each reference section for each time step. The variance of the residuals between the measured Stokes and anti-Stokes signals and the fitted signals is used as an estimate of the variance in measured signals. This algorithm assumes that the temperature is the same for the entire section but may vary over time and differ per section.

[4]:
st_var, resid = variance_stokes_constant(
    ds.dts.st, sections, ds.dts.acquisitiontime_fw, reshape_residuals=True
)
ast_var, _ = variance_stokes_constant(
    ds.dts.ast, sections, ds.dts.acquisitiontime_fw, reshape_residuals=False
)

The following plot can be used to check if there are no spatial or temporal correlated residuals. If you see horizontal or vertical lines that means that you overestimate the st_var. Common reasons are that the temperature of that section is not uniform, e.g. that the reference sections were defined falsely or that the temperature of the water baths were not uniform.

[5]:
resid.plot(figsize=(12, 4))
[5]:
<matplotlib.collections.QuadMesh at 0x7fb9512fce20>
../_images/notebooks_07Calibrate_single_ended_10_1.png

Perform calibration and compute the temperature

We calibrate the measurements and their uncertainty with a single method call. The temperature is stored by default as the ds.tmpf dataarray and the variance of its approximation as ds.tmpf_var.

[6]:
out = ds.dts.calibrate_single_ended(sections=sections, st_var=st_var, ast_var=ast_var)

Plot the temperature and uncertainty of the estimated temperature

First, the temperature for the entire fiber is plotted. Second, the temperature and its standard error are plotted for the first timestep.

[7]:
out.tmpf.plot(figsize=(12, 4))
[7]:
<matplotlib.collections.QuadMesh at 0x7fb950096a90>
../_images/notebooks_07Calibrate_single_ended_14_1.png
[8]:
ds1 = out.isel(time=0)
ds1.tmpf.plot(figsize=(12, 4))
(ds1.tmpf_var**0.5).plot(figsize=(12, 4))
plt.ylabel("$\sigma$ ($^\circ$C)")
[8]:
Text(0, 0.5, '$\\sigma$ ($^\\circ$C)')
../_images/notebooks_07Calibrate_single_ended_15_1.png
../_images/notebooks_07Calibrate_single_ended_15_2.png

The variance of the temperature measurement appears to be larger than what the manufacturer reports. This is already the case for the internal cable; it is not caused by a dirty connector/bad splice on our side. Maybe the length of the calibration section was not sufficient.

At 30 m the variance sharply increases. There are several possible explanations. E.g., large temperatures or decreased signal strength.

Lets have a look at the Stokes and anti-Stokes signal.

[9]:
ds.isel(time=0).st.plot(figsize=(12, 8))
ds.isel(time=0).ast.plot()
[9]:
[<matplotlib.lines.Line2D at 0x7fb949d4be20>]
../_images/notebooks_07Calibrate_single_ended_17_1.png

Clearly there was a bad splice at 30 m that resulted in the sharp increase of measurement uncertainty for the cable section after the bad splice.

Note that the uncertainty of the temperature strongly varies along the fiber. Dive deeper in the uncertainty of the temperature estimate in another notebook