obsarray 0.2.6__tar.gz → 1.0__tar.gz

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.
Files changed (71) hide show
  1. {obsarray-0.2.6/obsarray.egg-info → obsarray-1.0}/PKG-INFO +1 -1
  2. {obsarray-0.2.6 → obsarray-1.0}/docs/conf.py +1 -1
  3. {obsarray-0.2.6 → obsarray-1.0}/obsarray/_version.py +3 -3
  4. {obsarray-0.2.6 → obsarray-1.0}/obsarray/err_corr.py +39 -36
  5. {obsarray-0.2.6 → obsarray-1.0}/obsarray/test/test_err_corr_forms.py +52 -11
  6. {obsarray-0.2.6 → obsarray-1.0}/obsarray/test/test_unc_accessor.py +8 -8
  7. {obsarray-0.2.6 → obsarray-1.0}/obsarray/unc_accessor.py +3 -2
  8. {obsarray-0.2.6 → obsarray-1.0/obsarray.egg-info}/PKG-INFO +1 -1
  9. {obsarray-0.2.6 → obsarray-1.0}/obsarray.egg-info/SOURCES.txt +0 -2
  10. obsarray-0.2.6/obsarray/templater/dsdoc.py +0 -302
  11. obsarray-0.2.6/obsarray/templater/tests/test_dsdoc.py +0 -312
  12. {obsarray-0.2.6 → obsarray-1.0}/.gitignore +0 -0
  13. {obsarray-0.2.6 → obsarray-1.0}/.pre-commit-config.yaml +0 -0
  14. {obsarray-0.2.6 → obsarray-1.0}/LICENSE +0 -0
  15. {obsarray-0.2.6 → obsarray-1.0}/MANIFEST.in +0 -0
  16. {obsarray-0.2.6 → obsarray-1.0}/README.md +0 -0
  17. {obsarray-0.2.6 → obsarray-1.0}/docs/Makefile +0 -0
  18. {obsarray-0.2.6 → obsarray-1.0}/docs/index.rst +0 -0
  19. {obsarray-0.2.6 → obsarray-1.0}/docs/make.bat +0 -0
  20. {obsarray-0.2.6 → obsarray-1.0}/obsarray/__init__.py +0 -0
  21. {obsarray-0.2.6 → obsarray-1.0}/obsarray/flag_accessor.py +0 -0
  22. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/__init__.py +0 -0
  23. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/dataset_util.py +0 -0
  24. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/dstemplater.py +0 -0
  25. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/dswriter.py +0 -0
  26. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/template_util.py +0 -0
  27. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/template_util_jon.py +0 -0
  28. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/tests/__init__.py +0 -0
  29. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/tests/test_dataset_util.py +0 -0
  30. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/tests/test_dswriter.py +0 -0
  31. {obsarray-0.2.6 → obsarray-1.0}/obsarray/templater/tests/test_template_util.py +0 -0
  32. {obsarray-0.2.6 → obsarray-1.0}/obsarray/test/__init__.py +0 -0
  33. {obsarray-0.2.6 → obsarray-1.0}/obsarray/test/test_flag_accessor.py +0 -0
  34. {obsarray-0.2.6 → obsarray-1.0}/obsarray/utils.py +0 -0
  35. {obsarray-0.2.6 → obsarray-1.0}/obsarray.egg-info/dependency_links.txt +0 -0
  36. {obsarray-0.2.6 → obsarray-1.0}/obsarray.egg-info/requires.txt +0 -0
  37. {obsarray-0.2.6 → obsarray-1.0}/obsarray.egg-info/top_level.txt +0 -0
  38. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/.gitignore +0 -0
  39. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/QualityDocumentation.tex +0 -0
  40. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/CookiecutterMacros.tex +0 -0
  41. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/acronyms.tex +0 -0
  42. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/history.tex +0 -0
  43. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/metadata.tex +0 -0
  44. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/pythoninputstyle.tex +0 -0
  45. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/sil2.tex +0 -0
  46. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/sil3.tex +0 -0
  47. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/sources.bib +0 -0
  48. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/base/sources.tex +0 -0
  49. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/countpdfpages.sh +0 -0
  50. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/footnotehyper-sphinx.sty +0 -0
  51. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/obsarray_QF-59.docm +0 -0
  52. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/obsarray_requirements.docx +0 -0
  53. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16a.docx +0 -0
  54. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16b.docx +0 -0
  55. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16c.docx +0 -0
  56. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16d.docx +0 -0
  57. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16e.docx +0 -0
  58. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/review_checklists/qf-16f.docx +0 -0
  59. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/softwareRequirements.sty +0 -0
  60. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinx.sty +0 -0
  61. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxcyrillic.sty +0 -0
  62. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxhighlight.sty +0 -0
  63. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxhowto.cls +0 -0
  64. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxmanual.cls +0 -0
  65. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxmessages.sty +0 -0
  66. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/sphinxmulticell.sty +0 -0
  67. {obsarray-0.2.6 → obsarray-1.0}/quality_documentation/uml/copy your design png file into this folder.txt +0 -0
  68. {obsarray-0.2.6 → obsarray-1.0}/setup.cfg +0 -0
  69. {obsarray-0.2.6 → obsarray-1.0}/setup.py +0 -0
  70. {obsarray-0.2.6 → obsarray-1.0}/tox.ini +0 -0
  71. {obsarray-0.2.6 → obsarray-1.0}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: obsarray
3
- Version: 0.2.6
3
+ Version: 1.0
4
4
  Summary: Measurement data handling in Python
5
5
  Home-page: https://github.com/comet-toolkit/obsarray
6
6
  Author: CoMet Toolkit Team
@@ -112,7 +112,7 @@ html_theme = "sphinx_book_theme"
112
112
  #
113
113
  # html_theme_options = {}
114
114
 
115
- html_logo = "figs/comet_logo.png"
115
+ html_logo = "figs/obsarray.png"
116
116
 
117
117
  # Add any paths that contain custom static files (such as style sheets) here,
118
118
  # relative to this directory. They are copied after the builtin static files,
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-03-26T17:59:27+0000",
11
+ "date": "2024-04-02T15:14:15+0100",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "3f90a44048e43a24a7ec1115d7b727944416ba9f",
15
- "version": "v0.2.6"
14
+ "full-revisionid": "22fe504c5299f2e3adbb924ab737227182325cf6",
15
+ "version": "v1.0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -69,22 +69,23 @@ class BaseErrCorrForm(abc.ABC):
69
69
  """Form name"""
70
70
  pass
71
71
 
72
- def expand_dim_matrix(
73
- self, submatrix: np.ndarray, submatrix_dim: Union[str, List[str]], sli: tuple
74
- ):
75
- return expand_errcorr_dims(
76
- in_corr=submatrix,
77
- in_dim=submatrix_dim,
78
- out_dim=list(self._obj[self._unc_var_name][sli].dims),
79
- dim_sizes=self.get_sliced_dim_sizes_uncvar(sli),
80
- )
72
+ def get_varshape_errcorr(self):
73
+ """
74
+ return shape of uncertainty variable, including only dimensions which are included in the current error correlation form.
75
+
76
+ :return: shape of included dimensions
77
+ """
78
+ all_dims = self._obj[self._unc_var_name].dims
79
+ all_dims_sizes = self._obj.sizes
80
+
81
+ return tuple([all_dims_sizes[dim] for dim in all_dims if dim in self.dims])
81
82
 
82
83
  def get_sliced_dim_sizes_uncvar(self, sli: tuple) -> dict:
83
84
  """
84
85
  Return dictionary with sizes of sliced dimensions of unc variable, including all dimensions.
85
86
 
86
87
  :param sli: slice (tuple with slice for each dimension)
87
- :return: shape of included sliced dimensions
88
+ :return: dictionary with shape of included sliced dimensions
88
89
  """
89
90
  uncvar_dims = self._obj[self._unc_var_name][sli].dims
90
91
  uncvar_shape = self._obj[self._unc_var_name][sli].shape
@@ -98,7 +99,7 @@ class BaseErrCorrForm(abc.ABC):
98
99
  included in the current error correlation form.
99
100
 
100
101
  :param sli: slice (tuple with slice for each dimension)
101
- :return: shape of included sliced dimensions
102
+ :return: dictionary with shape of included sliced dimensions
102
103
  """
103
104
  uncvar_sizes = self.get_sliced_dim_sizes_uncvar(sli)
104
105
  sliced_dims = self.get_sliced_dims_errcorr(sli)
@@ -131,17 +132,21 @@ class BaseErrCorrForm(abc.ABC):
131
132
 
132
133
  return tuple([uncvar_sizes[dim] for dim in sliced_dims])
133
134
 
134
- def slice_full_cov(self, full_matrix: np.ndarray, sli: tuple) -> np.ndarray:
135
- return self.slice_flattened_matrix(
136
- full_matrix, self._obj[self._unc_var_name].shape, sli
137
- )
135
+ def slice_errcorr_matrix(self, err_corr_matrix, variable_shape, sli) -> np.ndarray:
136
+ """
137
+ Slice the provided error correlation matrix (typically the error correlation matrix of the
138
+ BaseErrCorrForm) using the
138
139
 
139
- def slice_flattened_matrix(self, flattened_matrix, variable_shape, sli):
140
+ :param err_corr_matrix: error correlation matrix to be sliced
141
+ :param variable_shape: tuple with the length of the dimensions in the error correlation matrix (in correct order for flattening)
142
+ :param sli: slice of observation variable to return error-correlation matrix for
143
+ :return: sliced error correlation matrix
144
+ """
140
145
  mask_array = np.ones(variable_shape, dtype=bool)
141
146
  mask_array[sli] = False
142
147
 
143
148
  return np.delete(
144
- np.delete(flattened_matrix, mask_array.ravel(), 0), mask_array.ravel(), 1
149
+ np.delete(err_corr_matrix, mask_array.ravel(), 0), mask_array.ravel(), 1
145
150
  )
146
151
 
147
152
  @abc.abstractmethod
@@ -158,16 +163,24 @@ class BaseErrCorrForm(abc.ABC):
158
163
 
159
164
  def build_dot_matrix(self, sli: Union[np.ndarray, tuple]) -> np.ndarray:
160
165
  """
161
- Returns uncertainty effect error-correlation matrix, populated with error-correlation values defined
162
- in this parameterisation
166
+ Returns expanded error correlation matrix for use in dot product with error correlation
167
+ in other dimensions.
163
168
 
164
- :param sli: slice of observation variable to return error-correlation matrix for
169
+ The (sliced) error correlation matrix for this BaseErrCorrForm is expanded from its current
170
+ (sliced) dimensions (which often don't include all dimensions of the associated uncertainty
171
+ variable) to the dimensions of the full (sliced) error correlation (i.e. all dimensions of
172
+ the uncertainty).
173
+ The returned matrix is not meaningfull unless combined in a dot product with the expanded
174
+ matrices of other error correlation matrices (together spanning all uncertainty dimensions).
165
175
 
166
- :return: populated error-correlation matrix
176
+ :param sli: slice of observation variable to return error-correlation matrix for
177
+ :return: expanded matrix for use in dot product with error correlation in other dimensions.
167
178
  """
168
-
169
- return self.expand_dim_matrix(
170
- self.build_matrix(sli), self.get_sliced_dims_errcorr(sli), sli
179
+ return expand_errcorr_dims(
180
+ in_corr=self.build_matrix(sli),
181
+ in_dim=self.get_sliced_dims_errcorr(sli),
182
+ out_dim=list(self._obj[self._unc_var_name][sli].dims),
183
+ dim_sizes=self.get_sliced_dim_sizes_uncvar(sli),
171
184
  )
172
185
 
173
186
 
@@ -250,24 +263,14 @@ class ErrCorrMatrixCorrelation(BaseErrCorrForm):
250
263
 
251
264
  :return: populated error-correlation matrix
252
265
  """
253
-
254
266
  all_dims = self._obj[self._unc_var_name].dims
255
- all_dims_sizes = self._obj.sizes
256
267
 
257
268
  sli_submatrix = tuple(
258
269
  [sli[i] for i in range(len(all_dims)) if all_dims[i] in self.dims]
259
270
  )
260
271
 
261
- sliced_shape = tuple(
262
- [
263
- all_dims_sizes[all_dims[i]]
264
- for i in range(len(all_dims))
265
- if all_dims[i] in self.dims
266
- ]
267
- )
268
-
269
- submatrix = self.slice_flattened_matrix(
270
- self._obj[self.params[0]], sliced_shape, sli_submatrix
272
+ submatrix = self.slice_errcorr_matrix(
273
+ self._obj[self.params[0]], self.get_varshape_errcorr(), sli_submatrix
271
274
  )
272
275
 
273
276
  return submatrix
@@ -7,6 +7,7 @@ from obsarray.err_corr import (
7
7
  ErrCorrForms,
8
8
  RandomCorrelation,
9
9
  SystematicCorrelation,
10
+ ErrCorrMatrixCorrelation,
10
11
  )
11
12
  from obsarray.test.test_unc_accessor import create_ds
12
13
 
@@ -65,18 +66,26 @@ class TestBaseErrCorrForm(unittest.TestCase):
65
66
  form = "basic"
66
67
 
67
68
  def build_matrix(self, sli):
68
- return None
69
+ full_matrix = np.arange(144).reshape((12, 12))
70
+ return self.slice_errcorr_matrix(full_matrix, (2, 2, 3), sli)
69
71
 
70
72
  self.BasicErrCorrForm = BasicErrCorrForm
71
73
 
74
+ def test_get_varshape_errcorr(self):
75
+ basicerrcorr = self.BasicErrCorrForm(
76
+ self.ds, "u_ran_temperature", ["x", "y", "time"], [], []
77
+ )
78
+ shape = basicerrcorr.get_varshape_errcorr()
79
+ np.testing.assert_equal(shape, (2, 2, 3))
80
+
72
81
  def test_slice_full_cov_full(self):
73
82
  basicerrcorr = self.BasicErrCorrForm(
74
83
  self.ds, "u_ran_temperature", ["x"], [], []
75
84
  )
76
85
 
77
86
  full_matrix = np.arange(144).reshape((12, 12))
78
- slice_matrix = basicerrcorr.slice_full_cov(
79
- full_matrix, (slice(None), slice(None), slice(None))
87
+ slice_matrix = basicerrcorr.build_matrix(
88
+ (slice(None), slice(None), slice(None))
80
89
  )
81
90
 
82
91
  np.testing.assert_equal(full_matrix, slice_matrix)
@@ -118,13 +127,13 @@ class TestBaseErrCorrForm(unittest.TestCase):
118
127
  shape = basicerrcorr.get_sliced_shape_errcorr((slice(None), 0, slice(0, 2, 1)))
119
128
  assert shape == (2, 2)
120
129
 
121
- def test_slice_flattened_matrix(self):
130
+ def test_slice_errcorr_matrix(self):
122
131
  basicerrcorr = self.BasicErrCorrForm(
123
- self.ds, "u_ran_temperature", ["x"], [], []
132
+ self.ds, "u_ran_temperature", ["x", "y", "z"], [], []
124
133
  )
125
134
 
126
135
  full_matrix = np.arange(144).reshape((12, 12))
127
- slice_matrix = basicerrcorr.slice_flattened_matrix(
136
+ slice_matrix = basicerrcorr.slice_errcorr_matrix(
128
137
  full_matrix, (2, 2, 3), (slice(None), slice(None), 0)
129
138
  )
130
139
 
@@ -136,13 +145,10 @@ class TestBaseErrCorrForm(unittest.TestCase):
136
145
 
137
146
  def test_slice_full_cov_slice(self):
138
147
  basicerrcorr = self.BasicErrCorrForm(
139
- self.ds, "u_ran_temperature", ["x"], [], []
148
+ self.ds, "u_ran_temperature", ["x", "y", "z"], [], []
140
149
  )
141
150
 
142
- full_matrix = np.arange(144).reshape((12, 12))
143
- slice_matrix = basicerrcorr.slice_full_cov(
144
- full_matrix, (slice(None), slice(None), 0)
145
- )
151
+ slice_matrix = basicerrcorr.build_dot_matrix((slice(None), slice(None), 0))
146
152
 
147
153
  exp_slice_matrix = np.array(
148
154
  [[0, 3, 6, 9], [36, 39, 42, 45], [72, 75, 78, 81], [108, 111, 114, 117]]
@@ -206,5 +212,40 @@ class TestSystematicUnc(unittest.TestCase):
206
212
  np.testing.assert_equal((x.dot(y)).dot(time), np.ones((12, 12)))
207
213
 
208
214
 
215
+ class TestErrCorrMatrixCorrelation(unittest.TestCase):
216
+ def setUp(self) -> None:
217
+ self.ds = create_ds()
218
+
219
+ def test_build_matrix_full(self):
220
+ ec = ErrCorrMatrixCorrelation(
221
+ self.ds,
222
+ "u_str_temperature",
223
+ ["x", "time"],
224
+ ["err_corr_str_temperature"],
225
+ [],
226
+ )
227
+
228
+ ecrm = ec.build_matrix((slice(None), slice(None), slice(None)))
229
+ np.testing.assert_equal(ecrm, np.ones((6, 6)))
230
+
231
+ def test_build_matrix_sliced(self):
232
+ ec = ErrCorrMatrixCorrelation(
233
+ self.ds,
234
+ "u_str_temperature",
235
+ ["x", "time"],
236
+ ["err_corr_str_temperature"],
237
+ [],
238
+ )
239
+
240
+ ecrm = ec.build_matrix((0, slice(None), slice(None)))
241
+ np.testing.assert_equal(ecrm, np.ones((3, 3)))
242
+
243
+ ecrm = ec.build_matrix((slice(None), 0, slice(None)))
244
+ np.testing.assert_equal(ecrm, np.ones((6, 6)))
245
+
246
+ ecrm = ec.build_matrix((slice(None), slice(None), 0))
247
+ np.testing.assert_equal(ecrm, np.ones((2, 2)))
248
+
249
+
209
250
  if __name__ == "main":
210
251
  unittest.main()
@@ -98,7 +98,7 @@ def create_ds():
98
98
  "units": "K",
99
99
  "err_corr": [
100
100
  {
101
- "dim": "x",
101
+ "dim": ["x", "time"],
102
102
  "form": "err_corr_matrix",
103
103
  "params": ["err_corr_str_temperature"],
104
104
  },
@@ -107,19 +107,19 @@ def create_ds():
107
107
  "form": "systematic",
108
108
  "params": [],
109
109
  },
110
- {
111
- "dim": "time",
112
- "form": "systematic",
113
- "params": [],
114
- },
115
110
  ],
116
111
  "pdf_shape": "gaussian",
117
112
  },
118
113
  )
119
114
 
120
115
  ds["err_corr_str_temperature"] = (
121
- ["x", "x"],
122
- np.eye(temperature.shape[0]),
116
+ ["x.time", "x.time"],
117
+ np.ones(
118
+ (
119
+ temperature.shape[0] * temperature.shape[2],
120
+ temperature.shape[0] * temperature.shape[2],
121
+ )
122
+ ),
123
123
  )
124
124
 
125
125
  return ds
@@ -354,7 +354,7 @@ class Uncertainty:
354
354
  err_cov_matrix = empty_err_corr_matrix(self._obj[self._unc_var_name][self._sli])
355
355
 
356
356
  err_cov_matrix.values = convert_corr_to_cov(
357
- self.err_corr_matrix().values, self.value.values
357
+ self.err_corr_matrix().values, self.abs_value.values
358
358
  )
359
359
 
360
360
  return err_cov_matrix
@@ -877,7 +877,8 @@ class UncAccessor(object):
877
877
  self._obj[obs_var].attrs["unc_comps"]
878
878
  ]
879
879
 
880
- self._obj[obs_var].attrs["unc_comps"].append(unc_var)
880
+ if unc_var not in self._obj[obs_var].attrs["unc_comps"]:
881
+ self._obj[obs_var].attrs["unc_comps"].append(unc_var)
881
882
 
882
883
  else:
883
884
  self._obj[obs_var].attrs["unc_comps"] = unc_var
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: obsarray
3
- Version: 0.2.6
3
+ Version: 1.0
4
4
  Summary: Measurement data handling in Python
5
5
  Home-page: https://github.com/comet-toolkit/obsarray
6
6
  Author: CoMet Toolkit Team
@@ -24,14 +24,12 @@ obsarray.egg-info/requires.txt
24
24
  obsarray.egg-info/top_level.txt
25
25
  obsarray/templater/__init__.py
26
26
  obsarray/templater/dataset_util.py
27
- obsarray/templater/dsdoc.py
28
27
  obsarray/templater/dstemplater.py
29
28
  obsarray/templater/dswriter.py
30
29
  obsarray/templater/template_util.py
31
30
  obsarray/templater/template_util_jon.py
32
31
  obsarray/templater/tests/__init__.py
33
32
  obsarray/templater/tests/test_dataset_util.py
34
- obsarray/templater/tests/test_dsdoc.py
35
33
  obsarray/templater/tests/test_dswriter.py
36
34
  obsarray/templater/tests/test_template_util.py
37
35
  obsarray/test/__init__.py
@@ -1,302 +0,0 @@
1
- """
2
- dsdoc - module for documenting defined ds formats
3
- """
4
-
5
- from obsarray import DSTemplater
6
- import os
7
- import numpy as np
8
- from obsarray.templater.dataset_util import DatasetUtil
9
-
10
-
11
- __author__ = "Sam Hunt <sam.hunt@npl.co.uk>"
12
-
13
-
14
- TEXT = {
15
- "title": "Product Data Format",
16
- "section_title-introduction": "Introduction",
17
- "paragraph-introduction": "This document aims to specify definitions, conventions and formats of the various data "
18
- "products generated in the Hypernets land and water network processors.",
19
- "section_title-formats": "Product Definitions",
20
- "paragraph-formats": "Text",
21
- "section_title-dimensions": "Dimension",
22
- "paragraph-dimensions": "Text",
23
- "section_title-variables": "Variables Definition",
24
- "paragraph-variables": "Text",
25
- "subsection_title-fmt_variables": "<fmt> Variables",
26
- "paragraph-fmt_variables": "<fmt> Text",
27
- "section_title-metadata": "Metadata",
28
- "paragraph-metadata": "Text",
29
- "subsection_title-fmt_metadata": "<fmt> Metadata",
30
- "paragraph-fmt_metadata": "<fmt> Text",
31
- }
32
-
33
-
34
- class RSTDocWriter:
35
- def __init__(self):
36
- self.doc = []
37
-
38
- def write_doc(self, path):
39
- with open(path, "w") as f:
40
- for elem in self.doc:
41
- f.write(elem + "\n")
42
-
43
- def add_table(self, rows, title, header_widths=None, stub_columns=None):
44
- self.doc.append(
45
- self.create_table(
46
- rows, title, header_widths=header_widths, stub_columns=stub_columns
47
- )
48
- )
49
-
50
- def add_heading(self, title):
51
- self.doc.append(self.create_heading(title))
52
-
53
- def add_subheading(self, title):
54
- self.doc.append(self.create_subheading(title))
55
-
56
- def add_subsubheading(self, title):
57
- self.doc.append(self.create_subsubheading(title))
58
-
59
- def add_paragraph(self, paragraph):
60
- self.doc.append(paragraph + "\n")
61
-
62
- def create_table(self, rows, title, header_widths=None, stub_columns=None):
63
-
64
- rst_table = ".. list-table:: " + str(title) + "\n" " :header-rows: 1\n"
65
-
66
- if header_widths is not None:
67
- widths_string = self.fmt_list_to_str(header_widths)
68
- rst_table += " :widths: " + widths_string + "\n"
69
-
70
- if stub_columns is not None:
71
- rst_table += " :stub-columns: " + str(stub_columns) + "\n"
72
-
73
- rst_table += "\n"
74
-
75
- for row in rows:
76
-
77
- if type(row) != list:
78
- row = [row]
79
-
80
- for i, column_value in enumerate(row):
81
- if i == 0:
82
- rst_table += " * - " + str(column_value) + "\n"
83
- else:
84
- rst_table += " - " + str(column_value) + "\n"
85
-
86
- return rst_table
87
-
88
- def _create_rst_heading(self, title, character="="):
89
-
90
- rst_header = title + "\n"
91
- rst_header += character * len(title) + "\n"
92
-
93
- return rst_header
94
-
95
- def create_heading(self, title):
96
- return self._create_rst_heading(title, character="=")
97
-
98
- def create_subheading(self, title):
99
- return self._create_rst_heading(title, character="-")
100
-
101
- def create_subsubheading(self, title):
102
- return self._create_rst_heading(title, character="~")
103
-
104
- def fmt_list_to_str(self, lst):
105
-
106
- lst_str = str(lst)
107
- lst_str = lst_str.replace("[", "")
108
- lst_str = lst_str.replace("]", "")
109
- lst_str = lst_str.replace("\\", "")
110
- lst_str = lst_str.replace("'", "")
111
- return lst_str
112
-
113
-
114
- class DSDoc(RSTDocWriter):
115
- def __init__(self, dsb, text=TEXT):
116
-
117
- self.dsb = dsb
118
- self.text = text
119
- super().__init__()
120
-
121
- def build_dsdoc(self):
122
-
123
- self.add_heading(self.text["title"])
124
-
125
- # Add introduction
126
-
127
- self.add_subheading(self.text["section_title-introduction"])
128
- self.add_paragraph(self.text["paragraph-introduction"])
129
-
130
- # Add format
131
-
132
- self.add_subheading(self.text["section_title-formats"])
133
- self.add_paragraph(self.text["paragraph-formats"])
134
-
135
- fmt_bullets = ""
136
- for fmt in self.dsb.return_ds_formats():
137
- fmt_bullets += "* " + fmt + "\n"
138
-
139
- self.add_paragraph(fmt_bullets)
140
-
141
- # Add dimensions section
142
-
143
- self.add_subheading(self.text["section_title-dimensions"])
144
- self.add_paragraph(self.text["paragraph-dimensions"])
145
- self.add_dims_table()
146
-
147
- # Add variables section
148
-
149
- self.add_subheading(self.text["section_title-variables"])
150
- self.add_paragraph(self.text["paragraph-variables"])
151
-
152
- # Add variables subsections per ds_format
153
- for fmt in self.dsb.return_ds_formats():
154
- self.add_subsubheading(
155
- TEXT["subsection_title-fmt_variables"].replace("<fmt>", fmt)
156
- )
157
- self.add_paragraph(TEXT["paragraph-fmt_variables"].replace("<fmt>", fmt))
158
-
159
- self.add_ds_format_var_tables(fmt)
160
-
161
- # Add metadata section
162
- self.add_subheading(TEXT["section_title-metadata"])
163
- self.add_paragraph(TEXT["paragraph-metadata"])
164
-
165
- for fmt in self.dsb.return_ds_formats():
166
- self.add_subsubheading(
167
- TEXT["subsection_title-fmt_metadata"].replace("<fmt>", fmt)
168
- )
169
- self.add_paragraph(TEXT["paragraph-fmt_metadata"].replace("<fmt>", fmt))
170
-
171
- def add_dims_table(self):
172
-
173
- rows = [["Format", "Dimensions"]]
174
-
175
- for ds_format in self.dsb.return_ds_formats():
176
- dims = str(sorted(self.dsb.return_ds_format_dim_names(ds_format)))
177
- dims_str = self.fmt_list_to_str(dims)
178
-
179
- rows.append([ds_format, dims_str])
180
-
181
- return self.add_table(rows, "Dimensions")
182
-
183
- def add_ds_format_var_summary_table(self, ds_format):
184
-
185
- rows = [["Variable Name", "Standard Name", "Data Type", "Dimension"]]
186
-
187
- for variable_name in self.dsb.return_ds_format_variable_names(ds_format):
188
- variable_dict = self.dsb.return_ds_format_variable_dict(
189
- ds_format, variable_name
190
- )
191
-
192
- var_dim_str = self.fmt_list_to_str(variable_dict["dim"])
193
- var_dtype = self.fmt_dtype_to_str(variable_dict["dtype"])
194
-
195
- var_std_name = None
196
- if "attributes" in variable_dict.keys():
197
- var_std_name = (
198
- variable_dict["attributes"]["standard_name"]
199
- if "standard_name" in variable_dict["attributes"]
200
- else ""
201
- )
202
-
203
- rows.append([variable_name, var_std_name, var_dtype, var_dim_str])
204
-
205
- return self.add_table(rows, ds_format + " variables")
206
-
207
- def add_var_table(self, variable_name, ds_format):
208
-
209
- variable_dict = self.dsb.return_ds_format_variable_dict(
210
- ds_format, variable_name
211
- )
212
-
213
- rows = [[variable_name, "Attribute", "Value"]]
214
-
215
- fill_value_str = (
216
- str(variable_dict["fill_value"])
217
- if "fill_value" in variable_dict
218
- else str(DatasetUtil.get_default_fill_value(variable_dict["dtype"]))
219
- )
220
- dtype_str = self.fmt_dtype_to_str(variable_dict["dtype"])
221
- var_dim_str = self.fmt_list_to_str(variable_dict["dim"])
222
-
223
- rows.append(["", "dim", var_dim_str])
224
- rows.append(["", "dtype", dtype_str])
225
-
226
- if "attributes" in variable_dict.keys():
227
- for attribute in variable_dict["attributes"].keys():
228
- rows.append(
229
- ["", attribute, str(variable_dict["attributes"][attribute])]
230
- )
231
-
232
- rows.append(["", "_FillValue", fill_value_str])
233
-
234
- if "encoding" in variable_dict.keys():
235
- for encode in variable_dict["encoding"]:
236
-
237
- encode_str = str(variable_dict["encoding"][encode])
238
- if encode == "dtype":
239
- encode_str = self.fmt_dtype_to_str(
240
- variable_dict["encoding"][encode]
241
- )
242
-
243
- rows.append(["", "encoding" + "_" + encode, encode_str])
244
-
245
- return self.add_table(rows, variable_name + " definition", stub_columns=1)
246
-
247
- def add_ds_format_var_tables(self, ds_format):
248
-
249
- self.add_ds_format_var_summary_table(ds_format)
250
-
251
- for variable_name in self.dsb.return_ds_format_variable_names(ds_format):
252
- self.add_var_table(variable_name, ds_format)
253
-
254
- def fmt_dtype_to_str(self, dtype):
255
-
256
- if dtype == np.int8:
257
- return "int8"
258
- if dtype == np.uint8:
259
- return "uint8"
260
- elif dtype == np.int16:
261
- return "int16"
262
- elif dtype == np.uint16:
263
- return "uint16"
264
- elif dtype == np.int32:
265
- return "int32"
266
- elif dtype == np.uint32:
267
- return "uint32"
268
- elif dtype == np.int64:
269
- return "int64"
270
- elif dtype == np.float32:
271
- return "float32"
272
- elif dtype == np.float64:
273
- return "float64"
274
- elif dtype == int:
275
- return "int"
276
- elif dtype == float:
277
- return "float"
278
-
279
-
280
- def dsdoc_main(path, variables_defs, metadata_defs, custom_text=None):
281
-
282
- # Setup
283
- dsb = DSBuilder(variables_defs=variables_defs, metadata_defs=metadata_defs)
284
-
285
- if custom_text is not None:
286
- TEXT.update(custom_text)
287
-
288
- dsdoc = DSDoc(dsb, text=TEXT)
289
-
290
- # Build docs
291
- dsdoc.build_dsdoc()
292
-
293
- # Write docs
294
- outdir = os.path.dirname(path)
295
- if not os.path.exists(outdir):
296
- os.mkdir(outdir)
297
-
298
- dsdoc.write_doc(os.path.join(outdir, "format.rst"))
299
-
300
-
301
- if __name__ == "__main__":
302
- pass
@@ -1,312 +0,0 @@
1
- # """
2
- # Tests for DatasetUtil class
3
- # """
4
- #
5
- # import unittest
6
- # from unittest.mock import patch, call
7
- # from obsarray import DSTemplater
8
- # from obsarray.templater.dsdoc import RSTDocWriter, DSDoc, dsdoc_main
9
- # import numpy as np
10
- #
11
- # """___Authorship___"""
12
- # __author__ = "Sam Hunt"
13
- # __created__ = "17/9/2020"
14
- #
15
- #
16
- # TEST_TEXT = {
17
- # "title": "Product Data Format",
18
- # "section_title-introduction": "Introduction",
19
- # "paragraph-introduction": "Text",
20
- # "section_title-formats": "Formats",
21
- # "paragraph-formats": "Text",
22
- # "section_title-dimensions": "Dimension",
23
- # "paragraph-dimensions": "Text",
24
- # "section_title-variables": "Variables Definition",
25
- # "paragraph-variables": "Text",
26
- # "subsection_title-fmt_variables": "<fmt> Variables",
27
- # "paragraph-fmt_variables": "<fmt> Text",
28
- # "section_title-metadata": "Metadata",
29
- # "paragraph-metadata": "Text",
30
- # "subsection_title-fmt_metadata": "<fmt> Metadata",
31
- # "paragraph-fmt_metadata": "<fmt> Text",
32
- # }
33
- #
34
- # array_variable1_rows = [
35
- # ["array_variable1", "Attribute", "Value"],
36
- # ["", "dim", "dim1, dim2"],
37
- # ["", "dtype", "float32"],
38
- # ["", "standard_name", "array_variable_std_name1"],
39
- # ["", "long_name", "array_variable_long_name1"],
40
- # ["", "units", "units"],
41
- # ["", "preferred_symbol", "av"],
42
- # ["", "_FillValue", "9.96921e+36"],
43
- # ["", "encoding_dtype", "uint16"],
44
- # ["", "encoding_scale_factor", "1.0"],
45
- # ["", "encoding_offset", "0.0"],
46
- # ]
47
- #
48
- # array_variable2_rows = [
49
- # ["array_variable2", "Attribute", "Value"],
50
- # ["", "dim", "dim3, dim4"],
51
- # ["", "dtype", "float32"],
52
- # ["", "standard_name", "array_variable_std_name2"],
53
- # ["", "long_name", "array_variable_long_name2"],
54
- # ["", "units", "units"],
55
- # ["", "preferred_symbol", "av"],
56
- # ["", "_FillValue", "9.96921e+36"],
57
- # ["", "encoding_dtype", "uint16"],
58
- # ["", "encoding_scale_factor", "1.0"],
59
- # ["", "encoding_offset", "0.0"],
60
- # ]
61
- #
62
- #
63
- # def setup_variables_defs():
64
- # test_variables = {
65
- # "array_variable1": {
66
- # "dim": ["dim1", "dim2"],
67
- # "dtype": np.float32,
68
- # "attributes": {
69
- # "standard_name": "array_variable_std_name1",
70
- # "long_name": "array_variable_long_name1",
71
- # "units": "units",
72
- # "preferred_symbol": "av",
73
- # },
74
- # "encoding": {"dtype": np.uint16, "scale_factor": 1.0, "offset": 0.0},
75
- # },
76
- # "array_variable2": {
77
- # "dim": ["dim3", "dim4"],
78
- # "dtype": np.float32,
79
- # "attributes": {
80
- # "standard_name": "array_variable_std_name2",
81
- # "long_name": "array_variable_long_name2",
82
- # "units": "units",
83
- # "preferred_symbol": "av",
84
- # },
85
- # "encoding": {"dtype": np.uint16, "scale_factor": 1.0, "offset": 0.0},
86
- # },
87
- # }
88
- #
89
- # return {"def1": test_variables}
90
- #
91
- #
92
- # def setup_metadata_defs():
93
- # return {}
94
- #
95
- #
96
- # def setup_dsb(
97
- # templates=setup_variables_defs(), metadata_defs=setup_metadata_defs()
98
- # ):
99
- # return DSTemplater(templates=templates, metadata_defs=metadata_defs)
100
- #
101
- #
102
- # class TestRSTDocWriter(unittest.TestCase):
103
- # def test_create_table(self):
104
- # dw = RSTDocWriter()
105
- #
106
- # rows = [["test1", "test2", "test3"], ["test4", "test5", "test6"]]
107
- # title = "table title"
108
- # spacing = [30, 40, 30]
109
- #
110
- # tbl = dw.create_table(rows, title, spacing)
111
- # expected_tbl = (
112
- # ".. list-table:: table title\n"
113
- # " :header-rows: 1\n"
114
- # " :widths: 30 40 30\n\n"
115
- # " * - test1\n"
116
- # " - test2\n"
117
- # " - test3\n"
118
- # " * - test4\n"
119
- # " - test5\n"
120
- # " - test6\n"
121
- # )
122
- #
123
- # self.assertEqual(tbl, expected_tbl)
124
- #
125
- # def test_create_table_single_column(self):
126
- # dw = RSTDocWriter()
127
- #
128
- # rows = ["test1", "test2", "test3"]
129
- # title = "table title"
130
- #
131
- # tbl = dw.create_table(rows, title)
132
- # expected_tbl = (
133
- # ".. list-table:: table title\n"
134
- # " :header-rows: 1\n\n"
135
- # " * - test1\n"
136
- # " * - test2\n"
137
- # " * - test3\n"
138
- # )
139
- #
140
- # self.assertEqual(tbl, expected_tbl)
141
- #
142
- # def test__create_rst_heading(self):
143
- # dw = RSTDocWriter()
144
- #
145
- # heading = dw._create_rst_heading("text", "=")
146
- # expected_heading = "text\n" "====\n"
147
- #
148
- # self.assertEqual(heading, expected_heading)
149
- #
150
- # @patch("templater.dsdoc.RSTDocWriter.create_table")
151
- # def test_add_table(self, mock):
152
- # dw = RSTDocWriter()
153
- # dw.add_table("rows", "title", "widths")
154
- # mock.assert_called_once_with("rows", "title", header_widths="widths")
155
- #
156
- # self.assertEqual(dw.doc[0], mock.return_value)
157
- #
158
- # @patch("templater.dsdoc.RSTDocWriter._create_rst_heading")
159
- # def test_create_heading(self, mock):
160
- # dw = RSTDocWriter()
161
- # heading = dw.create_heading("text")
162
- # mock.assert_called_once_with("text", character="=")
163
- #
164
- # @patch("templater.dsdoc.RSTDocWriter._create_rst_heading")
165
- # def test_create_subheading(self, mock):
166
- # dw = RSTDocWriter()
167
- # heading = dw.create_subheading("text")
168
- # mock.assert_called_once_with("text", character="-")
169
- #
170
- # @patch("templater.dsdoc.RSTDocWriter._create_rst_heading")
171
- # def test_create_subsubheading(self, mock):
172
- # dw = RSTDocWriter()
173
- # heading = dw.create_subsubheading("text")
174
- # mock.assert_called_once_with("text", character="~")
175
- #
176
- # @patch("templater.dsdoc.RSTDocWriter.create_heading")
177
- # def test_add_heading(self, mock):
178
- # dw = RSTDocWriter()
179
- # dw.add_heading("text")
180
- # mock.assert_called_once_with("text")
181
- #
182
- # self.assertEqual(dw.doc[0], mock.return_value)
183
- #
184
- # @patch("templater.dsdoc.RSTDocWriter.create_subheading")
185
- # def test_add_subheading(self, mock):
186
- # dw = RSTDocWriter()
187
- # heading = dw.add_subheading("text")
188
- # mock.assert_called_once_with("text")
189
- #
190
- # self.assertEqual(dw.doc[0], mock.return_value)
191
- #
192
- # @patch("templater.dsdoc.RSTDocWriter.create_subsubheading")
193
- # def test_add_subsubheading(self, mock):
194
- # dw = RSTDocWriter()
195
- # dw.add_subsubheading("text")
196
- # mock.assert_called_once_with("text")
197
- #
198
- # self.assertEqual(dw.doc[0], mock.return_value)
199
- #
200
- # def test_add_paragraph(self):
201
- # dw = RSTDocWriter()
202
- # dw.add_paragraph("text")
203
- #
204
- # self.assertEqual(dw.doc[0], "text" + "\n")
205
- #
206
- #
207
- # class TestDSDoc(unittest.TestCase):
208
- # @patch("templater.dsdoc.RSTDocWriter.add_table")
209
- # def test_build_dims_table(self, mock):
210
- #
211
- # dsb = setup_dsb()
212
- # dsdoc = DSDoc(dsb)
213
- #
214
- # dsdoc.add_dims_table()
215
- #
216
- # expected_rows = [["Format", "Dimensions"], ["def1", "dim1, dim2, dim3, dim4"]]
217
- # expected_title = "Dimensions"
218
- #
219
- # mock.assert_called_once_with(expected_rows, expected_title)
220
- #
221
- # @patch("templater.dsdoc.DSDoc.add_var_table")
222
- # def test_add_ds_format_var_tables(self, mock):
223
- # dsb = setup_dsb()
224
- # dsdoc = DSDoc(dsb)
225
- #
226
- # dsdoc.add_ds_format_var_tables("def1")
227
- #
228
- # calls = [call("array_variable1", "def1"), call("array_variable2", "def1")]
229
- #
230
- # self.assertCountEqual(mock.call_args_list, calls)
231
- #
232
- # @patch("templater.dsdoc.RSTDocWriter.add_table")
233
- # def test_build_var_table(self, mock):
234
- # dsb = setup_dsb()
235
- # dsdoc = DSDoc(dsb)
236
- #
237
- # dsdoc.add_var_table("array_variable1", "def1")
238
- #
239
- # expected_rows = array_variable1_rows
240
- # expected_title = "array_variable1 definition"
241
- #
242
- # mock.assert_called_once_with(expected_rows, expected_title, stub_columns=1)
243
- #
244
- # @patch("templater.dsdoc.RSTDocWriter.add_table")
245
- # def test_add_ds_format_var_summary_table(self, mock):
246
- # dsb = setup_dsb()
247
- # dsdoc = DSDoc(dsb)
248
- #
249
- # dsdoc.add_ds_format_var_summary_table("def1")
250
- #
251
- # expected_rows = [
252
- # ["Variable Name", "Standard Name", "Data Type", "Dimension"],
253
- # ["array_variable1", "array_variable_std_name1", "float32", "dim1, dim2"],
254
- # ["array_variable2", "array_variable_std_name2", "float32", "dim3, dim4"],
255
- # ]
256
- # expected_title = "def1 variables"
257
- #
258
- # mock.assert_called_once_with(expected_rows, expected_title)
259
- #
260
- # def test_build_dsdoc(self):
261
- #
262
- # dsb = setup_dsb()
263
- # dsdoc = DSDoc(dsb, text=TEST_TEXT)
264
- #
265
- # dsdoc.build_dsdoc()
266
- #
267
- # dsdoc_mk = DSDoc(dsb, text=TEST_TEXT)
268
- # dsdoc_mk.add_ds_format_var_summary_table("def1")
269
- # dsdoc_mk.add_dims_table()
270
- # def1_summary_tbl = dsdoc_mk.doc[0]
271
- # dims_tbl = dsdoc_mk.doc[1]
272
- #
273
- # expected_doc = [
274
- # "Product Data Format\n===================\n",
275
- # "Formats\n-------\n",
276
- # "Text\n",
277
- # "* def1\n",
278
- # "Introduction\n------------\n",
279
- # "Text\n",
280
- # "Dimension\n---------\n",
281
- # "Text\n",
282
- # dims_tbl,
283
- # "Variables Definition\n--------------------\n",
284
- # "Text\n",
285
- # "def1 Variables\n~~~~~~~~~~~~~~\n",
286
- # "def1 Text\n",
287
- # def1_summary_tbl,
288
- # dsdoc.create_table(
289
- # array_variable1_rows, "array_variable1 definition", stub_columns=1
290
- # ),
291
- # dsdoc.create_table(
292
- # array_variable2_rows, "array_variable2 definition", stub_columns=1
293
- # ),
294
- # "Metadata\n--------\n",
295
- # "Text\n",
296
- # "def1 Metadata\n~~~~~~~~~~~~~\n",
297
- # "def1 Text\n",
298
- # ]
299
- #
300
- # self.assertCountEqual(expected_doc, dsdoc.doc)
301
- #
302
- # def test_write_dsdoc(self):
303
- #
304
- # dsb = setup_dsb()
305
- # dsdoc = DSDoc(dsb, text=TEST_TEXT)
306
- #
307
- # dsdoc.build_dsdoc()
308
- # dsdoc.write_doc("dsdoc/src/ds.rst")
309
- #
310
- #
311
- # if __name__ == "__main__":
312
- # unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes