Skip to content

Commit d4feb64

Browse files
committed
dev
1 parent c8bd171 commit d4feb64

5 files changed

Lines changed: 133 additions & 255 deletions

File tree

cf/data/dask_utils.py

Lines changed: 9 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from functools import partial
99

1010
import numpy as np
11-
from cfdm import integer_dtype
1211
from cfdm.data.dask_utils import cfdm_to_memory
1312
from scipy.ndimage import convolve1d
1413

@@ -761,161 +760,6 @@ def cf_healpix_coordinates(
761760
return c
762761

763762

764-
def cf_healpix_increase_refinement(a, ncells, iaxis, quantity):
765-
"""Increase the refinement level of a HEALPix data.
766-
767-
Data are broadcast to cells of at the higher refinement level. For
768-
an "extensive" quantity only, the broadcast values are reduced to
769-
be consistent with the new smaller cell areas.
770-
771-
.. warning:: The returned `numpy` array will take up *ncells*
772-
times more memory than the input array *a* (or two
773-
times *ncells* more memory, if *a* contains 32-bit
774-
integers and *quantity* is ``'extensive'``). For
775-
instance, if 64-bit *a* has shape ``(3600, 48)``
776-
(1.318 MiB), the HEALPix axis is ``1``, and *ncells*
777-
is ``4096``, then the returned array will have shape
778-
``(3600, 196608)`` (5.4 GiB), where 196608=48*4096.
779-
780-
K. Gorski, Eric Hivon, A. Banday, B. Wandelt, M. Bartelmann, et
781-
al.. HEALPix: A Framework for High-Resolution Discretization and
782-
Fast Analysis of Data Distributed on the Sphere. The Astrophysical
783-
Journal, 2005, 622 (2), pp.759-771.
784-
https://dx.doi.org/10.1086/427976
785-
786-
.. versionadded:: NEXTVERSION
787-
788-
.. seealso:: `cf.Field.healpix_increase_refinement_level`
789-
790-
:Parameters:
791-
792-
a: `numpy.ndarray`
793-
The array.
794-
795-
ncells: `int`
796-
The number of cells at the new refinement level which are
797-
contained in one cell at the original refinement level.
798-
799-
iaxis: `int`
800-
The position of the HEALPix axis in the array dimensions.
801-
802-
quantity: `str`
803-
Whether the array values represent intensive or extensive
804-
quantities, specified with ``'intensive'`` and
805-
``'extensive'`` respectively.
806-
807-
:Returns:
808-
809-
`numpy.ndarray`
810-
The array at the new refinement level.
811-
812-
"""
813-
a = cfdm_to_memory(a)
814-
815-
if quantity == "extensive":
816-
a = a / ncells
817-
818-
# Create a new dimension over which the original HEALPix axis will
819-
# be broadcast
820-
iaxis = iaxis + 1
821-
a = np.expand_dims(a, iaxis)
822-
823-
# Define the shape of the new array, and broadcast 'a' to it.
824-
# shape
825-
shape = list(a.shape)
826-
shape[iaxis] = ncells
827-
a = np.broadcast_to(a, shape, subok=True)
828-
829-
# Reshape the new array to combine the original HEALPix and
830-
# broadcast dimensions into a single new HEALPix dimension
831-
a = a.reshape(
832-
shape[: iaxis - 1]
833-
+ [shape[iaxis - 1] * shape[iaxis]]
834-
+ shape[iaxis + 1 :]
835-
)
836-
837-
return a
838-
839-
840-
def cf_healpix_increase_refinement_indices(a, refinement_level, ncells):
841-
"""Increase the refinement level of HEALPix indices.
842-
843-
For instance, when going from refinement level 1 to refinement
844-
level 2, if *a* is ``(2, 23, 17)`` then it will be transformed to
845-
``(8, 9, 10, 11, 92, 93, 94, 95, 68, 69, 70, 71)`` where
846-
``8=2*ncells, 9=2*ncells+1, ..., 71=17*ncells+3``, and where
847-
``ncells`` is the number of cells at refinement level 2 that lie
848-
inside one cell at refinement level 1, i.e. ``ncells=4**(2-1)=4``.
849-
850-
.. warning:: The returned `numpy` array will take up *ncells*
851-
times more memory than the input array *a* (or two
852-
times *ncells* more memory, if *a* is 32-bit and the
853-
output requires 64-bit integers). For instance, if
854-
32-bit *a* has shape ``(48,)`` (192 B), and *ncells*
855-
is ``67108864``, then the returned 64-bit array will
856-
have shape ``(3221225472,)`` (24 GiB), where
857-
3221225472=48*67108864.
858-
859-
K. Gorski, Eric Hivon, A. Banday, B. Wandelt, M. Bartelmann, et
860-
al.. HEALPix: A Framework for High-Resolution Discretization and
861-
Fast Analysis of Data Distributed on the Sphere. The Astrophysical
862-
Journal, 2005, 622 (2), pp.759-771.
863-
https://dx.doi.org/10.1086/427976
864-
865-
.. versionadded:: NEXTVERSION
866-
867-
.. seealso:: `cf.Field.healpix_increase_refinement_level`
868-
869-
:Parameters:
870-
871-
a: `numpy.ndarray`
872-
The array of HEALPix nested indices.
873-
874-
refinement_level: `int`
875-
The new higher HEALPix refinement level.
876-
877-
ncells: `int`
878-
The number of cells at the new refinement level which are
879-
contained in one cell at the original refinement level
880-
881-
:Returns:
882-
883-
`numpy.ndarray`
884-
The array at the new refinement level.
885-
886-
"""
887-
a = cfdm_to_memory(a)
888-
889-
# Set the data type to allow for the largest possible HEALPix
890-
# index at the new refinement level
891-
dtype = integer_dtype(12 * (4**refinement_level) - 1)
892-
if a.dtype != dtype:
893-
a = a.astype(dtype, copy=True)
894-
a *= ncells
895-
else:
896-
a = a * ncells
897-
898-
# Create a new dimension over which the original HEALPix axis will
899-
# be broadcast
900-
a = np.expand_dims(a, -1)
901-
902-
# Define the shape of the new array, and broadcast 'a' to it.
903-
shape = (a.size, ncells)
904-
a = np.broadcast_to(a, shape, subok=True).copy()
905-
906-
# Increment the broadcast values along the new dimension, so that
907-
# a[i, :] contains all of the nested indices at the higher
908-
# refinement level that correspond to index i at the original
909-
# refinement level.
910-
a += np.arange(ncells)
911-
912-
# Reshape the new array to combine the original HEALPix and
913-
# broadcast dimensions into a single new HEALPix dimension
914-
a = a.flatten()
915-
916-
return a
917-
918-
919763
def cf_healpix_indexing_scheme(
920764
a, indexing_scheme, new_indexing_scheme, refinement_level=None
921765
):
@@ -972,7 +816,7 @@ def cf_healpix_indexing_scheme(
972816
)
973817
array([16, 17, 18, 19])
974818
>>> cf.data.dask_utils.cf_healpix_indexing_scheme(
975-
... [16, 17, 18, 19], 'nested_unique', 'nest', None
819+
... [16, 17, 18, 19], 'nested_unique', 'nested', None
976820
)
977821
array([0, 1, 2, 3])
978822
@@ -1030,12 +874,15 @@ def cf_healpix_indexing_scheme(
1030874

1031875
case _:
1032876
raise ValueError(
1033-
"Can't calculate HEALPix cell coordinates: Unknown "
1034-
f"'indexing_scheme': {indexing_scheme!r}"
877+
"Can't change HEALPix indexing scheme: Unknown "
878+
f"'indexing_scheme' in cf_healpix_indexing_scheme: "
879+
f"{indexing_scheme!r}"
1035880
)
1036881

1037-
raise RuntimeError(
1038-
"cf_healpix_indexing_scheme: Failed during Dask computation"
882+
raise ValueError(
883+
"Can't change HEALPix indexing scheme: Unknown "
884+
f"'new_indexing_scheme in cf_healpix_indexing_scheme: "
885+
f"{new_indexing_scheme!r}"
1039886
)
1040887

1041888

@@ -1117,7 +964,7 @@ def cf_healpix_weights(a, indexing_scheme, measure=False, radius=None):
1117964
if measure:
1118965
# Cell weights equal cell areas. Surface area of a sphere is
1119966
# 4*pi*(r**2), number of HEALPix cells at refinement level N
1120-
# is 12*(4**N) => Area of each cell is (pi*(r**2)/3.0)/(4**N)
967+
# is 12*(4**N) => Area of each cell is (pi*(r**2)/3)/(4**N)
1121968
x = np.pi * (radius**2) / 3.0
1122969
else:
1123970
# Normalised weights

cf/field.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5279,7 +5279,8 @@ def healpix_increase_refinement_level(self, refinement_level, quantity):
52795279
"sea_ice_amount" with units of kg m-2, or "air_temperature"
52805280
with units of K). For an extensive quantity only, the
52815281
broadcast values are reduced to be consistent with the new
5282-
smaller cell areas.
5282+
smaller cell areas x(by dividing them by the number of new
5283+
cells per original cell).
52835284

52845285
**References**
52855286

@@ -5410,14 +5411,6 @@ def healpix_increase_refinement_level(self, refinement_level, quantity):
54105411

54115412
# Get the HEALPix axis
54125413
axis = hp["domain_axis_key"]
5413-
try:
5414-
iaxis = f.get_data_axes().index(axis)
5415-
except ValueError:
5416-
# Field data doesn't span the HEALPix axis, so insert it
5417-
# (note that it must be size 1, given that the Field data
5418-
# doen't span it).
5419-
f.insert_dimension(axis, -1, inplace=True)
5420-
iaxis = f.get_data_axes().index(axis)
54215414

54225415
# Whether or not to create lat/lon coordinates for the new
54235416
# refinement level. Only do so if the original grid has
@@ -5432,17 +5425,26 @@ def healpix_increase_refinement_level(self, refinement_level, quantity):
54325425
)
54335426
)
54345427

5428+
# Find the position of the HEALPix axis in the Field data
5429+
try:
5430+
iaxis = f.get_data_axes().index(axis)
5431+
except ValueError:
5432+
# The Field data doesn't span the HEALPix axis, so insert
5433+
# it.
5434+
f.insert_dimension(axis, -1, inplace=True)
5435+
iaxis = f.get_data_axes().index(axis)
5436+
54355437
# Re-size the HEALPix axis
54365438
domain_axis = f.domain_axis(axis)
54375439
domain_axis.set_size(f.shape[iaxis] * ncells)
54385440

5439-
# Increase the refinement of the Field data
5441+
# Increase the refinement level of the Field data
54405442
_healpix_increase_refinement_level(f, ncells, iaxis, quantity)
54415443

54425444
# Increase the refinement level of domain ancillary constructs
54435445
# that span the HEALPix axis. We're assuming that domain
5444-
# ancillary data are intensive (i.e. do not depend on the size
5445-
# of the cell).
5446+
# ancillary data are intensive (i.e. they do not depend on the
5447+
# size of the cell).
54465448
for key, domain_ancillary in f.domain_ancillaries(
54475449
filter_by_axis=(axis,), axis_mode="and", todict=True
54485450
).items():
@@ -5453,7 +5455,7 @@ def healpix_increase_refinement_level(self, refinement_level, quantity):
54535455

54545456
# Increase the refinement level of cell measure constructs
54555457
# that span the HEALPix axis. Cell measure data are extensive
5456-
# (i.e. depend on the size of the cell).
5458+
# (i.e. they depend on the size of the cell).
54575459
for key, cell_measure in f.cell_measures(
54585460
filter_by_axis=(axis,), axis_mode="and", todict=True
54595461
).items():
@@ -5465,12 +5467,11 @@ def healpix_increase_refinement_level(self, refinement_level, quantity):
54655467
# Remove all other metadata constructs that span the HEALPix
54665468
# axis (including the original healpix_index coordinate
54675469
# construct, and any lat/lon coordinate constructs that span
5468-
# the HEALPix axis)
5470+
# the HEALPix axis).
54695471
for key in (
54705472
f.constructs.filter_by_axis(axis, axis_mode="and")
54715473
.filter_by_type("cell_measure", "domain_ancillary")
54725474
.inverse_filter(1)
5473-
.todict()
54745475
):
54755476
f.del_construct(key)
54765477

0 commit comments

Comments
 (0)