|
1 |
| -# A .lut file contains processing directives for a whole project |
2 | 1 | import dataclasses
|
3 | 2 | from configparser import ConfigParser
|
4 | 3 |
|
5 | 4 | from pathlib import Path
|
6 | 5 |
|
7 | 6 |
|
8 |
| -class Lut: |
9 |
| - def __init__(self): |
10 |
| - self.min: int = 0 |
11 |
| - self.max: int = 65536 |
12 |
| - self.gamma: float = 1 |
13 |
| - self.sens: str = "before" |
14 |
| - # Appeared in a later version |
15 |
| - self.adjust: str = "no" |
16 |
| - self.odrange: float = 1.8 |
17 |
| - # Appeared in a later version |
18 |
| - self.ratio: float = 1.15 |
19 |
| - # Appeared in a later version |
20 |
| - self.sizelimit: int = 800 # Unused? |
21 |
| - self.overlap: float = 0.07 |
22 |
| - # Appeared in a later version |
23 |
| - self.medianchoice: str = "no" |
24 |
| - self.medianvalue: int = 1 |
25 |
| - # Appeared in a later version |
26 |
| - self.resolutionreduct: int = 1200 |
27 |
| - |
28 |
| - @staticmethod |
29 |
| - def read(path: Path) -> "Lut": |
30 |
| - ret = Lut() |
31 |
| - with open(path, "r") as f: |
32 |
| - lines = f.readlines() |
33 |
| - for a_var_name, a_line in zip(ret.__dict__.keys(), lines): |
34 |
| - a_var = getattr(ret, a_var_name) |
35 |
| - # Below for clarity and extensibility, as we could use directly the class, class(a_line) |
36 |
| - if isinstance(a_var, int): |
37 |
| - setattr(ret, a_var_name, int(a_line)) |
38 |
| - elif isinstance(a_var, float): |
39 |
| - setattr(ret, a_var_name, float(a_line)) |
40 |
| - elif isinstance(a_var, str): |
41 |
| - setattr(ret, a_var_name, a_line.strip()) |
42 |
| - # From legacy macro, there is a typo "od_g_range" so the code doesn't do what it should I guess |
43 |
| - # if ret.odrange >= 3: |
44 |
| - # ret.odgrange = 1.15 |
45 |
| - return ret |
46 |
| - |
47 |
| - |
48 | 7 | # Full dump of a config file, for future use:
|
49 | 8 | # _Used_:
|
50 | 9 | # background_process= last
|
@@ -114,135 +73,3 @@ def read(cls, path: Path) -> "ZooscanConfig":
|
114 | 73 | raise
|
115 | 74 | args.append(value)
|
116 | 75 | return ZooscanConfig(*args)
|
117 |
| - |
118 |
| - |
119 |
| -@dataclasses.dataclass(frozen=False) |
120 |
| -class ProjectMeta: |
121 |
| - """ |
122 |
| - Class to read and store metadata from a metadata.txt file. |
123 |
| - All fields are explicitly defined with proper type annotations. |
124 |
| - """ |
125 |
| - |
126 |
| - # String fields |
127 |
| - SampleId: str = "" # e.g. apero2023_tha_bioness_sup2000_017_st66_d_n1 |
128 |
| - Scanop: str = "" # e.g. adelaide_perruchon |
129 |
| - Ship: str = "" # e.g. thalassa |
130 |
| - Scientificprog: str = "" # e.g. apero |
131 |
| - Date: str = "" # e.g. 20230704-0503 |
132 |
| - CTDref: str = "" # e.g. apero_bio_ctd_017 |
133 |
| - Otherref: str = "" # e.g. apero_bio_uvp6_017u |
134 |
| - Nettype: str = "" # e.g. bioness |
135 |
| - Observation: str = "" # e.g. no |
136 |
| - SubMethod: str = "" # e.g. motoda |
137 |
| - Sample_comment: str = "" # e.g. vol_zooprocess_saisi |
138 |
| - barcode: str = "" # e.g. ape000000147 |
139 |
| - FracId: str = "" # e.g. d2_4_sur_4 |
140 |
| - |
141 |
| - # Integer fields |
142 |
| - StationId: int = -1 # e.g. 66 |
143 |
| - Townb: int = -1 # e.g. 1 |
144 |
| - Towtype: int = -1 # e.g. 1 |
145 |
| - Netmesh: int = -1 # e.g. 2000 |
146 |
| - Netsurf: int = -1 # e.g. 1 |
147 |
| - Vol: int = -1 # e.g. 357 |
148 |
| - Fracmin: int = -1 # e.g. 2000 |
149 |
| - Fracsup: int = -1 # e.g. 999999 |
150 |
| - Fracnb: int = -1 # e.g. 4 |
151 |
| - Code: int = -1 # e.g. 1 |
152 |
| - CellPart: int = -1 # e.g. 1 |
153 |
| - Replicates: int = -1 # e.g. 1 |
154 |
| - VolIni: int = -1 # e.g. 1 |
155 |
| - VolPrec: int = -1 # e.g. 1 |
156 |
| - vol_qc: int = -1 # e.g. 1 |
157 |
| - depth_qc: int = -1 # e.g. 1 |
158 |
| - sample_qc: int = -1 # e.g. 1111 |
159 |
| - |
160 |
| - # Float fields |
161 |
| - Depth: float = -1.0 # e.g. 99999 |
162 |
| - Zmax: float = -1.0 # e.g. 1008 |
163 |
| - Zmin: float = -1.0 # e.g. 820 |
164 |
| - net_duration: float = -1.0 # e.g. 20 |
165 |
| - ship_speed_knots: float = -1.0 # e.g. 2 |
166 |
| - cable_length: float = -1.0 # e.g. 9999 |
167 |
| - cable_angle: float = -1.0 # e.g. 99999 |
168 |
| - cable_speed: float = -1.0 # e.g. 0 |
169 |
| - nb_jar: float = -1.0 # e.g. 1 |
170 |
| - Latitude: float = -1.0 # e.g. 51.4322000 |
171 |
| - Longitude: float = -1.0 # e.g. 18.3108000 |
172 |
| - latitude_end: float = -1.0 # e.g. 51.4421000 |
173 |
| - longitude_end: float = -1.0 # e.g. 18.3417000 |
174 |
| - |
175 |
| - @classmethod |
176 |
| - def read(cls, path: Path) -> "ProjectMeta": |
177 |
| - """ |
178 |
| - Read a metadata.txt file and return a ProjectMeta instance with fields |
179 |
| - populated from the file. |
180 |
| - """ |
181 |
| - meta = ProjectMeta() |
182 |
| - with open(path, "r") as strm: |
183 |
| - for line in strm: |
184 |
| - if "=" in line: |
185 |
| - key, value = line.split("=", 1) |
186 |
| - key = key.strip() |
187 |
| - value = value.strip() |
188 |
| - |
189 |
| - if hasattr(meta, key): |
190 |
| - field_type = type(getattr(meta, key)) |
191 |
| - try: |
192 |
| - if field_type == int: |
193 |
| - setattr(meta, key, int(value)) |
194 |
| - elif field_type == float: |
195 |
| - setattr(meta, key, float(value)) |
196 |
| - else: |
197 |
| - setattr(meta, key, value) |
198 |
| - except ValueError: |
199 |
| - # If conversion fails, keep as string |
200 |
| - setattr(meta, key, value) |
201 |
| - else: |
202 |
| - # For any fields not explicitly defined, add them as strings |
203 |
| - setattr(meta, key, value) |
204 |
| - |
205 |
| - return meta |
206 |
| - |
207 |
| - def _relevant_attributes(self): |
208 |
| - """ |
209 |
| - Generator that yields relevant attributes for writing to a metadata file. |
210 |
| - Yields tuples of (attr_name, attr_value) for non-default attributes. |
211 |
| - """ |
212 |
| - for attr_name in dir(self): |
213 |
| - # Skip special attributes, methods, and class variables |
214 |
| - if ( |
215 |
| - attr_name.startswith("__") |
216 |
| - or callable(getattr(self, attr_name)) |
217 |
| - or attr_name == "__annotations__" |
218 |
| - ): |
219 |
| - continue |
220 |
| - |
221 |
| - # Get the attribute value |
222 |
| - attr_value = getattr(self, attr_name) |
223 |
| - |
224 |
| - # Skip default values for primitive types |
225 |
| - if attr_value == "" or attr_value == -1 or attr_value == -1.0: |
226 |
| - continue |
227 |
| - |
228 |
| - yield attr_name, attr_value |
229 |
| - |
230 |
| - def to_dict(self) -> dict: |
231 |
| - """ |
232 |
| - Convert the ProjectMeta instance to a dictionary using the _relevant_attributes generator. |
233 |
| - Returns a dictionary with attribute names as keys and their values as values. |
234 |
| - """ |
235 |
| - return { |
236 |
| - attr_name: attr_value |
237 |
| - for attr_name, attr_value in self._relevant_attributes() |
238 |
| - } |
239 |
| - |
240 |
| - def write(self, path: Path) -> None: |
241 |
| - """ |
242 |
| - Write the ProjectMeta instance to a metadata.txt file in the same format |
243 |
| - as it is read. |
244 |
| - """ |
245 |
| - with open(path, "w") as strm: |
246 |
| - # Write all relevant attributes to the file |
247 |
| - for attr_name, attr_value in self._relevant_attributes(): |
248 |
| - strm.write(f"{attr_name}= {attr_value}\n") |
0 commit comments