cecil 0.0.21__py3-none-any.whl → 0.0.23__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 cecil might be problematic. Click here for more details.

cecil/client.py CHANGED
@@ -1,12 +1,14 @@
1
1
  import os
2
- from typing import Dict, List
3
2
 
4
3
  import pandas as pd
5
4
  import requests
6
5
  import snowflake.connector
6
+ import xarray
7
+
7
8
  from pydantic import BaseModel
8
9
  from requests import auth
9
10
  from cryptography.hazmat.primitives import serialization
11
+ from typing import Dict, List, Optional
10
12
 
11
13
  from .errors import (
12
14
  Error,
@@ -31,8 +33,10 @@ from .models import (
31
33
  TransformationCreate,
32
34
  User,
33
35
  UserCreate,
36
+ DataRequestMetadata,
34
37
  )
35
38
  from .version import __version__
39
+ from .xarray import load_xarray
36
40
 
37
41
 
38
42
  class Client:
@@ -43,9 +47,12 @@ class Client:
43
47
  )
44
48
  self._snowflake_user_creds = None
45
49
 
46
- def create_aoi(self, name: str, geometry: Dict) -> AOI:
50
+ def create_aoi(self, geometry: Dict, external_ref: Optional[str] = None) -> AOI:
47
51
  # TODO: validate geometry
48
- res = self._post(url="/v0/aois", model=AOICreate(name=name, geometry=geometry))
52
+ res = self._post(
53
+ url="/v0/aois",
54
+ model=AOICreate(geometry=geometry, external_ref=external_ref),
55
+ )
49
56
  return AOI(**res)
50
57
 
51
58
  def get_aoi(self, id: str) -> AOI:
@@ -56,10 +63,14 @@ class Client:
56
63
  res = self._get(url="/v0/aois")
57
64
  return [AOIRecord(**record) for record in res["records"]]
58
65
 
59
- def create_data_request(self, aoi_id: str, dataset_id: str) -> DataRequest:
66
+ def create_data_request(
67
+ self, aoi_id: str, dataset_id: str, external_ref: Optional[str] = None
68
+ ) -> DataRequest:
60
69
  res = self._post(
61
70
  url="/v0/data-requests",
62
- model=DataRequestCreate(aoi_id=aoi_id, dataset_id=dataset_id),
71
+ model=DataRequestCreate(
72
+ aoi_id=aoi_id, dataset_id=dataset_id, external_ref=external_ref
73
+ ),
63
74
  )
64
75
  return DataRequest(**res)
65
76
 
@@ -71,6 +82,11 @@ class Client:
71
82
  res = self._get(url="/v0/data-requests")
72
83
  return [DataRequest(**record) for record in res["records"]]
73
84
 
85
+ def load_xarray(self, id: str) -> xarray.Dataset:
86
+ res = self._get(url=f"/v0/data-requests/{id}/metadata")
87
+ metadata = DataRequestMetadata(**res)
88
+ return load_xarray(metadata)
89
+
74
90
  def create_transformation(
75
91
  self, data_request_id: str, crs: str, spatial_resolution: float
76
92
  ) -> Transformation:
cecil/models.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import datetime
2
- from typing import Dict, Optional
2
+ from typing import Dict, Optional, List
3
3
 
4
4
  from pydantic import BaseModel, ConfigDict, SecretStr
5
5
  from pydantic.alias_generators import to_camel
@@ -8,7 +8,7 @@ from pydantic.alias_generators import to_camel
8
8
  class AOI(BaseModel):
9
9
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
10
10
  id: str
11
- name: str
11
+ external_ref: Optional[str]
12
12
  geometry: Dict
13
13
  hectares: float
14
14
  created_at: datetime.datetime
@@ -18,7 +18,7 @@ class AOI(BaseModel):
18
18
  class AOIRecord(BaseModel):
19
19
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
20
20
  id: str
21
- name: str
21
+ external_ref: Optional[str]
22
22
  hectares: float
23
23
  created_at: datetime.datetime
24
24
  created_by: str
@@ -26,8 +26,8 @@ class AOIRecord(BaseModel):
26
26
 
27
27
  class AOICreate(BaseModel):
28
28
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
29
- name: str
30
29
  geometry: Dict
30
+ external_ref: Optional[str]
31
31
 
32
32
 
33
33
  class DataRequest(BaseModel):
@@ -35,6 +35,7 @@ class DataRequest(BaseModel):
35
35
  id: str
36
36
  aoi_id: str
37
37
  dataset_id: str
38
+ external_ref: Optional[str]
38
39
  created_at: datetime.datetime
39
40
  created_by: str
40
41
 
@@ -43,6 +44,7 @@ class DataRequestCreate(BaseModel):
43
44
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
44
45
  aoi_id: str
45
46
  dataset_id: str
47
+ external_ref: Optional[str]
46
48
 
47
49
 
48
50
  class OrganisationSettings(BaseModel):
@@ -108,3 +110,28 @@ class UserCreate(BaseModel):
108
110
  first_name: str
109
111
  last_name: str
110
112
  email: str
113
+
114
+
115
+ class Band(BaseModel):
116
+ model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
117
+ variable_name: str
118
+ time: str
119
+ time_pattern: str
120
+ number: int
121
+
122
+
123
+ class File(BaseModel):
124
+ model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
125
+ url: str
126
+ bands: List[Band]
127
+
128
+
129
+ class DataRequestMetadata(BaseModel):
130
+ model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
131
+ provider_name: str
132
+ dataset_id: str
133
+ dataset_name: str
134
+ dataset_crs: str
135
+ aoi_id: str
136
+ data_request_id: str
137
+ files: List[File]
cecil/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.21"
1
+ __version__ = "0.0.23"
cecil/xarray.py ADDED
@@ -0,0 +1,74 @@
1
+ import os
2
+ import rioxarray
3
+ import xarray
4
+
5
+ from datetime import datetime
6
+
7
+ from .errors import Error
8
+ from .models import DataRequestMetadata
9
+
10
+ os.environ["GDAL_NUM_THREADS"] = "1"
11
+ os.environ["GDAL_DISABLE_READDIR_ON_OPEN"] = "FALSE"
12
+
13
+
14
+ def align_pixel_grids(time_series):
15
+ # Use the first timestep as reference
16
+ reference_da = time_series[0]
17
+ aligned_series = [reference_da]
18
+
19
+ # Align all other timesteps to the reference grid
20
+ for i, da in enumerate(time_series[1:], 1):
21
+ try:
22
+ aligned_da = da.rio.reproject_match(reference_da)
23
+ aligned_series.append(aligned_da)
24
+ except Exception as e:
25
+ raise Error
26
+ continue
27
+
28
+ return aligned_series
29
+
30
+
31
+ def load_xarray(metadata: DataRequestMetadata) -> xarray.Dataset:
32
+ data_vars = {}
33
+
34
+ for f in metadata.files:
35
+ dataset = rioxarray.open_rasterio(
36
+ f.url,
37
+ chunks={"x": 2000, "y": 2000},
38
+ )
39
+
40
+ for b in f.bands:
41
+ band = dataset.sel(band=b.number, drop=True)
42
+
43
+ if b.time and b.time_pattern:
44
+ time = datetime.strptime(b.time, b.time_pattern)
45
+ band = band.expand_dims("time")
46
+ band = band.assign_coords(time=[time])
47
+
48
+ band.name = b.variable_name
49
+
50
+ if b.variable_name not in data_vars:
51
+ data_vars[b.variable_name] = []
52
+
53
+ data_vars[b.variable_name].append(band)
54
+
55
+ for variable_name, time_series in data_vars.items():
56
+ if "time" in time_series[0].dims:
57
+ # time_series = align_pixel_grids(time_series)
58
+ data_vars[variable_name] = xarray.concat(
59
+ time_series, dim="time", join="exact"
60
+ )
61
+ else:
62
+ data_vars[variable_name] = time_series[0]
63
+
64
+ return xarray.Dataset(
65
+ data_vars=data_vars,
66
+ attrs={
67
+ "provider_name": metadata.provider_name,
68
+ "dataset_id": metadata.dataset_id,
69
+ "dataset_name": metadata.dataset_name,
70
+ "dataset_crs": metadata.dataset_crs,
71
+ "aoi_id": metadata.aoi_id,
72
+ "data_request_id": metadata.data_request_id,
73
+ },
74
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cecil
3
- Version: 0.0.21
3
+ Version: 0.0.23
4
4
  Summary: Python SDK for Cecil Earth
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE.txt
@@ -0,0 +1,10 @@
1
+ cecil/__init__.py,sha256=AEcRl73BDSAQe6W0d1PDD87IEcumARtREl7dCVa_YQY,86
2
+ cecil/client.py,sha256=MabuVG8UgFnjjED9duDS8cpPmPs_uT_D4M11uY2aYQk,7897
3
+ cecil/errors.py,sha256=ZNiSTYH2MgNZ7tNIgV07-Ge3KtmdncfzWiBi9yjURGs,1818
4
+ cecil/models.py,sha256=3W892XywxLIZL6TDCHM8_PVRHzR48bJXT5kTV7UU_bY,3509
5
+ cecil/version.py,sha256=CO0VmekjZ_r8LBYVaUXTM3i08rEVwYKhjb9sy0X7vz0,23
6
+ cecil/xarray.py,sha256=CvqfJ7NBMLLA4jf73ek2ZtV3sj8xOII__5S0_l3KXYI,2161
7
+ cecil-0.0.23.dist-info/METADATA,sha256=o3aYhhB16HENBSy8mVkzfeRardw7dddyATL326yJ7Eo,2659
8
+ cecil-0.0.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ cecil-0.0.23.dist-info/licenses/LICENSE.txt,sha256=mUexcmfYx3bG1VIzAdQTOf_NzStYw6-QkKVdUY_d4i4,1066
10
+ cecil-0.0.23.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- cecil/__init__.py,sha256=AEcRl73BDSAQe6W0d1PDD87IEcumARtREl7dCVa_YQY,86
2
- cecil/client.py,sha256=TXcTdNUF8ER8gs8KQBzHIsoQPqDLj3npFeF0PWEi4EI,7430
3
- cecil/errors.py,sha256=ZNiSTYH2MgNZ7tNIgV07-Ge3KtmdncfzWiBi9yjURGs,1818
4
- cecil/models.py,sha256=GpW1pT9NBKS5y4Os0pW8UR3MO9kVJe1r8jOK-MjADLA,2799
5
- cecil/version.py,sha256=PsqtE_T084MVsMv47JyTQ3DK2CRZJ3Kd9Q_vnw02oZk,23
6
- cecil-0.0.21.dist-info/METADATA,sha256=2Q9DsNWUMtimtqNDdDqbssyFGT33DgWaVjrYHrkLmrs,2659
7
- cecil-0.0.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- cecil-0.0.21.dist-info/licenses/LICENSE.txt,sha256=mUexcmfYx3bG1VIzAdQTOf_NzStYw6-QkKVdUY_d4i4,1066
9
- cecil-0.0.21.dist-info/RECORD,,
File without changes