• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Ouranosinc / miranda / 2197509238

pending completion
2197509238

Pull #33

github

GitHub
Merge ddfe0e667 into d55f76503
Pull Request #33: Support CORDEX and CMIP5/6

2 of 26 new or added lines in 5 files covered. (7.69%)

571 existing lines in 15 files now uncovered.

737 of 3286 relevant lines covered (22.43%)

0.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

14.95
/miranda/decode/_decoder.py
1
import logging
3✔
2
import multiprocessing as mp
3✔
3
import os
3✔
4
import warnings
3✔
5
from functools import partial
3✔
6
from logging import config
3✔
7
from os import PathLike
3✔
8
from pathlib import Path
3✔
9
from types import GeneratorType
3✔
10
from typing import Dict, List, Optional, Union
3✔
11

12
import netCDF4 as nc  # noqa
3✔
13
import pandas as pd
3✔
14
import schema
3✔
15
import zarr
3✔
16
from pandas._libs.tslibs import NaTType  # noqa
3✔
17

18
from miranda.cv import INSTITUTIONS, PROJECT_MODELS
3✔
19
from miranda.scripting import LOGGING_CONFIG
3✔
20

21
from ._time import (
3✔
22
    TIME_UNITS_TO_FREQUENCY,
23
    TIME_UNITS_TO_TIMEDELTA,
24
    DecoderError,
25
    date_parser,
26
)
27

28
config.dictConfig(LOGGING_CONFIG)
3✔
29

30
__all__ = [
3✔
31
    "Decoder",
32
    "guess_project",
33
]
34

35

36
def guess_project(file: Union[os.PathLike, str]) -> str:
3✔
UNCOV
37
    file_name = Path(file).stem
×
38

39
    potential_names = file_name.split("_")
×
UNCOV
40
    for project, models in PROJECT_MODELS.items():
×
41
        if any([model in potential_names for model in models]):
×
42
            return project
×
43
    raise DecoderError(f"Unable to determine project from file name: '{file_name}'.")
×
44

45

46
class Decoder:
3✔
47

48
    project = None
3✔
49
    _file_facets = dict()
3✔
50

51
    def __init__(self, project: Optional[str]):
3✔
UNCOV
52
        self.project = project
×
53

54
    @staticmethod
3✔
55
    def _decoder(
3✔
56
        d: dict,
57
        m: str,
58
        fail_early: bool,
59
        proj: str,
60
        lock,
61
        file: Union[str, Path],
62
    ) -> None:
63
        """lock is a threading lock object"""
64
        with lock:
×
65
            if proj is None:
×
66
                try:
×
67
                    proj = guess_project(file)
×
68
                except DecoderError:
×
69
                    print(
×
70
                        f"Unable to determine 'project': Signature for 'project' must be set manually for file: {file}."
71
                    )
72
                    if fail_early:
×
73
                        raise
×
74

75
            decode_function_name = f"decode_{proj.lower().replace('-','_')}_{m}"
×
UNCOV
76
            try:
×
UNCOV
77
                _deciphered = getattr(Decoder, decode_function_name)(Path(file))
×
78
                # FACETS_SCHEMA.validate(_deciphered)
79
                print(
×
80
                    f"Deciphered the following from {Path(file).name}: {_deciphered.items()}"
81
                )
82
                d[file] = _deciphered
×
83
            except AttributeError as e:
×
84
                print(f"Unable to read data from {Path(file).name}: {e}")
×
85
            except schema.SchemaError as e:
×
UNCOV
86
                print(f"Decoded facets from {Path(file).name} are not valid: {e}")
×
87

88
    def decode(
3✔
89
        self,
90
        files: Union[os.PathLike, str, List[Union[str, os.PathLike]], GeneratorType],
91
        method: str = "data",
92
        raise_error: bool = False,
93
    ):
94
        """Decode facets from file or list of files.
95

96
        Parameters
97
        ----------
98
        files: Union[str, Path, List[Union[str, Path]]]
99
        method: {"data", "name"}
100
        raise_error: bool
101
        """
102

UNCOV
103
        if isinstance(files, (str, os.PathLike)):
×
UNCOV
104
            files = [files]
×
UNCOV
105
        if self.project is None:
×
UNCOV
106
            warnings.warn(
×
107
                "The decoder 'project' is not set; Decoding step will be much slower."
108
            )
109
        else:
110
            logging.info(f"Deciphering metadata with project = '{self.project}'")
×
111
        manager = mp.Manager()
×
UNCOV
112
        _file_facets = manager.dict()
×
UNCOV
113
        lock = manager.Lock()
×
UNCOV
114
        func = partial(
×
115
            self._decoder, _file_facets, method, raise_error, self.project, lock
116
        )
117

118
        with mp.Pool() as pool:
×
119
            pool.imap(func, files, chunksize=10)
×
UNCOV
120
            pool.close()
×
121
            pool.join()
×
122

123
        self._file_facets.update(_file_facets)
×
124

125
    def facets_table(self):
3✔
126
        raise NotImplementedError()
×
127

128
    def file_facets(self) -> Dict[os.PathLike, Dict]:
3✔
129
        return self._file_facets
×
130

131
    @staticmethod
3✔
132
    def guess_project(file: Union[Path, str]) -> str:
3✔
UNCOV
133
        file_name = Path(file).stem
×
134

UNCOV
135
        potential_names = file_name.split("_")
×
136
        for project, models in PROJECT_MODELS.items():
×
UNCOV
137
            if any([model in potential_names for model in models]):
×
138
                return project
×
139
        raise DecoderError("Unable to determine project from file name.")
×
140

141
    @classmethod
3✔
142
    def _from_dataset(cls, file: Union[Path, str]) -> (str, str, Dict):
3✔
143
        file_name = Path(file).stem
×
144

145
        variable_name = cls._decode_primary_variable(file)
×
146
        variable_date = file_name.split("_")[-1]
×
147

148
        if file.is_file() and file.suffix in [".nc", ".nc4"]:
×
UNCOV
149
            ds = nc.Dataset(file)
×
150
            data = dict()
×
151
            for k in ds.ncattrs():
×
UNCOV
152
                data[k] = getattr(ds, k)
×
UNCOV
153
        elif file.is_dir() and file.suffix == ".zarr":
×
UNCOV
154
            ds = zarr.open(file, mode="r")
×
UNCOV
155
            data = ds.attrs.asdict()
×
156
        else:
UNCOV
157
            raise DecoderError("Unable to read dataset.")
×
UNCOV
158
        return variable_name, variable_date, data
×
159

160
    @staticmethod
3✔
161
    def _from_filename(file: Union[Path, str]) -> List[str]:
3✔
UNCOV
162
        file_name = Path(file).stem
×
UNCOV
163
        decode_file = file_name.split("_")
×
UNCOV
164
        return decode_file
×
165

166
    @staticmethod
3✔
167
    def _decode_primary_variable(file: Path) -> str:
3✔
168
        """Attempts to find the primary variable of a netCDF
169

170
        Parameters
171
        ----------
172
        file: Union[Path, str]
173

174
        Returns
175
        -------
176
        str
177
        """
UNCOV
178
        dimsvar_dict = dict()
×
179
        coords = ("time", "lat", "lon", "rlat", "rlon", "height", "lev", "rotated_pole")
×
180
        suggested_variable = file.name.split("_")[0]
×
181

182
        if file.is_file() and file.suffix in [".nc", ".nc4"]:
×
183
            data = nc.Dataset(file, mode="r")
×
UNCOV
184
            for var_name, var_attrs in data.variables.items():
×
185
                dimsvar_dict[var_name] = {
×
186
                    k: var_attrs.getncattr(k) for k in var_attrs.ncattrs()
187
                }
UNCOV
188
            for k in dimsvar_dict.keys():
×
UNCOV
189
                if not str(k).startswith(coords) and suggested_variable == k:
×
UNCOV
190
                    return str(k)
×
191

UNCOV
192
        elif file.is_dir() and file.suffix == ".zarr":
×
UNCOV
193
            data = zarr.open(str(file), mode="r")
×
UNCOV
194
            for k in data.array_keys():
×
UNCOV
195
                if not str(k).startswith(coords) and suggested_variable == k:
×
UNCOV
196
                    return str(k)
×
197
        else:
198
            raise NotImplementedError()
×
199

200
    @staticmethod
3✔
201
    def _decode_time_info(
3✔
202
        file: Optional[Union[PathLike, str, List[str]]] = None,
203
        data: Optional[Dict] = None,
204
        *,
205
        field: str,
206
    ) -> Union[str, NaTType]:
207
        """
208

209
        Parameters
210
        ----------
211
        file
212
        data
213
        field: {"timedelta", "frequency"}
214

215
        Returns
216
        -------
217

218
        """
219
        if not file and not data:
×
220
            raise ValueError()
×
221

222
        if field == "frequency":
×
223
            time_dictionary = TIME_UNITS_TO_FREQUENCY
×
224
        elif field == "timedelta":
×
225
            time_dictionary = TIME_UNITS_TO_TIMEDELTA
×
226
        else:
227
            raise NotImplementedError()
×
228

229
        if isinstance(file, (str, PathLike)):
×
230
            file = Path(file).name.split("_")
×
231

232
        if isinstance(file, list):
×
233
            potential_times = [segment in file for segment in time_dictionary.keys()]
×
234
            if potential_times:
×
235
                if potential_times[0] in ["fx", "fixed"]:
×
236
                    if field == "timedelta":
×
237
                        return pd.NaT
×
238
                    return "fx"
×
UNCOV
239
                if field == "timedelta":
×
UNCOV
240
                    return pd.to_timedelta(time_dictionary[potential_times[0]])
×
241
                return time_dictionary[potential_times[0]]
×
242
        elif data:
×
UNCOV
243
            potential_time = data["frequency"]
×
244
            if potential_time == "":
×
245
                time_units = data["time"].units
×
246
                potential_time = time_units.split()[0]
×
UNCOV
247
            if field == "timedelta":
×
248
                if potential_time in ["fx", "fixed"]:
×
249
                    return pd.NaT
×
250
                return pd.to_timedelta(time_dictionary[potential_time])
×
251
            return time_dictionary[potential_time]
×
252

253
    @classmethod
3✔
254
    def decode_reanalysis_data(cls, file: Union[PathLike, str]) -> dict:
3✔
255
        variable, date, data = cls._from_dataset(file=file)
×
256

257
        facets = dict()
×
UNCOV
258
        facets.update(data)
×
259
        del facets["history"]
×
260

261
        facets["date"] = date
×
262
        try:  # FIXME: This should be adjusted in files.
×
263
            facets["format"] = data["output_format"]
×
UNCOV
264
        except KeyError:
×
265
            facets["format"] = data["format"]
×
UNCOV
266
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
UNCOV
267
        facets["variable"] = variable
×
268

269
        try:
×
UNCOV
270
            facets["date_start"] = date_parser(date)
×
UNCOV
271
            facets["date_end"] = date_parser(date, end_of_period=True)
×
UNCOV
272
        except DecoderError:
×
273
            pass
×
274

UNCOV
275
        return facets
×
276

277
    @classmethod
3✔
278
    def decode_reanalysis_name(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
279
        raise NotImplementedError()
×
280

281
    @staticmethod
3✔
282
    def decode_eccc_obs(self, file: Union[PathLike, str]) -> dict:
3✔
283
        raise NotImplementedError()
×
284

285
    @staticmethod
3✔
286
    def decode_ahccd_obs(self, file: Union[PathLike, str]) -> dict:
3✔
287
        raise NotImplementedError()
×
288

289
    @staticmethod
3✔
290
    def decode_melcc_obs(self, file: Union[PathLike, str]) -> dict:
3✔
291
        raise NotImplementedError()
×
292

293
    @classmethod
3✔
294
    def decode_pcic_candcs_u6_data(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
295
        variable, date, data = cls._from_dataset(file=file)
×
296

UNCOV
297
        facets = dict()
×
UNCOV
298
        facets["activity"] = data["activity_id"]
×
299
        facets["mip_era"] = data["project_id"]
×
300
        facets["bias_adjust_institution"] = "PCIC"
×
301
        facets["date"] = date
×
302
        facets["domain"] = data["domain"]
×
303
        facets["experiment"] = str(data["GCM__experiment_id"]).replace(",", "-")
×
304
        facets["format"] = "netcdf"
×
305
        facets["frequency"] = data["frequency"]
×
UNCOV
306
        facets["institution"] = data["GCM__institution_id"]
×
307
        facets["member"] = (
×
308
            f"r{data['GCM__realization_index']}"
309
            f"i{data['GCM__initialization_index']}"
310
            f"p{data['GCM__physics_index']}"
311
            f"f{data['GCM__forcing_index']}"
312
        )
313
        # facets["modeling_realm"] = data.realm
UNCOV
314
        facets["processing_level"] = "bias_adjusted"
×
UNCOV
315
        facets["bias_adjust_project"] = "CanDCS-U6"
×
316
        facets["source"] = data["GCM__source_id"]
×
317
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
UNCOV
318
        facets["type"] = "simulation"
×
319
        facets["variable"] = variable
×
320
        facets["version"] = data["GCM__data_specs_version"]
×
321

322
        try:
×
323
            facets["date_start"] = date_parser(date)
×
324
            facets["date_end"] = date_parser(date, end_of_period=True)
×
325
        except DecoderError:
×
326
            pass
×
327

328
        return facets
×
329

330
    @classmethod
3✔
331
    def decode_cmip6_data(cls, file: Union[PathLike, str]) -> dict:
3✔
332
        variable, date, data = cls._from_dataset(file=file)
×
333

334
        facets = dict()
×
NEW
335
        facets["activity"] = data["activity_id"]
×
336
        facets["date"] = date
×
UNCOV
337
        facets["domain"] = "global"
×
NEW
338
        facets["experiment"] = data["experiment_id"]
×
339
        facets["format"] = "netcdf"
×
NEW
340
        facets["frequency"] = data["frequency"]
×
NEW
341
        facets["institution"] = data["institution_id"]
×
NEW
342
        facets["member"] = data["variant_label"]
×
NEW
343
        facets["modeling_realm"] = data["realm"]
×
344
        facets["processing_level"] = "raw"
×
NEW
345
        facets["project"] = data["project"]
×
NEW
346
        facets["mip_era"] = data["mip_era"]
×
NEW
347
        facets["source"] = data["source_id"]
×
348
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
349
        facets["type"] = "simulation"
×
350
        facets["variable"] = variable
×
NEW
UNCOV
351
        facets["version"] = data["version"]
×
352

UNCOV
353
        try:
×
UNCOV
354
            facets["date_start"] = date_parser(date)
×
355
            facets["date_end"] = date_parser(date, end_of_period=True)
×
356
        except DecoderError:
×
UNCOV
357
            pass
×
358

359
        return facets
×
360

361
    # TODO: Remove name-based methods
362
    @classmethod
3✔
363
    def decode_cmip6_name(cls, file: Union[PathLike, str]) -> dict:
3✔
364
        decode_file = cls._from_filename(file=file)
×
365

366
        facets = dict()
×
367
        facets["activity"] = "CMIP"
×
368
        facets["date"] = decode_file[-1]
×
369
        facets["domain"] = "global"
×
370
        facets["experiment"] = decode_file[3]
×
371
        facets["format"] = "netcdf"
×
372
        facets["frequency"] = cls._decode_time_info(file=decode_file, field="frequency")
×
373
        facets["grid_label"] = decode_file[5]
×
UNCOV
374
        facets["member"] = decode_file[4]
×
375
        facets["processing_level"] = "raw"
×
376
        facets["mip_era"] = "CMIP6"
×
377
        facets["source"] = decode_file[2]
×
378
        facets["timedelta"] = cls._decode_time_info(file=decode_file, field="timedelta")
×
379
        facets["type"] = "simulation"
×
380
        facets["variable"] = decode_file[0]
×
381

382
        if "mon" in facets["frequency"]:
×
383
            facets["frequency"] = "mon"
×
384

385
        logging.warning(
×
386
            f"Cannot accurately find institute for model: {facets['source']} based on model name. "
387
            f"Consider parsing this information from the metadata."
388
        )
389

390
        try:
×
UNCOV
391
            facets["date_start"] = date_parser(decode_file[-1])
×
UNCOV
392
            facets["date_end"] = date_parser(decode_file[-1], end_of_period=True)
×
393
        except DecoderError:
×
394
            pass
×
395

UNCOV
396
        return facets
×
397

398
    @classmethod
3✔
399
    def decode_cmip5_data(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
400
        variable, date, data = cls._from_dataset(file=file)
×
401

402
        facets = dict()
×
403
        facets["activity"] = "CMIP"
×
404
        facets["date"] = date
×
UNCOV
405
        facets["domain"] = "global"
×
406
        facets["experiment"] = data["experiment_id"]
×
407
        facets["format"] = "netcdf"
×
408
        facets["frequency"] = cls._decode_time_info(data=data, field="frequency")
×
409
        facets["institution"] = data["institute_id"]
×
410
        facets["member"] = data["parent_experiment_rip"]
×
411
        facets["modeling_realm"] = data["modeling_realm"]
×
412
        facets["processing_level"] = "raw"
×
413
        facets["mip_era"] = data["project_id"]
×
414
        facets["source"] = data["model_id"]
×
415
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
416
        facets["type"] = "simulation"
×
417
        facets["variable"] = variable
×
418

419
        try:
×
420
            facets["date_start"] = date_parser(date)
×
421
            facets["date_end"] = date_parser(date, end_of_period=True)
×
UNCOV
422
        except DecoderError:
×
423
            pass
×
424

425
        return facets
×
426

427
    # TODO: Remove name-based methods
428
    @classmethod
3✔
429
    def decode_cmip5_name(cls, file: Union[PathLike, str]) -> dict:
3✔
430
        decode_file = cls._from_filename(file=file)
×
431

432
        facets = dict()
×
433
        facets["activity"] = "CMIP"
×
434
        facets["date"] = decode_file[-1]
×
UNCOV
435
        facets["domain"] = "global"
×
436
        facets["experiment"] = decode_file[3]
×
UNCOV
437
        facets["format"] = "netcdf"
×
438
        facets["frequency"] = cls._decode_time_info(file=decode_file, field="frequency")
×
439
        facets["member"] = decode_file[4]
×
440
        facets["mip_era"] = "CMIP5"
×
441
        facets["modeling_realm"] = None
×
UNCOV
442
        facets["processing_level"] = "raw"
×
443
        facets["source"] = decode_file[2]
×
444
        facets["variable"] = decode_file[0]
×
UNCOV
445
        facets["timedelta"] = cls._decode_time_info(file=decode_file, field="timedelta")
×
446
        facets["type"] = "simulation"
×
447

448
        logging.warning(
×
449
            f"Cannot accurately find institute for model: {facets['source']} based on model name. "
450
            f"Consider parsing this information from the metadata."
451
        )
452

UNCOV
453
        if "mon" in facets["frequency"]:
×
454
            facets["frequency"] = "mon"
×
455

456
        try:
×
457
            facets["date_start"] = date_parser(decode_file[-1])
×
458
            facets["date_end"] = date_parser(decode_file[-1], end_of_period=True)
×
459
        except DecoderError:
×
460
            pass
×
461

462
        return facets
×
463

464
    @classmethod
3✔
465
    def decode_cordex_data(cls, file: Union[PathLike, str]) -> dict:
3✔
466
        variable, date, data = cls._from_dataset(file=file)
×
467

468
        # FIXME: What to do about our internal data that breaks all established conventions?
469
        facets = dict()
×
470
        facets["activity"] = "CMIP"
×
471
        facets["project"] = "CORDEX"
×
472

UNCOV
473
        if data["project_id"] == "":
×
474
            facets["mip_era"] = "internal"
×
475
        elif data["project_id"] == "CORDEX":
×
476
            facets["mip_era"] = "CMIP5"
×
477

NEW
478
        if date == "r0i0p0":
×
NEW
479
            facets["date"] = "fx"
×
480
        else:
NEW
481
            facets["date"] = date
×
482

483
        try:
×
484
            facets["domain"] = data["CORDEX_domain"].strip()
×
UNCOV
485
        except KeyError:
×
486
            try:
×
UNCOV
487
                facets["domain"] = data["ouranos_domain_name"].strip()
×
UNCOV
488
            except KeyError:
×
489
                msg = f"File {Path(file).name} has a nonstandard domain name."
×
490
                logging.error(msg)
×
UNCOV
491
                raise NotImplementedError(msg)
×
492

493
        driving_institution_parts = str(data["driving_model_id"]).split("-")
×
494
        if driving_institution_parts[0] in INSTITUTIONS:
×
UNCOV
495
            driving_institution = driving_institution_parts[0]
×
496
        elif "-".join(driving_institution_parts[:2]) in INSTITUTIONS:
×
497
            driving_institution = "-".join(driving_institution_parts[:2])
×
498
        elif "-".join(driving_institution_parts[:3]) in INSTITUTIONS:
×
499
            driving_institution = "-".join(driving_institution_parts[:3])
×
500
        else:
501
            raise AttributeError("driving_institution not valid.")
×
502

503
        facets["driving_institution"] = driving_institution
×
504
        facets["driving_model"] = data["driving_model_id"]
×
505
        facets["format"] = "netcdf"
×
506
        facets["frequency"] = cls._decode_time_info(data=data, field="frequency")
×
507

508
        if data["institute_id"].strip() == "Our.":
×
509
            facets["institution"] = "Ouranos"
×
510
        else:
UNCOV
511
            facets["institution"] = data["institute_id"].strip()
×
512

513
        facets["processing_level"] = "raw"
×
514
        facets["source"] = data["model_id"]
×
515
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
516
        facets["type"] = "simulation"
×
UNCOV
517
        facets["variable"] = variable
×
518

UNCOV
519
        try:
×
UNCOV
520
            facets["date_start"] = date_parser(date)
×
UNCOV
521
            facets["date_end"] = date_parser(date, end_of_period=True)
×
UNCOV
522
        except DecoderError:
×
UNCOV
523
            pass
×
524

UNCOV
525
        try:
×
UNCOV
526
            facets["experiment"] = data["experiment_id"].strip()
×
UNCOV
527
        except KeyError:
×
UNCOV
528
            facets["experiment"] = data["driving_experiment_name"].strip()
×
529

UNCOV
530
        try:
×
UNCOV
531
            facets["member"] = data["parent_experiment_rip"].strip()
×
NEW
UNCOV
532
            if facets["member"] == "N/A":
×
NEW
UNCOV
533
                raise KeyError()
×
UNCOV
534
        except KeyError:
×
UNCOV
535
            facets["member"] = data["driving_model_ensemble_member"].strip()
×
536

UNCOV
537
        return facets
×
538

539
    # TODO: Remove name-based methods
540
    @classmethod
3✔
541
    def decode_cordex_name(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
542
        decode_file = cls._from_filename(file=file)
×
543

UNCOV
544
        facets = dict()
×
UNCOV
545
        facets["activity"] = "CMIP"
×
UNCOV
546
        facets["mip_era5"] = "CMIP5"
×
UNCOV
547
        facets["project"] = "CORDEX"
×
548

UNCOV
549
        facets["date"] = decode_file[-1]
×
UNCOV
550
        facets["domain"] = decode_file[1]
×
UNCOV
551
        facets["driving_model"] = "_".join(decode_file[2].split("-")[1:])
×
UNCOV
552
        facets["driving_institution"] = decode_file[2].split("-")[0]
×
UNCOV
553
        facets["experiment"] = decode_file[3]
×
UNCOV
554
        facets["format"] = "netcdf"
×
UNCOV
555
        facets["frequency"] = cls._decode_time_info(file=decode_file, field="frequency")
×
UNCOV
556
        facets["institution"] = decode_file[5].split("-")[0]
×
UNCOV
557
        facets["member"] = decode_file[4].strip()
×
UNCOV
558
        facets["processing_level"] = "raw"
×
UNCOV
559
        facets["source"] = decode_file[5]
×
UNCOV
560
        facets["timedelta"] = cls._decode_time_info(file=decode_file, field="timedelta")
×
UNCOV
561
        facets["type"] = "simulation"
×
UNCOV
562
        facets["variable"] = decode_file[0]
×
563

UNCOV
564
        try:
×
UNCOV
565
            facets["date_start"] = date_parser(decode_file[-1])
×
UNCOV
566
            facets["date_end"] = date_parser(decode_file[-1], end_of_period=True)
×
UNCOV
567
        except DecoderError:
×
UNCOV
568
            pass
×
569

UNCOV
570
        return facets
×
571

572
    @classmethod
3✔
573
    def decode_isimip_ft_data(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
574
        variable, date, data = cls._from_dataset(file=file)
×
575

UNCOV
576
        facets = dict()
×
UNCOV
577
        facets["activity"] = "ISIMIP"
×
UNCOV
578
        facets["mip_era"] = data["project_id"]
×
579

UNCOV
580
        facets["date"] = date
×
UNCOV
581
        facets["domain"] = "global"
×
UNCOV
582
        facets["co2_forcing_id"] = data["co2_forcing_id"]
×
UNCOV
583
        facets["experiment"] = data["experiment_id"]
×
UNCOV
584
        facets["format"] = "netcdf"
×
UNCOV
585
        facets["frequency"] = cls._decode_time_info(data=data, field="frequency")
×
UNCOV
586
        facets["impact_model"] = data["impact_model_id"]
×
UNCOV
587
        facets["institution"] = data["institute_id"]
×
UNCOV
588
        facets["member"] = data["driving_model_ensemble_member"]
×
UNCOV
589
        facets["modeling_realm"] = data["modeling_realm"]
×
UNCOV
590
        facets["social_forcing_id"] = data["social_forcing_id"]
×
UNCOV
591
        facets["source"] = data["model_id"]
×
UNCOV
592
        facets["timedelta"] = cls._decode_time_info(data=data, field="timedelta")
×
UNCOV
593
        facets["type"] = "simulation"
×
UNCOV
594
        facets["variable"] = variable
×
595

UNCOV
596
        try:
×
UNCOV
597
            facets["date_start"] = date_parser(date)
×
UNCOV
598
            facets["date_end"] = date_parser(date, end_of_period=True)
×
UNCOV
599
        except DecoderError:
×
UNCOV
600
            pass
×
601

UNCOV
602
        return facets
×
603

604
    # TODO: Remove name-based methods
605
    @classmethod
3✔
606
    def decode_isimip_ft_name(cls, file: Union[PathLike, str]) -> dict:
3✔
UNCOV
607
        decode_file = cls._from_filename(file=file)
×
608

UNCOV
609
        facets = dict()
×
UNCOV
610
        facets["activity"] = "ISIMIP"
×
UNCOV
611
        facets["mip_era"] = "ISIMIP-FT"
×
612

UNCOV
613
        facets["date"] = decode_file[-1]
×
UNCOV
614
        facets["domain"] = "global"
×
UNCOV
615
        facets["co2_forcing_id"] = decode_file[4]
×
UNCOV
616
        facets["experiment"] = decode_file[2]
×
UNCOV
617
        facets["format"] = "netcdf"
×
UNCOV
618
        facets["frequency"] = cls._decode_time_info(file=decode_file, field="frequency")
×
UNCOV
619
        facets["impact_model_id"] = decode_file[0]
×
UNCOV
620
        facets["institution"] = decode_file[1].split("-")[0]
×
UNCOV
621
        facets["soc_forcing_id"] = decode_file[3]
×
UNCOV
622
        facets["source"] = "-".join(decode_file[1].split("-")[1:])
×
UNCOV
623
        facets["timedelta"] = cls._decode_time_info(file=decode_file, field="timedelta")
×
UNCOV
624
        facets["type"] = "simulation"
×
UNCOV
625
        facets["variable"] = decode_file[-4]
×
626

UNCOV
627
        facets["setup"] = "-".join([facets["source"], facets["experiment"]])
×
628

UNCOV
629
        if facets["co2_forcing_id"] == facets["variable"]:
×
UNCOV
630
            if facets["soc_forcing"] in [
×
631
                "nosoc",
632
                "pressoc",
633
                "ssp1soc",
634
                "ssp2",
635
                "ssp2soc",
636
                "ssp3soc",
637
                "ssp4soc",
638
                "ssp5soc",
639
            ]:
UNCOV
640
                facets["co2_forcing_id"] = "NAco2"
×
UNCOV
641
            elif facets["soc_forcing"] in ["co2", "nocco2", "pico2"]:
×
UNCOV
642
                facets["co2_forcing"] = facets["soc_forcing"]
×
UNCOV
643
                facets["soc_forcing"] = "NAsoc"
×
644

UNCOV
645
        try:
×
UNCOV
646
            facets["date_start"] = date_parser(decode_file[-1])
×
UNCOV
647
            facets["date_end"] = date_parser(decode_file[-1], end_of_period=True)
×
UNCOV
648
        except DecoderError:
×
UNCOV
649
            pass
×
650

UNCOV
651
        return facets
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2024 Coveralls, Inc