lib/numru/gphys/gphys_dim_op.rb in gphys-1.5.2 vs lib/numru/gphys/gphys_dim_op.rb in gphys-1.5.3
- old
+ new
@@ -18,19 +18,20 @@
# ARGUMENTS
# * dim (Integer or String) : the dimension
# * len_or_wgt : If Integer, specifies the length; if 1D NArray,
# specifies the weight (e.g., NArray[1.0, 2.0, 1.0] for
# the 1-2-1 smooting)
- # * bc (Integer; optional) : Speficy one of the folloing:
- # * GPhys::BC_SIMPLE (default) : Averaging is trucated at the boundaries
+ # * bc (Integer; optional) : Specify one of the following:
+ # * nil (default) : choose BC_SIMPLE or BC_CYCLIC automatically
+ # * GPhys::BC_SIMPLE : Averaging is truncated at the boundaries
# (the number of grid points used is reduced near the boundaries).
# The shape of the object is conserved.
# * GPhys::BC_CYCLIC : Cyclic boundary condition. Shape conserved.
# * GPhys::BC_TRIM : Grids near the boundaries are trimmed to
# secure the number of grid points to average.
# Shape not conserved; length along the dim is reduced by (len-1).
- # * nminvalid (Integer; optional; defualt=1):
+ # * nminvalid (Integer; optional; default=1):
# This parameter is used only when the data have missing.
# Minimum number of grid points needed for averaging.
# Must be from 1 to len.
#
# RETURN VALUE
@@ -38,19 +39,27 @@
#
# REMARK AND LIMITATION
# * If the length of the running mean is even number, fewer
# grid points are used from the "left" side; e.g.,
# If len is 6, result[2] is a mean over self[0]..self[5].
- # * Regardless the na_type of self, double is used for avaraging, so:
+ # * Regardless the na_type of self, double is used for averaging, so:
# * This method does not support complex numbers.
#
- def running_mean(dim, len_or_wgt=nil, bc=BC_SIMPLE, nminvalid=1)
+ def running_mean(dim, len_or_wgt=nil, bc=nil, nminvalid=1)
#< process arguments >
dim = dim_index(dim) # to handle String or negative specification
+ if bc.nil?
+ if axis(dim).cyclic_extendible?
+ bc=BC_CYCLIC
+ else
+ bc=BC_SIMPLE
+ end
+ end
+
case len_or_wgt
when nil
raise ArgumentError, "You need to specify the length (Integer) or the weight (1D NArray) as the 2nd argument"
when Integer
# len_or_wgt is a length
@@ -93,10 +102,82 @@
vvo = VArray.new( vo, self.data, self.name ) # Inherit name & attrs
GPhys.new( grid, vvo )
end
+ # Running mean along two dimensions (with optional weight specification).
+ #
+ # This method would be needed for data with missing. If the data
+ # has no missing, you should apply running_mean consecutively
+ # along the two dimensions you want, which will be faster and efficient.
+ #
+ # However, if the data have missing, the results are not the same.
+ # That's why this method is needed.
+ #
+ # ARGUMENTS
+ # * dim1 (Integer or String) : a dimension to apply the running mean
+ # * dim2 (Integer or String) : another dimension to apply the running mean
+ # (dim1 must be smaller than dim2)
+ # * len_or_wgt1 : If Integer, specifies the length of running mean for dim1.
+ # If 1D NArray, it specifies the weight (e.g., NArray[1.0, 2.0, 1.0] for
+ # the 1-2-1 smoothing)
+ # * len_or_wgt2 : as len_or_wgt1 but for dim2.
+ # * bc1 (Integer or nil; optional) : Specify one of the following for dim1:
+ # * nil : choose BC_SIMPLE or BC_CYCLIC automatically
+ # * GPhys::BC_SIMPLE : Averaging is truncated at the boundaries
+ # (the number of grid points used is reduced near the boundaries).
+ # The shape of the object is conserved.
+ # * GPhys::BC_CYCLIC : Cyclic boundary condition. Shape conserved.
+ # * bc2 : as bc1 but for dim2.
+ # * nminvalid (Integer; optional; default=1):
+ # Minimum number of grid points needed to define the running mean
+ # (it is the number of valid data in the 2-dimensional tile).
+ #
+ def running_mean_2D(dim1, dim2, len_or_wgt1, len_or_wgt2,
+ bc1=nil, bc2=nil,
+ nminvalid=1)
+
+ dim1 = dim_index(dim1) # to handle String or negative specification
+ dim2 = dim_index(dim2) # to handle String or negative specification
+
+ if bc1.nil?
+ if axis(dim1).cyclic_extendible?
+ bc1=BC_CYCLIC
+ else
+ bc1=BC_SIMPLE
+ end
+ end
+ if bc2.nil?
+ if axis(dim2).cyclic_extendible?
+ bc2=BC_CYCLIC
+ else
+ bc2=BC_SIMPLE
+ end
+ end
+
+ vi = self.val
+ if vi.is_a?(NArray)
+ # Just for convenience.
+ self.running_mean(dim1, len_or_wgt1, bc1, nminvalid).running_mean(dim2, len_or_wgt2, bc2, nminvalid)
+ end
+
+ if (vi.typecode > NArray::DFLOAT)
+ raise("This method supports only real or integer data")
+ end
+ if vi.is_a?(NArrayMiss)
+ vi, missval = nam2na_missval(vi)
+ vo = c_running_mean_2D(vi, dim1,len_or_wgt1,bc1, dim2,len_or_wgt2,bc2,
+ missval, nminvalid)
+ vo = NArrayMiss.to_nam(vo, vo.ne(missval) )
+ else
+ raise("This method accepts only data with missing. If not, you should apply running_mean twice for dim1 & dim2, respectively")
+ end
+
+ vvo = VArray.new( vo, self.data, self.name ) # Inherit name & attrs
+ GPhys.new( self.grid, vvo )
+ end
+
# Binning along a dimension (mean)
#
# The values are averaged every "len" grids; unlike running_mean
# the number of grids is reduced to 1/len.
# Currently, the only available boundary condition is BC_TRIM.
@@ -197,10 +278,10 @@
if assoc_coords
dimname = self.axis(dim).name
acs = Array.new
assoccoordnames.each do |nm|
ac = assoc_coord_gphys(nm)
- acs.push(ac) if !ac.dimnames.include?(dimname)
+ acs.push(ac) if !ac.axnames.include?(dimname)
end
newgrid.set_assoc_coords(acs) if acs.length > 0
end
#< return >