freva-client 2502.0.0__py3-none-any.whl → 2506.0.0__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 freva-client might be problematic. Click here for more details.

freva_client/query.py CHANGED
@@ -44,12 +44,12 @@ class databrowser:
44
44
  Parameters
45
45
  ~~~~~~~~~~
46
46
 
47
- *facets: str
47
+ facets: str
48
48
  If you are not sure about the correct search key's you can use
49
49
  positional arguments to search of any matching entries. For example
50
50
  'era5' would allow you to search for any entries
51
51
  containing era5, regardless of project, product etc.
52
- **search_keys: str
52
+ search_keys: str
53
53
  The search constraints applied in the data search. If not given
54
54
  the whole dataset will be queried.
55
55
  flavour: str, default: freva
@@ -63,8 +63,10 @@ class databrowser:
63
63
  timestamp. The timestamps has to follow ISO-8601. Valid strings are
64
64
  ``%Y-%m-%dT%H:%M to %Y-%m-%dT%H:%M`` for time ranges or
65
65
  ``%Y-%m-%dT%H:%M`` for single time stamps.
66
- **Note**: You don't have to give the full string format to subset
67
- time steps: `%Y`, `%Y-%m` etc are also valid.
66
+
67
+ .. note:: You don't have to give the full string format to subset time
68
+ steps ``%Y``, ``%Y-%m`` etc are also valid.
69
+
68
70
  time_select: str, default: flexible
69
71
  Operator that specifies how the time period is selected. Choose from
70
72
  flexible (default), strict or file. ``strict`` returns only those files
@@ -74,11 +76,25 @@ class databrowser:
74
76
  ``flexible`` returns those files that have either start or end period
75
77
  covered. ``file`` will only return files where the entire time
76
78
  period is contained within `one single` file.
79
+ bbox: str, default: ""
80
+ Special search facet to refine/subset search results by spatial extent.
81
+ This can be a list representation of a bounding box or a WKT polygon.
82
+ Valid lists are ``min_lon max_lon min_lat max_lat`` for bounding
83
+ boxes and Well-Known Text (WKT) format for polygons.
84
+
85
+ bbox_select: str, default: flexible
86
+ Operator that specifies how the spatial extent is selected. Choose from
87
+ flexible (default), strict or file. ``strict`` returns only those files
88
+ that fully contain the query extent. The bbox search ``-10 10 -10 10``
89
+ will not select files covering only ``0 5 0 5`` with the ``strict``
90
+ method. ``flexible`` will select those files as it returns files that
91
+ have any overlap with the query extent. ``file`` will only return files
92
+ where the entire spatial extent is contained by the query geometry.
77
93
  uniq_key: str, default: file
78
94
  Chose if the solr search query should return paths to files or
79
95
  uris, uris will have the file path along with protocol of the storage
80
- system. Uris can be useful if the search query result should be
81
- used libraries like fsspec.
96
+ system. URIs are useful when working with libraries like fsspec, which
97
+ require protocol information.
82
98
  host: str, default: None
83
99
  Override the host name of the databrowser server. This is usually the
84
100
  url where the freva web site can be found. Such as www.freva.dkrz.de.
@@ -112,7 +128,7 @@ class databrowser:
112
128
  databrowser class using the ``experiment`` search constraint.
113
129
  If you just 'print' the created object you will get a quick overview:
114
130
 
115
- .. execute_code::
131
+ .. code-block:: python
116
132
 
117
133
  from freva_client import databrowser
118
134
  db = databrowser(experiment="cmorph", uniq_key="uri")
@@ -121,7 +137,7 @@ class databrowser:
121
137
  After having created the search object you can acquire different kinds of
122
138
  information like the number of found objects:
123
139
 
124
- .. execute_code::
140
+ .. code-block:: python
125
141
 
126
142
  from freva_client import databrowser
127
143
  db = databrowser(experiment="cmorph", uniq_key="uri")
@@ -130,7 +146,7 @@ class databrowser:
130
146
 
131
147
  Or you can retrieve the combined metadata of the search objects.
132
148
 
133
- .. execute_code::
149
+ .. code-block:: python
134
150
 
135
151
  from freva_client import databrowser
136
152
  db = databrowser(experiment="cmorph", uniq_key="uri")
@@ -138,7 +154,7 @@ class databrowser:
138
154
 
139
155
  Most importantly you can retrieve the locations of all encountered objects
140
156
 
141
- .. execute_code::
157
+ .. code-block:: python
142
158
 
143
159
  from freva_client import databrowser
144
160
  db = databrowser(experiment="cmorph", uniq_key="uri")
@@ -151,7 +167,7 @@ class databrowser:
151
167
  You can also set a different flavour, for example according to cmip6
152
168
  standard:
153
169
 
154
- .. execute_code::
170
+ .. code-block:: python
155
171
 
156
172
  from freva_client import databrowser
157
173
  db = databrowser(flavour="cmip6", experiment_id="cmorph")
@@ -163,7 +179,7 @@ class databrowser:
163
179
  for getting all ocean reanalysis datasets you can apply the 'reana*'
164
180
  search key as a positional argument:
165
181
 
166
- .. execute_code::
182
+ .. code-block:: python
167
183
 
168
184
  from freva_client import databrowser
169
185
  db = databrowser("reana*", realm="ocean", flavour="cmip6")
@@ -179,17 +195,15 @@ class databrowser:
179
195
  before you are able to access the data. Refer also to the
180
196
  :py:meth:`freva_client.authenticate` method.
181
197
 
182
- .. execute_code::
198
+ .. code-block:: python
183
199
 
184
- from freva_client import authenticate, databrowser
185
- token_info = authenticate(username="janedoe")
200
+ from freva_client import databrowser
186
201
  db = databrowser(dataset="cmip6-fs", stream_zarr=True)
187
202
  zarr_files = list(db)
188
- print(zarr_files)
189
203
 
190
204
  After you have created the paths to the zarr files you can open them
191
205
 
192
- ::
206
+ .. code-block:: python
193
207
 
194
208
  import xarray as xr
195
209
  dset = xr.open_dataset(
@@ -214,6 +228,8 @@ class databrowser:
214
228
  time: Optional[str] = None,
215
229
  host: Optional[str] = None,
216
230
  time_select: Literal["flexible", "strict", "file"] = "flexible",
231
+ bbox: Optional[Tuple[float, float, float, float]] = None,
232
+ bbox_select: Literal["flexible", "strict", "file"] = "flexible",
217
233
  stream_zarr: bool = False,
218
234
  multiversion: bool = False,
219
235
  fail_on_error: bool = False,
@@ -238,6 +254,10 @@ class databrowser:
238
254
  if time:
239
255
  self._params["time"] = time
240
256
  self._params["time_select"] = time_select
257
+ if bbox:
258
+ bbox_str = ",".join(map(str, bbox))
259
+ self._params["bbox"] = bbox_str
260
+ self._params["bbox_select"] = bbox_select
241
261
  if facets:
242
262
  self._add_search_keyword_args_from_facet(facets, facet_search)
243
263
 
@@ -269,7 +289,7 @@ class databrowser:
269
289
  headers = {}
270
290
  if self._stream_zarr:
271
291
  query_url = self._cfg.zarr_loader_url
272
- token = self._auth.check_authentication(auth_url=self._cfg.auth_url)
292
+ token = self._auth.authenticate(config=self._cfg)
273
293
  headers = {"Authorization": f"Bearer {token['access_token']}"}
274
294
  result = self._request("GET", query_url, headers=headers, stream=True)
275
295
  if result is not None:
@@ -328,7 +348,7 @@ class databrowser:
328
348
 
329
349
  Example
330
350
  ~~~~~~~
331
- .. execute_code::
351
+ .. code-block:: python
332
352
 
333
353
  from freva_client import databrowser
334
354
  print(len(databrowser(experiment="cmorph")))
@@ -345,7 +365,7 @@ class databrowser:
345
365
  kwargs: Dict[str, Any] = {"stream": True}
346
366
  url = self._cfg.intake_url
347
367
  if self._stream_zarr:
348
- token = self._auth.check_authentication(auth_url=self._cfg.auth_url)
368
+ token = self._auth.authenticate(config=self._cfg)
349
369
  url = self._cfg.zarr_loader_url
350
370
  kwargs["headers"] = {
351
371
  "Authorization": f"Bearer {token['access_token']}"
@@ -385,7 +405,7 @@ class databrowser:
385
405
  Let's create an intake-esm catalogue that points points allows for
386
406
  streaming the target data as zarr:
387
407
 
388
- .. execute_code::
408
+ .. code-block:: python
389
409
 
390
410
  from freva_client import databrowser
391
411
  db = databrowser(dataset="cmip6-hsm", stream_zarr=True)
@@ -399,6 +419,84 @@ class databrowser:
399
419
  intake.open_esm_datastore(temp_f.name),
400
420
  )
401
421
 
422
+ def stac_catalogue(
423
+ self,
424
+ filename: Optional[Union[str, Path]] = None,
425
+ **kwargs: Any,
426
+ ) -> str:
427
+ """Create a static STAC catalogue from
428
+ the search.
429
+
430
+ Parameters
431
+ ~~~~~~~~~~
432
+ filename: str, default: None
433
+ The filename of the STAC catalogue. If not given
434
+ or doesn't exist the STAC catalogue will be saved
435
+ to the current working directory.
436
+ kwargs: Any
437
+ Additional keyword arguments to be passed to the request.
438
+
439
+ Returns
440
+ ~~~~~~~
441
+ BinaryIO
442
+ A zip file stream
443
+
444
+ Raises
445
+ ~~~~~~
446
+ ValueError: If stac-catalogue creation failed.
447
+
448
+ Example
449
+ ~~~~~~~
450
+ Let's create a static STAC catalogue:
451
+
452
+ .. code-block:: python
453
+
454
+ from tempfile import mktemp
455
+ temp_path = mktemp(suffix=".zip")
456
+
457
+ from freva_client import databrowser
458
+ db = databrowser(dataset="cmip6-hsm")
459
+ db.stac_catalogue(filename=temp_path)
460
+ print(f"STAC catalog saved to: {temp_path}")
461
+
462
+ """
463
+
464
+ kwargs.update({"stream": True})
465
+ stac_url = self._cfg.stac_url
466
+ pprint("[b][green]Downloading the STAC catalog started ...[green][b]")
467
+ result = self._request("GET", stac_url, **kwargs)
468
+ if result is None or result.status_code == 404:
469
+ raise ValueError( # pragma: no cover
470
+ "No STAC catalog found. Please check if you have any search results."
471
+ )
472
+ default_filename = (
473
+ result.headers.get("Content-Disposition", "")
474
+ .split("filename=")[-1]
475
+ .strip('"')
476
+ )
477
+
478
+ if filename is None:
479
+ save_path = Path.cwd() / default_filename
480
+ else:
481
+ save_path = Path(cast(str, filename))
482
+ if save_path.is_dir() and save_path.exists():
483
+ save_path = save_path / default_filename
484
+
485
+ save_path.parent.mkdir(parents=True, exist_ok=True)
486
+
487
+ total_size = 0
488
+ with open(save_path, "wb") as f:
489
+ for chunk in result.iter_content(chunk_size=8192):
490
+ if chunk:
491
+ f.write(chunk)
492
+ total_size += len(chunk)
493
+
494
+ return (
495
+ f"STAC catalog saved to: {save_path} "
496
+ f"(size: {total_size / 1024 / 1024:.2f} MB). "
497
+ f"Or simply download from: {result.url}"
498
+ )
499
+
402
500
  @classmethod
403
501
  def count_values(
404
502
  cls,
@@ -409,6 +507,8 @@ class databrowser:
409
507
  time: Optional[str] = None,
410
508
  host: Optional[str] = None,
411
509
  time_select: Literal["flexible", "strict", "file"] = "flexible",
510
+ bbox: Optional[Tuple[float, float, float, float]] = None,
511
+ bbox_select: Literal["flexible", "strict", "file"] = "flexible",
412
512
  multiversion: bool = False,
413
513
  fail_on_error: bool = False,
414
514
  extended_search: bool = False,
@@ -419,7 +519,7 @@ class databrowser:
419
519
  Parameters
420
520
  ~~~~~~~~~~
421
521
 
422
- *facets: str
522
+ facets: str
423
523
  If you are not sure about the correct search key's you can use
424
524
  positional arguments to search of any matching entries. For example
425
525
  'era5' would allow you to search for any entries
@@ -432,8 +532,11 @@ class databrowser:
432
532
  This can be a string representation of a time range or a single
433
533
  timestamp. The timestamp has to follow ISO-8601. Valid strings are
434
534
  ``%Y-%m-%dT%H:%M`` to ``%Y-%m-%dT%H:%M`` for time ranges and
435
- ``%Y-%m-%dT%H:%M``. **Note**: You don't have to give the full string
436
- format to subset time steps ``%Y``, ``%Y-%m`` etc are also valid.
535
+ ``%Y-%m-%dT%H:%M``.
536
+
537
+ .. note:: You don't have to give the full string format to subset time
538
+ steps ``%Y``, ``%Y-%m`` etc are also valid.
539
+
437
540
  time_select: str, default: flexible
438
541
  Operator that specifies how the time period is selected. Choose from
439
542
  flexible (default), strict or file. ``strict`` returns only those files
@@ -443,6 +546,20 @@ class databrowser:
443
546
  ``flexible`` returns those files that have either start or end period
444
547
  covered. ``file`` will only return files where the entire time
445
548
  period is contained within `one single` file.
549
+ bbox: str, default: ""
550
+ Special search facet to refine/subset search results by spatial extent.
551
+ This can be a list representation of a bounding box or a WKT polygon.
552
+ Valid lists are ``min_lon max_lon min_lat max_lat`` for bounding
553
+ boxes and Well-Known Text (WKT) format for polygons.
554
+
555
+ bbox_select: str, default: flexible
556
+ Operator that specifies how the spatial extent is selected. Choose from
557
+ flexible (default), strict or file. ``strict`` returns only those files
558
+ that fully contain the query extent. The bbox search ``-10 10 -10 10``
559
+ will not select files covering only ``0 5 0 5`` with the ``strict``
560
+ method. ``flexible`` will select those files as it returns files that
561
+ have any overlap with the query extent. ``file`` will only return files
562
+ where the entire spatial extent is contained by the query geometry.
446
563
  extended_search: bool, default: False
447
564
  Retrieve information on additional search keys.
448
565
  host: str, default: None
@@ -455,7 +572,7 @@ class databrowser:
455
572
  fail_on_error: bool, default: False
456
573
  Make the call fail if the connection to the databrowser could not
457
574
  be established.
458
- **search_keys: str
575
+ search_keys: str
459
576
  The search constraints to be applied in the data search. If not given
460
577
  the whole dataset will be queried.
461
578
 
@@ -468,12 +585,12 @@ class databrowser:
468
585
  Example
469
586
  ~~~~~~~
470
587
 
471
- .. execute_code::
588
+ .. code-block:: python
472
589
 
473
590
  from freva_client import databrowser
474
591
  print(databrowser.count_values(experiment="cmorph"))
475
592
 
476
- .. execute_code::
593
+ .. code-block:: python
477
594
 
478
595
  from freva_client import databrowser
479
596
  print(databrowser.count_values("model"))
@@ -483,7 +600,7 @@ class databrowser:
483
600
  example for getting all ocean reanalysis datasets you can apply the
484
601
  'reana*' search key as a positional argument:
485
602
 
486
- .. execute_code::
603
+ .. code-block:: python
487
604
 
488
605
  from freva_client import databrowser
489
606
  print(databrowser.count_values("reana*", realm="ocean", flavour="cmip6"))
@@ -494,6 +611,8 @@ class databrowser:
494
611
  flavour=flavour,
495
612
  time=time,
496
613
  time_select=time_select,
614
+ bbox=bbox,
615
+ bbox_select=bbox_select,
497
616
  host=host,
498
617
  multiversion=multiversion,
499
618
  fail_on_error=fail_on_error,
@@ -522,7 +641,7 @@ class databrowser:
522
641
 
523
642
  Reverse search: retrieving meta data from a known file
524
643
 
525
- .. execute_code::
644
+ .. code-block:: python
526
645
 
527
646
  from freva_client import databrowser
528
647
  db = databrowser(uri="slk:///arch/*/CPC/*")
@@ -545,6 +664,8 @@ class databrowser:
545
664
  time: Optional[str] = None,
546
665
  host: Optional[str] = None,
547
666
  time_select: Literal["flexible", "strict", "file"] = "flexible",
667
+ bbox: Optional[Tuple[float, float, float, float]] = None,
668
+ bbox_select: Literal["flexible", "strict", "file"] = "flexible",
548
669
  multiversion: bool = False,
549
670
  fail_on_error: bool = False,
550
671
  extended_search: bool = False,
@@ -558,7 +679,7 @@ class databrowser:
558
679
  Parameters
559
680
  ~~~~~~~~~~
560
681
 
561
- *facets: str
682
+ facets: str
562
683
  If you are not sure about the correct search key's you can use
563
684
  positional arguments to search of any matching entries. For example
564
685
  'era5' would allow you to search for any entries
@@ -571,8 +692,11 @@ class databrowser:
571
692
  This can be a string representation of a time range or a single
572
693
  timestamp. The timestamp has to follow ISO-8601. Valid strings are
573
694
  ``%Y-%m-%dT%H:%M`` to ``%Y-%m-%dT%H:%M`` for time ranges and
574
- ``%Y-%m-%dT%H:%M``. **Note**: You don't have to give the full string
575
- format to subset time steps ``%Y``, ``%Y-%m`` etc are also valid.
695
+ ``%Y-%m-%dT%H:%M``.
696
+
697
+ .. note:: You don't have to give the full string format to subset time
698
+ steps ``%Y``, ``%Y-%m`` etc are also valid.
699
+
576
700
  time_select: str, default: flexible
577
701
  Operator that specifies how the time period is selected. Choose from
578
702
  flexible (default), strict or file. ``strict`` returns only those files
@@ -582,6 +706,20 @@ class databrowser:
582
706
  ``flexible`` returns those files that have either start or end period
583
707
  covered. ``file`` will only return files where the entire time
584
708
  period is contained within *one single* file.
709
+ bbox: str, default: ""
710
+ Special search facet to refine/subset search results by spatial extent.
711
+ This can be a list representation of a bounding box or a WKT polygon.
712
+ Valid lists are ``min_lon max_lon min_lat max_lat`` for bounding
713
+ boxes and Well-Known Text (WKT) format for polygons.
714
+
715
+ bbox_select: str, default: flexible
716
+ Operator that specifies how the spatial extent is selected. Choose from
717
+ flexible (default), strict or file. ``strict`` returns only those files
718
+ that fully contain the query extent. The bbox search ``-10 10 -10 10``
719
+ will not select files covering only ``0 5 0 5`` with the ``strict``
720
+ method. ``flexible`` will select those files as it returns files that
721
+ have any overlap with the query extent. ``file`` will only return files
722
+ where the entire spatial extent is contained by the query geometry.
585
723
  extended_search: bool, default: False
586
724
  Retrieve information on additional search keys.
587
725
  multiversion: bool, default: False
@@ -594,7 +732,7 @@ class databrowser:
594
732
  fail_on_error: bool, default: False
595
733
  Make the call fail if the connection to the databrowser could not
596
734
  be established.
597
- **search_keys: str, list[str]
735
+ search_keys: str, list[str]
598
736
  The facets to be applied in the data search. If not given
599
737
  the whole dataset will be queried.
600
738
 
@@ -607,7 +745,7 @@ class databrowser:
607
745
  Example
608
746
  ~~~~~~~
609
747
 
610
- .. execute_code::
748
+ .. code-block:: python
611
749
 
612
750
  from freva_client import databrowser
613
751
  all_facets = databrowser.metadata_search(project='obs*')
@@ -615,7 +753,7 @@ class databrowser:
615
753
 
616
754
  You can also search for all metadata matching a search string:
617
755
 
618
- .. execute_code::
756
+ .. code-block:: python
619
757
 
620
758
  from freva_client import databrowser
621
759
  spec_facets = databrowser.metadata_search("obs*")
@@ -623,7 +761,7 @@ class databrowser:
623
761
 
624
762
  Get all models that have a given time step:
625
763
 
626
- .. execute_code::
764
+ .. code-block:: python
627
765
 
628
766
  from freva_client import databrowser
629
767
  model = databrowser.metadata_search(
@@ -634,7 +772,7 @@ class databrowser:
634
772
 
635
773
  Reverse search: retrieving meta data from a known file
636
774
 
637
- .. execute_code::
775
+ .. code-block:: python
638
776
 
639
777
  from freva_client import databrowser
640
778
  res = databrowser.metadata_search(file="/arch/*CPC/*")
@@ -645,17 +783,35 @@ class databrowser:
645
783
  example for getting all ocean reanalysis datasets you can apply the
646
784
  'reana*' search key as a positional argument:
647
785
 
648
- .. execute_code::
786
+ .. code-block:: python
649
787
 
650
788
  from freva_client import databrowser
651
789
  print(databrowser.metadata_search("reana*", realm="ocean", flavour="cmip6"))
652
790
 
791
+ In datasets with multiple versions only the `latest` version (i.e.
792
+ `highest` version number) is returned by default. Querying a specific
793
+ version from a multi versioned datasets requires the ``multiversion``
794
+ flag in combination with the ``version`` special attribute:
795
+
796
+ .. code-block:: python
797
+
798
+ from freva_client import databrowser
799
+ res = databrowser.metadata_search(dataset="cmip6-fs",
800
+ model="access-cm2", version="v20191108", extended_search=True,
801
+ multiversion=True)
802
+ print(res)
803
+
804
+ If no particular ``version`` is requested, information of all versions
805
+ will be returned.
806
+
653
807
  """
654
808
  this = cls(
655
809
  *facets,
656
810
  flavour=flavour,
657
811
  time=time,
658
812
  time_select=time_select,
813
+ bbox=bbox,
814
+ bbox_select=bbox_select,
659
815
  host=host,
660
816
  multiversion=multiversion,
661
817
  fail_on_error=fail_on_error,
@@ -694,7 +850,7 @@ class databrowser:
694
850
  Example
695
851
  ~~~~~~~
696
852
 
697
- .. execute_code::
853
+ .. code-block:: python
698
854
 
699
855
  from freva_client import databrowser
700
856
  print(databrowser.overview())
@@ -711,7 +867,7 @@ class databrowser:
711
867
  Example
712
868
  ~~~~~~~
713
869
 
714
- .. execute_code::
870
+ .. code-block:: python
715
871
 
716
872
  from freva_client import databrowser
717
873
  db = databrowser()
@@ -790,11 +946,10 @@ class databrowser:
790
946
 
791
947
  Adding user data:
792
948
 
793
- .. execute_code::
949
+ .. code-block:: python
794
950
 
795
- from freva_client import authenticate, databrowser
951
+ from freva_client import databrowser
796
952
  import xarray as xr
797
- token_info = authenticate(username="janedoe")
798
953
  filenames = (
799
954
  "../freva-rest/src/freva_rest/databrowser_api/mock/data/model/regional/cordex/output/EUR-11/"
800
955
  "GERICS/NCC-NorESM1-M/rcp85/r1i1p1/GERICS-REMO2015/v1/3hr/pr/v20181212/*.nc"
@@ -813,10 +968,9 @@ class databrowser:
813
968
 
814
969
  Deleting user data:
815
970
 
816
- .. execute_code::
971
+ .. code-block:: python
817
972
 
818
- from freva_client import authenticate, databrowser
819
- token_info = authenticate(username="janedoe")
973
+ from freva_client import databrowser
820
974
  databrowser.userdata(
821
975
  action="delete",
822
976
  metadata={"project": "cmip5", "experiment": "myFavExp"}
@@ -829,7 +983,7 @@ class databrowser:
829
983
  userdata_items = userdata_items or []
830
984
  metadata = metadata or {}
831
985
  url = f"{this._cfg.userdata_url}"
832
- token = this._auth.check_authentication(auth_url=this._cfg.auth_url)
986
+ token = this._auth.authenticate(config=this._cfg)
833
987
  headers = {"Authorization": f"Bearer {token['access_token']}"}
834
988
  payload_metadata: dict[str, Collection[Collection[str]]] = {}
835
989