Skip to content

Commit

Permalink
Merge pull request #32 from ecmwf/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
awarde96 authored Aug 28, 2024
2 parents e497f60 + c672ec5 commit 5816992
Show file tree
Hide file tree
Showing 20 changed files with 297 additions and 103 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ encoder = Covjsonkit().encode("CoverageCollection", "BoundingBox")
res = encoder.from_polytope(polytope_output)
```

### Config

Covjsonkit uses a config to determine what parameter metadata to use, an example can be found in [example_config.json](example_config.json). This will automatically be loaded at runtime to point to the correct parameter metadata files.

The example config has to be stored in one of the following places:

1. System-wide configuration in /etc/covjsonkit/config.json (and yaml)
2. User configuration in ~/.covjsonkit.json (and yaml)

Users can add their own parameter metadata in the [data directory](covjsonkit/data/) by add ing a new directory containing a param.json, param_id.json, and units.json in a format the same as can be found in [ecmwf directory](covjsonkit/data/ecmwf/). Then edit the config to point to your newly named directory.

If users want to pass in their own config tehy can do this as a python dictioanry in the following way:

```Python
encoder = Covjsonkit(cf).encode("CoverageCollection", "BoundingBox")
```

Where `cf` is a valid covjsonkit config.
## Testing

Python unit tests can be run with pytest:
Expand Down
15 changes: 12 additions & 3 deletions covjsonkit/api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from conflator import Conflator

import covjsonkit.decoder.BoundingBox
import covjsonkit.decoder.Frame
import covjsonkit.decoder.Path
Expand All @@ -13,6 +15,8 @@
import covjsonkit.encoder.VerticalProfile
import covjsonkit.encoder.Wkt

from .config import CovjsonKitConfig

features_encoder = {
"pointseries": covjsonkit.encoder.TimeSeries.TimeSeries,
"verticalprofile": covjsonkit.encoder.VerticalProfile.VerticalProfile,
Expand All @@ -34,16 +38,21 @@


class Covjsonkit:
def __init__(self):
pass
def __init__(self, config=None):
# If no config check default locations
if config is None:
self.conf = Conflator(app_name="covjsonkit", model=CovjsonKitConfig).load()
# else initialise with provided config
else:
self.conf = CovjsonKitConfig.model_validate(config)

def encode(self, type, domaintype):
if domaintype == "timeseries":
domaintype = "PointSeries"
elif domaintype == "trajectory":
domaintype = "path"
feature = self._feature_factory(domaintype.lower(), "encoder")
return feature(type, domaintype)
return feature(self.conf, domaintype)

def decode(self, covjson):
requesttype = covjson["domainType"]
Expand Down
5 changes: 5 additions & 0 deletions covjsonkit/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from conflator import ConfigModel


class CovjsonKitConfig(ConfigModel):
param_db: str = "ecmwf"
3 changes: 3 additions & 0 deletions covjsonkit/decoder/BoundingBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ def to_xarray(self):
# Get coordinates
x = []
y = []
z = []
datetimes = []
for coord in self.get_coordinates()["composite"]["values"]:
x.append(float(coord[0]))
y.append(float(coord[1]))
z.append(float(coord[2]))
for datetime in self.get_coordinates()["t"]["values"]:
datetimes.append(datetime)

Expand Down Expand Up @@ -112,6 +114,7 @@ def to_xarray(self):
points=(["points"], list(range(0, len(x)))),
x=(["points"], x),
y=(["points"], y),
z=(["points"], z),
),
)
for mars_metadata in self.mars_metadata[0]:
Expand Down
2 changes: 1 addition & 1 deletion covjsonkit/decoder/TimeSeries.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def to_xarray(self):
param_values[parameter][i][j] = coverage["ranges"][parameter]["values"]

for parameter in self.parameters:
param_coords = {"x": x, "y": y, "z": [z], "number": nums, "datetime": datetime, "t": steps}
param_coords = {"x": x, "y": y, "z": z, "number": nums, "datetime": datetime, "t": steps}
dataarray = xr.DataArray(
[[[param_values[parameter]]]],
dims=dims,
Expand Down
47 changes: 40 additions & 7 deletions covjsonkit/encoder/BoundingBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ def from_xarray(self, dataset):
def from_polytope(self, result):

coords = {}
# coords['composite'] = []
mars_metadata = {}
range_dict = {}
lat = 0
param = 0
number = [0]
step = 0
dates = [0]
levels = [0]

self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates)
self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates, levels)

self.add_reference(
{
Expand All @@ -102,18 +102,51 @@ def from_polytope(self, result):
}
)

combined_dict = {}

for date in range_dict:
if date not in combined_dict:
combined_dict[date] = {}
for level in range_dict[date]:
for num in range_dict[date][level]:
if num not in combined_dict[date]:
combined_dict[date][num] = {}
for para in range_dict[date][level][num]:
if para not in combined_dict[date][num]:
combined_dict[date][num][para] = {}
for s, value in range_dict[date][level][num][para].items():
if s not in combined_dict[date][num][para]:
combined_dict[date][num][para][s] = value
else:
# Cocatenate arrays
combined_dict[date][num][para][s] += value

levels = []
for date in range_dict.keys():
for num in range_dict[date].keys():
for level in range_dict[date].keys():
levels.append(level)
break

for date in coords.keys():
coord = coords[date]["composite"]
coords[date]["composite"] = []
for level in levels:
for cor in coord:
coords[date]["composite"].append([cor[0], cor[1], level])

for date in combined_dict.keys():
for num in combined_dict[date].keys():
val_dict = {}
for step in range_dict[date][num][self.parameters[0]].keys():
for step in combined_dict[date][num][self.parameters[0]].keys():
val_dict[step] = {}
for para in range_dict[date][num].keys():
for step in range_dict[date][num][para].keys():
val_dict[step][para] = range_dict[date][num][para][step]
for para in combined_dict[date][num].keys():
for step in combined_dict[date][num][para].keys():
val_dict[step][para] = combined_dict[date][num][para][step]
for step in val_dict.keys():
mm = mars_metadata.copy()
mm["number"] = num
mm["step"] = step
mm["Forecast date"] = date
self.add_coverage(mm, coords[date], val_dict[step])

# self.add_coverage(mars_metadata, coords, range_dict)
Expand Down
47 changes: 40 additions & 7 deletions covjsonkit/encoder/Frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ def from_xarray(self, dataset):
def from_polytope(self, result):

coords = {}
# coords['composite'] = []
mars_metadata = {}
range_dict = {}
lat = 0
param = 0
number = [0]
step = 0
dates = [0]
levels = [0]

self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates)
self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates, levels)

self.add_reference(
{
Expand All @@ -102,18 +102,51 @@ def from_polytope(self, result):
}
)

combined_dict = {}

for date in range_dict:
if date not in combined_dict:
combined_dict[date] = {}
for level in range_dict[date]:
for num in range_dict[date][level]:
if num not in combined_dict[date]:
combined_dict[date][num] = {}
for para in range_dict[date][level][num]:
if para not in combined_dict[date][num]:
combined_dict[date][num][para] = {}
for s, value in range_dict[date][level][num][para].items():
if s not in combined_dict[date][num][para]:
combined_dict[date][num][para][s] = value
else:
# Cocatenate arrays
combined_dict[date][num][para][s] += value

levels = []
for date in range_dict.keys():
for num in range_dict[date].keys():
for level in range_dict[date].keys():
levels.append(level)
break

for date in coords.keys():
coord = coords[date]["composite"]
coords[date]["composite"] = []
for level in levels:
for cor in coord:
coords[date]["composite"].append([cor[0], cor[1], level])

for date in combined_dict.keys():
for num in combined_dict[date].keys():
val_dict = {}
for step in range_dict[date][num][self.parameters[0]].keys():
for step in combined_dict[date][num][self.parameters[0]].keys():
val_dict[step] = {}
for para in range_dict[date][num].keys():
for step in range_dict[date][num][para].keys():
val_dict[step][para] = range_dict[date][num][para][step]
for para in combined_dict[date][num].keys():
for step in combined_dict[date][num][para].keys():
val_dict[step][para] = combined_dict[date][num][para][step]
for step in val_dict.keys():
mm = mars_metadata.copy()
mm["number"] = num
mm["step"] = step
mm["Forecast date"] = date
self.add_coverage(mm, coords[date], val_dict[step])

# self.add_coverage(mars_metadata, coords, range_dict)
Expand Down
47 changes: 40 additions & 7 deletions covjsonkit/encoder/Shapefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ def from_xarray(self, dataset):
def from_polytope(self, result):

coords = {}
# coords['composite'] = []
mars_metadata = {}
range_dict = {}
lat = 0
param = 0
number = [0]
step = 0
dates = [0]
levels = [0]

self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates)
self.walk_tree(result, lat, coords, mars_metadata, param, range_dict, number, step, dates, levels)

self.add_reference(
{
Expand All @@ -102,18 +102,51 @@ def from_polytope(self, result):
}
)

combined_dict = {}

for date in range_dict:
if date not in combined_dict:
combined_dict[date] = {}
for level in range_dict[date]:
for num in range_dict[date][level]:
if num not in combined_dict[date]:
combined_dict[date][num] = {}
for para in range_dict[date][level][num]:
if para not in combined_dict[date][num]:
combined_dict[date][num][para] = {}
for s, value in range_dict[date][level][num][para].items():
if s not in combined_dict[date][num][para]:
combined_dict[date][num][para][s] = value
else:
# Cocatenate arrays
combined_dict[date][num][para][s] += value

levels = []
for date in range_dict.keys():
for num in range_dict[date].keys():
for level in range_dict[date].keys():
levels.append(level)
break

for date in coords.keys():
coord = coords[date]["composite"]
coords[date]["composite"] = []
for level in levels:
for cor in coord:
coords[date]["composite"].append([cor[0], cor[1], level])

for date in combined_dict.keys():
for num in combined_dict[date].keys():
val_dict = {}
for step in range_dict[date][num][self.parameters[0]].keys():
for step in combined_dict[date][num][self.parameters[0]].keys():
val_dict[step] = {}
for para in range_dict[date][num].keys():
for step in range_dict[date][num][para].keys():
val_dict[step][para] = range_dict[date][num][para][step]
for para in combined_dict[date][num].keys():
for step in combined_dict[date][num][para].keys():
val_dict[step][para] = combined_dict[date][num][para][step]
for step in val_dict.keys():
mm = mars_metadata.copy()
mm["number"] = num
mm["step"] = step
mm["Forecast date"] = date
self.add_coverage(mm, coords[date], val_dict[step])

# self.add_coverage(mars_metadata, coords, range_dict)
Expand Down
Loading

0 comments on commit 5816992

Please sign in to comment.