@@ -11953,6 +11953,136 @@ def halo(
1195311953
1195411954 return f
1195511955
11956+ @_inplace_enabled(default=False)
11957+ def pad_missing(self, axis, pad_width=None, to_size=None, inplace=False):
11958+ """Pad an axis with missing data.
11959+
11960+ The field's data and all metadata constructs that span the
11961+ axis are padded.
11962+
11963+ .. versionadded:: 3.17.0
11964+
11965+ :Parameters:
11966+
11967+ axis: `str` or `int`
11968+ Select the domain axis which is to be padded, defined
11969+ by that which would be selected by passing the given
11970+ axis description to a call of the field construct's
11971+ `domain_axis` method. For example, for a value of
11972+ ``'X'``, the domain axis construct returned by
11973+ ``f.domain_axis('X')`` is selected.
11974+
11975+ {{pad_width: sequence of `int`, optional}}
11976+
11977+ {{to_size: `int`, optional}}
11978+
11979+ {{inplace: `bool`, optional}}
11980+
11981+ :Returns:
11982+
11983+ `Field` or `None`
11984+ The padded field construct, or `None` if the operation
11985+ was in-place.
11986+
11987+ **Examples*
11988+
11989+ >>> f = cf.example_field(6)
11990+ >>> print(f)
11991+ Field: precipitation_amount (ncvar%pr)
11992+ --------------------------------------
11993+ Data : precipitation_amount(cf_role=timeseries_id(2), time(4))
11994+ Dimension coords: time(4) = [2000-01-16 12:00:00, ..., 2000-04-15 00:00:00] gregorian
11995+ Auxiliary coords: latitude(cf_role=timeseries_id(2)) = [25.0, 7.0] degrees_north
11996+ : longitude(cf_role=timeseries_id(2)) = [10.0, 40.0] degrees_east
11997+ : cf_role=timeseries_id(cf_role=timeseries_id(2)) = [x1, y2]
11998+ : altitude(cf_role=timeseries_id(2), 3, 4) = [[[1.0, ..., --]]] m
11999+ Coord references: grid_mapping_name:latitude_longitude
12000+ >>> print(f.array)
12001+ [[1. 2. 3. 4.]
12002+ [5. 6. 7. 8.]]
12003+ >>> g = f.pad_missing('T', (0, 5))
12004+ >>> print(g)
12005+ Field: precipitation_amount (ncvar%pr)
12006+ --------------------------------------
12007+ Data : precipitation_amount(cf_role=timeseries_id(2), time(9))
12008+ Dimension coords: time(9) = [2000-01-16 12:00:00, ..., --] gregorian
12009+ Auxiliary coords: latitude(cf_role=timeseries_id(2)) = [25.0, 7.0] degrees_north
12010+ : longitude(cf_role=timeseries_id(2)) = [10.0, 40.0] degrees_east
12011+ : cf_role=timeseries_id(cf_role=timeseries_id(2)) = [x1, y2]
12012+ : altitude(cf_role=timeseries_id(2), 3, 4) = [[[1.0, ..., --]]] m
12013+ Coord references: grid_mapping_name:latitude_longitude
12014+ >>> print(g.array)
12015+ [[1.0 2.0 3.0 4.0 -- -- -- -- --]
12016+ [5.0 6.0 7.0 8.0 -- -- -- -- --]]
12017+ >>> h = g.pad_missing('cf_role=timeseries_id', (0, 1))
12018+ >>> print(h)
12019+ Field: precipitation_amount (ncvar%pr)
12020+ --------------------------------------
12021+ Data : precipitation_amount(cf_role=timeseries_id(3), time(9))
12022+ Dimension coords: time(9) = [2000-01-16 12:00:00, ..., --] gregorian
12023+ Auxiliary coords: latitude(cf_role=timeseries_id(3)) = [25.0, 7.0, --] degrees_north
12024+ : longitude(cf_role=timeseries_id(3)) = [10.0, 40.0, --] degrees_east
12025+ : cf_role=timeseries_id(cf_role=timeseries_id(3)) = [x1, y2, --]
12026+ : altitude(cf_role=timeseries_id(3), 3, 4) = [[[1.0, ..., --]]] m
12027+ Coord references: grid_mapping_name:latitude_longitude
12028+ >>> print(h.array)
12029+ [[1.0 2.0 3.0 4.0 -- -- -- -- --]
12030+ [5.0 6.0 7.0 8.0 -- -- -- -- --]
12031+ [ -- -- -- -- -- -- -- -- --]]
12032+
12033+ >>> print(f.pad_missing('time', to_size=6))
12034+ Field: precipitation_amount (ncvar%pr)
12035+ --------------------------------------
12036+ Data : precipitation_amount(cf_role=timeseries_id(2), time(6))
12037+ Dimension coords: time(6) = [2000-01-16 12:00:00, ..., --] gregorian
12038+ Auxiliary coords: latitude(cf_role=timeseries_id(2)) = [25.0, 7.0] degrees_north
12039+ : longitude(cf_role=timeseries_id(2)) = [10.0, 40.0] degrees_east
12040+ : cf_role=timeseries_id(cf_role=timeseries_id(2)) = [x1, y2]
12041+ : altitude(cf_role=timeseries_id(2), 3, 4) = [[[1.0, ..., --]]] m
12042+ Coord references: grid_mapping_name:latitude_longitude
12043+
12044+ """
12045+ f = _inplace_enabled_define_and_cleanup(self)
12046+
12047+ try:
12048+ axis1 = f._parse_axes(axis)
12049+ except ValueError:
12050+ raise ValueError(
12051+ f"Can't pad_missing: Bad axis specification: {axis!r}"
12052+ )
12053+
12054+ if len(axis1) != 1:
12055+ raise ValueError(
12056+ f"Can't pad_missing: Bad axis specification: {axis!r}"
12057+ )
12058+
12059+ data_axes = f.get_data_axes()
12060+ axis = axis1[0]
12061+ iaxis = data_axes.index(axis)
12062+
12063+ # Pad the field
12064+ super(Field, f).pad_missing(
12065+ iaxis, pad_width=pad_width, to_size=to_size, inplace=True
12066+ )
12067+
12068+ # Set new domain axis size
12069+ domain_axis = f.domain_axis(axis)
12070+ domain_axis.set_size(f.shape[iaxis])
12071+
12072+ data_axes = f.constructs.data_axes()
12073+ for key, construct in f.constructs.filter_by_data(todict=True).items():
12074+ construct_axes = data_axes[key]
12075+ if axis not in construct_axes:
12076+ continue
12077+
12078+ # Pad the construct
12079+ iaxis = construct_axes.index(axis)
12080+ construct.pad_missing(
12081+ iaxis, pad_width=pad_width, to_size=to_size, inplace=True
12082+ )
12083+
12084+ return f
12085+
1195612086 def percentile(
1195712087 self,
1195812088 ranks,
0 commit comments