gphys 1.5.5 → 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.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/ChangeLog +0 -7595
  3. data/LICENSE.txt +1 -1
  4. data/bin/gpcut +12 -0
  5. data/bin/gpvect +88 -77
  6. data/bin/gpview +200 -103
  7. data/ext/numru/ganalysis/ext_init.c +9 -0
  8. data/ext/numru/ganalysis/extconf.rb +43 -0
  9. data/ext/numru/ganalysis/narray_ext_dfloat.c +84 -0
  10. data/ext/numru/ganalysis/pde_ext.c +130 -0
  11. data/ext/numru/gphys/dim_op.c +336 -44
  12. data/ext/numru/gphys/ext_init.c +6 -0
  13. data/ext/numru/gphys/interpo.c +326 -3
  14. data/gphys.gemspec +1 -0
  15. data/lib/numru/dclext.rb +78 -16
  16. data/lib/numru/ganalysis/beta_plane.rb +6 -4
  17. data/lib/numru/ganalysis/eof.rb +63 -41
  18. data/lib/numru/ganalysis/fitting.rb +109 -30
  19. data/lib/numru/ganalysis/histogram.rb +3 -3
  20. data/lib/numru/ganalysis/log_p.rb +20 -0
  21. data/lib/numru/ganalysis/lomb_scargle.rb +205 -0
  22. data/lib/numru/ganalysis/met_z.rb +132 -3
  23. data/lib/numru/ganalysis/narray_ext.rb +13 -0
  24. data/lib/numru/ganalysis/pde.rb +109 -0
  25. data/lib/numru/ganalysis/planet.rb +136 -1
  26. data/lib/numru/ganalysis/qg.rb +224 -3
  27. data/lib/numru/ggraph.rb +95 -23
  28. data/lib/numru/gphys/axis.rb +4 -2
  29. data/lib/numru/gphys/gphys.rb +6 -5
  30. data/lib/numru/gphys/gphys_dim_op.rb +69 -6
  31. data/lib/numru/gphys/gphys_fft.rb +30 -0
  32. data/lib/numru/gphys/gphys_io_common.rb +2 -0
  33. data/lib/numru/gphys/grads_gridded.rb +77 -29
  34. data/lib/numru/gphys/grib.rb +2 -2
  35. data/lib/numru/gphys/grib_params.rb +3 -3
  36. data/lib/numru/gphys/interpolate.rb +153 -1
  37. data/lib/numru/gphys/varraycomposite.rb +7 -4
  38. data/lib/numru/gphys/version.rb +1 -1
  39. data/lib/numru/gphys.rb +1 -0
  40. data/testdata/pres.jan.nc +0 -0
  41. metadata +13 -4
@@ -213,7 +213,217 @@ module NumRu
213
213
  divh
214
214
  end
215
215
 
216
+ # Wave activity flux by Takaya and Nakamura (2001) (TN2001)
217
+ #
218
+ # This method works by mix-in in QG (Cartesian) or QG_sphere (spherical).
219
+ # (so the call it either as QG::waf_tn2001(gph, gphbs, ..) or
220
+ # QG_sphere::waf_tn2001(gph, gphbs, ..) ).
221
+ #
222
+ # DEFINITIONS
223
+ #
224
+ # * if called through QG: a modified version of Eq (32) of TN2001
225
+ # * if called through QG_sphere: a modified version of Eq (38) of TN2001
226
+ # The modification of Eq (32) and (38) is as follows:
227
+ # * The multiplication by p is omitted. This is because
228
+ # it is more convenient to do it afterwords if needed
229
+ # (for example, to integrate with p would require not to have
230
+ # done this multiplication).
231
+ # * The C_u M term is not included as in convention.
232
+ # (but the multiplication by cos(phi) is done in QG_sphere).
233
+ # Note that this term vanishes for stationary waves, because C_u=0.
234
+ # * The normal vector (n1, n2) in TN2001 can be set flexibly.
235
+ # This vector is called (nx, ny) in this method, since n2 is used
236
+ # for the buoyancy frequency. In eqs. (32) and (38), (nx, ny)
237
+ # is prescribed as (nx, ny) = (U,V)/|U,V| where U is ubs and V is vbs.
238
+ # However, this relation is not necessarily valid, since (nx, ny)
239
+ # is originally attributed to the QGPV gradient of the basic flow.
240
+ # Therefore, in this method, (nx, ny) can be set arbitrary.
241
+ # Also, one can set (nx, ny) = (1, 0) or (0, 1) by setting the
242
+ # optional argument zonal or merid to true.
243
+ #
244
+ # ARGUMENTS
245
+ # * gph: geopotential height
246
+ # * gphbs: geopotential height (basic state). Basically, it needs to have
247
+ # the same spacial grid as gph, but it can be a meridional section
248
+ # (such as zonal mean), if the normal vector is specified by
249
+ # (ubs, vbs) or (nx, ny) or zonal or merid.
250
+ # * nx, ny: normalized vector to designate the direction of wave
251
+ # propagation. By default, set to the direction of (ubs, vbs),
252
+ # or set by zonal/merid (see below).
253
+ # * ubs, vbs: Basic state zonal and meridional winds to compute
254
+ # the normal vector (nx,ny) as (ubs,vbs)/sqrt(ubs**2 + vbs**2).
255
+ # Neglected if nx and ny are specified. By default ubs and vbs
256
+ # are derived geostrophically from gphbs
257
+ # * zonal: derive the flux in the zonal direction assuming (nx,ny)=(1,0)
258
+ # * merid: derive the flux in the meridional dir assuming (nx,ny)=(0,1)
259
+ # * n2: Brunt-Vaisala (buoyancy) frequency squared. By default, derived
260
+ # from gphbs
261
+ # * derive_M0: derive M (the wave-activity pseudomomentum of TN20001)
262
+ # when the wave is stationary (cp=0). You need to give ubs and vbs
263
+ # (or have them derived from gphbs by not using nx, ny, zonal or merid)
264
+ # to make this option available.
265
+ #
266
+ # RETURN VALUE
267
+ # * [wx, wy, wz, ret_hash] where [wx, wy, wz] are the WAF vector
268
+ # and ret_hash provides extra derived quantities such as the
269
+ # perturbation stream function (:pp), pseudomomentum M0 (:M0), etc.
270
+ #
271
+ # REFERENCE
272
+ # * Takaya and Namaura (2001): A formulation of a phase-independent
273
+ # wave-activity flux for stationary and migratory quasigeostrophic
274
+ # eddies on a zonally varying basic flow. J. Atmos. Sci, 58, 608-627.
275
+ #
276
+ def waf_tn2001(gph, gphbs, nx: nil, ny: nil, ubs: nil, vbs: nil,
277
+ zonal: false, merid: false, n2: nil,
278
+ derive_M0: false)
279
+
280
+ #< prepration >
281
+ if self==QG
282
+ f = f0
283
+ wgt = nil
284
+ elsif self==QG_sphere
285
+ f = f_mask0(gph)
286
+ wgt = cos_phi(gph)
287
+ else
288
+ raise("unsupported module to mix-in #{self}")
289
+ end
290
+ ret_hash = Hash.new
291
+
292
+ #< perturbation stream function >
293
+ gf = Met::g / f
294
+ pp = (gph - gphbs)*gf # psi' (perturbation stream function)
295
+ if /gpm/i =~ (us=pp.units.to_s)
296
+ pp.units = us.sub(/gpm/i,'m')
297
+ end
298
+ ret_hash[:pp] = pp
299
+
300
+ #< derive nx, ny if not given >
301
+ ul = psibs = nil
302
+ if zonal
303
+ nx = 1.0
304
+ ny = 0.0
305
+ elsif merid
306
+ nx = 0.0
307
+ ny = 1.0
308
+ elsif nx.nil? && ny.nil?
309
+ if !ubs || !vbs
310
+ psibs, gpref = gph2psi_gpref(gphbs)
311
+ if /gpm/i =~ (us=psibs.units.to_s)
312
+ psibs.units = us.sub(/gpm/i,'m')
313
+ end
314
+ ubs, vbs = psi2ug_vg(psibs)
315
+ ret_hash[:ubs] = ubs
316
+ ret_hash[:vbs] = vbs
317
+ ret_hash[:gpref] = gpref
318
+ end
319
+ ul = (ubs**2+vbs**2).sqrt
320
+ nx = ubs/ul
321
+ ny = vbs/ul
322
+ end
323
+
324
+ #< derive aspect ratio >
325
+ unless n2
326
+ n2 = LogP::gph2n2(gphbs)
327
+ ret_hash[:n2] = n2
328
+ end
329
+ eps = f**2/n2
330
+
331
+ #< cross terms --> WAF >
332
+ px,py = grad_h(pp)
333
+ pxx,pxy = grad_h(px)
334
+ pyy = grad_hy(py) unless ny==0.0
335
+ pz = LogP::pcdata_dz(pp)
336
+ pxz = LogP::pcdata_dz(px) unless nx==0.0
337
+ pyz = LogP::pcdata_dz(py) unless ny==0.0
338
+ ret_hash[:px] = px
339
+ ret_hash[:py] = py
340
+
341
+ wx = nil
342
+ unless nx==0.0
343
+ wx = px*px - pp*pxx
344
+ wy = px*py - pp*pxy
345
+ wz = ( px*pz - pp*pxz ) * eps
346
+ nx2 = nx/2.0
347
+ wx = wx * nx2
348
+ wy = wy * nx2
349
+ wz = wz * nx2
350
+ end
351
+
352
+ unless ny==0.0
353
+ wx_ = px*py - pp*pxy
354
+ wy_ = py*py - pp*pyy
355
+ wz_ = (py*pz - pp*pyz) * eps
356
+ ny2 = ny/2.0
357
+ wx_ = wx_ * ny2
358
+ wy_ = wy_ * ny2
359
+ wz_ = wz_ * ny2
360
+ if wx
361
+ wx += wx_
362
+ wy += wy_
363
+ wz += wz_
364
+ else
365
+ wx = wx_
366
+ wy = wy_
367
+ wz = wz_
368
+ end
369
+ end
216
370
 
371
+ if wgt
372
+ wx = wx * wgt
373
+ wy = wy * wgt
374
+ wz = wz * wgt
375
+ end
376
+ wx.name = "Wx"
377
+ wy.name = "Wy"
378
+ wz.name = "Wz"
379
+ wx.long_name = "WAFx"
380
+ wy.long_name = "WAFy"
381
+ wz.long_name = "WAFz"
382
+
383
+ #< derive M0 if required >
384
+ if derive_M0
385
+ raise("ubs and vbs are needed to derive M0") if !ubs || !vbs
386
+ ul = (ubs**2+vbs**2).sqrt unless ul
387
+ unless psibs
388
+ psibs, gpref = gph2psi_gpref(gphbs)
389
+ if /gpm/i =~ (us=psibs.units.to_s)
390
+ psibs.units = us.sub(/gpm/i,'m')
391
+ end
392
+ ret_hash[:gpref] = gpref
393
+ end
394
+ n2p = Planet::ave_s(n2)
395
+ if n2p.rank >= 2
396
+ pdim = Met.find_prs_d(n2p)
397
+ ds = Array.new
398
+ (0...n2p.rank).each do |d|
399
+ ds.push(d) unless d == pdim
400
+ end
401
+ n2p = n2p.mean(*ds)
402
+ end
403
+ qp, = psi2q(pp,n2p)
404
+ qbs, = psi2q(psibs,n2p)
405
+ qbx, qby = grad_h(qbs)
406
+ e2 = px**2 + py**2 + pz**2 * eps # 2*e
407
+ qbgrad = (qbx**2+qby**2).sqrt.running_mean(0,3).running_mean(1,3)
408
+ a = qp**2 / qbgrad / 4.0 # A of TN2001
409
+ e0 = e2 / ul / 4.0 # E of TN2001 when cp=0
410
+ m0 = a + e0
411
+ a.name = "A"
412
+ a.long_name = "A"
413
+ e0.name = "E0"
414
+ e0.long_name = "stationary E"
415
+ m0.name = "M0"
416
+ m0.long_name = "stationary TN2001 pseudomomentum"
417
+ ret_hash[:qp] = qp
418
+ ret_hash[:qbs] = qbs
419
+ ret_hash[:A] = a
420
+ ret_hash[:E0] = e0
421
+ ret_hash[:M0] = m0
422
+ end
423
+
424
+ #< return >
425
+ [wx, wy, wz, ret_hash]
426
+ end
217
427
  end
218
428
 
219
429
  ######################################################
@@ -409,6 +619,12 @@ module NumRu
409
619
  def grad_h(gphys)
410
620
  @@bp.grad_h(gphys)
411
621
  end
622
+ def grad_hy(gphys)
623
+ @@bp.grad_y(gphys)
624
+ end
625
+ def grad_hx(gphys)
626
+ @@bp.grad_x(gphys)
627
+ end
412
628
 
413
629
  # horizontal divergence (Cartesian)
414
630
  def div_h(gphys_u, gphys_v)
@@ -442,9 +658,8 @@ module NumRu
442
658
 
443
659
  # geopotential height -> geostrophic winds
444
660
  def gph2ug_vg(gph)
445
- gpx, gpy = Planet::grad_s(gph * Met::g)
446
- f = f_mask0(gph)
447
- [ -gpy/f, gpx/f]
661
+ psi, gpref = gph2psi_gpref(gph)
662
+ psi2ug_vg(psi)
448
663
  end
449
664
 
450
665
  # geopotential height -> QG stream function and the reference geopotential
@@ -524,6 +739,12 @@ module NumRu
524
739
  def grad_h(gphys)
525
740
  Planet::grad_s(gphys)
526
741
  end
742
+ def grad_hx(gphys)
743
+ Planet::grad_sx(gphys)
744
+ end
745
+ def grad_hy(gphys)
746
+ Planet::grad_sy(gphys)
747
+ end
527
748
 
528
749
  # horizontal divergence (spherical)
529
750
  def div_h(fx, fy)
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
@@ -2839,11 +2886,7 @@ module NumRu
2839
2886
 
2840
2887
  @@used_fullcolor_tone = false
2841
2888
  val = gp.data.val
2842
- if ( opts['ltone'] &&
2843
- ( opts['tonf'] || opts['auto'] && !opts['tonb'] && !opts['tonc'] &&
2844
- ( val.length >= TONE_TONF_THRES_SIZE || val.shape.min >= TONE_TONF_THRES_LEN ) ) )
2845
- DCL.uetonf(val)
2846
- elsif opts['fullcolor']
2889
+ if opts['fullcolor']
2847
2890
  @@used_fullcolor_tone = true
2848
2891
  sopt = opts.dup.delete_if{|k,v| !DCLExt.shade_1_option_keys.include?(k)}
2849
2892
  DCLExt.ui_shade_1(val, sopt)
@@ -2851,21 +2894,31 @@ module NumRu
2851
2894
  DCL.uetonb(val)
2852
2895
  elsif opts['tonc'] && opts['ltone']
2853
2896
  DCL.uetonc(val)
2897
+ elsif ( opts['ltone'] &&
2898
+ ( opts['tonf'] ||
2899
+ opts['auto'] && ( val.length >= TONE_TONF_THRES_SIZE ||
2900
+ val.shape.min >= TONE_TONF_THRES_LEN ) ) )
2901
+ DCL.uetonf(val)
2854
2902
  else
2855
2903
  DCL.uetone(val)
2856
2904
  end
2857
2905
 
2858
2906
  if newframe
2907
+ if opts['proc_before_ax']
2908
+ opts['proc_before_ax'].call
2909
+ end
2859
2910
  axes_or_map_and_ttl(gp,opts, xax, yax)
2860
2911
  end
2861
2912
  DCL.uepset('icolor1', icolor1_bak) if opts['clr_min']
2862
2913
  DCL.uepset('icolor2', icolor2_bak) if opts['clr_max']
2863
2914
 
2864
2915
  if opts['color_bar']
2916
+ cbunits = opts['cbunits']
2917
+ cbunits = gphys.units.to_s if cbunits==true
2865
2918
  if @@used_fullcolor_tone
2866
- color_bar
2919
+ color_bar "units"=>cbunits
2867
2920
  else
2868
- color_bar "log"=>opts['log']
2921
+ color_bar "log"=>opts['log'], "units"=>cbunits
2869
2922
  end
2870
2923
  end
2871
2924
  closer.call if closer
@@ -2882,6 +2935,7 @@ module NumRu
2882
2935
  ['size', 0.01, 'marks size'],
2883
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.'],
2884
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.'],
2885
2939
  @@data_prep_options
2886
2940
  )
2887
2941
  ## @@scatter_options.delete("transpose") # delete is yet to be supported
@@ -2931,6 +2985,9 @@ module NumRu
2931
2985
  y = gpy.data
2932
2986
  if newframe
2933
2987
  fig(x, y)
2988
+ if opts['proc_before_ax']
2989
+ opts['proc_before_ax'].call
2990
+ end
2934
2991
  axes_or_map_and_ttl(gpx, opts, x, y, gpy)
2935
2992
  end
2936
2993
  DCL.uumrkz(x.val, y.val, opts['type'], opts['index'], opts['size'])
@@ -3151,6 +3208,7 @@ module NumRu
3151
3208
  ['keep', false, 'Use the same vector scaling as in the previous call. -- Currently, works only when "flow_vect" is true'],
3152
3209
  ['factor', 1.0, '(Effective only if flow_vect) scaling factor to strech/reduce the arrow lengths'],
3153
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'],
3154
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.'],
3155
3213
  ['ux_unit', nil, '(If Numeric) length of the x direction unit vector (precedence of this option is lower than max_unit_vect)'],
3156
3214
  ['uy_unit', nil, '(If Numeric) length of the y direction unit vector (precedence of this option is lower than max_unit_vect)'],
@@ -3199,6 +3257,20 @@ module NumRu
3199
3257
 
3200
3258
  oldindex = DCLExt.ug_set_params("index" => opts['index']) if opts['index']
3201
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
3202
3274
  if opts['flow_itr5']
3203
3275
  if itr_is?(5)
3204
3276
  DCLExt.flow_itr5( fx, fy, opts['factor'], opts['unit_vect'] )
@@ -3217,7 +3289,7 @@ module NumRu
3217
3289
  returnval = { "vfratio"=> @@vfratio, "flenmax"=>@@flenmax }
3218
3290
  if opts['unit_vect']
3219
3291
  len_unit = opts['len_unit'] || @@flenmax
3220
- DCLExt.unit_vect_single(@@vfratio, len_unit)
3292
+ DCLExt.unit_vect_single(@@vfratio, len_unit, uvopts)
3221
3293
  end
3222
3294
  elsif opts['flow_vect']
3223
3295
  uninfo = DCLExt.flow_vect(fx.val, fy.val, opts['factor'], 1, 1,
@@ -3229,7 +3301,7 @@ module NumRu
3229
3301
  uninfo[2] = opts['ux_unit'] # nil or a Numeric to specify the len
3230
3302
  uninfo[3] = opts['uy_unit'] # nil or a Numeric to specify the len
3231
3303
  end
3232
- DCLExt.unit_vect(*uninfo)
3304
+ DCLExt.unit_vect( *(uninfo+[uvopts]) )
3233
3305
  end
3234
3306
  else
3235
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
@@ -1210,7 +1210,8 @@ module NumRu
1210
1210
  grid = Grid.new(*axes)
1211
1211
  if gp0.assoc_coords
1212
1212
  assoc_coords = gp0.assoccoordnames.collect do |aname|
1213
- GPhys.join( gpnary.collect{|gp| gp.assoc_coord_gphys(aname)}, true )
1213
+ GPhys.join( gpnary.collect{|gp| gp.assoc_coord_gphys(aname)}, true,
1214
+ true )
1214
1215
  end
1215
1216
  grid.set_assoc_coords(assoc_coords)
1216
1217
  end
@@ -1222,7 +1223,7 @@ module NumRu
1222
1223
  GPhys.new(grid, data)
1223
1224
  end
1224
1225
 
1225
- def GPhys.join_md(gpnary)
1226
+ def GPhys.join_md(gpnary, no_sort=false)
1226
1227
  #< Check >
1227
1228
 
1228
1229
  if !gpnary.is_a?(NArray)
@@ -1283,7 +1284,7 @@ module NumRu
1283
1284
  end
1284
1285
 
1285
1286
  #< Sort along dimensions to join >
1286
- gpnary = __sort_gpnary(gpnary)
1287
+ gpnary = __sort_gpnary(gpnary) unless no_sort
1287
1288
 
1288
1289
  #< Join! >
1289
1290
  self.join_md_nocheck(gpnary)
@@ -1294,7 +1295,7 @@ module NumRu
1294
1295
  # ARGUMENT
1295
1296
  # * gpnarray [Array (or 1D NArray) of GPhys]
1296
1297
  #
1297
- def GPhys.join(gpary, ignore_overlap=false)
1298
+ def GPhys.join(gpary, ignore_overlap=false, no_sort=false)
1298
1299
 
1299
1300
  #< initialization with the first GPhys object >
1300
1301
 
@@ -1332,7 +1333,7 @@ module NumRu
1332
1333
  gpnary = gpstore.to_na
1333
1334
 
1334
1335
  #< Sort along dimensions to join >
1335
- gpnary = __sort_gpnary(gpnary)
1336
+ gpnary = __sort_gpnary(gpnary) unless no_sort
1336
1337
 
1337
1338
  #< Join! >
1338
1339
  self.join_md_nocheck(gpnary)