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.

@@ -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 is []:
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 SeaBirdFile, CnvFile, BottleFile, BottleLogFile
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 = self.get_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)
@@ -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):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: seabirdfilehandler
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Library of parsers to interact with SeaBird CTD files.
5
5
  Keywords: CTD,parser,seabird,data
6
6
  Author: Emil Michels
@@ -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,,