Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to implement CFA-0.6 #630

Merged
merged 151 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from 150 commits
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
f901843
dev
davidhassell Feb 6, 2023
a1ea1a2
dev
davidhassell Feb 7, 2023
4210fc0
dev
davidhassell Feb 7, 2023
6335b2e
dev
davidhassell Feb 7, 2023
0e759df
dev
davidhassell Feb 7, 2023
4853c9f
dev
davidhassell Feb 8, 2023
c6ba761
dev
davidhassell Feb 8, 2023
71361cc
dev
davidhassell Feb 9, 2023
bb77380
dev
davidhassell Feb 9, 2023
5bf4a65
Merge branch 'main' of github.com:NCAS-CMS/cf-python into cfa-0.6
davidhassell Feb 10, 2023
40f81d1
dev
davidhassell Feb 10, 2023
e1e9dbb
dev
davidhassell Feb 11, 2023
4bf3dc8
dev
davidhassell Feb 13, 2023
c793c82
dev
davidhassell Feb 13, 2023
c16585d
dev
davidhassell Feb 13, 2023
801b549
dev
davidhassell Feb 14, 2023
e841bc3
dev
davidhassell Feb 14, 2023
f76c979
mixin
davidhassell Feb 16, 2023
f5967f0
dev
davidhassell Feb 16, 2023
8a11033
dev
davidhassell Feb 16, 2023
4a773a9
dev
davidhassell Feb 17, 2023
fdb0998
dev
davidhassell Feb 20, 2023
ce98e3b
dev
davidhassell Feb 22, 2023
71e571d
dev
davidhassell Feb 22, 2023
d2fcd19
dev
davidhassell Feb 23, 2023
273ec73
dev
davidhassell Feb 24, 2023
6f46805
dev
davidhassell Feb 24, 2023
7cbb5b3
dev
davidhassell Feb 27, 2023
60aeb35
dev
davidhassell Feb 27, 2023
95c2622
dev
davidhassell Feb 28, 2023
79753dd
dev
davidhassell Feb 28, 2023
3fbb7c8
dev
davidhassell Feb 28, 2023
98aaa85
dev
davidhassell Mar 1, 2023
fa91e6a
dev
davidhassell Mar 1, 2023
21cf6de
main merge conflicts
davidhassell Mar 1, 2023
a49fb12
dev
davidhassell Mar 1, 2023
f9ca4f6
dev
davidhassell Mar 1, 2023
de5ae65
dev
davidhassell Mar 1, 2023
6dbb490
dev
davidhassell Mar 2, 2023
405b928
dev
davidhassell Mar 2, 2023
d83e839
dev
davidhassell Mar 3, 2023
fe3867f
dev
davidhassell Mar 3, 2023
1786eaf
dev
davidhassell Mar 4, 2023
da0747b
dev
davidhassell Mar 4, 2023
7e6e0cb
dev
davidhassell Mar 5, 2023
758f840
dev
davidhassell Mar 5, 2023
9e4600a
dev
davidhassell Mar 6, 2023
1e9a91f
dev
davidhassell Mar 6, 2023
5151d3a
Merge branch 'main' of github.com:NCAS-CMS/cf-python into cfa-0.6
davidhassell Mar 6, 2023
d4b6d0f
dev
davidhassell Mar 6, 2023
fc1631b
dev
davidhassell Mar 7, 2023
76eef2c
dev
davidhassell Mar 7, 2023
c27bbac
dev
davidhassell Mar 7, 2023
8cce776
dev
davidhassell Mar 8, 2023
1d9d309
dev
davidhassell Mar 8, 2023
347f074
dev
davidhassell Mar 8, 2023
855f992
dev
davidhassell Mar 9, 2023
6e253d1
dev
davidhassell Mar 9, 2023
0ed1fd8
dev
davidhassell Mar 9, 2023
9e338ec
dev
davidhassell Mar 10, 2023
d760445
dev
davidhassell Mar 10, 2023
aef8c51
Merge branch 'main' of github.com:NCAS-CMS/cf-python into cfa-0.6
davidhassell Mar 12, 2023
d56ae8f
dev
davidhassell Mar 12, 2023
ee0df71
dev
davidhassell Mar 13, 2023
0f46fb9
dev
davidhassell Mar 13, 2023
43fca49
dev
davidhassell Mar 15, 2023
f180def
correct bounds and units of PP hybrid height coordinates
davidhassell Mar 15, 2023
3663b15
dev
davidhassell Mar 18, 2023
2e6a3bd
dev
davidhassell Mar 19, 2023
5bb7e48
docs
davidhassell Mar 20, 2023
271fba9
cfanetcdfarray.to_dask_array bugfix
davidhassell Mar 23, 2023
c680bc5
dev
davidhassell Mar 27, 2023
9c2c6ff
customize -> customise
davidhassell Apr 17, 2023
d5e0bbf
domain_axes docs
davidhassell Apr 17, 2023
4ba5873
remove obselete file
davidhassell Apr 18, 2023
5ae26a7
Improved docstring
davidhassell Apr 18, 2023
d7a974b
Merge branch 'main' into cfa-0.6
sadielbartholomew Apr 18, 2023
37ff8a6
Remove dead code
davidhassell Apr 18, 2023
f76821f
Typo
davidhassell Apr 18, 2023
702f5b2
Typo
davidhassell Apr 18, 2023
bd95b68
Typo
davidhassell Apr 18, 2023
91bde24
Remove dead code
davidhassell Apr 18, 2023
b28fe8a
Typo
davidhassell Apr 18, 2023
5f4ac35
Typo
davidhassell Apr 18, 2023
5f2cba2
Typo
davidhassell Apr 18, 2023
2e70f16
Typo
davidhassell Apr 18, 2023
7790791
Typo
davidhassell Apr 18, 2023
0c7f7ab
byte string -> unicode
davidhassell Apr 18, 2023
ca18292
byte string -> unicode
davidhassell Apr 18, 2023
eedf033
dev
davidhassell Apr 18, 2023
5261e06
Typo
davidhassell Apr 20, 2023
5ba66cf
Typo
davidhassell Apr 20, 2023
42391c2
Typo
davidhassell Apr 20, 2023
b3a71c7
Typo
davidhassell Apr 20, 2023
785ea0e
Typo
davidhassell Apr 20, 2023
c0fdf72
Typo
davidhassell Apr 20, 2023
af589ce
Typo
davidhassell Apr 20, 2023
16ad8db
Typo
davidhassell Apr 20, 2023
283911f
Remove dead code
davidhassell Apr 20, 2023
c8598d3
Remove dead code
davidhassell Apr 20, 2023
7553a53
Typo
davidhassell Apr 20, 2023
44244ab
Typo
davidhassell Apr 20, 2023
1031ad2
Remove dead code
davidhassell Apr 20, 2023
ac40c4c
Typo
davidhassell Apr 20, 2023
7b63ca4
Docs
davidhassell Apr 20, 2023
acdfbc0
docs
davidhassell Apr 20, 2023
e19bc87
docs
davidhassell Apr 20, 2023
b70d054
Typo
davidhassell Apr 20, 2023
7e34daf
Typo
davidhassell Apr 20, 2023
b87733e
CFA format docs
davidhassell Apr 20, 2023
0db992e
deprecate cfa_base
davidhassell Apr 20, 2023
8c5848c
deprecate cfa_base, fix cfa_paths
davidhassell Apr 20, 2023
18683a3
Typo
davidhassell Apr 24, 2023
6dc72d3
Mark comment with TODOCFA
davidhassell Apr 24, 2023
4755345
Docs clarity
davidhassell Apr 24, 2023
d52741e
Typo
davidhassell Apr 24, 2023
912a50d
Typo
davidhassell Apr 24, 2023
03c2fad
Typo
davidhassell Apr 24, 2023
5a5620f
Docs clarity
davidhassell Apr 24, 2023
7cba540
Typo
davidhassell Apr 24, 2023
9901c47
Typo
davidhassell Apr 24, 2023
f702bf5
Docs improvement
davidhassell Apr 24, 2023
73cd14e
Remove dead code
davidhassell Apr 24, 2023
f4f15aa
Remove dead code
davidhassell Apr 24, 2023
98e8d23
Remove dead code
davidhassell Apr 24, 2023
1e543ad
Typo
davidhassell Apr 24, 2023
c8591c3
Remove dead code
davidhassell Apr 24, 2023
3fb2415
docs clarity
davidhassell Apr 24, 2023
d6102f3
Merge branch 'cfa-0.6' of github.com:davidhassell/cf-python into cfa-0.6
davidhassell Apr 24, 2023
10a7d44
Typo
davidhassell Apr 24, 2023
7f040fa
Typo
davidhassell Apr 24, 2023
3254e55
Typo
davidhassell Apr 24, 2023
f85981f
docs clarity
davidhassell Apr 24, 2023
d18b8db
Typo
davidhassell Apr 24, 2023
833c4fc
Merge branch 'cfa-0.6' of github.com:davidhassell/cf-python into cfa-0.6
davidhassell Apr 24, 2023
d0ad8ce
comment clarity
davidhassell Apr 24, 2023
84e2f1d
docs fix
davidhassell Apr 24, 2023
af45ce5
Typo
davidhassell Apr 24, 2023
ce6a1bd
Exception message clarity
davidhassell Apr 24, 2023
a7901e8
Typos
davidhassell Apr 24, 2023
9b9ea5c
CFA
davidhassell Apr 24, 2023
d523228
cfdm version
davidhassell Apr 24, 2023
6b7bc14
Merge branch 'main' into cfa-0.6
davidhassell Apr 24, 2023
a70e08e
Remove redundant code
davidhassell Apr 24, 2023
5eda8e9
test method docstrings
davidhassell Apr 24, 2023
5f32490
comment on CFA-netCDF file directory path
davidhassell Apr 24, 2023
36a6313
Remove redundant docstring
davidhassell Apr 24, 2023
b815e73
CFA methods docs
davidhassell Apr 24, 2023
a51a24c
linting
davidhassell Apr 24, 2023
c6d7fec
Typos
davidhassell Apr 24, 2023
31a53c4
basic CFA references
davidhassell Apr 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Changelog.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
version 3.14.2
version 3.15.0
--------------

**2023-04-??**

* Re-introduction of CFA-netCDF functionality for CFA-0.6
(https://github.com/NCAS-CMS/cf-python/issues/451,
https://github.com/NCAS-CMS/cf-python/issues/475,
https://github.com/NCAS-CMS/cf-python/issues/637)
* New function: `cf.CFA`
* New method: `cf.Data.get_cfa_write`
* New method: `cf.Data.set_cfa_write`
* Fix excessive memory use arising from `cf.Field.regrids` and
`cf.Field.regridc`
(https://github.com/NCAS-CMS/cf-python/issues/623)
* Fixed bug in `cf.Field.read` when reading UM/PP data that are
runlength encoded (https://github.com/NCAS-CMS/cf-python/issues/621)
* Removed benign UserWarning from `cf.Field.percentile`
(https://github.com/NCAS-CMS/cf-python/issues/619)
* Changed dependency: ``1.10.1.0<=cfdm<1.10.2.0``

----

Expand Down Expand Up @@ -49,6 +57,8 @@ version 3.14.0
https://github.com/NCAS-CMS/cf-python/issues/428)
* Backwards incompatible API changes to facilitate the use of Dask
(https://github.com/NCAS-CMS/cf-python/issues/579)
* Removal of CFA-0.4 functionality (CFA-0.6 will introduced at a later
version).
Comment on lines +60 to +61
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Removal of CFA-0.4 functionality (CFA-0.6 will introduced at a later
version).
* Removal of CFA-0.4 functionality (CFA-0.6 will be introduced at a
later version).

* New method: `cf.Field.get_original_filenames`
(https://github.com/NCAS-CMS/cf-python/issues/448)
* New method: `cf.Field.to_dask_array`
Expand Down
9 changes: 5 additions & 4 deletions cf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
raise ImportError(_error0 + str(error1))

__cf_version__ = cfdm.core.__cf_version__
__cfa_version__ = "0.6.2"

from packaging.version import Version
import importlib.util
Expand Down Expand Up @@ -188,8 +189,8 @@
)

# Check the version of cfdm
_minimum_vn = "1.10.0.3"
_maximum_vn = "1.10.1.0"
_minimum_vn = "1.10.1.0"
_maximum_vn = "1.10.2.0"
_cfdm_version = Version(cfdm.__version__)
if not Version(_minimum_vn) <= _cfdm_version < Version(_maximum_vn):
raise RuntimeError(
Expand All @@ -198,7 +199,7 @@
)

# Check the version of dask
_minimum_vn = "2022.12.1"
_minimum_vn = "2022.02.1"
if Version(dask.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad dask version: cf requires dask>={_minimum_vn}. "
Expand Down Expand Up @@ -262,7 +263,7 @@
)

from .data.fragment import (
MissingFragmentArray,
FullFragmentArray,
NetCDFFragmentArray,
UMFragmentArray,
)
Expand Down
195 changes: 154 additions & 41 deletions cf/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
from collections import namedtuple
from operator import itemgetter

import numpy as np
from cfdm import is_log_level_debug, is_log_level_detail, is_log_level_info
from numpy import argsort as numpy_argsort
from numpy import dtype as numpy_dtype
from numpy import sort as numpy_sort

from .auxiliarycoordinate import AuxiliaryCoordinate
from .data.data import Data
from .data import Data
from .data.array import FullArray
from .decorators import (
_manage_log_level_via_verbose_attr,
_manage_log_level_via_verbosity,
_reset_log_emergence_level,
)
from .domainaxis import DomainAxis
from .fieldancillary import FieldAncillary
from .fieldlist import FieldList
from .functions import _DEPRECATION_ERROR_FUNCTION_KWARGS, _numpy_allclose
from .functions import atol as cf_atol
Expand All @@ -26,7 +26,7 @@
logger = logging.getLogger(__name__)


_dtype_float = numpy_dtype(float)
_dtype_float = np.dtype(float)

# # --------------------------------------------------------------------
# # Global properties, as defined in Appendix A of the CF conventions.
Expand Down Expand Up @@ -134,10 +134,11 @@ def __init__(
equal=None,
exist=None,
ignore=None,
dimension=(),
dimension=None,
relaxed_identities=False,
ncvar_identities=False,
field_identity=None,
field_ancillaries=(),
copy=True,
):
"""**initialisation**
Expand Down Expand Up @@ -207,6 +208,11 @@ def __init__(
coordinate whose datum is the property's value and the
property itself is deleted from that field.

field_ancillaries: (sequence of) `str`, optional
See `cf.aggregate` for details.

.. versionadded:: TODOCFAVER

copy: `bool` optional
If False then do not copy fields prior to aggregation.
Setting this option to False may change input fields in
Expand Down Expand Up @@ -289,41 +295,22 @@ def __init__(
"no identity; consider setting " "relaxed_identities"
)
return
# elif not self.has_data:
# self.message = "{} has no data".format(f.__class__.__name__)
# return

# ------------------------------------------------------------
# Promote selected properties to 1-d, size 1 auxiliary
# coordinates
# coordinates with new independent domain axes
# ------------------------------------------------------------
_copy = copy
for prop in dimension:
value = f.get_property(prop, None)
if value is None:
continue

aux_coord = AuxiliaryCoordinate(
properties={"long_name": prop},
data=Data([value], units=""),
copy=False,
)
aux_coord.nc_set_variable(prop)
aux_coord.id = prop

if _copy:
# Copy the field, as we're about to change it.
f = f.copy()
self.field = f
_copy = False

axis = f.set_construct(DomainAxis(1))
f.set_construct(aux_coord, axes=[axis], copy=False)
if dimension:
f = self.promote_to_auxiliary_coordinate(dimension)

f.del_property(prop)
# ------------------------------------------------------------
# Promote selected properties to field ancillaries that span
# the same domain axes as the field
# ------------------------------------------------------------
if field_ancillaries:
f = self.promote_to_field_ancillary(field_ancillaries)

if dimension:
construct_axes = f.constructs.data_axes()
construct_axes = f.constructs.data_axes()

self.units = self.canonical_units(
f, self.identity, relaxed_units=relaxed_units
Expand Down Expand Up @@ -400,7 +387,6 @@ def __init__(
"coordrefs": self.find_coordrefs(axis),
}
)
# 'size' : None})

# Find the 1-d auxiliary coordinates which span this axis
aux_coords = {
Expand Down Expand Up @@ -546,10 +532,10 @@ def __init__(
# Field ancillaries
# ------------------------------------------------------------
self.field_anc = {}
field_ancillaries = f.constructs.filter_by_type(
field_ancs = f.constructs.filter_by_type(
"field_ancillary", todict=True
)
for key, field_anc in field_ancillaries.items():
for key, field_anc in field_ancs.items():
# Find this field ancillary's identity
identity = self.field_ancillary_has_identity_and_data(field_anc)
if identity is None:
Expand Down Expand Up @@ -1395,6 +1381,117 @@ def find_coordrefs(self, key):

return tuple(sorted(names))

def promote_to_auxiliary_coordinate(self, properties):
"""Promote properties to auxiliary coordinate constructs.

Each property is converted to a 1-d auxilliary coordinate
construct that spans a new independent size 1 domain axis of
the field, and the property is deleted.

... versionadded:: TODOCFAVER

:Parameters:

properties: sequence of `str`
The names of the properties to be promoted.

:Returns:

`Field` or `Domain`
The field or domain with the new auxiliary coordinate
constructs.

"""
f = self.field

copy = True
for prop in properties:
value = f.get_property(prop, None)
if value is None:
continue

aux_coord = AuxiliaryCoordinate(
properties={"long_name": prop},
data=Data([value]),
copy=False,
)
aux_coord.nc_set_variable(prop)
aux_coord.id = prop

if copy:
# Copy the field as we're about to change it
f = f.copy()
copy = False

axis = f.set_construct(DomainAxis(1))
f.set_construct(aux_coord, axes=[axis], copy=False)
f.del_property(prop)

self.field = f
return f

def promote_to_field_ancillary(self, properties):
"""Promote properties to field ancillary constructs.

For each input field, each property is converted to a field
ancillary construct that spans the entire domain, with the
constant value of the property.

The `Data` of any new field ancillary construct is marked
as a CFA term, meaning that it will only be written to disk if
the parent field construct is written as a CFA aggregation
variable, and in that case the field ancillary is written as a
non-standard CFA aggregation instruction variable, rather than
a CF-netCDF ancillary variable.

If a domain construct is being aggregated then it is always
returned unchanged.

... versionadded:: TODOCFAVER

:Parameters:

properties: sequnce of `str`
The names of the properties to be promoted.

:Returns:

`Field` or `Domain`
The field or domain with the new field ancillary
constructs.

"""
f = self.field
if f.construct_type != "field":
return f

copy = True
for prop in properties:
value = f.get_property(prop, None)
if value is None:
continue

data = Data(
FullArray(value, shape=f.shape, dtype=np.array(value).dtype)
)
data._cfa_set_term(True)

field_anc = FieldAncillary(
data=data, properties={"long_name": prop}, copy=False
)
field_anc.id = prop

if copy:
# Copy the field as we're about to change it
f = f.copy()
copy = False

f.set_construct(field_anc, axes=f.get_data_axes(), copy=False)
f.del_property(prop)

self.field = f
return f


@_manage_log_level_via_verbosity
def aggregate(
Expand Down Expand Up @@ -1423,6 +1520,7 @@ def aggregate(
no_overlap=False,
shared_nc_domain=False,
field_identity=None,
field_ancillaries=None,
info=False,
):
"""Aggregate field constructs into as few field constructs as
Expand Down Expand Up @@ -1649,6 +1747,16 @@ def aggregate(
numbers. The default value is set by the
`cf.rtol` function.

field_ancillaries: (sequence of) `str`, optional
Create new field ancillary constructs for each input field
which has one or more of the given properties. For each
input field, each property is converted to a field
ancillary construct that spans the entire domain, with the
constant value of the property, and the property itself is
deleted.

.. versionadded:: TODOCFAVER

no_overlap:
Use the *overlap* parameter instead.

Expand Down Expand Up @@ -1705,6 +1813,7 @@ def aggregate(
"\ninfo=2 maps to verbose=3"
"\ninfo=3 maps to verbose=-1",
version="3.5.0",
removed_at="4.0.0",
) # pragma: no cover

# Initialise the cache for coordinate and cell measure hashes,
Expand Down Expand Up @@ -1738,6 +1847,9 @@ def aggregate(
if isinstance(dimension, str):
dimension = (dimension,)

if isinstance(field_ancillaries, str):
field_ancillaries = (field_ancillaries,)

if exist_all and equal_all:
raise ValueError(
"Only one of 'exist_all' and 'equal_all' can be True, since "
Expand Down Expand Up @@ -1808,6 +1920,7 @@ def aggregate(
ncvar_identities=ncvar_identities,
field_identity=field_identity,
respect_valid=respect_valid,
field_ancillaries=field_ancillaries,
copy=copy,
)

Expand Down Expand Up @@ -2220,7 +2333,7 @@ def _create_hash_and_first_values(
# ... or which doesn't have a dimension coordinate but
# does have one or more 1-d auxiliary coordinates
aux = m_axis_identity["keys"][0]
sort_indices = numpy_argsort(field.constructs[aux].array)
sort_indices = np.argsort(field.constructs[aux].array)
m_sort_keys[axis] = aux
null_sort = False

Expand Down Expand Up @@ -2662,8 +2775,8 @@ def _get_hfl(

if create_flb:
# Record the bounds of the first and last (sorted) cells
first = numpy_sort(array[0, ...])
last = numpy_sort(array[-1, ...])
first = np.sort(array[0, ...])
last = np.sort(array[-1, ...])
hfl_cache.flb[key] = (first, last)

if first_and_last_values or first_and_last_bounds:
Expand Down
Loading