14. Calibration over (lossy) splices and connectors

Background

While it is best practice to not have connectors or splices within a DTS calibration, sometimes it can’t be avoided. For example, in a borehole the fibers in a duplex cable are often connected with either a splice or a loopback connector.

Splices and connectors will cause a step loss in the signal strength, and with varying strain and temperature, this step loss will vary. In double ended setups this step loss can even be asymmetrical for the forward and backward measurements. All these effects have to be taken into account in the calibration.

To calibrate over these splices/connectors, locations with ‘transient attenuation’ can be defined along the length of the fiber. Adding these does mean that more information is needed to perform the calibration, such as extra reference sections or matching sections of fiber. Matching sections will be explained in notebook 15.

Demonstration

To demonstrate the effect of a lossy splice, we’ll load the same dataset that was used in previous notebooks, and modify the data to simulate a lossy splice.

[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
[2]:
filepath = os.path.join("..", "..", "tests", "data", "double_ended2")

ds_ = read_silixa_files(directory=filepath, timezone_netcdf="UTC", file_ext="*.xml")

ds = ds_.sel(x=slice(0, 110))  # only calibrate parts of the fiber


sections = {
    "probe1Temperature": [slice(7.5, 17.0), slice(70.0, 80.0)],  # cold bath
    "probe2Temperature": [slice(24.0, 34.0), slice(85.0, 95.0)],  # warm bath
}
6 files were found, each representing a single timestep
6 recorded vars were found: LAF, ST, AST, REV-ST, REV-AST, TMP
Recorded at 1693 points along the cable
The measurement is double ended
Reading the data from disk

To simulate the lossy splice, we introduce a step loss in the signal strength at x = 50 m. For the forward channel, this means all data beyond 50 meters is reduced with a ‘random’ factor. For the backward channel, this means all data up to 50 meters is reduced with a ‘random’ factor.

In the plots of the Stokes and anti-Stokes signal the big step loss is clearly visible.

[3]:
ds["st"] = ds.st.where(ds.x < 50, ds.st * 0.8)
ds["ast"] = ds.ast.where(ds.x < 50, ds.ast * 0.82)

ds["rst"] = ds.rst.where(ds.x > 50, ds.rst * 0.85)
ds["rast"] = ds.rast.where(ds.x > 50, ds.rast * 0.81)
[4]:
ds.isel(time=0).st.plot(label="st")
ds.isel(time=0).ast.plot(label="ast")
ds.isel(time=0).rst.plot(label="rst")
ds.isel(time=0).rast.plot(label="rast")
plt.legend()
[4]:
<matplotlib.legend.Legend at 0x7f5b092563d0>
../_images/notebooks_14Lossy_splices_7_1.png

We will first run a calibration without adding the transient attenuation location. A big jump in the calibrated temperature is visible at x = 50, and all temperatures before the jump are too low, and the temperatures after the jump are too high.

[5]:
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
)
rst_var, _ = variance_stokes_constant(
    ds.dts.rst, sections, ds.dts.acquisitiontime_bw, reshape_residuals=False
)
rast_var, _ = variance_stokes_constant(
    ds.dts.rast, sections, ds.dts.acquisitiontime_bw, reshape_residuals=False
)

out = ds.dts.calibrate_double_ended(
    sections=sections,
    st_var=st_var,
    ast_var=ast_var,
    rst_var=rst_var,
    rast_var=rast_var,
)

out.isel(time=0).tmpw.plot(label="calibrated")
[5]:
[<matplotlib.lines.Line2D at 0x7f5b0885f2b0>]
../_images/notebooks_14Lossy_splices_9_1.png

Now we run a calibration, adding the keyword argument ‘trans_att’, and provide a list of floats containing the locations of the splices. In this case we only add a single one at x = 50 m. After running the calibration you will see that by adding the transient attenuation location the calibration returns the correct temperature, without the big jump.

In single-ended calibration the keyword is called ‘trans_att‘.

[6]:
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
)
rst_var, _ = variance_stokes_constant(
    ds.dts.rst, sections, ds.dts.acquisitiontime_bw, reshape_residuals=False
)
rast_var, _ = variance_stokes_constant(
    ds.dts.rast, sections, ds.dts.acquisitiontime_bw, reshape_residuals=False
)

out2 = ds.dts.calibrate_double_ended(
    sections=sections,
    st_var=st_var,
    ast_var=ast_var,
    rst_var=rst_var,
    rast_var=rast_var,
    trans_att=[50.0],
)

out.isel(time=0).tmpw.plot(label="no trans. att.")
out2.isel(time=0).tmpw.plot(label="with trans. att.")
plt.legend()
[6]:
<matplotlib.legend.Legend at 0x7f5b086a94c0>
../_images/notebooks_14Lossy_splices_11_1.png
[ ]: