From dd1c57de2ed7200d44026993dc555e6b4ef58f42 Mon Sep 17 00:00:00 2001
From: Hendrik Meuwese <117160147+HMEUW@users.noreply.github.com>
Date: Thu, 11 Jan 2024 08:44:37 +0100
Subject: [PATCH 1/3] First commit
First phase of programming. Function can import an existing file now. Next step to test also other files (with other frequency, without x-y-location); and tests.
---
hydropandas/io/soilinst.py | 129 +++++++++++++++++++++++++++++++++++++
hydropandas/observation.py | 40 ++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 hydropandas/io/soilinst.py
diff --git a/hydropandas/io/soilinst.py b/hydropandas/io/soilinst.py
new file mode 100644
index 00000000..0655d202
--- /dev/null
+++ b/hydropandas/io/soilinst.py
@@ -0,0 +1,129 @@
+import os
+import zipfile
+
+import numpy as np
+import pandas as pd
+
+
+def read_soilinst_file(
+ path,
+ transform_coords=True,
+):
+ """Read Soilinst file (XLE)
+
+ Parameters
+ ----------
+ path : str
+ path to Soilint file (.xle)
+ transform_coords : boolean
+ convert coordinates from WGS84 to RD
+
+ Returns
+ -------
+ df : pandas.DataFrame
+ DataFrame containing file content
+ metadata : dict, optional
+ dict containing metadata
+ """
+ from pyproj import Transformer
+
+ # open file
+ name = os.path.splitext(os.path.basename(path))[0]
+ if path.endswith(".xle"):
+ f = path
+ elif path.endswith(".zip"):
+ zf = zipfile.ZipFile(path)
+ f = zf.open("{}.xle".format(name))
+ else:
+ raise NotImplementedError(
+ "File type '{}' not supported!".format(os.path.splitext(path)[-1])
+ )
+
+ # read channel 1 data header
+ df_ch1_data_header = pd.read_xml(
+ path,
+ xpath="/Body_xle/Ch1_data_header"
+ )
+ series_ch1_data_header = df_ch1_data_header.T.iloc[:, 0]
+ colname_ch1 = series_ch1_data_header.Identification.lower() + \
+ '_' + series_ch1_data_header.Unit.lower()
+
+ # read channel 2 data header
+ df_ch2_data_header = pd.read_xml(
+ path,
+ xpath="/Body_xle/Ch2_data_header"
+ )
+ series_ch2_data_header = df_ch2_data_header.T.iloc[:, 0]
+ colname_ch2 = series_ch2_data_header.Identification.lower() + \
+ '_' + series_ch2_data_header.Unit.lower()
+
+ # read observations
+ df = pd.read_xml(
+ path,
+ xpath="/Body_xle/Data/Log",
+ )
+ df.rename(
+ columns={'ch1': colname_ch1,
+ 'ch2': colname_ch2},
+ inplace=True
+ )
+ if 'ms' in df.columns:
+ df['date_time'] = pd.to_datetime(
+ df['Date'] + ' ' + df['Time']) + \
+ pd.to_timedelta(df['ms'], unit='ms')
+ drop_cols = ['id', 'Date', 'Time', 'ms']
+ else:
+ df['date_time'] = pd.to_datetime(
+ df['Date'] + ' ' + df['Time'])
+ drop_cols = ['id', 'Date', 'Time']
+ df.set_index('date_time', inplace=True)
+
+ df.drop(columns=drop_cols, inplace=True)
+
+ # parse metadata into dict, per group in XLE file
+ metadata = {}
+ # read file info
+ df_file_info = pd.read_xml(
+ path,
+ xpath="/Body_xle/File_info"
+ )
+ dict_file_info = df_file_info.T.iloc[:, 0].to_dict()
+
+ # read instrument info
+ df_instrument_info = pd.read_xml(
+ path,
+ xpath="/Body_xle/Instrument_info"
+ )
+ dict_instrument_info = df_instrument_info.T.iloc[:, 0].to_dict()
+
+ # read instrument info
+ df_instrument_info_data_header = pd.read_xml(
+ path,
+ xpath="/Body_xle/Instrument_info_data_header"
+ )
+ dict_instrument_info_data_header = df_instrument_info_data_header.T.iloc[
+ :, 0].to_dict()
+
+ metadata = {**dict_file_info,
+ **dict_instrument_info,
+ **dict_instrument_info_data_header}
+
+ if transform_coords:
+ transformer = Transformer.from_crs("epsg:4326", "epsg:28992")
+ x, y = transformer.transform(metadata["Latitude"], metadata["Longtitude"])
+ x = np.round(x, 2)
+ y = np.round(y, 2)
+ else:
+ x = metadata["Latitude"]
+ y = metadata["Longtitude"]
+ metadata["x"] = x
+ metadata["y"] = y
+ metadata["filename"] = f
+ metadata["source"] = metadata["Created_by"]
+ metadata["name"] = name
+ metadata["monitoring_well"] = name
+ metadata["unit"] = series_ch1_data_header.Unit.lower()
+ metadata["metadata_available"] = True
+
+ return df, metadata
+
diff --git a/hydropandas/observation.py b/hydropandas/observation.py
index 730e3882..6963fd59 100644
--- a/hydropandas/observation.py
+++ b/hydropandas/observation.py
@@ -777,6 +777,46 @@ def from_pastastore(cls, pstore, libname, name, metadata_mapping=None):
return cls(data, meta=metadata, **kwargs)
+ @classmethod
+ def from_soilinst(
+ cls,
+ path,
+ transform_coords=True,
+ screen_bottom=None, screen_top=None, ground_level=None,
+ tube_nr=None, tube_top=None):
+ """Read data from Soilinst xle file.
+
+ Parameters
+ ----------
+ path : str
+ path to file (file can zip or xle)
+
+ """
+ from .io import soilinst
+
+ df, meta = soilinst.read_soilinst_file(
+ path,
+ transform_coords=transform_coords
+ )
+
+ return cls(
+ df,
+ name=meta.pop("name"),
+ x=meta.pop("x"),
+ y=meta.pop("y"),
+ filename=meta.pop("filename"),
+ source=meta.pop("source"),
+ unit=meta.pop("unit"),
+ screen_bottom=screen_bottom,
+ screen_top=screen_top,
+ ground_level=ground_level,
+ metadata_available=meta.pop("metadata_available"),
+ monitoring_well=meta.pop("monitoring_well"),
+ tube_nr=tube_nr,
+ tube_top=tube_top,
+ meta=meta,
+ )
+
class WaterQualityObs(Obs):
"""class for water quality ((grond)watersamenstelling) point
From 88d4d9b9d48313d1a7d111b3c989773640e269d8 Mon Sep 17 00:00:00 2001
From: Hendrik Meuwese <117160147+HMEUW@users.noreply.github.com>
Date: Thu, 11 Jan 2024 16:24:13 +0100
Subject: [PATCH 2/3] including test function
Update typo in brandname, should be Solinst (thanks @MattBrst)
---
hydropandas/io/{soilinst.py => solinst.py} | 63 +-
hydropandas/observation.py | 8 +-
.../WsNoo_dp366_BUB_20231222_slug1m.xle | 4164 +++++++++++++++++
.../example-10min-interval-via-laptop.xle | 229 +
tests/test_013_solinst.py | 54 +
5 files changed, 4490 insertions(+), 28 deletions(-)
rename hydropandas/io/{soilinst.py => solinst.py} (66%)
create mode 100644 tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle
create mode 100644 tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
create mode 100644 tests/test_013_solinst.py
diff --git a/hydropandas/io/soilinst.py b/hydropandas/io/solinst.py
similarity index 66%
rename from hydropandas/io/soilinst.py
rename to hydropandas/io/solinst.py
index 0655d202..a36fce86 100644
--- a/hydropandas/io/soilinst.py
+++ b/hydropandas/io/solinst.py
@@ -1,20 +1,22 @@
+import logging
import os
import zipfile
import numpy as np
import pandas as pd
+logger = logging.getLogger(__name__)
-def read_soilinst_file(
+def read_solinst_file(
path,
transform_coords=True,
):
- """Read Soilinst file (XLE)
+ """Read Solinst logger file (XLE)
Parameters
----------
path : str
- path to Soilint file (.xle)
+ path to Solinst file (.xle)
transform_coords : boolean
convert coordinates from WGS84 to RD
@@ -22,8 +24,8 @@ def read_soilinst_file(
-------
df : pandas.DataFrame
DataFrame containing file content
- metadata : dict, optional
- dict containing metadata
+ meta : dict, optional
+ dict containing meta
"""
from pyproj import Transformer
@@ -39,6 +41,8 @@ def read_soilinst_file(
"File type '{}' not supported!".format(os.path.splitext(path)[-1])
)
+ logger.info("reading -> {}".format(f))
+
# read channel 1 data header
df_ch1_data_header = pd.read_xml(
path,
@@ -80,8 +84,8 @@ def read_soilinst_file(
df.drop(columns=drop_cols, inplace=True)
- # parse metadata into dict, per group in XLE file
- metadata = {}
+ # parse meta into dict, per group in XLE file
+ meta = {}
# read file info
df_file_info = pd.read_xml(
path,
@@ -104,26 +108,37 @@ def read_soilinst_file(
dict_instrument_info_data_header = df_instrument_info_data_header.T.iloc[
:, 0].to_dict()
- metadata = {**dict_file_info,
+ meta = {**dict_file_info,
**dict_instrument_info,
**dict_instrument_info_data_header}
if transform_coords:
- transformer = Transformer.from_crs("epsg:4326", "epsg:28992")
- x, y = transformer.transform(metadata["Latitude"], metadata["Longtitude"])
- x = np.round(x, 2)
- y = np.round(y, 2)
+ # lat and lon has 0,000 when location is not supplied
+ # replace comma with point first
+ if isinstance(meta["Latitude"], str):
+ meta["Latitude"] = float(meta["Latitude"].replace(',', '.'))
+ if isinstance(meta["Longtitude"], str):
+ meta["Longtitude"] = float(meta["Longtitude"].replace(',', '.'))
+ if (meta["Latitude"] != 0) & (meta["Longtitude"] != 0):
+ transformer = Transformer.from_crs("epsg:4326", "epsg:28992")
+ x, y = transformer.transform(meta["Latitude"], meta["Longtitude"])
+ x = np.round(x, 2)
+ y = np.round(y, 2)
+ else:
+ logger.warning("file has no location included")
+ x = None
+ y = None
else:
- x = metadata["Latitude"]
- y = metadata["Longtitude"]
- metadata["x"] = x
- metadata["y"] = y
- metadata["filename"] = f
- metadata["source"] = metadata["Created_by"]
- metadata["name"] = name
- metadata["monitoring_well"] = name
- metadata["unit"] = series_ch1_data_header.Unit.lower()
- metadata["metadata_available"] = True
-
- return df, metadata
+ x = meta["Latitude"]
+ y = meta["Longtitude"]
+ meta["x"] = x
+ meta["y"] = y
+ meta["filename"] = f
+ meta["source"] = meta["Created_by"]
+ meta["name"] = name
+ meta["monitoring_well"] = name
+ meta["unit"] = series_ch1_data_header.Unit.lower()
+ meta["metadata_available"] = True
+
+ return df, meta
diff --git a/hydropandas/observation.py b/hydropandas/observation.py
index 6963fd59..36f6b157 100644
--- a/hydropandas/observation.py
+++ b/hydropandas/observation.py
@@ -778,13 +778,13 @@ def from_pastastore(cls, pstore, libname, name, metadata_mapping=None):
return cls(data, meta=metadata, **kwargs)
@classmethod
- def from_soilinst(
+ def from_solinst(
cls,
path,
transform_coords=True,
screen_bottom=None, screen_top=None, ground_level=None,
tube_nr=None, tube_top=None):
- """Read data from Soilinst xle file.
+ """Read data from Solinst xle file.
Parameters
----------
@@ -792,9 +792,9 @@ def from_soilinst(
path to file (file can zip or xle)
"""
- from .io import soilinst
+ from .io import solinst
- df, meta = soilinst.read_soilinst_file(
+ df, meta = solinst.read_solinst_file(
path,
transform_coords=transform_coords
)
diff --git a/tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle b/tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle
new file mode 100644
index 00000000..4124b10e
--- /dev/null
+++ b/tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle
@@ -0,0 +1,4164 @@
+
+
+
+
+
+2023/12/22
+
+
+iOS App Version 3.5.1
+iOS App Version 3.5.1
+iOS App Version 3.5.1
+Desktop Reader
+
+
+L5_LT
+M5
+Stopped
+2170536
+3.50600
+1378.03
+1970/01/01 00:00:00
+2
+1.006
+
+
+20231123
+slugtest
+51.4253
+3.91670
+12
+0
+
+Slate
+2
+0.000000
+
+2023/12/22 10:16:37
+2023/12/22 10:17:50
+587
+
+
+LEVEL
+m
+
+
+
+
+
+TEMPERATURE
+°C
+
+
+
+
+2023/12/22
+
+0
+10.2388
+15.462
+
+
+2023/12/22
+
+125
+10.2392
+15.462
+
+
+2023/12/22
+
+250
+10.2389
+15.463
+
+
+2023/12/22
+
+375
+10.2389
+15.464
+
+
+2023/12/22
+
+500
+10.2390
+15.464
+
+
+2023/12/22
+
+625
+10.2391
+15.466
+
+
+2023/12/22
+
+750
+10.2389
+15.464
+
+
+2023/12/22
+
+875
+10.2389
+15.463
+
+
+2023/12/22
+
+0
+10.2389
+15.466
+
+
+2023/12/22
+
+125
+10.2389
+15.466
+
+
+2023/12/22
+
+250
+10.2392
+15.466
+
+
+2023/12/22
+
+375
+10.2387
+15.466
+
+
+2023/12/22
+
+500
+10.2390
+15.468
+
+
+2023/12/22
+
+625
+10.2389
+15.467
+
+
+2023/12/22
+
+750
+10.2389
+15.468
+
+
+2023/12/22
+
+875
+10.2386
+15.465
+
+
+2023/12/22
+
+0
+10.2388
+15.466
+
+
+2023/12/22
+
+125
+10.2391
+15.467
+
+
+2023/12/22
+
+250
+10.2388
+15.468
+
+
+2023/12/22
+
+375
+10.2388
+15.466
+
+
+2023/12/22
+
+500
+10.2387
+15.468
+
+
+2023/12/22
+
+625
+10.2390
+15.469
+
+
+2023/12/22
+
+750
+10.2389
+15.467
+
+
+2023/12/22
+
+875
+10.2390
+15.468
+
+
+2023/12/22
+
+0
+10.2390
+15.467
+
+
+2023/12/22
+
+125
+10.2391
+15.469
+
+
+2023/12/22
+
+250
+10.2390
+15.470
+
+
+2023/12/22
+
+375
+10.2392
+15.470
+
+
+2023/12/22
+
+500
+10.2391
+15.471
+
+
+2023/12/22
+
+625
+10.2391
+15.469
+
+
+2023/12/22
+
+750
+10.2392
+15.471
+
+
+2023/12/22
+
+875
+10.2393
+15.471
+
+
+2023/12/22
+
+0
+10.2392
+15.471
+
+
+2023/12/22
+
+125
+10.2392
+15.471
+
+
+2023/12/22
+
+250
+10.2391
+15.469
+
+
+2023/12/22
+
+375
+10.2393
+15.470
+
+
+2023/12/22
+
+500
+10.2392
+15.472
+
+
+2023/12/22
+
+625
+10.2392
+15.471
+
+
+2023/12/22
+
+750
+10.2393
+15.474
+
+
+2023/12/22
+
+875
+10.2393
+15.473
+
+
+2023/12/22
+
+0
+10.2394
+15.473
+
+
+2023/12/22
+
+125
+10.2393
+15.473
+
+
+2023/12/22
+
+250
+10.2393
+15.473
+
+
+2023/12/22
+
+375
+10.2392
+15.474
+
+
+2023/12/22
+
+500
+10.2393
+15.474
+
+
+2023/12/22
+
+625
+10.2393
+15.476
+
+
+2023/12/22
+
+750
+10.2394
+15.476
+
+
+2023/12/22
+
+875
+10.2394
+15.474
+
+
+2023/12/22
+
+0
+10.2394
+15.475
+
+
+2023/12/22
+
+125
+10.2395
+15.478
+
+
+2023/12/22
+
+250
+10.2394
+15.475
+
+
+2023/12/22
+
+375
+10.2395
+15.474
+
+
+2023/12/22
+
+500
+10.2396
+15.476
+
+
+2023/12/22
+
+625
+10.2395
+15.477
+
+
+2023/12/22
+
+750
+10.2395
+15.477
+
+
+2023/12/22
+
+875
+10.2393
+15.476
+
+
+2023/12/22
+
+0
+10.2394
+15.477
+
+
+2023/12/22
+
+125
+10.2394
+15.479
+
+
+2023/12/22
+
+250
+10.2396
+15.478
+
+
+2023/12/22
+
+375
+10.2394
+15.478
+
+
+2023/12/22
+
+500
+10.2392
+15.478
+
+
+2023/12/22
+
+625
+10.2393
+15.478
+
+
+2023/12/22
+
+750
+10.2394
+15.481
+
+
+2023/12/22
+
+875
+10.2396
+15.478
+
+
+2023/12/22
+
+0
+10.2394
+15.479
+
+
+2023/12/22
+
+125
+10.2393
+15.479
+
+
+2023/12/22
+
+250
+10.2391
+15.481
+
+
+2023/12/22
+
+375
+10.2391
+15.481
+
+
+2023/12/22
+
+500
+10.2391
+15.479
+
+
+2023/12/22
+
+625
+10.2391
+15.481
+
+
+2023/12/22
+
+750
+10.2390
+15.479
+
+
+2023/12/22
+
+875
+10.2390
+15.481
+
+
+2023/12/22
+
+0
+10.2391
+15.483
+
+
+2023/12/22
+
+125
+10.2389
+15.482
+
+
+2023/12/22
+
+250
+10.2386
+15.482
+
+
+2023/12/22
+
+375
+10.2388
+15.482
+
+
+2023/12/22
+
+500
+10.2389
+15.483
+
+
+2023/12/22
+
+625
+10.2389
+15.483
+
+
+2023/12/22
+
+750
+10.2386
+15.483
+
+
+2023/12/22
+
+875
+10.2384
+15.485
+
+
+2023/12/22
+
+0
+10.2387
+15.485
+
+
+2023/12/22
+
+125
+10.2385
+15.484
+
+
+2023/12/22
+
+250
+10.2386
+15.485
+
+
+2023/12/22
+
+375
+10.2387
+15.485
+
+
+2023/12/22
+
+500
+10.2390
+15.485
+
+
+2023/12/22
+
+625
+10.2388
+15.485
+
+
+2023/12/22
+
+750
+10.2390
+15.487
+
+
+2023/12/22
+
+875
+10.2388
+15.487
+
+
+2023/12/22
+
+0
+10.2390
+15.488
+
+
+2023/12/22
+
+125
+10.2392
+15.486
+
+
+2023/12/22
+
+250
+10.2391
+15.486
+
+
+2023/12/22
+
+375
+10.2390
+15.489
+
+
+2023/12/22
+
+500
+10.2390
+15.488
+
+
+2023/12/22
+
+625
+10.2389
+15.486
+
+
+2023/12/22
+
+750
+10.2390
+15.488
+
+
+2023/12/22
+
+875
+10.2393
+15.488
+
+
+2023/12/22
+
+0
+10.2389
+15.491
+
+
+2023/12/22
+
+125
+10.2391
+15.491
+
+
+2023/12/22
+
+250
+10.2390
+15.490
+
+
+2023/12/22
+
+375
+10.2392
+15.489
+
+
+2023/12/22
+
+500
+10.2391
+15.489
+
+
+2023/12/22
+
+625
+10.2392
+15.490
+
+
+2023/12/22
+
+750
+10.2392
+15.492
+
+
+2023/12/22
+
+875
+10.2391
+15.490
+
+
+2023/12/22
+
+0
+10.2390
+15.491
+
+
+2023/12/22
+
+125
+10.2392
+15.491
+
+
+2023/12/22
+
+250
+10.2391
+15.491
+
+
+2023/12/22
+
+375
+10.2391
+15.491
+
+
+2023/12/22
+
+500
+10.2389
+15.493
+
+
+2023/12/22
+
+625
+10.2391
+15.493
+
+
+2023/12/22
+
+750
+10.2390
+15.492
+
+
+2023/12/22
+
+875
+10.2388
+15.494
+
+
+2023/12/22
+
+0
+10.2390
+15.494
+
+
+2023/12/22
+
+125
+10.2390
+15.496
+
+
+2023/12/22
+
+250
+10.2389
+15.495
+
+
+2023/12/22
+
+375
+10.2390
+15.496
+
+
+2023/12/22
+
+500
+10.2390
+15.495
+
+
+2023/12/22
+
+625
+10.2389
+15.496
+
+
+2023/12/22
+
+750
+10.2392
+15.495
+
+
+2023/12/22
+
+875
+10.2391
+15.494
+
+
+2023/12/22
+
+0
+10.2387
+15.497
+
+
+2023/12/22
+
+125
+10.2386
+15.495
+
+
+2023/12/22
+
+250
+10.2389
+15.497
+
+
+2023/12/22
+
+375
+10.2390
+15.498
+
+
+2023/12/22
+
+500
+10.2390
+15.497
+
+
+2023/12/22
+
+625
+10.2391
+15.497
+
+
+2023/12/22
+
+750
+10.2392
+15.497
+
+
+2023/12/22
+
+875
+10.2391
+15.498
+
+
+2023/12/22
+
+0
+10.2390
+15.498
+
+
+2023/12/22
+
+125
+10.2391
+15.499
+
+
+2023/12/22
+
+250
+10.2388
+15.499
+
+
+2023/12/22
+
+375
+10.2390
+15.500
+
+
+2023/12/22
+
+500
+10.2389
+15.498
+
+
+2023/12/22
+
+625
+10.2395
+15.501
+
+
+2023/12/22
+
+750
+10.2393
+15.501
+
+
+2023/12/22
+
+875
+10.2391
+15.500
+
+
+2023/12/22
+
+0
+10.2392
+15.502
+
+
+2023/12/22
+
+125
+10.2391
+15.502
+
+
+2023/12/22
+
+250
+10.2394
+15.503
+
+
+2023/12/22
+
+375
+10.2390
+15.501
+
+
+2023/12/22
+
+500
+10.2389
+15.504
+
+
+2023/12/22
+
+625
+10.2389
+15.501
+
+
+2023/12/22
+
+750
+10.2390
+15.502
+
+
+2023/12/22
+
+875
+10.2389
+15.503
+
+
+2023/12/22
+
+0
+10.2387
+15.504
+
+
+2023/12/22
+
+125
+10.2390
+15.504
+
+
+2023/12/22
+
+250
+10.2389
+15.504
+
+
+2023/12/22
+
+375
+10.2389
+15.503
+
+
+2023/12/22
+
+500
+10.2391
+15.504
+
+
+2023/12/22
+
+625
+10.2389
+15.504
+
+
+2023/12/22
+
+750
+10.2391
+15.503
+
+
+2023/12/22
+
+875
+10.2391
+15.507
+
+
+2023/12/22
+
+0
+10.2393
+15.508
+
+
+2023/12/22
+
+125
+10.2390
+15.507
+
+
+2023/12/22
+
+250
+10.2392
+15.506
+
+
+2023/12/22
+
+375
+10.2392
+15.506
+
+
+2023/12/22
+
+500
+10.2391
+15.509
+
+
+2023/12/22
+
+625
+10.2393
+15.506
+
+
+2023/12/22
+
+750
+10.2391
+15.507
+
+
+2023/12/22
+
+875
+10.2392
+15.508
+
+
+2023/12/22
+
+0
+10.2391
+15.509
+
+
+2023/12/22
+
+125
+10.2392
+15.509
+
+
+2023/12/22
+
+250
+10.2391
+15.510
+
+
+2023/12/22
+
+375
+10.2392
+15.509
+
+
+2023/12/22
+
+500
+10.2396
+15.511
+
+
+2023/12/22
+
+625
+10.2392
+15.510
+
+
+2023/12/22
+
+750
+10.2392
+15.509
+
+
+2023/12/22
+
+875
+10.2392
+15.510
+
+
+2023/12/22
+
+0
+10.2394
+15.511
+
+
+2023/12/22
+
+125
+10.2394
+15.512
+
+
+2023/12/22
+
+250
+10.2394
+15.513
+
+
+2023/12/22
+
+375
+10.2395
+15.512
+
+
+2023/12/22
+
+500
+10.2394
+15.511
+
+
+2023/12/22
+
+625
+10.2393
+15.512
+
+
+2023/12/22
+
+750
+10.2393
+15.511
+
+
+2023/12/22
+
+875
+10.2395
+15.512
+
+
+2023/12/22
+
+0
+10.2394
+15.514
+
+
+2023/12/22
+
+125
+10.2394
+15.514
+
+
+2023/12/22
+
+250
+10.2394
+15.513
+
+
+2023/12/22
+
+375
+10.2394
+15.515
+
+
+2023/12/22
+
+500
+10.2393
+15.514
+
+
+2023/12/22
+
+625
+10.2394
+15.515
+
+
+2023/12/22
+
+750
+10.2393
+15.514
+
+
+2023/12/22
+
+875
+10.2392
+15.514
+
+
+2023/12/22
+
+0
+10.2393
+15.517
+
+
+2023/12/22
+
+125
+10.2393
+15.516
+
+
+2023/12/22
+
+250
+10.2391
+15.518
+
+
+2023/12/22
+
+375
+10.2393
+15.518
+
+
+2023/12/22
+
+500
+10.2392
+15.517
+
+
+2023/12/22
+
+625
+10.2391
+15.517
+
+
+2023/12/22
+
+750
+10.2392
+15.517
+
+
+2023/12/22
+
+875
+10.2393
+15.518
+
+
+2023/12/22
+
+0
+10.2392
+15.517
+
+
+2023/12/22
+
+125
+10.2394
+15.519
+
+
+2023/12/22
+
+250
+10.2392
+15.520
+
+
+2023/12/22
+
+375
+10.2392
+15.520
+
+
+2023/12/22
+
+500
+10.2393
+15.521
+
+
+2023/12/22
+
+625
+10.2392
+15.519
+
+
+2023/12/22
+
+750
+10.2393
+15.522
+
+
+2023/12/22
+
+875
+10.2394
+15.521
+
+
+2023/12/22
+
+0
+10.2392
+15.520
+
+
+2023/12/22
+
+125
+10.2393
+15.521
+
+
+2023/12/22
+
+250
+10.2394
+15.521
+
+
+2023/12/22
+
+375
+10.2394
+15.522
+
+
+2023/12/22
+
+500
+10.2393
+15.521
+
+
+2023/12/22
+
+625
+10.2391
+15.524
+
+
+2023/12/22
+
+750
+10.2390
+15.522
+
+
+2023/12/22
+
+875
+10.2392
+15.525
+
+
+2023/12/22
+
+0
+10.2395
+15.526
+
+
+2023/12/22
+
+125
+10.2396
+15.523
+
+
+2023/12/22
+
+250
+10.2394
+15.524
+
+
+2023/12/22
+
+375
+10.2394
+15.526
+
+
+2023/12/22
+
+500
+10.2394
+15.524
+
+
+2023/12/22
+
+625
+10.2394
+15.524
+
+
+2023/12/22
+
+750
+10.2394
+15.525
+
+
+2023/12/22
+
+875
+10.2394
+15.527
+
+
+2023/12/22
+
+0
+10.2397
+15.525
+
+
+2023/12/22
+
+125
+10.2391
+15.526
+
+
+2023/12/22
+
+250
+10.2391
+15.527
+
+
+2023/12/22
+
+375
+10.2390
+15.526
+
+
+2023/12/22
+
+500
+10.2389
+15.526
+
+
+2023/12/22
+
+625
+10.2389
+15.528
+
+
+2023/12/22
+
+750
+10.2390
+15.527
+
+
+2023/12/22
+
+875
+10.2390
+15.529
+
+
+2023/12/22
+
+0
+10.2387
+15.528
+
+
+2023/12/22
+
+125
+10.2389
+15.530
+
+
+2023/12/22
+
+250
+10.2389
+15.530
+
+
+2023/12/22
+
+375
+10.2389
+15.528
+
+
+2023/12/22
+
+500
+10.2388
+15.530
+
+
+2023/12/22
+
+625
+10.2389
+15.529
+
+
+2023/12/22
+
+750
+10.2386
+15.531
+
+
+2023/12/22
+
+875
+10.2386
+15.532
+
+
+2023/12/22
+
+0
+10.2385
+15.532
+
+
+2023/12/22
+
+125
+10.2392
+15.532
+
+
+2023/12/22
+
+250
+10.2392
+15.532
+
+
+2023/12/22
+
+375
+10.2392
+15.532
+
+
+2023/12/22
+
+500
+10.2391
+15.534
+
+
+2023/12/22
+
+625
+10.2391
+15.531
+
+
+2023/12/22
+
+750
+10.2391
+15.533
+
+
+2023/12/22
+
+875
+10.2395
+15.532
+
+
+2023/12/22
+
+0
+10.2395
+15.534
+
+
+2023/12/22
+
+125
+10.2395
+15.533
+
+
+2023/12/22
+
+250
+10.2395
+15.535
+
+
+2023/12/22
+
+375
+10.2395
+15.536
+
+
+2023/12/22
+
+500
+10.2394
+15.536
+
+
+2023/12/22
+
+625
+10.2395
+15.535
+
+
+2023/12/22
+
+750
+10.2397
+15.536
+
+
+2023/12/22
+
+875
+10.2398
+15.535
+
+
+2023/12/22
+
+0
+10.2396
+15.537
+
+
+2023/12/22
+
+125
+10.2392
+15.537
+
+
+2023/12/22
+
+250
+10.2388
+15.536
+
+
+2023/12/22
+
+375
+10.2393
+15.537
+
+
+2023/12/22
+
+500
+10.2395
+15.537
+
+
+2023/12/22
+
+625
+10.2395
+15.536
+
+
+2023/12/22
+
+750
+10.2401
+15.538
+
+
+2023/12/22
+
+875
+10.2403
+15.538
+
+
+2023/12/22
+
+0
+10.2405
+15.538
+
+
+2023/12/22
+
+125
+10.2400
+15.539
+
+
+2023/12/22
+
+250
+10.2403
+15.540
+
+
+2023/12/22
+
+375
+10.2402
+15.539
+
+
+2023/12/22
+
+500
+10.2402
+15.540
+
+
+2023/12/22
+
+625
+10.2400
+15.540
+
+
+2023/12/22
+
+750
+10.2399
+15.541
+
+
+2023/12/22
+
+875
+10.2401
+15.540
+
+
+2023/12/22
+
+0
+10.2398
+15.541
+
+
+2023/12/22
+
+125
+10.2401
+15.541
+
+
+2023/12/22
+
+250
+10.2404
+15.542
+
+
+2023/12/22
+
+375
+10.2401
+15.541
+
+
+2023/12/22
+
+500
+10.2403
+15.542
+
+
+2023/12/22
+
+625
+10.2399
+15.542
+
+
+2023/12/22
+
+750
+10.2401
+15.542
+
+
+2023/12/22
+
+875
+10.2400
+15.542
+
+
+2023/12/22
+
+0
+10.2400
+15.544
+
+
+2023/12/22
+
+125
+10.2400
+15.544
+
+
+2023/12/22
+
+250
+10.2397
+15.544
+
+
+2023/12/22
+
+375
+10.2399
+15.546
+
+
+2023/12/22
+
+500
+10.2399
+15.545
+
+
+2023/12/22
+
+625
+10.2398
+15.545
+
+
+2023/12/22
+
+750
+10.2398
+15.546
+
+
+2023/12/22
+
+875
+10.2397
+15.546
+
+
+2023/12/22
+
+0
+10.2395
+15.546
+
+
+2023/12/22
+
+125
+10.2396
+15.545
+
+
+2023/12/22
+
+250
+10.2397
+15.547
+
+
+2023/12/22
+
+375
+10.2397
+15.546
+
+
+2023/12/22
+
+500
+10.2396
+15.548
+
+
+2023/12/22
+
+625
+10.2397
+15.549
+
+
+2023/12/22
+
+750
+10.2397
+15.547
+
+
+2023/12/22
+
+875
+10.2397
+15.549
+
+
+2023/12/22
+
+0
+10.2395
+15.548
+
+
+2023/12/22
+
+125
+10.2395
+15.549
+
+
+2023/12/22
+
+250
+10.2395
+15.548
+
+
+2023/12/22
+
+375
+10.2398
+15.550
+
+
+2023/12/22
+
+500
+10.2397
+15.550
+
+
+2023/12/22
+
+625
+10.2397
+15.550
+
+
+2023/12/22
+
+750
+10.2398
+15.551
+
+
+2023/12/22
+
+875
+10.2396
+15.549
+
+
+2023/12/22
+
+0
+10.2398
+15.552
+
+
+2023/12/22
+
+125
+10.2398
+15.552
+
+
+2023/12/22
+
+250
+10.2396
+15.552
+
+
+2023/12/22
+
+375
+10.2396
+15.552
+
+
+2023/12/22
+
+500
+10.2397
+15.552
+
+
+2023/12/22
+
+625
+10.2397
+15.552
+
+
+2023/12/22
+
+750
+10.2398
+15.552
+
+
+2023/12/22
+
+875
+10.2397
+15.552
+
+
+2023/12/22
+
+0
+10.2398
+15.553
+
+
+2023/12/22
+
+125
+10.2399
+15.553
+
+
+2023/12/22
+
+250
+10.2397
+15.554
+
+
+2023/12/22
+
+375
+10.2397
+15.554
+
+
+2023/12/22
+
+500
+10.2398
+15.555
+
+
+2023/12/22
+
+625
+10.2398
+15.553
+
+
+2023/12/22
+
+750
+10.2396
+15.556
+
+
+2023/12/22
+
+875
+10.2396
+15.555
+
+
+2023/12/22
+
+0
+10.2396
+15.554
+
+
+2023/12/22
+
+125
+10.2398
+15.555
+
+
+2023/12/22
+
+250
+10.2398
+15.556
+
+
+2023/12/22
+
+375
+10.2396
+15.556
+
+
+2023/12/22
+
+500
+10.2395
+15.554
+
+
+2023/12/22
+
+625
+10.2402
+15.559
+
+
+2023/12/22
+
+750
+10.2403
+15.559
+
+
+2023/12/22
+
+875
+10.2400
+15.558
+
+
+2023/12/22
+
+0
+10.2400
+15.557
+
+
+2023/12/22
+
+125
+10.2398
+15.557
+
+
+2023/12/22
+
+250
+10.2398
+15.557
+
+
+2023/12/22
+
+375
+10.2399
+15.558
+
+
+2023/12/22
+
+500
+10.2399
+15.558
+
+
+2023/12/22
+
+625
+10.2399
+15.558
+
+
+2023/12/22
+
+750
+10.2396
+15.560
+
+
+2023/12/22
+
+875
+10.2398
+15.560
+
+
+2023/12/22
+
+0
+10.2397
+15.559
+
+
+2023/12/22
+
+125
+10.2399
+15.559
+
+
+2023/12/22
+
+250
+10.2399
+15.561
+
+
+2023/12/22
+
+375
+10.2398
+15.561
+
+
+2023/12/22
+
+500
+10.2399
+15.562
+
+
+2023/12/22
+
+625
+10.2398
+15.562
+
+
+2023/12/22
+
+750
+10.2397
+15.561
+
+
+2023/12/22
+
+875
+10.2398
+15.562
+
+
+2023/12/22
+
+0
+10.2397
+15.563
+
+
+2023/12/22
+
+125
+10.2399
+15.562
+
+
+2023/12/22
+
+250
+10.2399
+15.563
+
+
+2023/12/22
+
+375
+10.2399
+15.562
+
+
+2023/12/22
+
+500
+10.2400
+15.562
+
+
+2023/12/22
+
+625
+10.2397
+15.564
+
+
+2023/12/22
+
+750
+10.2399
+15.563
+
+
+2023/12/22
+
+875
+10.2399
+15.565
+
+
+2023/12/22
+
+0
+10.2399
+15.562
+
+
+2023/12/22
+
+125
+10.2400
+15.562
+
+
+2023/12/22
+
+250
+10.2398
+15.565
+
+
+2023/12/22
+
+375
+10.2398
+15.564
+
+
+2023/12/22
+
+500
+10.2398
+15.564
+
+
+2023/12/22
+
+625
+10.2398
+15.565
+
+
+2023/12/22
+
+750
+10.2399
+15.565
+
+
+2023/12/22
+
+875
+10.2400
+15.566
+
+
+2023/12/22
+
+0
+10.2399
+15.565
+
+
+2023/12/22
+
+125
+10.2399
+15.564
+
+
+2023/12/22
+
+250
+10.2399
+15.564
+
+
+2023/12/22
+
+375
+10.2397
+15.565
+
+
+2023/12/22
+
+500
+10.2397
+15.566
+
+
+2023/12/22
+
+625
+10.2397
+15.562
+
+
+2023/12/22
+
+750
+10.2397
+15.566
+
+
+2023/12/22
+
+875
+10.2398
+15.567
+
+
+2023/12/22
+
+0
+10.2398
+15.566
+
+
+2023/12/22
+
+125
+10.2399
+15.568
+
+
+2023/12/22
+
+250
+10.2397
+15.567
+
+
+2023/12/22
+
+375
+10.2396
+15.567
+
+
+2023/12/22
+
+500
+10.2397
+15.568
+
+
+2023/12/22
+
+625
+10.2398
+15.567
+
+
+2023/12/22
+
+750
+10.2394
+15.567
+
+
+2023/12/22
+
+875
+10.2396
+15.569
+
+
+2023/12/22
+
+0
+10.2395
+15.568
+
+
+2023/12/22
+
+125
+10.2395
+15.569
+
+
+2023/12/22
+
+250
+10.2397
+15.567
+
+
+2023/12/22
+
+375
+10.2396
+15.565
+
+
+2023/12/22
+
+500
+10.2396
+15.568
+
+
+2023/12/22
+
+625
+10.2395
+15.566
+
+
+2023/12/22
+
+750
+10.2395
+15.570
+
+
+2023/12/22
+
+875
+10.2395
+15.568
+
+
+2023/12/22
+
+0
+10.2395
+15.568
+
+
+2023/12/22
+
+125
+10.2396
+15.569
+
+
+2023/12/22
+
+250
+10.2395
+15.568
+
+
+2023/12/22
+
+375
+10.2395
+15.568
+
+
+2023/12/22
+
+500
+10.2394
+15.570
+
+
+2023/12/22
+
+625
+10.2395
+15.569
+
+
+2023/12/22
+
+750
+10.2391
+15.572
+
+
+2023/12/22
+
+875
+10.2394
+15.570
+
+
+2023/12/22
+
+0
+10.2395
+15.568
+
+
+2023/12/22
+
+125
+10.2394
+15.569
+
+
+2023/12/22
+
+250
+10.2393
+15.571
+
+
+2023/12/22
+
+375
+10.2393
+15.569
+
+
+2023/12/22
+
+500
+10.2395
+15.569
+
+
+2023/12/22
+
+625
+10.2397
+15.570
+
+
+2023/12/22
+
+750
+10.2394
+15.569
+
+
+2023/12/22
+
+875
+10.2396
+15.571
+
+
+2023/12/22
+
+0
+10.2396
+15.571
+
+
+2023/12/22
+
+125
+10.2396
+15.571
+
+
+2023/12/22
+
+250
+10.2398
+15.573
+
+
+2023/12/22
+
+375
+10.2395
+15.571
+
+
+2023/12/22
+
+500
+10.2395
+15.571
+
+
+2023/12/22
+
+625
+10.2394
+15.570
+
+
+2023/12/22
+
+750
+10.2393
+15.571
+
+
+2023/12/22
+
+875
+10.2393
+15.571
+
+
+2023/12/22
+
+0
+10.2396
+15.571
+
+
+2023/12/22
+
+125
+10.2395
+15.571
+
+
+2023/12/22
+
+250
+10.2395
+15.571
+
+
+2023/12/22
+
+375
+10.2394
+15.571
+
+
+2023/12/22
+
+500
+10.2394
+15.572
+
+
+2023/12/22
+
+625
+10.2396
+15.573
+
+
+2023/12/22
+
+750
+10.2395
+15.573
+
+
+2023/12/22
+
+875
+10.2395
+15.572
+
+
+2023/12/22
+
+0
+10.2396
+15.572
+
+
+2023/12/22
+
+125
+10.2396
+15.573
+
+
+2023/12/22
+
+250
+10.2395
+15.572
+
+
+2023/12/22
+
+375
+10.2397
+15.573
+
+
+2023/12/22
+
+500
+10.2400
+15.571
+
+
+2023/12/22
+
+625
+10.2400
+15.574
+
+
+2023/12/22
+
+750
+10.2398
+15.571
+
+
+2023/12/22
+
+875
+10.2397
+15.574
+
+
+2023/12/22
+
+0
+10.2400
+15.573
+
+
+2023/12/22
+
+125
+10.2396
+15.573
+
+
+2023/12/22
+
+250
+10.2398
+15.573
+
+
+2023/12/22
+
+375
+10.2398
+15.574
+
+
+2023/12/22
+
+500
+10.2397
+15.574
+
+
+2023/12/22
+
+625
+10.2397
+15.574
+
+
+2023/12/22
+
+750
+10.2398
+15.574
+
+
+2023/12/22
+
+875
+10.2397
+15.574
+
+
+2023/12/22
+
+0
+10.2397
+15.573
+
+
+2023/12/22
+
+125
+10.2398
+15.575
+
+
+2023/12/22
+
+250
+10.2396
+15.573
+
+
+2023/12/22
+
+375
+10.2397
+15.573
+
+
+2023/12/22
+
+500
+10.2397
+15.575
+
+
+2023/12/22
+
+625
+10.2399
+15.574
+
+
+2023/12/22
+
+750
+10.2397
+15.573
+
+
+2023/12/22
+
+875
+10.2397
+15.575
+
+
+2023/12/22
+
+0
+10.2397
+15.575
+
+
+2023/12/22
+
+125
+10.2396
+15.576
+
+
+2023/12/22
+
+250
+10.2396
+15.576
+
+
+2023/12/22
+
+375
+10.2400
+15.576
+
+
+2023/12/22
+
+500
+10.2398
+15.576
+
+
+2023/12/22
+
+625
+10.2398
+15.576
+
+
+2023/12/22
+
+750
+10.2400
+15.576
+
+
+2023/12/22
+
+875
+10.2400
+15.577
+
+
+2023/12/22
+
+0
+10.2401
+15.576
+
+
+2023/12/22
+
+125
+10.2400
+15.575
+
+
+2023/12/22
+
+250
+10.2402
+15.575
+
+
+2023/12/22
+
+375
+10.2402
+15.576
+
+
+2023/12/22
+
+500
+10.2401
+15.577
+
+
+2023/12/22
+
+625
+10.2401
+15.577
+
+
+2023/12/22
+
+750
+10.2401
+15.577
+
+
+2023/12/22
+
+875
+10.2402
+15.576
+
+
+2023/12/22
+
+0
+10.2400
+15.577
+
+
+2023/12/22
+
+125
+10.2401
+15.577
+
+
+2023/12/22
+
+250
+10.2400
+15.576
+
+
+2023/12/22
+
+375
+10.2398
+15.577
+
+
+2023/12/22
+
+500
+10.2399
+15.577
+
+
+2023/12/22
+
+625
+10.2400
+15.576
+
+
+2023/12/22
+
+750
+10.2397
+15.578
+
+
+2023/12/22
+
+875
+10.2394
+15.578
+
+
+2023/12/22
+
+0
+10.2392
+15.578
+
+
+2023/12/22
+
+125
+10.2394
+15.577
+
+
+2023/12/22
+
+250
+10.2395
+15.578
+
+
+2023/12/22
+
+375
+10.2393
+15.577
+
+
+2023/12/22
+
+500
+10.2397
+15.578
+
+
+2023/12/22
+
+625
+10.2400
+15.576
+
+
+2023/12/22
+
+750
+10.2402
+15.579
+
+
+2023/12/22
+
+875
+10.2400
+15.577
+
+
+2023/12/22
+
+0
+10.2401
+15.576
+
+
+2023/12/22
+
+125
+10.2400
+15.578
+
+
+2023/12/22
+
+250
+10.2400
+15.578
+
+
+2023/12/22
+
+375
+10.2397
+15.578
+
+
+2023/12/22
+
+500
+10.2394
+15.579
+
+
+2023/12/22
+
+625
+10.2394
+15.578
+
+
+2023/12/22
+
+750
+10.2396
+15.581
+
+
+2023/12/22
+
+875
+10.2398
+15.578
+
+
+2023/12/22
+
+0
+10.2399
+15.578
+
+
+2023/12/22
+
+125
+10.2398
+15.577
+
+
+2023/12/22
+
+250
+10.2400
+15.580
+
+
+2023/12/22
+
+375
+10.2401
+15.579
+
+
+2023/12/22
+
+500
+10.2402
+15.579
+
+
+2023/12/22
+
+625
+10.2401
+15.578
+
+
+2023/12/22
+
+750
+10.2400
+15.577
+
+
+2023/12/22
+
+875
+10.2399
+15.579
+
+
+2023/12/22
+
+0
+10.2397
+15.579
+
+
+2023/12/22
+
+125
+10.2396
+15.579
+
+
+2023/12/22
+
+250
+10.2398
+15.581
+
+
+2023/12/22
+
+375
+10.2397
+15.581
+
+
+2023/12/22
+
+500
+10.2396
+15.578
+
+
+2023/12/22
+
+625
+10.2397
+15.578
+
+
+2023/12/22
+
+750
+10.2397
+15.579
+
+
+2023/12/22
+
+875
+10.2396
+15.580
+
+
+2023/12/22
+
+0
+10.2395
+15.579
+
+
+2023/12/22
+
+125
+10.2399
+15.580
+
+
+2023/12/22
+
+250
+10.2399
+15.581
+
+
+2023/12/22
+
+375
+10.2400
+15.580
+
+
+2023/12/22
+
+500
+10.2399
+15.581
+
+
+2023/12/22
+
+625
+10.2401
+15.580
+
+
+2023/12/22
+
+750
+10.2402
+15.580
+
+
+2023/12/22
+
+875
+10.2404
+15.581
+
+
+2023/12/22
+
+0
+10.2407
+15.581
+
+
+2023/12/22
+
+125
+10.2405
+15.581
+
+
+2023/12/22
+
+250
+10.2404
+15.581
+
+
+2023/12/22
+
+375
+10.2404
+15.581
+
+
+2023/12/22
+
+500
+10.2406
+15.580
+
+
+2023/12/22
+
+625
+10.2410
+15.580
+
+
+2023/12/22
+
+750
+10.2409
+15.579
+
+
+2023/12/22
+
+875
+10.2409
+15.579
+
+
+2023/12/22
+
+0
+10.2408
+15.580
+
+
+2023/12/22
+
+125
+10.2414
+15.581
+
+
+2023/12/22
+
+250
+10.2415
+15.579
+
+
+2023/12/22
+
+375
+10.2415
+15.580
+
+
+2023/12/22
+
+500
+10.2417
+15.579
+
+
+2023/12/22
+
+625
+10.2418
+15.580
+
+
+2023/12/22
+
+750
+10.2414
+15.579
+
+
+2023/12/22
+
+875
+10.2415
+15.580
+
+
+2023/12/22
+
+0
+10.2418
+15.579
+
+
+2023/12/22
+
+125
+10.2416
+15.580
+
+
+2023/12/22
+
+250
+10.2415
+15.580
+
+
+2023/12/22
+
+375
+10.2418
+15.581
+
+
+2023/12/22
+
+500
+10.2420
+15.580
+
+
+2023/12/22
+
+625
+10.2419
+15.581
+
+
+2023/12/22
+
+750
+10.2420
+15.580
+
+
+2023/12/22
+
+875
+10.2417
+15.580
+
+
+2023/12/22
+
+0
+10.2416
+15.581
+
+
+2023/12/22
+
+125
+10.2413
+15.577
+
+
+2023/12/22
+
+250
+10.2415
+15.582
+
+
+2023/12/22
+
+375
+10.2415
+15.580
+
+
+2023/12/22
+
+500
+10.2413
+15.580
+
+
+2023/12/22
+
+625
+10.2414
+15.578
+
+
+2023/12/22
+
+750
+10.2412
+15.581
+
+
+2023/12/22
+
+875
+10.2411
+15.578
+
+
+2023/12/22
+
+0
+10.2408
+15.580
+
+
+2023/12/22
+
+125
+10.2407
+15.579
+
+
+2023/12/22
+
+250
+10.2404
+15.578
+
+
+2023/12/22
+
+375
+10.2404
+15.578
+
+
+2023/12/22
+
+500
+10.2401
+15.578
+
+
+2023/12/22
+
+625
+10.2402
+15.579
+
+
+2023/12/22
+
+750
+10.2400
+15.578
+
+
+2023/12/22
+
+875
+10.2402
+15.579
+
+
+2023/12/22
+
+0
+10.2407
+15.581
+
+
+2023/12/22
+
+125
+10.2448
+15.579
+
+
+2023/12/22
+
+250
+10.2389
+15.579
+
+
+2023/12/22
+
+375
+10.2394
+15.579
+
+
+2023/12/22
+
+500
+10.2397
+15.578
+
+
+2023/12/22
+
+625
+10.2398
+15.580
+
+
+2023/12/22
+
+750
+10.2399
+15.578
+
+
+2023/12/22
+
+875
+10.2397
+15.579
+
+
+2023/12/22
+
+0
+10.2398
+15.578
+
+
+2023/12/22
+
+125
+10.2398
+15.580
+
+
+2023/12/22
+
+250
+10.2397
+15.578
+
+
+2023/12/22
+
+375
+10.2396
+15.578
+
+
+2023/12/22
+
+500
+10.2397
+15.579
+
+
+2023/12/22
+
+625
+10.2396
+15.576
+
+
+2023/12/22
+
+750
+10.2394
+15.579
+
+
+2023/12/22
+
+875
+10.2395
+15.577
+
+
+2023/12/22
+
+0
+10.2396
+15.579
+
+
+2023/12/22
+
+125
+10.2394
+15.577
+
+
+2023/12/22
+
+250
+10.2394
+15.576
+
+
+2023/12/22
+
+375
+10.2395
+15.577
+
+
+2023/12/22
+
+500
+10.2394
+15.578
+
+
+2023/12/22
+
+625
+10.2392
+15.577
+
+
+2023/12/22
+
+750
+10.2392
+15.578
+
+
+2023/12/22
+
+875
+10.2390
+15.578
+
+
+2023/12/22
+
+0
+10.2394
+15.578
+
+
+2023/12/22
+
+125
+10.2392
+15.578
+
+
+2023/12/22
+
+250
+10.2391
+15.578
+
+
+2023/12/22
+
+375
+10.2391
+15.575
+
+
+2023/12/22
+
+500
+10.2392
+15.579
+
+
+2023/12/22
+
+625
+10.2392
+15.577
+
+
+2023/12/22
+
+750
+10.2390
+15.577
+
+
+2023/12/22
+
+875
+10.2390
+15.576
+
+
+2023/12/22
+
+0
+10.2390
+15.575
+
+
+2023/12/22
+
+125
+10.2391
+15.575
+
+
+2023/12/22
+
+250
+10.2392
+15.577
+
+
+2023/12/22
+
+375
+10.2393
+15.575
+
+
+2023/12/22
+
+500
+10.2391
+15.578
+
+
+2023/12/22
+
+625
+10.2393
+15.577
+
+
+2023/12/22
+
+750
+10.2391
+15.576
+
+
+2023/12/22
+
+875
+10.2392
+15.577
+
+
+2023/12/22
+
+0
+10.2392
+15.577
+
+
+2023/12/22
+
+125
+10.2391
+15.576
+
+
+2023/12/22
+
+250
+10.2392
+15.576
+
+
+2023/12/22
+
+375
+10.2391
+15.576
+
+
+2023/12/22
+
+500
+10.2391
+15.577
+
+
+2023/12/22
+
+625
+10.2391
+15.575
+
+
+2023/12/22
+
+750
+10.2391
+15.576
+
+
+2023/12/22
+
+875
+10.2392
+15.577
+
+
+2023/12/22
+
+0
+10.2389
+15.578
+
+
+2023/12/22
+
+125
+10.2387
+15.576
+
+
+2023/12/22
+
+250
+10.2390
+15.578
+
+
+
diff --git a/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle b/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
new file mode 100644
index 00000000..5178224b
--- /dev/null
+++ b/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
@@ -0,0 +1,229 @@
+
+
+
+
+
+ 2024/01/11
+
+
+ Version 4.6.3
+ Version 4.6.3
+ PC Software 4.6.2
+ Desktop Reader (567751)
+
+
+ L5_LT
+ M5
+ Stopped
+ 2170536
+ 3,59600
+ 1372,54
+ 2
+ 1,006
+
+
+ 20231123
+ slugtest
+ 0,000
+ 0,000
+ 60000
+ 0
+
+ Slate
+ 1
+ 0,000000
+
+ 2024/01/11 11:00:00
+ 2024/01/11 15:00:00
+ 25
+
+
+ LEVEL
+ m
+
+
+
+
+
+ TEMPERATURE
+ °C
+
+
+
+
+ 2024/01/11
+
+ 0
+ 10.5288
+ 21.879
+
+
+ 2024/01/11
+
+ 0
+ 10.5300
+ 21.585
+
+
+ 2024/01/11
+
+ 0
+ 10.5319
+ 21.403
+
+
+ 2024/01/11
+
+ 0
+ 10.5343
+ 21.285
+
+
+ 2024/01/11
+
+ 0
+ 10.5339
+ 21.205
+
+
+ 2024/01/11
+
+ 0
+ 10.5329
+ 21.177
+
+
+ 2024/01/11
+
+ 0
+ 10.5335
+ 21.204
+
+
+ 2024/01/11
+
+ 0
+ 10.5323
+ 21.258
+
+
+ 2024/01/11
+
+ 0
+ 10.5319
+ 21.311
+
+
+ 2024/01/11
+
+ 0
+ 10.5323
+ 21.429
+
+
+ 2024/01/11
+
+ 0
+ 10.5320
+ 21.474
+
+
+ 2024/01/11
+
+ 0
+ 10.5333
+ 21.469
+
+
+ 2024/01/11
+
+ 0
+ 10.5341
+ 21.424
+
+
+ 2024/01/11
+
+ 0
+ 10.5350
+ 21.394
+
+
+ 2024/01/11
+
+ 0
+ 10.5344
+ 21.412
+
+
+ 2024/01/11
+
+ 0
+ 10.5336
+ 21.410
+
+
+ 2024/01/11
+
+ 0
+ 10.5341
+ 21.429
+
+
+ 2024/01/11
+
+ 0
+ 10.5346
+ 21.452
+
+
+ 2024/01/11
+
+ 0
+ 10.5331
+ 21.444
+
+
+ 2024/01/11
+
+ 0
+ 10.5311
+ 21.399
+
+
+ 2024/01/11
+
+ 0
+ 10.5293
+ 21.337
+
+
+ 2024/01/11
+
+ 0
+ 10.5292
+ 21.270
+
+
+ 2024/01/11
+
+ 0
+ 10.5282
+ 21.205
+
+
+ 2024/01/11
+
+ 0
+ 10.5277
+ 21.170
+
+
+ 2024/01/11
+
+ 0
+ 10.5281
+ 21.176
+
+
+
diff --git a/tests/test_013_solinst.py b/tests/test_013_solinst.py
new file mode 100644
index 00000000..d45f5999
--- /dev/null
+++ b/tests/test_013_solinst.py
@@ -0,0 +1,54 @@
+# %%
+import logging
+
+from hydropandas.io import solinst
+from hydropandas import observation
+
+logging.basicConfig(level=logging.DEBUG)
+
+
+# %% test observations
+
+
+def test_read_solinst_file_obs():
+ # observation of slugtest, 8 observations per second
+ df, meta = solinst.read_solinst_file(
+ "./tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle",
+ )
+
+ assert len(df) == 587, "Dataframe should have 587 readings"
+
+def test_read_solinst_file_meta_has_location():
+ # observation of slugtest, created via iOs app, location included by app
+ df, meta = solinst.read_solinst_file(
+ "./tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle",
+ )
+
+ assert meta['x'] == 52730.58, "x coordinate should be 52730.58"
+
+def test_read_solinst_file_meta_without_location():
+ # example observation created via desktop, location not included
+ df, meta = solinst.read_solinst_file(
+ "./tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle",
+ )
+
+ assert meta['x'] is None, "x coordinate not available"
+
+def test_read_solinst_file_with_manual_meta():
+ # manual metadata about levels provided
+ screen_bottom = -10,
+ screen_top = -5,
+ ground_level = -1,
+ tube_nr = 1,
+ tube_top = -0.5
+
+ oc = observation.GroundwaterObs.from_solinst(
+ "./tests/data/2024-solinst-test/WsNoo_dp366_BUB_20231222_slug1m.xle",
+ screen_bottom=screen_bottom,
+ screen_top=screen_top,
+ ground_level=ground_level,
+ tube_nr=tube_nr,
+ tube_top=tube_top
+ )
+
+ assert oc.tube_top == tube_top, "tube_top should be in oc"
From 57c6cefde44f74a72322d388bb06dd23aeab2635 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dav=C3=ADd=20Brakenhoff?=
Date: Fri, 12 Jan 2024 11:44:34 +0100
Subject: [PATCH 3/3] minor changes on review - black formatting - move import
to top - zip one test file to test zip file read
---
hydropandas/io/solinst.py | 85 +++----
hydropandas/observation.py | 21 +-
.../example-10min-interval-via-laptop.xle | 229 ------------------
.../example-10min-interval-via-laptop.zip | Bin 0 -> 1329 bytes
tests/test_013_solinst.py | 29 ++-
5 files changed, 66 insertions(+), 298 deletions(-)
delete mode 100644 tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
create mode 100644 tests/data/2024-solinst-test/example-10min-interval-via-laptop.zip
diff --git a/hydropandas/io/solinst.py b/hydropandas/io/solinst.py
index a36fce86..90d31212 100644
--- a/hydropandas/io/solinst.py
+++ b/hydropandas/io/solinst.py
@@ -4,9 +4,11 @@
import numpy as np
import pandas as pd
+from pyproj import Transformer
logger = logging.getLogger(__name__)
+
def read_solinst_file(
path,
transform_coords=True,
@@ -27,7 +29,6 @@ def read_solinst_file(
meta : dict, optional
dict containing meta
"""
- from pyproj import Transformer
# open file
name = os.path.splitext(os.path.basename(path))[0]
@@ -44,82 +45,75 @@ def read_solinst_file(
logger.info("reading -> {}".format(f))
# read channel 1 data header
- df_ch1_data_header = pd.read_xml(
- path,
- xpath="/Body_xle/Ch1_data_header"
- )
+ df_ch1_data_header = pd.read_xml(path, xpath="/Body_xle/Ch1_data_header")
series_ch1_data_header = df_ch1_data_header.T.iloc[:, 0]
- colname_ch1 = series_ch1_data_header.Identification.lower() + \
- '_' + series_ch1_data_header.Unit.lower()
+ colname_ch1 = (
+ series_ch1_data_header.Identification.lower()
+ + "_"
+ + series_ch1_data_header.Unit.lower()
+ )
# read channel 2 data header
- df_ch2_data_header = pd.read_xml(
- path,
- xpath="/Body_xle/Ch2_data_header"
- )
+ df_ch2_data_header = pd.read_xml(path, xpath="/Body_xle/Ch2_data_header")
series_ch2_data_header = df_ch2_data_header.T.iloc[:, 0]
- colname_ch2 = series_ch2_data_header.Identification.lower() + \
- '_' + series_ch2_data_header.Unit.lower()
+ colname_ch2 = (
+ series_ch2_data_header.Identification.lower()
+ + "_"
+ + series_ch2_data_header.Unit.lower()
+ )
# read observations
df = pd.read_xml(
path,
xpath="/Body_xle/Data/Log",
- )
- df.rename(
- columns={'ch1': colname_ch1,
- 'ch2': colname_ch2},
- inplace=True
- )
- if 'ms' in df.columns:
- df['date_time'] = pd.to_datetime(
- df['Date'] + ' ' + df['Time']) + \
- pd.to_timedelta(df['ms'], unit='ms')
- drop_cols = ['id', 'Date', 'Time', 'ms']
+ )
+ df.rename(columns={"ch1": colname_ch1, "ch2": colname_ch2}, inplace=True)
+ if "ms" in df.columns:
+ df["date_time"] = pd.to_datetime(
+ df["Date"] + " " + df["Time"]
+ ) + pd.to_timedelta(df["ms"], unit="ms")
+ drop_cols = ["id", "Date", "Time", "ms"]
else:
- df['date_time'] = pd.to_datetime(
- df['Date'] + ' ' + df['Time'])
- drop_cols = ['id', 'Date', 'Time']
- df.set_index('date_time', inplace=True)
+ df["date_time"] = pd.to_datetime(df["Date"] + " " + df["Time"])
+ drop_cols = ["id", "Date", "Time"]
+ df.set_index("date_time", inplace=True)
df.drop(columns=drop_cols, inplace=True)
# parse meta into dict, per group in XLE file
meta = {}
# read file info
- df_file_info = pd.read_xml(
- path,
- xpath="/Body_xle/File_info"
- )
+ df_file_info = pd.read_xml(path, xpath="/Body_xle/File_info")
dict_file_info = df_file_info.T.iloc[:, 0].to_dict()
# read instrument info
- df_instrument_info = pd.read_xml(
- path,
- xpath="/Body_xle/Instrument_info"
- )
+ df_instrument_info = pd.read_xml(path, xpath="/Body_xle/Instrument_info")
dict_instrument_info = df_instrument_info.T.iloc[:, 0].to_dict()
# read instrument info
df_instrument_info_data_header = pd.read_xml(
- path,
- xpath="/Body_xle/Instrument_info_data_header"
- )
+ path, xpath="/Body_xle/Instrument_info_data_header"
+ )
dict_instrument_info_data_header = df_instrument_info_data_header.T.iloc[
- :, 0].to_dict()
+ :, 0
+ ].to_dict()
- meta = {**dict_file_info,
- **dict_instrument_info,
- **dict_instrument_info_data_header}
+ meta = {
+ **dict_file_info,
+ **dict_instrument_info,
+ **dict_instrument_info_data_header,
+ }
if transform_coords:
# lat and lon has 0,000 when location is not supplied
# replace comma with point first
if isinstance(meta["Latitude"], str):
- meta["Latitude"] = float(meta["Latitude"].replace(',', '.'))
+ meta["Latitude"] = float(meta["Latitude"].replace(",", "."))
if isinstance(meta["Longtitude"], str):
- meta["Longtitude"] = float(meta["Longtitude"].replace(',', '.'))
+ meta["Longtitude"] = float(meta["Longtitude"].replace(",", "."))
if (meta["Latitude"] != 0) & (meta["Longtitude"] != 0):
+ # NOTE: check EPSG:28992 definition and whether location is showing up in
+ # the right spot.
transformer = Transformer.from_crs("epsg:4326", "epsg:28992")
x, y = transformer.transform(meta["Latitude"], meta["Longtitude"])
x = np.round(x, 2)
@@ -141,4 +135,3 @@ def read_solinst_file(
meta["metadata_available"] = True
return df, meta
-
diff --git a/hydropandas/observation.py b/hydropandas/observation.py
index 36f6b157..45d87900 100644
--- a/hydropandas/observation.py
+++ b/hydropandas/observation.py
@@ -779,11 +779,15 @@ def from_pastastore(cls, pstore, libname, name, metadata_mapping=None):
@classmethod
def from_solinst(
- cls,
- path,
- transform_coords=True,
- screen_bottom=None, screen_top=None, ground_level=None,
- tube_nr=None, tube_top=None):
+ cls,
+ path,
+ transform_coords=True,
+ screen_bottom=None,
+ screen_top=None,
+ ground_level=None,
+ tube_nr=None,
+ tube_top=None,
+ ):
"""Read data from Solinst xle file.
Parameters
@@ -794,13 +798,11 @@ def from_solinst(
"""
from .io import solinst
- df, meta = solinst.read_solinst_file(
- path,
- transform_coords=transform_coords
- )
+ df, meta = solinst.read_solinst_file(path, transform_coords=transform_coords)
return cls(
df,
+ meta=meta,
name=meta.pop("name"),
x=meta.pop("x"),
y=meta.pop("y"),
@@ -814,7 +816,6 @@ def from_solinst(
monitoring_well=meta.pop("monitoring_well"),
tube_nr=tube_nr,
tube_top=tube_top,
- meta=meta,
)
diff --git a/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle b/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
deleted file mode 100644
index 5178224b..00000000
--- a/tests/data/2024-solinst-test/example-10min-interval-via-laptop.xle
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
- 2024/01/11
-
-
- Version 4.6.3
- Version 4.6.3
- PC Software 4.6.2
- Desktop Reader (567751)
-
-
- L5_LT
- M5
- Stopped
- 2170536
- 3,59600
- 1372,54
- 2
- 1,006
-
-
- 20231123
- slugtest
- 0,000
- 0,000
- 60000
- 0
-
- Slate
- 1
- 0,000000
-
- 2024/01/11 11:00:00
- 2024/01/11 15:00:00
- 25
-
-
- LEVEL
- m
-
-
-
-
-
- TEMPERATURE
- °C
-
-
-
-
- 2024/01/11
-
- 0
- 10.5288
- 21.879
-
-
- 2024/01/11
-
- 0
- 10.5300
- 21.585
-
-
- 2024/01/11
-
- 0
- 10.5319
- 21.403
-
-
- 2024/01/11
-
- 0
- 10.5343
- 21.285
-
-
- 2024/01/11
-
- 0
- 10.5339
- 21.205
-
-
- 2024/01/11
-
- 0
- 10.5329
- 21.177
-
-
- 2024/01/11
-
- 0
- 10.5335
- 21.204
-
-
- 2024/01/11
-
- 0
- 10.5323
- 21.258
-
-
- 2024/01/11
-
- 0
- 10.5319
- 21.311
-
-
- 2024/01/11
-
- 0
- 10.5323
- 21.429
-
-
- 2024/01/11
-
- 0
- 10.5320
- 21.474
-
-
- 2024/01/11
-
- 0
- 10.5333
- 21.469
-
-
- 2024/01/11
-
- 0
- 10.5341
- 21.424
-
-
- 2024/01/11
-
- 0
- 10.5350
- 21.394
-
-
- 2024/01/11
-
- 0
- 10.5344
- 21.412
-
-
- 2024/01/11
-
- 0
- 10.5336
- 21.410
-
-
- 2024/01/11
-
- 0
- 10.5341
- 21.429
-
-
- 2024/01/11
-
- 0
- 10.5346
- 21.452
-
-
- 2024/01/11
-
- 0
- 10.5331
- 21.444
-
-
- 2024/01/11
-
- 0
- 10.5311
- 21.399
-
-
- 2024/01/11
-
- 0
- 10.5293
- 21.337
-
-
- 2024/01/11
-
- 0
- 10.5292
- 21.270
-
-
- 2024/01/11
-
- 0
- 10.5282
- 21.205
-
-
- 2024/01/11
-
- 0
- 10.5277
- 21.170
-
-
- 2024/01/11
-
- 0
- 10.5281
- 21.176
-
-
-
diff --git a/tests/data/2024-solinst-test/example-10min-interval-via-laptop.zip b/tests/data/2024-solinst-test/example-10min-interval-via-laptop.zip
new file mode 100644
index 0000000000000000000000000000000000000000..0788fb495fb23cf29f81ed4876e9e13259373057
GIT binary patch
literal 1329
zcmWIWW@Zs#-~dA27@Y_PDA*{;z@W;Yz>r#zm|KvOs%vPFo0+GZnOBlpRF;^dTb7xq
zo0C{jl3$=#k&_x4!pp#JExIrjhD$5B85mh!Ff%ZKiLH^h^B!49?0X-avg6j&D53cr
zA(?K*QzmL%%)44vC0*Ikc;;Dy&}GScS@RR;=e!Llm=tuqYwO;Xf920SKR^G!edB}A
z?{!M!A|h2?>r5G(^B>gkoo`z2x~IEtxsFZok@yd~o{>|YoKCV|pL<#9_Jta8ws(n3
zYCg|?`6kawc;8`hZ!9#Zcj5EH0z#bIzFB(nY-L;mwtDsr*Y<<`Bwc$C;eZf
zx_WcM1G7C^Pt~5UiMhney*~1*xxU#sW?}B>=j2nK{AT$hxkD@E{EpiTW7Y(IESkM>
zPC5UghYxr2az9s@Wq(ricG}c}=p#D4pK`x7PkpFcxpkNB=aWyh_4;20<|G_`bWQz@
zt=7wlQ#oz**c#spnsD9O7TH?AG$yBBe6NV+a&56i#YU2qaSzI5^Ml2*qqx`|>};l2
zy}TiPE8?>TQe!TEQ8Unf(sX=5)v6}D*qAeu=Un{sXpyGbG|@*EuWlR<(a~z5n$Mr^K_ZFD?W%2L;LhmQ6tE=z`(
zs(Yzt8$Ov&?mBy0W>FDe-qfP)XBTaWXq~|FF0m%cH@{T*2-m&9%f337CZ>>i+qr
z(o9@?+ghzZ)$=|WaNqe=?>sp~L{m-AYiZBc$LpVNO1e|I?B&%2|BnYI?hJ3vxv=Qs
zTRp|~S2-^vXkAH=Y6tN*bh0=AnR`KuSR3-eaJQFQ)tgU$9;ubeV(RmK_HjgI}*i`}i>
zEllsKOKG0>#f`u8MdN$vMc;ofZvUIj=j3wQ*389zo8$fc&m7jiJ9$Ik?-91Y|3iu=
z{E1Nha$s}g{rxX8P9DFoC6=)}k6U*Y-<7Z0Z)R)BM{J4C2rQd0?e9dx-(r8oBCp8u
zY