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 >