seabirdfilehandler 0.5.4__tar.gz → 0.6.0__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: seabirdfilehandler
3
- Version: 0.5.4
3
+ Version: 0.6.0
4
4
  Summary: Library of parsers to interact with SeaBird CTD files.
5
5
  Keywords: CTD,parser,seabird,data
6
6
  Author: Emil Michels
@@ -20,7 +20,7 @@ urls.homepage = "https://ctd-software.pages.io-warnemuende.de/seabirdfilehandler
20
20
  urls.repository = "https://git.io-warnemuende.de/CTD-Software/SeabirdFileHandler"
21
21
  urls.documentation = "https://ctd-software.pages.io-warnemuende.de/seabirdfilehandler"
22
22
  dynamic = []
23
- version = "0.5.4"
23
+ version = "0.6.0"
24
24
 
25
25
  [tool.poetry]
26
26
 
@@ -3,6 +3,8 @@ from .bottlefile import *
3
3
  from .bottlelogfile import *
4
4
  from .cnvfile import *
5
5
  from .xmlfiles import *
6
+ from .hexfile import *
6
7
  from .validation_modules import *
7
- from .file_collection import *
8
8
  from .geomar_ctd_file_parser import *
9
+ from .parameter import *
10
+ from .file_collection import *
@@ -9,8 +9,9 @@ from seabirdfilehandler import (
9
9
  CnvFile,
10
10
  BottleFile,
11
11
  BottleLogFile,
12
+ DataFile,
13
+ HexFile,
12
14
  )
13
- from seabirdfilehandler import DataFile
14
15
  from seabirdfilehandler.utils import get_unique_sensor_data
15
16
 
16
17
  logger = logging.getLogger(__name__)
@@ -20,6 +21,7 @@ def get_collection(
20
21
  path_to_files: Path | str,
21
22
  file_suffix: str = "cnv",
22
23
  only_metadata: bool = False,
24
+ pattern: str = "",
23
25
  sorting_key: Callable | None = None,
24
26
  ) -> Type[FileCollection]:
25
27
  """
@@ -33,6 +35,8 @@ def get_collection(
33
35
  The suffix to search for. (Default value = "cnv")
34
36
  only_metadata : bool :
35
37
  Whether to read only metadata. (Default value = False)
38
+ pattern: str
39
+ A filter for file selection. (Default value = '')
36
40
  sorting_key : Callable | None :
37
41
  A callable that returns the filename-part to use to sort the collection. (Default value = None)
38
42
  Returns
@@ -44,13 +48,14 @@ def get_collection(
44
48
  "cnv": CnvCollection,
45
49
  "btl": FileCollection,
46
50
  "bl": FileCollection,
51
+ "hex": HexCollection,
47
52
  }
48
53
  file_suffix = file_suffix.strip(".")
49
54
  try:
50
55
  collection = mapping_suffix_to_type[file_suffix](
51
- path_to_files, file_suffix, only_metadata, sorting_key
56
+ path_to_files, file_suffix, only_metadata, pattern, sorting_key
52
57
  )
53
- except ValueError:
58
+ except KeyError:
54
59
  raise ValueError(f"Unknown input file type: {file_suffix}, aborting.")
55
60
  else:
56
61
  return collection
@@ -71,6 +76,8 @@ class FileCollection(UserList):
71
76
  The suffix to search for. (Default value = "cnv")
72
77
  only_metadata : bool :
73
78
  Whether to read only metadata. (Default value = False)
79
+ pattern: str
80
+ A filter for file selection. (Default value = '')
74
81
  sorting_key : Callable | None :
75
82
  A callable that returns the filename-part to use to sort the collection. (Default value = None)
76
83
  """
@@ -80,14 +87,18 @@ class FileCollection(UserList):
80
87
  path_to_files: str | Path,
81
88
  file_suffix: str,
82
89
  only_metadata: bool = False,
90
+ pattern: str = "",
83
91
  sorting_key: Callable | None = None,
84
92
  ):
85
93
  super().__init__()
86
94
  self.path_to_files = Path(path_to_files)
87
95
  self.file_suffix = file_suffix.strip(".")
96
+ self.pattern = pattern
97
+ self.sorting_key = sorting_key
88
98
  self.file_type = self.extract_file_type(self.file_suffix)
89
99
  self.individual_file_paths = self.collect_files(
90
- sorting_key=sorting_key
100
+ pattern=pattern,
101
+ sorting_key=sorting_key,
91
102
  )
92
103
  self.data = self.load_files(only_metadata)
93
104
  if not only_metadata:
@@ -113,6 +124,7 @@ class FileCollection(UserList):
113
124
  "cnv": CnvFile,
114
125
  "btl": BottleFile,
115
126
  "bl": BottleLogFile,
127
+ "hex": HexFile,
116
128
  }
117
129
  file_type = DataFile
118
130
  for key, value in mapping_suffix_to_type.items():
@@ -123,6 +135,7 @@ class FileCollection(UserList):
123
135
 
124
136
  def collect_files(
125
137
  self,
138
+ pattern: str = "",
126
139
  sorting_key: Callable | None = lambda file: int(
127
140
  file.stem.split("_")[3]
128
141
  ),
@@ -135,6 +148,8 @@ class FileCollection(UserList):
135
148
 
136
149
  Parameters
137
150
  ----------
151
+ pattern: str
152
+ A filter for file selection. Is given to rglob. (Default value = '')
138
153
  sorting_key : Callable | None :
139
154
  The part of the filename to use in sorting. (Default value = lambda file: int(file.stem.split("_")[3]))
140
155
  Returns
@@ -142,7 +157,7 @@ class FileCollection(UserList):
142
157
  A list of all paths found.
143
158
  """
144
159
  return sorted(
145
- self.path_to_files.rglob(f"*{self.file_suffix}"),
160
+ self.path_to_files.rglob(f"*{pattern}*{self.file_suffix}"),
146
161
  key=sorting_key,
147
162
  )
148
163
 
@@ -161,7 +176,12 @@ class FileCollection(UserList):
161
176
  data = []
162
177
  for file in self.individual_file_paths:
163
178
  try:
164
- data.append(self.file_type(file, only_metadata))
179
+ data.append(
180
+ self.file_type(
181
+ path_to_file=file,
182
+ only_header=only_metadata,
183
+ )
184
+ )
165
185
  except TypeError:
166
186
  logger.error(
167
187
  f"Could not open file {file} with the type "
@@ -409,3 +429,64 @@ class CnvCollection(FileCollection):
409
429
  return np.concatenate(
410
430
  [file.parameters.create_full_ndarray() for file in self.data]
411
431
  )
432
+
433
+
434
+ class HexCollection(FileCollection):
435
+ """
436
+ Specific methods to work with collections of .hex files.
437
+
438
+ Especially concerned with the detection of corresponding .XMLCON files.
439
+ """
440
+
441
+ def __init__(
442
+ self,
443
+ *args,
444
+ xmlcon_pattern: str = "",
445
+ path_to_xmlcons: Path | str = "",
446
+ **kwargs,
447
+ ):
448
+ # force only_metadata, as the hex data cannot be put into a DataFrame
449
+ kwargs["only_metadata"] = True
450
+ super().__init__(*args, **kwargs)
451
+ if not xmlcon_pattern:
452
+ xmlcon_pattern = self.pattern
453
+ self.xmlcon_pattern = xmlcon_pattern
454
+ self.path_to_xmlcons = (
455
+ Path(path_to_xmlcons)
456
+ if path_to_xmlcons
457
+ else self.path_to_files.parent
458
+ )
459
+ self.xmlcons = self.get_xmlcons()
460
+
461
+ def get_xmlcons(self) -> list[str]:
462
+ """
463
+ Returns all .xmlcon files found inside the root directory and its
464
+ children, matching a given pattern.
465
+
466
+ Does use the global sorting_key to attempt to also sort the xmlcons the
467
+ same way.
468
+ This is meant to be used in the future for a more specific hex-xmlcon
469
+ matching.
470
+
471
+ Returns
472
+ -------
473
+ A list of the found xmlcon filenames.
474
+ """
475
+ try:
476
+ xmlcons = [
477
+ Path(xmlcon_path).stem
478
+ for xmlcon_path in sorted(
479
+ self.path_to_xmlcons.rglob(
480
+ f"*{self.xmlcon_pattern}*.XMLCON"
481
+ ),
482
+ key=self.sorting_key,
483
+ )
484
+ ]
485
+ except (KeyError, IndexError):
486
+ xmlcons = [
487
+ Path(xmlcon_path).stem
488
+ for xmlcon_path in self.path_to_xmlcons.rglob(
489
+ f"*{self.xmlcon_pattern}*.XMLCON"
490
+ )
491
+ ]
492
+ return xmlcons
@@ -0,0 +1,71 @@
1
+ from pathlib import Path
2
+ from seabirdfilehandler import DataFile, XMLCONFile
3
+
4
+
5
+ class HexFile(DataFile):
6
+ """
7
+ A representation of a .hex file as used by SeaBird.
8
+
9
+ Parameters
10
+ ----------
11
+ path_to_file: Path | str:
12
+ the path to the file
13
+ """
14
+
15
+ def __init__(
16
+ self,
17
+ path_to_file: Path | str,
18
+ path_to_xmlcon: Path | str = "",
19
+ *args,
20
+ **kwargs,
21
+ ):
22
+ # force loading only metadata
23
+ super().__init__(path_to_file, True)
24
+ self.xmlcon = self.get_corresponding_xmlcon(path_to_xmlcon)
25
+
26
+ def get_corresponding_xmlcon(
27
+ self,
28
+ path_to_xmlcon: Path | str = "",
29
+ ) -> XMLCONFile | None:
30
+ """
31
+ Finds the best matching .xmlcon file inside the same directory.
32
+
33
+ Parameters
34
+ ----------
35
+ path_to_xmlcon: Path | str:
36
+ A fixed path to a xmlcon file. Will be checked.
37
+ """
38
+ # xmlcon path given, test and use it
39
+ if isinstance(path_to_xmlcon, str):
40
+ if path_to_xmlcon:
41
+ return XMLCONFile(path_to_xmlcon)
42
+ else:
43
+ if path_to_xmlcon.exists():
44
+ return XMLCONFile(path_to_xmlcon)
45
+ # no xmlcon path, lets find one in the same dir
46
+ # get all xmlcons in the dir
47
+ xmlcons = [
48
+ xmlcon.stem
49
+ for xmlcon in self.file_dir.glob("*.XMLCON", case_sensitive=False)
50
+ ]
51
+ if not xmlcons:
52
+ return None
53
+ # find excact match
54
+ if self.file_name in xmlcons:
55
+ return XMLCONFile(
56
+ self.file_dir.joinpath(self.file_name + ".XMLCON")
57
+ )
58
+ # TODO:
59
+ # otherwise, take the last fitting one in a sorted xmlcon list, or,
60
+ # the one sharing the same prefix
61
+ else:
62
+ same_prefix_xmlcons = [
63
+ xmlcon
64
+ for xmlcon in xmlcons
65
+ if self.file_name.startswith(xmlcon[:5])
66
+ ]
67
+ if not same_prefix_xmlcons:
68
+ return None
69
+ return XMLCONFile(
70
+ self.file_dir.joinpath(same_prefix_xmlcons[0] + ".XMLCON")
71
+ )
@@ -33,6 +33,23 @@ class XMLFile(UserDict):
33
33
  self.xml_tree = ET.fromstring(self.input)
34
34
  self.data = xmltodict.parse(self.input)
35
35
 
36
+ def __eq__(self, other) -> bool:
37
+ """
38
+ Allows comparison of two instances of this class.
39
+
40
+ Uses the parsed xml information to determine equality.
41
+
42
+ Parameters
43
+ ----------
44
+ other: XMLFile
45
+ An instance of this class.
46
+
47
+ Returns
48
+ -------
49
+ Whether the given instance and this one are equal.
50
+ """
51
+ return self.data == other.data
52
+
36
53
  def to_xml(self, file_name=None, file_path=None):
37
54
  """
38
55
  Writes the dictionary to xml.