obsarray 1.0.2__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.
- docs/conf.py +181 -0
- notebook/test_register_err_corr_form.py +45 -0
- obsarray/__init__.py +14 -0
- obsarray/_version.py +21 -0
- obsarray/err_corr.py +298 -0
- obsarray/flag_accessor.py +442 -0
- obsarray/templater/__init__.py +0 -0
- obsarray/templater/dataset_util.py +659 -0
- obsarray/templater/dstemplater.py +133 -0
- obsarray/templater/dswriter.py +113 -0
- obsarray/templater/template_util.py +257 -0
- obsarray/templater/tests/__init__.py +0 -0
- obsarray/templater/tests/test_dataset_util.py +488 -0
- obsarray/templater/tests/test_dswriter.py +31 -0
- obsarray/templater/tests/test_template_util.py +334 -0
- obsarray/test/__init__.py +0 -0
- obsarray/test/test_err_corr_forms.py +251 -0
- obsarray/test/test_flag_accessor.py +373 -0
- obsarray/test/test_unc_accessor.py +745 -0
- obsarray/unc_accessor.py +899 -0
- obsarray/utils.py +31 -0
- obsarray-1.0.2.dist-info/METADATA +57 -0
- obsarray-1.0.2.dist-info/RECORD +26 -0
- obsarray-1.0.2.dist-info/WHEEL +5 -0
- obsarray-1.0.2.dist-info/licenses/LICENSE +165 -0
- obsarray-1.0.2.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Handling for multiple ds templates
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, List
|
|
6
|
+
import xarray
|
|
7
|
+
from obsarray import create_ds
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__author__ = "Sam Hunt <sam.hunt@npl.co.uk>"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DSTemplater:
|
|
14
|
+
"""
|
|
15
|
+
Class to generate ``xarray.Dataset``'s from a set of templates.
|
|
16
|
+
|
|
17
|
+
:param templates: template dictionary for each product format
|
|
18
|
+
:param metadata_defs: metadata for each product format
|
|
19
|
+
|
|
20
|
+
Each dictionary has as keys ``"template_name"`` strings that define the names of the different available dataset
|
|
21
|
+
templates, e.g. "Level-0".
|
|
22
|
+
|
|
23
|
+
For the ``templates`` dictionary the corresponding entries should be a `variable definition dictionary <https://dsbuilder.readthedocs.io/en/latest/content/quickstart.html#defining-a-template-dataset>`_.
|
|
24
|
+
|
|
25
|
+
For ``metadata_defs`` the corresponding entries should be a dictionary of per product metadata.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self, templates: Optional[Dict] = None, metadata_defs: Optional[Dict] = None
|
|
30
|
+
):
|
|
31
|
+
self.templates = templates if templates is not None else {}
|
|
32
|
+
self.metadata_defs = metadata_defs if metadata_defs is not None else {}
|
|
33
|
+
|
|
34
|
+
def create(self, template_name: str, size: Dict[str, int]) -> xarray.Dataset:
|
|
35
|
+
"""
|
|
36
|
+
Returns template dataset
|
|
37
|
+
|
|
38
|
+
:param template_name: name of template to create (value returned by ``self.return_template_names()``)
|
|
39
|
+
:param size: entry per dataset dimension with value of size
|
|
40
|
+
|
|
41
|
+
:returns: Empty dataset
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# Find template
|
|
45
|
+
if template_name in self.return_template_names():
|
|
46
|
+
template = self.templates[template_name]
|
|
47
|
+
else:
|
|
48
|
+
raise NameError(
|
|
49
|
+
"No template: "
|
|
50
|
+
+ template_name
|
|
51
|
+
+ " - must be one of "
|
|
52
|
+
+ str(self.return_template_names())
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Find metadata def
|
|
56
|
+
metadata = (
|
|
57
|
+
self.metadata_defs[template_name]
|
|
58
|
+
if template_name in self.metadata_defs.keys()
|
|
59
|
+
else None
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return create_ds(template, size, metadata=metadata)
|
|
63
|
+
|
|
64
|
+
def return_template_names(self) -> list:
|
|
65
|
+
"""
|
|
66
|
+
Returns available ds template names
|
|
67
|
+
|
|
68
|
+
:returns: template names
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
return list(self.templates.keys())
|
|
72
|
+
|
|
73
|
+
def return_template_var_names(self, template_name: str) -> List[str]:
|
|
74
|
+
"""
|
|
75
|
+
Returns variables for specified template
|
|
76
|
+
|
|
77
|
+
:param template_name: template name (value returned by ``self.return_template_names()``)
|
|
78
|
+
|
|
79
|
+
:returns: variable names for specified template
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
return list(self.templates[template_name].keys())
|
|
83
|
+
|
|
84
|
+
def return_ds_format_variable_dict(
|
|
85
|
+
self, template_name: str, variable_name: str
|
|
86
|
+
) -> Dict:
|
|
87
|
+
"""
|
|
88
|
+
Returns variable definition info for specified template variable
|
|
89
|
+
|
|
90
|
+
:param template_name: template name (value returned by ``self.return_template_names()``)
|
|
91
|
+
:param variable_name: variable name
|
|
92
|
+
|
|
93
|
+
:returns: variable definition info
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
return self.templates[template_name][variable_name]
|
|
97
|
+
|
|
98
|
+
def return_template_dim_names(self, template_name: str) -> List[str]:
|
|
99
|
+
"""
|
|
100
|
+
Returns dims required for specified template
|
|
101
|
+
|
|
102
|
+
:param template_name: template name (value returned by ``self.return_template_names()``)
|
|
103
|
+
|
|
104
|
+
:returns: template dimensions
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
template = self.templates[template_name]
|
|
108
|
+
|
|
109
|
+
template_dims = set()
|
|
110
|
+
|
|
111
|
+
for var_name in template.keys():
|
|
112
|
+
template_dims.update(template[var_name]["dim"])
|
|
113
|
+
|
|
114
|
+
return list(template_dims)
|
|
115
|
+
|
|
116
|
+
def create_size_dict(self, ds_format: str) -> Dict[str, None]:
|
|
117
|
+
"""
|
|
118
|
+
Returns empty size dictionary for specified template
|
|
119
|
+
|
|
120
|
+
:param template_name: template name (value returned by ``self.return_template_names()``)
|
|
121
|
+
|
|
122
|
+
:return: empty sizes dictionary
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
dim_sizes_dict = dict()
|
|
126
|
+
for dim in self.return_template_dim_names(ds_format):
|
|
127
|
+
dim_sizes_dict[dim] = None
|
|
128
|
+
|
|
129
|
+
return dim_sizes_dict
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
pass
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DSWriter class
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from obsarray.templater.template_util import DatasetUtil
|
|
7
|
+
|
|
8
|
+
__author__ = "Sam Hunt <sam.hunt@npl.co.uk>"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DSWriter:
|
|
12
|
+
"""
|
|
13
|
+
Class to write datasets to output files
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def write(ds, path, overwrite=False, fmt="netCDF4", compression_level=None):
|
|
18
|
+
"""
|
|
19
|
+
Write xarray dataset to file
|
|
20
|
+
|
|
21
|
+
:type ds: xarray.Dataset
|
|
22
|
+
:param ds: dataset
|
|
23
|
+
|
|
24
|
+
:type path: str
|
|
25
|
+
:param path: file path
|
|
26
|
+
|
|
27
|
+
:type overwrite: bool
|
|
28
|
+
:param overwrite: set to true to overwrite existing file
|
|
29
|
+
|
|
30
|
+
:type fmt: str
|
|
31
|
+
:param fmt: format to write to, may be 'netCDF4' (default) or 'csv'
|
|
32
|
+
|
|
33
|
+
:type compression_level: int
|
|
34
|
+
:param compression_level: the file compression level if 'netCDF4' fmt, 0 - 9 (default is 5)
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if os.path.isfile(path):
|
|
38
|
+
if overwrite is True:
|
|
39
|
+
os.remove(path)
|
|
40
|
+
else:
|
|
41
|
+
raise IOError("The file already exists: " + path)
|
|
42
|
+
|
|
43
|
+
if (fmt.lower() == "netcdf4") or (fmt.lower() == "netcdf"):
|
|
44
|
+
DSWriter._write_netcdf(ds, path, compression_level=compression_level)
|
|
45
|
+
|
|
46
|
+
elif fmt == "csv":
|
|
47
|
+
DSWriter._write_csv(ds, path)
|
|
48
|
+
|
|
49
|
+
else:
|
|
50
|
+
raise NameError("Invalid fmt: " + fmt)
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def _write_netcdf(ds, path, compression_level=None):
|
|
54
|
+
"""
|
|
55
|
+
Write xarray dataset to file to netcdf
|
|
56
|
+
|
|
57
|
+
:type ds: xarray.Dataset
|
|
58
|
+
:param ds: dataset
|
|
59
|
+
|
|
60
|
+
:type path: str
|
|
61
|
+
:param path: file path
|
|
62
|
+
|
|
63
|
+
:type compression_level: int
|
|
64
|
+
:param compression_level: the file compression level if 'netCDF4' fmt, 0 - 9 (default is 5)
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
if compression_level is None:
|
|
68
|
+
compression_level = 5
|
|
69
|
+
|
|
70
|
+
comp = dict(zlib=True, complevel=compression_level)
|
|
71
|
+
|
|
72
|
+
encoding = dict()
|
|
73
|
+
for var_name in ds.data_vars:
|
|
74
|
+
var_encoding = dict(comp)
|
|
75
|
+
var_encoding.update(ds[var_name].encoding)
|
|
76
|
+
if "dtype" in var_encoding.keys():
|
|
77
|
+
var_encoding.update(
|
|
78
|
+
{
|
|
79
|
+
"_FillValue": DatasetUtil.get_default_fill_value(
|
|
80
|
+
var_encoding["dtype"]
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
if "_FillValue" in ds[var_name].attrs:
|
|
85
|
+
ds[var_name].attrs.pop("_FillValue")
|
|
86
|
+
encoding.update({var_name: var_encoding})
|
|
87
|
+
|
|
88
|
+
ds.to_netcdf(path, format="netCDF4", engine="netcdf4", encoding=encoding)
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def _write_csv(ds, path):
|
|
92
|
+
"""
|
|
93
|
+
Write xarray dataset to file to csv
|
|
94
|
+
|
|
95
|
+
:type ds: xarray.Dataset
|
|
96
|
+
:param ds: dataset
|
|
97
|
+
|
|
98
|
+
:type path: str
|
|
99
|
+
:param path: file path
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
# write data variables (via pandas dataframe)
|
|
103
|
+
ds.to_dataframe().to_csv(path)
|
|
104
|
+
|
|
105
|
+
# write metadata
|
|
106
|
+
metadata_path = os.path.splitext(path)[0] + "_meta.txt"
|
|
107
|
+
with open(metadata_path, "w") as f:
|
|
108
|
+
for meta_name in ds.attrs.keys():
|
|
109
|
+
f.write(meta_name + ": " + ds.attrs[meta_name] + "\n")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
pass
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utilities for creating template xarray datasets
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Dict, List
|
|
6
|
+
from obsarray.templater.dataset_util import DatasetUtil
|
|
7
|
+
import xarray
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__author__ = "Sam Hunt <sam.hunt@npl.co.uk>"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def create_ds(
|
|
14
|
+
template: Dict[str, Dict],
|
|
15
|
+
size: Dict[str, int],
|
|
16
|
+
metadata: Optional[Dict] = None,
|
|
17
|
+
append_ds: Optional[xarray.Dataset] = None,
|
|
18
|
+
propagate_ds: Optional[xarray.Dataset] = None,
|
|
19
|
+
) -> xarray.Dataset:
|
|
20
|
+
"""
|
|
21
|
+
Returns template dataset
|
|
22
|
+
|
|
23
|
+
:param template: dictionary defining ds variable structure, as defined below.
|
|
24
|
+
:param size: dictionary of dataset dimensions, entry per dataset dimension with value of size as int
|
|
25
|
+
:param metadata: dictionary of dataset metadata
|
|
26
|
+
:param append_ds: base dataset to append with template variables
|
|
27
|
+
:param propagate_ds: template dataset is populated with data from propagate_ds for their variables with
|
|
28
|
+
common names and dimensions. Useful for transferring common data between datasets at different processing levels
|
|
29
|
+
(e.g. times, etc.).
|
|
30
|
+
:returns: template dataset
|
|
31
|
+
|
|
32
|
+
For the ``template`` dictionary each key/value pair defines one variable, where the key is the variable name and the value is a dictionary with the following entries:
|
|
33
|
+
|
|
34
|
+
* ``"dtype"`` (*np.typecodes*/*str*) - variable data type, either a numpy data type or special value ``"flag"`` for
|
|
35
|
+
flag variable
|
|
36
|
+
* ``"dim"`` (*list*) - list of variable dimension names
|
|
37
|
+
* ``"attributes"`` (*dict*) - (optional) variable attributes
|
|
38
|
+
* ``"encoding"`` (*dict*) - (optional) variable encoding.
|
|
39
|
+
|
|
40
|
+
For more information on the required form of these entries, see the :ref:`variables definition section <variables dict>`
|
|
41
|
+
of the user guide.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# Create dataset
|
|
45
|
+
ds = append_ds if append_ds is not None else xarray.Dataset()
|
|
46
|
+
|
|
47
|
+
# Add variables
|
|
48
|
+
ds = TemplateUtil.add_variables(ds, template, size)
|
|
49
|
+
|
|
50
|
+
# Add metadata
|
|
51
|
+
if metadata is not None:
|
|
52
|
+
ds = TemplateUtil.add_metadata(ds, metadata)
|
|
53
|
+
|
|
54
|
+
# Propagate variable data
|
|
55
|
+
if propagate_ds is not None:
|
|
56
|
+
TemplateUtil.propagate_values(ds, propagate_ds)
|
|
57
|
+
|
|
58
|
+
return ds
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def create_var(var_name: str, var_attrs: Dict, size: Dict[str, int]) -> xarray.Variable:
|
|
62
|
+
"""
|
|
63
|
+
Returns template variable
|
|
64
|
+
|
|
65
|
+
:param var_name: variable name
|
|
66
|
+
:param var_attrs: variable definition dictionary (as an entry to a template dictionary)
|
|
67
|
+
:param size: dictionary of dataset dimensions, entry per dataset dimension with value of size as int
|
|
68
|
+
:return:
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
return TemplateUtil._create_var(var_name, var_attrs, size)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class TemplateUtil:
|
|
75
|
+
"""
|
|
76
|
+
Class to create template xarray datasets
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def add_variables(
|
|
81
|
+
ds: xarray.Dataset, template: Dict[str, Dict], size: Dict[str, int]
|
|
82
|
+
) -> xarray.Dataset:
|
|
83
|
+
"""
|
|
84
|
+
Adds defined variables dataset
|
|
85
|
+
|
|
86
|
+
:param ds: dataset
|
|
87
|
+
:param template: dictionary defining variables, see the :ref:`variables definition section <variables dict>` of the user guide for more information.
|
|
88
|
+
:param size: dictionary of dataset dimensions, entry per dataset dimension with value of size as int
|
|
89
|
+
|
|
90
|
+
:returns: dataset with defined variables
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
for var_name in template.keys():
|
|
94
|
+
|
|
95
|
+
var = TemplateUtil._create_var(var_name, template[var_name], size)
|
|
96
|
+
|
|
97
|
+
ds[var_name] = var
|
|
98
|
+
|
|
99
|
+
return ds
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def _create_var(
|
|
103
|
+
var_name: str, var_attrs: dict, size: Dict[str, int]
|
|
104
|
+
) -> xarray.Variable:
|
|
105
|
+
|
|
106
|
+
du = DatasetUtil()
|
|
107
|
+
|
|
108
|
+
# Check variable definition
|
|
109
|
+
TemplateUtil._check_variable_definition(var_name, var_attrs)
|
|
110
|
+
|
|
111
|
+
# Unpack variable attributes
|
|
112
|
+
dtype = var_attrs["dtype"]
|
|
113
|
+
dim_names = var_attrs["dim"]
|
|
114
|
+
attributes = var_attrs["attributes"] if "attributes" in var_attrs else None
|
|
115
|
+
|
|
116
|
+
err_corr = None
|
|
117
|
+
if attributes is not None:
|
|
118
|
+
if "err_corr" in attributes:
|
|
119
|
+
err_corr = attributes.pop("err_corr")
|
|
120
|
+
|
|
121
|
+
# Determine variable shape from dims
|
|
122
|
+
try:
|
|
123
|
+
dim_sizes = TemplateUtil._return_variable_shape(dim_names, size)
|
|
124
|
+
except KeyError:
|
|
125
|
+
raise KeyError(
|
|
126
|
+
"Dim Name Error - Variable "
|
|
127
|
+
+ var_name
|
|
128
|
+
+ " defined with dim not in dim_sizes_dict"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Create variable and add to dataset
|
|
132
|
+
if isinstance(dtype, str):
|
|
133
|
+
if dtype == "flag":
|
|
134
|
+
flag_meanings = attributes.pop("flag_meanings")
|
|
135
|
+
variable = du.create_flags_variable(
|
|
136
|
+
dim_sizes,
|
|
137
|
+
meanings=flag_meanings,
|
|
138
|
+
dim_names=dim_names,
|
|
139
|
+
attributes=attributes,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
else:
|
|
143
|
+
raise ValueError("unknown dtype - " + dtype)
|
|
144
|
+
|
|
145
|
+
else:
|
|
146
|
+
if err_corr is None:
|
|
147
|
+
variable = du.create_variable(
|
|
148
|
+
dim_sizes, dim_names=dim_names, dtype=dtype, attributes=attributes
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
else:
|
|
152
|
+
variable = du.create_unc_variable(
|
|
153
|
+
dim_sizes,
|
|
154
|
+
dim_names=dim_names,
|
|
155
|
+
dtype=dtype,
|
|
156
|
+
attributes=attributes,
|
|
157
|
+
err_corr=err_corr,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if "encoding" in var_attrs:
|
|
161
|
+
du.add_encoding(variable, **var_attrs["encoding"])
|
|
162
|
+
variable.attrs.pop("_FillValue")
|
|
163
|
+
|
|
164
|
+
return variable
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def _check_variable_definition(variable_name: str, variable_attrs: Dict):
|
|
168
|
+
"""
|
|
169
|
+
Checks validity of variable definition, raising errors as appropriate
|
|
170
|
+
|
|
171
|
+
:param variable_name: variable name
|
|
172
|
+
:param variable_attrs: variable defining dictionary
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
# Variable name must be type str
|
|
176
|
+
if type(variable_name) != str:
|
|
177
|
+
raise TypeError(
|
|
178
|
+
"Invalid variable name: " + str(variable_name) + " (must be string)"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# todo - add more tests to check validity of variable definition
|
|
182
|
+
|
|
183
|
+
@staticmethod
|
|
184
|
+
def _return_variable_shape(dim_names: List[str], size: Dict[str, int]) -> List[int]:
|
|
185
|
+
"""
|
|
186
|
+
Returns dimension sizes of specified dimensions
|
|
187
|
+
|
|
188
|
+
:param dim_names: dimension names
|
|
189
|
+
:param size: dictionary of dataset dimensions, entry per dataset dimension with value of size as int
|
|
190
|
+
|
|
191
|
+
:returns: dimension sizes
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
return [size[dim_name] for dim_name in dim_names]
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def add_metadata(ds: xarray.Dataset, metadata: Dict) -> xarray.Dataset:
|
|
198
|
+
"""
|
|
199
|
+
Adds metadata to dataset
|
|
200
|
+
|
|
201
|
+
:param ds: dataset
|
|
202
|
+
:param metadata: dictionary of dataset metadata
|
|
203
|
+
|
|
204
|
+
:returns: dataset with updated metadata
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
ds.attrs.update(metadata)
|
|
208
|
+
|
|
209
|
+
return ds
|
|
210
|
+
|
|
211
|
+
@staticmethod
|
|
212
|
+
def propagate_values(target_ds, source_ds, exclude=None):
|
|
213
|
+
"""
|
|
214
|
+
Populates target_ds in-place with data from source_ds for their variables with common names and dimensions.
|
|
215
|
+
Useful for transferring common data between datasets at different processing levels (e.g. times, etc.).
|
|
216
|
+
|
|
217
|
+
N.B. propagates data only, not variables as a whole with attributes etc.
|
|
218
|
+
|
|
219
|
+
:type target_ds: xarray.Dataset
|
|
220
|
+
:param target_ds: ds to populate (perhaps data at new processing level)
|
|
221
|
+
|
|
222
|
+
:type source_ds: xarray.Dataset
|
|
223
|
+
:param source_ds: ds to take data from (perhaps data at previous processing level)
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
# Find variable names common to target_ds and source_ds, excluding specified exclude variables
|
|
227
|
+
common_variable_names = list(set(target_ds).intersection(source_ds))
|
|
228
|
+
# common_variable_names = list(set(target_ds.variables).intersection(source_ds.variables))
|
|
229
|
+
# print(common_variable_names)
|
|
230
|
+
|
|
231
|
+
if exclude is not None:
|
|
232
|
+
common_variable_names = [
|
|
233
|
+
name for name in common_variable_names if name not in exclude
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
# Remove any common variables that have different dimensions in target_ds and source_ds
|
|
237
|
+
common_variable_names = [
|
|
238
|
+
name
|
|
239
|
+
for name in common_variable_names
|
|
240
|
+
if target_ds[name].dims == source_ds[name].dims
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
# Propagate data
|
|
244
|
+
for common_variable_name in common_variable_names:
|
|
245
|
+
if (
|
|
246
|
+
target_ds[common_variable_name].shape
|
|
247
|
+
== source_ds[common_variable_name].shape
|
|
248
|
+
):
|
|
249
|
+
target_ds[common_variable_name].values = source_ds[
|
|
250
|
+
common_variable_name
|
|
251
|
+
].values
|
|
252
|
+
|
|
253
|
+
# to do - add method to propagate common unpopulated metadata
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
if __name__ == "__main__":
|
|
257
|
+
pass
|
|
File without changes
|