A4. Loading sensortran files¶
This example loads sensortran files. Only single-ended measurements are currently supported. Sensortran files are in binary format. The library requires the *BinaryRawDTS.dat
and *BinaryTemp.dat
files.
[1]:
import os
import glob
import matplotlib.pyplot as plt
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
from dtscalibration import read_sensortran_files
The example data files are located in ./python-dts-calibration/tests/data
.
[2]:
filepath = os.path.join("..", "..", "tests", "data", "sensortran_binary")
print(filepath)
../../tests/data/sensortran_binary
[3]:
filepathlist = sorted(glob.glob(os.path.join(filepath, "*.dat")))
filenamelist = [os.path.basename(path) for path in filepathlist]
for fn in filenamelist:
print(fn)
15_56_47_BinaryRawDTS.dat
15_56_47_BinaryTemp.dat
16_11_31_BinaryRawDTS.dat
16_11_31_BinaryTemp.dat
16_29_23_BinaryRawDTS.dat
16_29_23_BinaryTemp.dat
We will simply load in the binary files
[4]:
ds = read_sensortran_files(directory=filepath)
3 files were found, each representing a single timestep
Recorded at 11582 points along the cable
The measurement is single ended
/home/docs/checkouts/readthedocs.org/user_builds/python-dts-calibration/envs/latest/lib/python3.9/site-packages/dtscalibration/datastore.py:81: UserWarning: Converting non-nanosecond precision timedelta values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.
super().__init__(*args, **kwargs)
/home/docs/checkouts/readthedocs.org/user_builds/python-dts-calibration/envs/latest/lib/python3.9/site-packages/dtscalibration/datastore.py:81: UserWarning: Converting non-nanosecond precision timedelta values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.
super().__init__(*args, **kwargs)
The object tries to gather as much metadata from the measurement files as possible (temporal and spatial coordinates, filenames, temperature probes measurements). All other configuration settings are loaded from the first files and stored as attributes of the DataStore
. Sensortran’s data files contain less information than the other manufacturer’s devices, one being the acquisition time. The acquisition time is needed for estimating variances, and is set a constant 1s.
[5]:
print(ds)
<dtscalibration.DataStore>
Sections: ()
Dimensions: (x: 11582, time: 3, trans_att: 0)
Coordinates:
* x (x) float32 -451.4 -450.9 ... 5.408e+03 5.409e+03
filename (time) <U25 '15_56_47_BinaryRawDTS.dat' ... '16_29...
filename_temp (time) <U23 '15_56_47_BinaryTemp.dat' ... '16_29_2...
timestart (time) datetime64[ns] 2009-09-23T22:56:46 ... 2009...
timeend (time) datetime64[ns] 2009-09-23T22:56:47 ... 2009...
* time (time) datetime64[ns] 2009-09-23T22:56:47 ... 2009...
acquisitiontimeFW (time) timedelta64[ns] 00:00:01 00:00:01 00:00:01
* trans_att (trans_att) float64
Data variables:
st (x, time) int32 39040680 39057147 ... 39071213
ast (x, time) int32 39048646 39064414 ... 39407668
tmp (x, time) float64 -273.1 -273.1 ... 82.41 82.71
referenceTemperature (time) float64 28.61 29.24 30.29
st_zero (time) float64 3.904e+07 3.906e+07 3.907e+07
ast_zero (time) float64 3.905e+07 3.907e+07 3.908e+07
userAcquisitionTimeFW (time) float64 1.0 1.0 1.0
Attributes: (12/16)
survey_type: 2
hdr_version: 3
x_units: n/a
y_units: counts
num_points: 12000
num_pulses: 25000
... ...
hdr_size: 176
hw_config: 84
.. and many more attributes. See: ds.attrs
The sensortran files differ from other manufacturers, in that they return the ‘counts’ of the Stokes and anti-Stokes signals. These are not corrected for offsets, which has to be done manually for proper calibration.
Based on the data available in the binary files, the library estimates a zero-count to correct the signals, but this is not perfectly accurate or constant over time. For proper calibration, the offsets would have to be incorporated into the calibration routine.
[6]:
ds
[6]:
<dtscalibration.DataStore> Sections: () Dimensions: (x: 11582, time: 3, trans_att: 0) Coordinates: * x (x) float32 -451.4 -450.9 ... 5.408e+03 5.409e+03 filename (time) <U25 '15_56_47_BinaryRawDTS.dat' ... '16_29... filename_temp (time) <U23 '15_56_47_BinaryTemp.dat' ... '16_29_2... timestart (time) datetime64[ns] 2009-09-23T22:56:46 ... 2009... timeend (time) datetime64[ns] 2009-09-23T22:56:47 ... 2009... * time (time) datetime64[ns] 2009-09-23T22:56:47 ... 2009... acquisitiontimeFW (time) timedelta64[ns] 00:00:01 00:00:01 00:00:01 * trans_att (trans_att) float64 Data variables: st (x, time) int32 39040680 39057147 ... 39071213 ast (x, time) int32 39048646 39064414 ... 39407668 tmp (x, time) float64 -273.1 -273.1 ... 82.41 82.71 referenceTemperature (time) float64 28.61 29.24 30.29 st_zero (time) float64 3.904e+07 3.906e+07 3.907e+07 ast_zero (time) float64 3.905e+07 3.907e+07 3.908e+07 userAcquisitionTimeFW (time) float64 1.0 1.0 1.0 Attributes: (12/16) survey_type: 2 hdr_version: 3 x_units: n/a y_units: counts num_points: 12000 num_pulses: 25000 ... ... hdr_size: 176 hw_config: 84 .. and many more attributes. See: ds.attrs
[7]:
ds0 = ds.isel(time=0)
plt.figure()
ds0.st.plot(label="Stokes signal")
plt.axhline(ds0.st_zero.values, c="r", label="'zero' measurement")
plt.legend()
plt.title("")
plt.axhline(c="k")
[7]:
<matplotlib.lines.Line2D at 0x7f9c2bbc6910>

After a correction and rescaling (for human readability) the data will look more like other manufacturer’s devices
[8]:
ds["st"] = (ds.st - ds.st_zero) / 1e4
ds["ast"] = (ds.ast - ds.ast_zero) / 1e4
[9]:
ds.isel(time=0).st.plot(label="Stokes intensity")
ds.isel(time=0).ast.plot(label="anti-Stokes intensity")
plt.legend()
plt.axhline(c="k", lw=1)
plt.xlabel("")
plt.title("")
plt.ylim([-50, 500])
[9]:
(-50.0, 500.0)

[ ]: