seabirdfilehandler 0.4.2__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of seabirdfilehandler might be problematic. Click here for more details.
- seabirdfilehandler/datatablefiles.py +3 -3
- seabirdfilehandler/file_collection.py +10 -23
- seabirdfilehandler/utils.py +53 -0
- seabirdfilehandler/xmlfiles.py +54 -0
- {seabirdfilehandler-0.4.2.dist-info → seabirdfilehandler-0.4.3.dist-info}/METADATA +1 -1
- seabirdfilehandler-0.4.3.dist-info/RECORD +14 -0
- seabirdfilehandler-0.4.2.dist-info/RECORD +0 -13
- {seabirdfilehandler-0.4.2.dist-info → seabirdfilehandler-0.4.3.dist-info}/LICENSE +0 -0
- {seabirdfilehandler-0.4.2.dist-info → seabirdfilehandler-0.4.3.dist-info}/WHEEL +0 -0
|
@@ -10,8 +10,8 @@ from seabirdfilehandler.parameter import Parameters
|
|
|
10
10
|
from seabirdfilehandler.validation_modules import CnvValidationList
|
|
11
11
|
from seabirdfilehandler.seabirdfiles import SeaBirdFile
|
|
12
12
|
from seabirdfilehandler.dataframe_meta_accessor import (
|
|
13
|
-
SeriesMetaAccessor,
|
|
14
|
-
DataFrameMetaAccessor,
|
|
13
|
+
SeriesMetaAccessor, # noqa: F401
|
|
14
|
+
DataFrameMetaAccessor, # noqa: F401
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
@@ -384,7 +384,7 @@ class CnvFile(DataTableFile):
|
|
|
384
384
|
a list of dictionaries, that organize the table header information
|
|
385
385
|
|
|
386
386
|
"""
|
|
387
|
-
if header_info
|
|
387
|
+
if header_info == []:
|
|
388
388
|
header_info = self.data_table_description
|
|
389
389
|
table_header = {}
|
|
390
390
|
duplicate_columns = []
|
|
@@ -4,8 +4,14 @@ from collections import UserList
|
|
|
4
4
|
from typing import Type
|
|
5
5
|
import pandas as pd
|
|
6
6
|
import numpy as np
|
|
7
|
-
from seabirdfilehandler import
|
|
7
|
+
from seabirdfilehandler import (
|
|
8
|
+
SeaBirdFile,
|
|
9
|
+
CnvFile,
|
|
10
|
+
BottleFile,
|
|
11
|
+
BottleLogFile,
|
|
12
|
+
)
|
|
8
13
|
from seabirdfilehandler.datatablefiles import DataTableFile
|
|
14
|
+
from seabirdfilehandler.utils import get_unique_sensor_data
|
|
9
15
|
|
|
10
16
|
logger = logging.getLogger(__name__)
|
|
11
17
|
|
|
@@ -49,7 +55,9 @@ class FileCollection(UserList):
|
|
|
49
55
|
self.df = self.get_collection_dataframe(self.df_list)
|
|
50
56
|
if self.file_type == CnvFile:
|
|
51
57
|
self.data_meta_info = self.get_data_table_meta_info()
|
|
52
|
-
self.sensor_data =
|
|
58
|
+
self.sensor_data = get_unique_sensor_data(
|
|
59
|
+
[file.sensors for file in self.data]
|
|
60
|
+
)
|
|
53
61
|
|
|
54
62
|
def __str__(self):
|
|
55
63
|
return "/n".join(self.data)
|
|
@@ -247,24 +255,3 @@ class FileCollection(UserList):
|
|
|
247
255
|
def get_data_table_meta_info(self) -> list[list[dict]]:
|
|
248
256
|
""" """
|
|
249
257
|
return [file.data_header_meta_info for file in self.data]
|
|
250
|
-
|
|
251
|
-
def get_sensor_data(self) -> list[tuple[list[dict]]]:
|
|
252
|
-
""" """
|
|
253
|
-
unique = []
|
|
254
|
-
last_unique = None
|
|
255
|
-
for file in [file for file in self.data]:
|
|
256
|
-
cast_sensors = file.sensors
|
|
257
|
-
if last_unique is None:
|
|
258
|
-
unique.append((file.file_name, cast_sensors))
|
|
259
|
-
else:
|
|
260
|
-
differing_dicts = [
|
|
261
|
-
current_dict
|
|
262
|
-
for last_dict, current_dict in zip(
|
|
263
|
-
last_unique, cast_sensors
|
|
264
|
-
)
|
|
265
|
-
if current_dict != last_dict
|
|
266
|
-
]
|
|
267
|
-
if differing_dicts:
|
|
268
|
-
unique.append((file.file_name, differing_dicts))
|
|
269
|
-
last_unique = cast_sensors
|
|
270
|
-
return unique
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_unique_sensor_data(
|
|
7
|
+
sensor_data: list[list[dict]],
|
|
8
|
+
) -> list[tuple[list[dict]]]:
|
|
9
|
+
"""
|
|
10
|
+
Returns all the unique sensors and their configuration used in the given
|
|
11
|
+
collection of sensor data. These will typically be parsed from xml inside
|
|
12
|
+
.cnv or .xmlcon files.
|
|
13
|
+
If for example, the first oxygen sensor has been replaced after the 8 cast,
|
|
14
|
+
then we will see that in the output structure by a seconde tuple, with the
|
|
15
|
+
number 8 and the individual sensor information for that new oxygen sensor.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
sensor_data:
|
|
20
|
+
The structure of xml-parsed dicts inside two organizing lists.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
The input structure stripped down to unique sensor data and appended by
|
|
25
|
+
the index, at which this new sensor appeared the first time.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
unique = []
|
|
29
|
+
last_unique = None
|
|
30
|
+
for index, individual_sensor_data in enumerate(
|
|
31
|
+
[file for file in sensor_data]
|
|
32
|
+
):
|
|
33
|
+
if last_unique is None:
|
|
34
|
+
unique.append((index, individual_sensor_data))
|
|
35
|
+
else:
|
|
36
|
+
differing_dicts = [
|
|
37
|
+
current_dict
|
|
38
|
+
for last_dict, current_dict in zip(
|
|
39
|
+
last_unique, individual_sensor_data
|
|
40
|
+
)
|
|
41
|
+
if current_dict != last_dict
|
|
42
|
+
]
|
|
43
|
+
if differing_dicts:
|
|
44
|
+
unique.append((index, differing_dicts))
|
|
45
|
+
last_unique = individual_sensor_data
|
|
46
|
+
return unique
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class UnexpectedFileFormat(Exception):
|
|
50
|
+
def __init__(self, file_type: str, error: str) -> None:
|
|
51
|
+
message = f"{file_type} is not formatted as expected: {error}"
|
|
52
|
+
logger.error(message)
|
|
53
|
+
super().__init__(message)
|
seabirdfilehandler/xmlfiles.py
CHANGED
|
@@ -4,6 +4,8 @@ import xml.etree.ElementTree as ET
|
|
|
4
4
|
import json
|
|
5
5
|
import xmltodict
|
|
6
6
|
|
|
7
|
+
from seabirdfilehandler.utils import UnexpectedFileFormat
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class XMLFile(UserDict):
|
|
9
11
|
"""
|
|
@@ -78,6 +80,58 @@ class XMLCONFile(XMLFile):
|
|
|
78
80
|
|
|
79
81
|
def __init__(self, path_to_file):
|
|
80
82
|
super().__init__(path_to_file)
|
|
83
|
+
self.sensor_info = self.get_sensor_info()
|
|
84
|
+
|
|
85
|
+
def get_sensor_info(self) -> list[dict]:
|
|
86
|
+
"""
|
|
87
|
+
Creates a multilevel dictionary, dropping the first four dictionaries,
|
|
88
|
+
to retrieve pure sensor information.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
A list of all the individual sensor information, stored in dictionaries
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
sensors = self.data["SBE_InstrumentConfiguration"]["Instrument"][
|
|
97
|
+
"SensorArray"
|
|
98
|
+
]["Sensor"]
|
|
99
|
+
except KeyError as error:
|
|
100
|
+
raise UnexpectedFileFormat("XMLCON", error)
|
|
101
|
+
else:
|
|
102
|
+
# create a tidied version of the xml-parsed sensor dict
|
|
103
|
+
sensor_names = []
|
|
104
|
+
tidied_sensor_list = []
|
|
105
|
+
for entry in sensors:
|
|
106
|
+
sensor_key = list(entry.keys())[-1]
|
|
107
|
+
if not sensor_key.endswith(("Sensor", "Meter")):
|
|
108
|
+
continue
|
|
109
|
+
sensor_name = sensor_key.removesuffix("Sensor")
|
|
110
|
+
# the wetlab sensors feature a suffix _Sensor
|
|
111
|
+
sensor_name = sensor_name.removesuffix("_")
|
|
112
|
+
# assuming, that the first sensor in the xmlcon is also on the
|
|
113
|
+
# first sensor strand, the second occurence of the name is
|
|
114
|
+
# suffixed with '2'
|
|
115
|
+
if sensor_name in sensor_names:
|
|
116
|
+
sensor_name += "2"
|
|
117
|
+
sensor_names.append(sensor_name)
|
|
118
|
+
# move the calibration info one dictionary level up
|
|
119
|
+
calibration_info = entry[sensor_key]
|
|
120
|
+
# build the new dictionary
|
|
121
|
+
try:
|
|
122
|
+
new_dict = {
|
|
123
|
+
"Channel": str(int(entry["@index"]) + 1),
|
|
124
|
+
"SensorName": sensor_name,
|
|
125
|
+
**calibration_info,
|
|
126
|
+
}
|
|
127
|
+
except TypeError:
|
|
128
|
+
new_dict = {
|
|
129
|
+
"Channel": entry["@Channel"],
|
|
130
|
+
"SensorName": sensor_name,
|
|
131
|
+
"Info": calibration_info,
|
|
132
|
+
}
|
|
133
|
+
tidied_sensor_list.append(new_dict)
|
|
134
|
+
return tidied_sensor_list
|
|
81
135
|
|
|
82
136
|
|
|
83
137
|
class PsaFile(XMLFile):
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
seabirdfilehandler/__init__.py,sha256=8Vk2TURWXv2_NG_U_fR0fIVDFymkFkBipvmlS5ucB3M,147
|
|
2
|
+
seabirdfilehandler/dataframe_meta_accessor.py,sha256=x4mSEN49us6Ezzjdt41fl5Ry8IJR09ORrZ1roOIJbyc,6439
|
|
3
|
+
seabirdfilehandler/datatablefiles.py,sha256=yzTAzsWcdrHYaa2QaR6OpdEs-cu2py8V5o79s2Uz7MM,31646
|
|
4
|
+
seabirdfilehandler/file_collection.py,sha256=nWyi5FToCV9-e_zcaLhRb4oOt8KAmyHC-SBGLJO9KQ4,6909
|
|
5
|
+
seabirdfilehandler/logging.yaml,sha256=mXxbhJPio3OGaukTpc3rLGA8Ywq1DNqp0Vn5YCbH6jY,459
|
|
6
|
+
seabirdfilehandler/parameter.py,sha256=UyKb_HGQ57pETdhSfR5FbJ60aOj8_d3_Tgw_akth0TY,13283
|
|
7
|
+
seabirdfilehandler/seabirdfiles.py,sha256=BKLyk5gUMkt1CG4ljDXlCqcr5zej0-9PjPS0sX2E4n8,7449
|
|
8
|
+
seabirdfilehandler/utils.py,sha256=5KXdB8Hdv65dv5tPyXxNMct1mCEOyA3S8XP54AFAnx0,1745
|
|
9
|
+
seabirdfilehandler/validation_modules.py,sha256=eZ6x0giftUtlxnRMOnK_vCkgccdwUXPrDjajFa-E6n0,4698
|
|
10
|
+
seabirdfilehandler/xmlfiles.py,sha256=L_puQf8eg0ojv85AyEMID4jnwkOlV_fgZP3W5yeSUBY,4668
|
|
11
|
+
seabirdfilehandler-0.4.3.dist-info/LICENSE,sha256=Ifd1VPmYv32oJd2QVh3wIQP9X05vYJlcY6kONz360ws,34603
|
|
12
|
+
seabirdfilehandler-0.4.3.dist-info/METADATA,sha256=ODlAzixojiAr_KtwyXVmYlWDn0UJTzFlp_RBAWzLxug,1289
|
|
13
|
+
seabirdfilehandler-0.4.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
14
|
+
seabirdfilehandler-0.4.3.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
seabirdfilehandler/__init__.py,sha256=8Vk2TURWXv2_NG_U_fR0fIVDFymkFkBipvmlS5ucB3M,147
|
|
2
|
-
seabirdfilehandler/dataframe_meta_accessor.py,sha256=x4mSEN49us6Ezzjdt41fl5Ry8IJR09ORrZ1roOIJbyc,6439
|
|
3
|
-
seabirdfilehandler/datatablefiles.py,sha256=LwHAh_2dUSERHvs-ql_wBl2a5jcHabOAD5i33fASfs0,31618
|
|
4
|
-
seabirdfilehandler/file_collection.py,sha256=eFJqKnKMwAGC37D27FsPUi7ceTU3iUC0Y_wG2HzxwmU,7518
|
|
5
|
-
seabirdfilehandler/logging.yaml,sha256=mXxbhJPio3OGaukTpc3rLGA8Ywq1DNqp0Vn5YCbH6jY,459
|
|
6
|
-
seabirdfilehandler/parameter.py,sha256=UyKb_HGQ57pETdhSfR5FbJ60aOj8_d3_Tgw_akth0TY,13283
|
|
7
|
-
seabirdfilehandler/seabirdfiles.py,sha256=BKLyk5gUMkt1CG4ljDXlCqcr5zej0-9PjPS0sX2E4n8,7449
|
|
8
|
-
seabirdfilehandler/validation_modules.py,sha256=eZ6x0giftUtlxnRMOnK_vCkgccdwUXPrDjajFa-E6n0,4698
|
|
9
|
-
seabirdfilehandler/xmlfiles.py,sha256=Es0pUCoB0af-meCH-75h-s-r0mEfrthl-8QDjqNBWPk,2441
|
|
10
|
-
seabirdfilehandler-0.4.2.dist-info/LICENSE,sha256=Ifd1VPmYv32oJd2QVh3wIQP9X05vYJlcY6kONz360ws,34603
|
|
11
|
-
seabirdfilehandler-0.4.2.dist-info/METADATA,sha256=9HcKSVWHN90OnsS86UftA7plWh6ho_BUV1sbf5eHESo,1289
|
|
12
|
-
seabirdfilehandler-0.4.2.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
13
|
-
seabirdfilehandler-0.4.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|