gphys 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/numru/ggraph.rb CHANGED
@@ -788,9 +788,9 @@ library if you like.
788
788
  "interval" nil # contour interval
789
789
  "nozero" nil # delete zero contour
790
790
  "coloring" false # set color contours with ud_coloring
791
- "clr_min" 13 # (if coloring) minimum color number for the
791
+ "clr_min" nil # (if coloring) minimum color number for the
792
792
  # minimum data values
793
- "clr_max" 99 # (if coloring) maximum color number for the
793
+ "clr_max" nil # (if coloring) maximum color number for the
794
794
  # maximum data values
795
795
  "help" false # show help message if true
796
796
  "log" nil # approximately log-scaled levels (by using
@@ -919,6 +919,10 @@ library if you like.
919
919
  "color_bar" false # Add a color bar: THIS IS ONLY FOR QUICK
920
920
  # LOOK. Use the GGraph::color_bar method explicitly
921
921
  # for full option control
922
+ "cbunits" nil # [nil or true or String] if non nil, shows units
923
+ # in color_bar using the specified string or, when
924
+ # true, the units of the argument
925
+ # using the specified string or, if true, the units of the argument
922
926
  "min" nil # minimum tone level
923
927
  "max" nil # maximum tone level
924
928
  "nlev" nil # number of levels
@@ -1588,6 +1592,7 @@ module NumRu
1588
1592
  ['title', nil, 'Title of the figure'],
1589
1593
  ['xunits', nil, 'Units of x axis (if nil, internally determined)'],
1590
1594
  ['yunits', nil, 'Units of y axis (if nil, internally determined)'],
1595
+ ['format_units', true, 'Format unit expressions for DCL, e.g. m.s-1 -> m s\^{-1}'],
1591
1596
  ['xtickint', nil,
1592
1597
  'Interval of x axis tickmark (if nil, internally determined)'],
1593
1598
  ['ytickint', nil,
@@ -1641,16 +1646,27 @@ module NumRu
1641
1646
  ts = [t0,t1].min
1642
1647
  time = UNumeric.new(ts,sunits)
1643
1648
  tstr = time.to_datetime(0.1,calendar)
1644
- jd0 = tstr.strftime('%Y%m%d').to_i
1649
+ #jd0 = tstr.strftime('%Y%m%d').to_i
1645
1650
  tlen = tun.convert( t1-t0, dayun ).abs
1646
1651
  axtype ||= (tlen < 5) ? 'h' : 'ymd'
1647
1652
  reverse = t1 < t0
1653
+ if axtype == 'h'
1654
+ dh = 0.0
1655
+ else
1656
+ tstr0 = tstr.to_date
1657
+ dh = tstr - tstr0
1658
+ if dh>1e-2 # << 1 な適当な小さな数
1659
+ dh -= 1.0
1660
+ tstr0 += 1.0
1661
+ end
1662
+ tend0 = (tstr+tlen).to_date
1663
+ end
1648
1664
 
1649
1665
  if xax
1650
1666
  unless(reverse)
1651
- DCL.grswnd(0.0, tlen, window[2], window[3] )
1667
+ DCL.grswnd(dh, tlen+dh, window[2], window[3] )
1652
1668
  else
1653
- DCL.grswnd(tlen, 0.0, window[2], window[3] )
1669
+ DCL.grswnd(tlen+dh, dh, window[2], window[3] )
1654
1670
  end
1655
1671
  DCL.grstrf
1656
1672
  opts = {'cside'=>side}
@@ -1659,14 +1675,14 @@ module NumRu
1659
1675
  if axtype == 'h'
1660
1676
  DCLExt.datetime_ax(tstr, tstr+tlen, opts )
1661
1677
  else
1662
- DCLExt.date_ax(tstr, tstr+tlen, opts )
1678
+ DCLExt.date_ax(tstr0, tend0, opts )
1663
1679
  ## DCL.ucxacl(side,jd0,tlen) #Old: use it again if UCPACK is improved
1664
1680
  end
1665
1681
  else
1666
1682
  unless(reverse)
1667
- DCL.grswnd(window[0], window[1], 0.0, tlen)
1683
+ DCL.grswnd(window[0], window[1], dh, tlen+dh)
1668
1684
  else
1669
- DCL.grswnd(window[0], window[1], tlen, 0.0)
1685
+ DCL.grswnd(window[0], window[1], tlen+dh, dh)
1670
1686
  end
1671
1687
  DCL.grstrf
1672
1688
  opts = {'yax'=>true, 'cside'=>side}
@@ -1675,7 +1691,7 @@ module NumRu
1675
1691
  if axtype == 'h'
1676
1692
  DCLExt.datetime_ax(tstr, tstr+tlen, opts )
1677
1693
  else
1678
- DCLExt.date_ax(tstr, tstr+tlen, opts )
1694
+ DCLExt.date_ax(tstr0, tend0, opts )
1679
1695
  ## DCL.ucyacl(side,jd0,tlen) #Old: use it again if UCPACK is improved
1680
1696
  end
1681
1697
  end
@@ -1721,6 +1737,7 @@ module NumRu
1721
1737
  opts['xtickint'], opts['xlabelint'])
1722
1738
  end
1723
1739
  else
1740
+ sunits = DCLExt.format_units(sunits) if opts['format_units']
1724
1741
  DCL.uscset('cxttl', (opts['xtitle'] || xai['title']) )
1725
1742
  DCL.uscset('cxunit', sunits)
1726
1743
  DCL.uspset('dxt', opts['xtickint']) if(opts['xtickint'])
@@ -1760,6 +1777,7 @@ module NumRu
1760
1777
  opts['ytickint'], opts['ylabelint'])
1761
1778
  end
1762
1779
  else
1780
+ sunits = DCLExt.format_units(sunits) if opts['format_units']
1763
1781
  DCL.uscset('cyttl', (opts['ytitle'] || yai['title']) )
1764
1782
  DCL.uscset('cyunit', sunits )
1765
1783
  DCL.uspset('dyt', opts['ytickint']) if(opts['ytickint'])
@@ -2112,6 +2130,7 @@ module NumRu
2112
2130
  ['step_plot', false, 'If true, draw stair step plot (piecewise constant line plot).'],
2113
2131
  # ['step_extend_ends', false, 'If true, extend both ends of stair step plot.'], # NOT YET IMPLEMENTED
2114
2132
  ['step_position', 0, 'Data point will be at the right corner of each step if negative, center if 0, and left corner if positive.'],
2133
+ ['proc_before_ax', nil, 'Proc (with no argument) to be called just before drawing the axes.'],
2115
2134
  @@data_prep_options
2116
2135
  )
2117
2136
 
@@ -2154,6 +2173,9 @@ module NumRu
2154
2173
  x, y, closer, gp, window = data_prep_1D(gphys, opts)
2155
2174
  if newframe
2156
2175
  fig(x, y, {'window'=>window})
2176
+ if opts['proc_before_ax']
2177
+ opts['proc_before_ax'].call
2178
+ end
2157
2179
  axes_or_map_and_ttl(gp, opts, x, y)
2158
2180
  end
2159
2181
 
@@ -2245,6 +2267,7 @@ module NumRu
2245
2267
  ['legend_vy', nil, '(effective if legend) viewport y value of the legend (Float; or nil for automatic settting)'],
2246
2268
  ['legend_size', nil, '(effective if legend) character size of the legend'],
2247
2269
  ['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
2270
+ ['proc_before_ax', nil, 'Proc (with no argument) to be called just before drawing the axes.'],
2248
2271
  @@data_prep_options
2249
2272
  )
2250
2273
 
@@ -2275,6 +2298,9 @@ module NumRu
2275
2298
  x, y, closer, gp, window = data_prep_1D(gphys, opts, len1ok: true)
2276
2299
  if newframe
2277
2300
  fig(x, y, {'window'=>window})
2301
+ if opts['proc_before_ax']
2302
+ opts['proc_before_ax'].call
2303
+ end
2278
2304
  axes_or_map_and_ttl(gp, opts, x, y)
2279
2305
  end
2280
2306
  DCL.uumrkz(x.val, y.val, opts['type'], opts['index'], opts['size'])
@@ -2298,8 +2324,8 @@ module NumRu
2298
2324
  ['interval', nil, 'contour interval'],
2299
2325
  ['nozero', nil, 'delete zero contour'],
2300
2326
  ['coloring', false, 'set color contours with ud_coloring'],
2301
- ['clr_min', 13, '(if coloring) minimum color number for the minimum data values'],
2302
- ['clr_max', 99, '(if coloring) maximum color number for the maximum data values']
2327
+ ['clr_min', nil, '(if coloring) minimum color number for the minimum data values (nil -> uepack parameter icolor1)'],
2328
+ ['clr_max', nil, '(if coloring) maximum color number for the maximum data values (nil -> uepack parameter icolor2)']
2303
2329
  )
2304
2330
  def set_linear_contour_options(options)
2305
2331
  @@linear_contour_options.set(options)
@@ -2497,9 +2523,21 @@ module NumRu
2497
2523
 
2498
2524
  def tone_and_contour(gphys, newframe=true, options=nil)
2499
2525
  options ? copt=@@contour_options.select_existent(options) : copt=nil
2500
- options ? topt=@@tone_options.select_existent(options) : topt=nil
2526
+ options ? topt=@@tone_options.select_existent(options) : topt=Hash.new
2527
+ topt = @@tone_options.interpret(topt)
2528
+ cbar = topt["color_bar"]
2529
+ topt["color_bar"]=false if cbar # color bar will be plotted after contour
2501
2530
  tone(gphys, newframe, topt)
2502
2531
  contour(gphys, false, copt)
2532
+ if cbar
2533
+ cbunits = topt['cbunits']
2534
+ cbunits = gphys.units.to_s if cbunits==true
2535
+ if @@used_fullcolor_tone
2536
+ color_bar "units"=>cbunits
2537
+ else
2538
+ color_bar "log"=>topt['log'], "units"=>cbunits
2539
+ end
2540
+ end
2503
2541
  end
2504
2542
 
2505
2543
  @@contour_levels = Misc::KeywordOptAutoHelp.new(
@@ -2549,6 +2587,7 @@ module NumRu
2549
2587
  ['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
2550
2588
  ['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
2551
2589
  ['keep', false, 'Use the contour levels used previously'],
2590
+ ['proc_before_ax', nil, 'Proc (with no argument) to be called just before drawing the axes.'],
2552
2591
  @@linear_contour_options,
2553
2592
  @@contour_levels,
2554
2593
  @@data_prep_options
@@ -2645,8 +2684,9 @@ module NumRu
2645
2684
  xax, yax, closer, gp = data_prep_2D([gphys], newframe, opts)
2646
2685
  if newframe
2647
2686
  fig(xax, yax)
2648
- end
2649
- if newframe
2687
+ if opts['proc_before_ax']
2688
+ opts['proc_before_ax'].call
2689
+ end
2650
2690
  axes_or_map_and_ttl(gp,opts, xax, yax)
2651
2691
  end
2652
2692
  if !opts['keep'] or DCL.udqcln==0
@@ -2776,6 +2816,9 @@ module NumRu
2776
2816
  ['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
2777
2817
  ['keep', false, 'Use the tone levels and patterns used previously'],
2778
2818
  ['color_bar', false, 'Add a color bar: THIS IS ONLY FOR QUICK LOOK. Use the GGraph::color_bar method explicitly for full option control'],
2819
+ ['cbunits', nil, '[nil or true or String] if non nil, shows units in color_bar using the specified string or, when true, the units of the argument'],
2820
+ ['proc_before_ax', nil, 'Proc (with no argument) to be called just before drawing the axes.'],
2821
+ ['proc_before_tone', nil, 'Proc (with no argument) to be called just before plotting tone.'],
2779
2822
  @@linear_tone_options,
2780
2823
  @@tone_levels,
2781
2824
  @@fullcolor_tone_options,
@@ -2812,6 +2855,10 @@ module NumRu
2812
2855
  if newframe
2813
2856
  fig(xax, yax)
2814
2857
  end
2858
+ if opts['proc_before_tone']
2859
+ opts['proc_before_tone'].call
2860
+ end
2861
+
2815
2862
  DCL.uwsgxa(xax.val) if xax.rank==1
2816
2863
  DCL.uwsgya(yax.val) if yax.rank==1
2817
2864
  if !opts['keep'] or DCL.ueqntl==0
@@ -2857,16 +2904,21 @@ module NumRu
2857
2904
  end
2858
2905
 
2859
2906
  if newframe
2907
+ if opts['proc_before_ax']
2908
+ opts['proc_before_ax'].call
2909
+ end
2860
2910
  axes_or_map_and_ttl(gp,opts, xax, yax)
2861
2911
  end
2862
2912
  DCL.uepset('icolor1', icolor1_bak) if opts['clr_min']
2863
2913
  DCL.uepset('icolor2', icolor2_bak) if opts['clr_max']
2864
2914
 
2865
2915
  if opts['color_bar']
2916
+ cbunits = opts['cbunits']
2917
+ cbunits = gphys.units.to_s if cbunits==true
2866
2918
  if @@used_fullcolor_tone
2867
- color_bar
2919
+ color_bar "units"=>cbunits
2868
2920
  else
2869
- color_bar "log"=>opts['log']
2921
+ color_bar "log"=>opts['log'], "units"=>cbunits
2870
2922
  end
2871
2923
  end
2872
2924
  closer.call if closer
@@ -2883,6 +2935,7 @@ module NumRu
2883
2935
  ['size', 0.01, 'marks size'],
2884
2936
  ['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
2885
2937
  ['correlation', false, 'calculate Pearson\'s correlation coefficient and show it on the bottom margin'],
2938
+ ['proc_before_ax', nil, 'Proc (with no argument) to be called just before drawing the axes.'],
2886
2939
  @@data_prep_options
2887
2940
  )
2888
2941
  ## @@scatter_options.delete("transpose") # delete is yet to be supported
@@ -2932,6 +2985,9 @@ module NumRu
2932
2985
  y = gpy.data
2933
2986
  if newframe
2934
2987
  fig(x, y)
2988
+ if opts['proc_before_ax']
2989
+ opts['proc_before_ax'].call
2990
+ end
2935
2991
  axes_or_map_and_ttl(gpx, opts, x, y, gpy)
2936
2992
  end
2937
2993
  DCL.uumrkz(x.val, y.val, opts['type'], opts['index'], opts['size'])
@@ -3152,6 +3208,7 @@ module NumRu
3152
3208
  ['keep', false, 'Use the same vector scaling as in the previous call. -- Currently, works only when "flow_vect" is true'],
3153
3209
  ['factor', 1.0, '(Effective only if flow_vect) scaling factor to strech/reduce the arrow lengths'],
3154
3210
  ['unit_vect', false, 'Show the unit vector'],
3211
+ ['uvunits', false, 'units in the unit vector (false: never, true: read from the GPhys; a String: use that'],
3155
3212
  ['max_unit_vect', false, '(Effective only if flow_vect && unit_vect) If true, use the maximum arrows to scale the unit vector; otherwise, normalize in V coordinate.'],
3156
3213
  ['ux_unit', nil, '(If Numeric) length of the x direction unit vector (precedence of this option is lower than max_unit_vect)'],
3157
3214
  ['uy_unit', nil, '(If Numeric) length of the y direction unit vector (precedence of this option is lower than max_unit_vect)'],
@@ -3200,6 +3257,20 @@ module NumRu
3200
3257
 
3201
3258
  oldindex = DCLExt.ug_set_params("index" => opts['index']) if opts['index']
3202
3259
 
3260
+ if opts['unit_vect']
3261
+ if (uvu=opts['uvunits'])
3262
+ case uvu
3263
+ when String
3264
+ un = uvu
3265
+ else
3266
+ raise("fx-fy units miss match") if fx.units != fy.units
3267
+ un = fx.units.to_s
3268
+ end
3269
+ uvopts = {'units'=>un}
3270
+ else
3271
+ uvopts = Hash.new
3272
+ end
3273
+ end
3203
3274
  if opts['flow_itr5']
3204
3275
  if itr_is?(5)
3205
3276
  DCLExt.flow_itr5( fx, fy, opts['factor'], opts['unit_vect'] )
@@ -3218,7 +3289,7 @@ module NumRu
3218
3289
  returnval = { "vfratio"=> @@vfratio, "flenmax"=>@@flenmax }
3219
3290
  if opts['unit_vect']
3220
3291
  len_unit = opts['len_unit'] || @@flenmax
3221
- DCLExt.unit_vect_single(@@vfratio, len_unit)
3292
+ DCLExt.unit_vect_single(@@vfratio, len_unit, uvopts)
3222
3293
  end
3223
3294
  elsif opts['flow_vect']
3224
3295
  uninfo = DCLExt.flow_vect(fx.val, fy.val, opts['factor'], 1, 1,
@@ -3230,7 +3301,7 @@ module NumRu
3230
3301
  uninfo[2] = opts['ux_unit'] # nil or a Numeric to specify the len
3231
3302
  uninfo[3] = opts['uy_unit'] # nil or a Numeric to specify the len
3232
3303
  end
3233
- DCLExt.unit_vect(*uninfo)
3304
+ DCLExt.unit_vect( *(uninfo+[uvopts]) )
3234
3305
  end
3235
3306
  else
3236
3307
  before=DCLExt.ug_set_params({'lunit'=>true}) if opts['unit_vect']
@@ -630,7 +630,7 @@ module NumRu
630
630
  end
631
631
 
632
632
  case slicer
633
- when Fixnum
633
+ when Integer
634
634
  pos=@pos[slicer]
635
635
  cval = ( pos.val.is_a?(Numeric) ? pos.val : pos.val[0] )
636
636
  units = pos.get_att('units')
@@ -1063,7 +1063,9 @@ module NumRu
1063
1063
  @integ_weight = posv.dup
1064
1064
  @integ_weight[0] = (posv[1]-posv[0]).abs/2
1065
1065
  @integ_weight[-1] = (posv[-1]-posv[-2]).abs/2
1066
- @integ_weight[1..-2] = (posv[2..-1] - posv[0..-3]).abs/2
1066
+ if posv.length > 2
1067
+ @integ_weight[1..-2] = (posv[2..-1] - posv[0..-3]).abs/2
1068
+ end
1067
1069
  else
1068
1070
  # --- assume that the center values represents the averages ---
1069
1071
  bd = @cell_bounds.val
@@ -33,6 +33,7 @@ module NumRu
33
33
  # This parameter is used only when the data have missing.
34
34
  # Minimum number of grid points needed for averaging.
35
35
  # Must be from 1 to len.
36
+ # * dont_expand (t/f; default: false): true -> keep where missing as missing
36
37
  #
37
38
  # RETURN VALUE
38
39
  # * a GPhys
@@ -44,7 +45,8 @@ module NumRu
44
45
  # * Regardless the na_type of self, double is used for averaging, so:
45
46
  # * This method does not support complex numbers.
46
47
  #
47
- def running_mean(dim, len_or_wgt=nil, bc=nil, nminvalid=1)
48
+ def running_mean(dim, len_or_wgt=nil, bc=nil, nminvalid=1,
49
+ dont_expand=false)
48
50
 
49
51
  #< process arguments >
50
52
 
@@ -81,9 +83,19 @@ module NumRu
81
83
  raise("This method supports only real or integer data")
82
84
  end
83
85
  if vi.is_a?(NArrayMiss)
86
+ omask = vi.get_mask if dont_expand
84
87
  vi, missval = nam2na_missval(vi)
85
88
  vo = c_running_mean(vi,dim,wgt,bc,missval,nminvalid)
86
- vo = NArrayMiss.to_nam(vo, vo.ne(missval) )
89
+ mask = vo.ne(missval)
90
+ if dont_expand
91
+ if (bc == BC_TRIM)
92
+ fst = (len-1)/2 # if odd len/2, if even len/2-1
93
+ lst = -(len/2) - 1
94
+ omask = omask[ *([true]*dim + [fst..lst, false]) ]
95
+ end
96
+ mask = mask & omask
97
+ end
98
+ vo = NArrayMiss.to_nam(vo, mask)
87
99
  else
88
100
  vo = c_running_mean(vi,dim,wgt,bc)
89
101
  end
@@ -134,7 +146,7 @@ module NumRu
134
146
  #
135
147
  def running_mean_2D(dim1, dim2, len_or_wgt1, len_or_wgt2,
136
148
  bc1=nil, bc2=nil,
137
- nminvalid=1)
149
+ nminvalid=1, dont_expand=false)
138
150
 
139
151
  dim1 = dim_index(dim1) # to handle String or negative specification
140
152
  dim2 = dim_index(dim2) # to handle String or negative specification
@@ -157,7 +169,7 @@ module NumRu
157
169
  vi = self.val
158
170
  if vi.is_a?(NArray)
159
171
  # Just for convenience.
160
- self.running_mean(dim1, len_or_wgt1, bc1, nminvalid).running_mean(dim2, len_or_wgt2, bc2, nminvalid)
172
+ self.running_mean(dim1, len_or_wgt1, bc1, nminvalid, dont_expand).running_mean(dim2, len_or_wgt2, bc2, nminvalid, dont_expand)
161
173
  end
162
174
 
163
175
  if (vi.typecode > NArray::DFLOAT)
@@ -166,8 +178,12 @@ module NumRu
166
178
  if vi.is_a?(NArrayMiss)
167
179
  vi, missval = nam2na_missval(vi)
168
180
  vo = c_running_mean_2D(vi, dim1,len_or_wgt1,bc1, dim2,len_or_wgt2,bc2,
169
- missval, nminvalid)
170
- vo = NArrayMiss.to_nam(vo, vo.ne(missval) )
181
+ missval, nminvalid)
182
+ mask = vo.ne(missval)
183
+ if dont_expand
184
+ mask = mask & vi.ne(missval)
185
+ end
186
+ vo = NArrayMiss.to_nam(vo, mask)
171
187
  else
172
188
  raise("This method accepts only data with missing. If not, you should apply running_mean twice for dim1 & dim2, respectively")
173
189
  end
@@ -225,6 +241,53 @@ module NumRu
225
241
 
226
242
  #def convolution(dim, g=nil, bc=BC_SIMPLE)
227
243
  #end
244
+
245
+
246
+ # find the positions or the values of y where the values of z crosses zval along dim (using the linear interpolation)
247
+ #
248
+ # * dim [Integer or String]
249
+ # * y [nil or VArray of float/sfloat] a coordinate variable or a NArray
250
+ # having the same shape as self (but data missig is ignored).
251
+ # If nil, dim indices are used.
252
+ # * nth [Integer] 1,2,3,... for the 1st, 2nd, 3rd,... crossing
253
+ # * descend [true, false, or nil] true: inspect dim indices from the last
254
+ # * incr [nil, true, or false] nil: any crsossing is detected; true:
255
+ # only increasing crossing is detected; false: only decreasing crossing
256
+ # is detected
257
+ #
258
+ def val_crossing(dim, zval, y: nil, nth: 1, descend: false, incr: nil)
259
+ z = self.val
260
+ if z.is_a?(NArrayMiss)
261
+ mask = z.get_mask
262
+ z = z.to_na
263
+ else
264
+ mask = nil
265
+ end
266
+ dim = dim_index(dim)
267
+ if y.nil?
268
+ yv = nil
269
+ elsif y.is_a?(VArray) || y.is_a?(GPhys)
270
+ y = y.data if y.is_a?(GPhys)
271
+ yv = y.val
272
+ if y.is_a?(NArrayMiss)
273
+ yv = yv.to_na # ignore missing
274
+ end
275
+ else
276
+ raise("y must be a VArray or GPhys")
277
+ end
278
+ yc,ycmk = GPhys.c_val_crossing(z, mask, dim, zval, yv, nth, descend, incr)
279
+ yc = NArrayMiss.to_nam(yc,ycmk)
280
+ if y
281
+ ycva = VArray.new(yc, y, y.name)
282
+ else
283
+ ycva = VArray.new(yc, {"units"=>"", "long_name"=>"index"}, "index")
284
+ end
285
+ axes = []
286
+ (0...rank).each{|d|
287
+ axes.push(axis(d)) if d != dim
288
+ }
289
+ GPhys.new( Grid.new(*axes), ycva )
290
+ end
228
291
  end
229
292
 
230
293
  class VArray
@@ -526,6 +526,36 @@ module NumRu
526
526
  end
527
527
  end
528
528
 
529
+ def fft_filter(dim, iwnmin = nil, iwnmax = nil)
530
+ dim = dim_index(dim)
531
+ fc = self.fft(false,dim)
532
+ mask = val.get_mask
533
+ len = shape[dim]
534
+ raise("meaningless unless iwnmin or iwnmax is set") if !iwnmin && !iwnmax
535
+ if iwnmin
536
+ iwnmin += len if iwnmin<0
537
+ raise("invalid iwnmin #{iwnmin}") if iwnmin < 0 || iwnmin > len/2
538
+ end
539
+ if iwnmax
540
+ iwnmax += len if iwnmax<0
541
+ raise("invalid iwnmax #{iwnmax}") if iwnmax < 0 || iwnmax > len/2
542
+ end
543
+ if iwnmax && iwnmin
544
+ raise("iwnmin>iwnmax") if iwnmin>iwnmax
545
+ end
546
+ s = [true]*dim
547
+ if iwnmin
548
+ fc[ *(s + [0..iwnmin-1,false]) ] = 0.0 if iwnmin >= 1
549
+ fc[ *(s + [-iwnmin+1..-1,false]) ] = 0.0 if iwnmin > 1
550
+ end
551
+ if iwnmax && iwnmax < len/2
552
+ fc[ *(s + [iwnmax+1..-iwnmax-1,false]) ] = 0.0
553
+ end
554
+ filted = fc.fft(true,dim).to_type(self.data.typecode)
555
+ filted.replace_val( NArrayMiss.to_nam(filted.val, mask) )
556
+ filted
557
+ end
558
+
529
559
  def __predefined_coord_units_conversion(coord)
530
560
  case coord.units
531
561
  when Units["degree"]
@@ -25,6 +25,8 @@ module NumRu
25
25
 
26
26
  if !files.is_a?(Array)
27
27
  files = [files] # put in an Array (if a single File)
28
+ else
29
+ files = files.clone # will be destroyed by shifting
28
30
  end
29
31
 
30
32
  if !loopdims.is_a?(Array)