Beispiel #1
0
def add_lon_labels(wks):
    #
    # List the longitude values where you want labels.  It's assumed that longitude=0
    # is at the bottom of the plot, and 180W at the top. You can adjust as necessary.
    #
    lon_values = numpy.arange(-180, 180, 30)

    nlon = lon_values.shape[0]
    lat_values = numpy.zeros(nlon, 'f') + mpres.mpMinLatF + 0.005

    #
    # Get the NDC coordinates of these lat,lon labels.
    # We'll use this information to place labels *outside* of
    # the map plot.
    #
    xndc, yndc = Ngl.datatondc(plot_base, lon_values, lat_values)

    #
    # Set an array of justification strings to use with the "txJust" resource
    # for each label, based on which quadrant it appears in.
    #
    just_strs = [
        "BottomCenter",  # top of plot
        "BottomRight",
        "BottomRight",  # upper left quadrant
        "CenterRight",  # left of plot
        "TopRight",
        "TopRight",  # lower left quadrant
        "TopCenter",  # bottom of plot
        "TopLeft",
        "TopLeft",  # lower right quadrant
        "CenterLeft",  # right of plot
        "BottomLeft",
        "BottomLeft"
    ]  # upper right qudrant

    # Create an array of longitude labels with "W" and "E" added.
    lon_labels = []
    for i in range(nlon):
        if lon_values[i] < 0:
            lon_labels.append("%gW" % abs(lon_values[i]))
        elif lon_values[i] > 0:
            lon_labels.append("%gE" % lon_values[i])
        else:
            lon_labels.append("%g" % lon_values[i])

# Loop through each label and add it.
    txres = Ngl.Resources()
    txres.txFontHeightF = 0.01
    for i in range(nlon):
        txres.txJust = just_strs[i]
        Ngl.text_ndc(wks, lon_labels[i], xndc[i], yndc[i], txres)

    return
Beispiel #2
0
npts = 400
x = Ngl.fspan(100., npts - 1, npts)
y = 500. + x * numpy.sin(0.031415926535898 * x)

wks = Ngl.open_wks("ps", "datandc")

xy = Ngl.xy(wks, x, y)

#
# Test with all in-range values and no missing values present.
#
x_dat = x
y_dat = numpy.absolute(y)

x_ndc, y_ndc = Ngl.datatondc(xy, x_dat, y_dat)
x_dat2, y_dat2 = Ngl.ndctodata(xy, x_ndc, y_ndc)

check_type(x_ndc)
check_type(y_ndc)
check_type(x_dat2)
check_type(y_dat2)

test_values("no oor or msg data: datatondc/ndctodata",
            x_dat,
            x_dat2,
            delta=1e-4)
test_values("no oor or msg data: datatondc/ndctodata",
            y_dat,
            y_dat2,
            delta=1e-4)
Beispiel #3
0
def trj(wks, x, y, time, res=None):
    ''' Plots trajectories with arrow heads attached.

    plot = trj(wks, x, y, time, res=None)

    wks : The identifier returned from calling Ngl.open_wks.

    x,y : The X and Y coordinates of the curve(s). These values can be
          one-dimensional NumPy arrays, NumPy masked arrays or two-dimensional
          NumPy arrays. If x and/or y are two-dimensional, then the leftmost
          dimension determines the number of curves.

    time : Time coordinates of the trajectories. These values can be
          one-dimensional NumPy arrays, NumPy masked arrays

    res:   Resource list using following special resources:

    Special resources:

    trjArrowStep  :     Number of samples between arrow heads.
                        Default: 10

    trjArrowOffsetF :   Shift the position of the arrows along the curve.
                        Should be between 0. and 1.
                        Default: 0.5

    trjArrowDirection : can be 'pos' or 'neg' to select direction of the
                        arrows.
                        Default: 'pos'

    trjArrowXShapeF :   Array containing the x NDC coordinates of the arrow
                        head relative to the heads centre.
                        Default: Equiliteral triangle

    trjArrowYShapeF :   Array containing the y NDC coordinates of the arrow
                        head relative to the heads centre.
                        Default: Equiliteral triangle

    trjArrowXScaleF :   Scales arrow head in X direction, befor rotation is
                        applied.
                        Default: 1.

    trjArrowYScaleF :   Scales arrow head in y direction, befor rotation is
                        applied.
                        Default: 1.

    trjArrowSizeF :     Scales the size of an arrow head.
                        Default: 0.02

    The arrow heads are plotted with add_polygon, so all gs* attributes of the
    resource list are applied to the arrow heads polygon.
    '''

    if not res:
        res = ngl.Resources()

    # set default values:
    if not hasattr(res, 'trjArrowStep'):
        res.trjArrowStep = 10
    if not hasattr(res, 'trjArrowOffsetF'):
        res.trjArrowOffsetF = .5
    else:
        res.trjArrowOffsetF -= np.floor(res.trjArrowOffsetF)
    if not hasattr(res, 'trjArrowDirection'):
        res.trjArrowDirection = 'pos'
    if not hasattr(res, 'trjArrowXShapeF'):
        res.trjArrowXShapeF = [np.sqrt(3) / 3.,
                              -np.sqrt(3) / 6.,
                              -np.sqrt(3) / 6.]
    res.trjArrowXShapeF = np.asarray(res.trjArrowXShapeF)
    if not hasattr(res, 'trjArrowYShapeF'):
        res.trjArrowYShapeF = [0., .5, -.5]
    res.trjArrowYShapeF = np.asarray(res.trjArrowYShapeF)
    if not hasattr(res, 'trjArrowXScaleF'):
        res.trjArrowXScaleF = 1.
    if not hasattr(res, 'trjArrowYScaleF'):
        res.trjArrowYScaleF = 1.
    if not hasattr(res, 'trjArrowSizeF'):
        res.trjArrowSizeF = .02

    # check for draw and frame
    if hasattr(res, "nglDraw"):
        doDraw = res.nglDraw
    else:
        doDraw = True
    res.nglDraw = False
    if hasattr(res, "nglFrame"):
        doFrame = res.nglFrame
    else:
        doFrame = True
    res.nglFrame = False

    # Convert to mask array
    x = np.ma.asarray(x)
    y = np.ma.asarray(y)
    time = np.ma.asarray(time)

    # check input data
    if x.shape != y.shape:
        raise ValueError("Inconsistend shape. x, y and time must have the "
                            + "same shape.")

    if x.ndim < 1 or x.ndim > 2:
        raise ValueError("Input arrays x and y must be of rank 1 or 2.")

    if np.rank(x) == 1:
        # add singleton dimension to the begining
        x = x[np.newaxis, ...]
        y = y[np.newaxis, ...]

    # Dimension of trajectories
    dim = 0

    # mask all missig values
    np.ma.masked_where(y.mask, x, copy=False)
    np.ma.masked_where(x.mask, y, copy=False)

    # create line plot resource
    res_lines = copy.deepcopy(res)

    # remove trj* attributes from res_lines
    for attr in dir(res_lines):
        if attr[0:3] == "trj" or (attr[0:2] == "gs" and attr[2] != "n"):
            delattr(res_lines, attr)

    # create line plot
    plot = ngl.xy(wks, x, y, res_lines)

    # get axes length in data coordinates
    xAxisLen, yAxisLen = [ngl.get_float(plot, "tr" + ax + "MaxF")
                          - ngl.get_float(plot, "tr" + ax + "MinF")
                          for ax in "XY"]

    # get marker color
    # to be implemented

    # place Marker
    marker_id = []
    for t in xrange(x.shape[dim]):
        xt = x[t, ...].compressed()
        yt = y[t, ...].compressed()
        tt = time[::res.trjArrowStep]

        # shift time by offset
        if res.trjArrowOffsetF != 0.:
            tt = tt[:-1] + res.trjArrowOffsetF * (tt[1:] - tt[:-1])

        # itterate over markers
        for tm in tt:
            # find nearest indices in time array
            idx = (np.abs(time - tm)).argmin().min()
            if time[idx] < tm:
                idx1 = idx
                idx2 = idx + 1
            elif time[idx] > tm:
                idx1 = idx - 1
                idx2 = idx
            else:
                if idx == 0:
                    idx1 = idx
                    idx2 = idx + 1
                else:
                    idx1 = idx - 1
                    idx2 = idx

            if idx >= len(xt) - 1:
                continue
            # interpolate linearly to get coordinates
            ds = (tm - time[idx1]) / (time[idx2] - time[idx1])
            xm, ym = [coord[idx1] + ds * (coord[idx2] - coord[idx1])
                      for coord in [xt, yt]]
            x1, y1 = ngl.datatondc(plot, xt[idx1], yt[idx1])
            x2, y2 = ngl.datatondc(plot, xt[idx2], yt[idx2])
            angle = np.arctan2(y2 - y1, x2 - x1)

            # create marker resource
            res_marker = copy.deepcopy(res)
            # scale adjust marker scale
            res_marker.trjArrowXScaleF = res.trjArrowXScaleF * xAxisLen
            res_marker.trjArrowYScaleF = res.trjArrowYScaleF * yAxisLen

            marker_id.append(
                _plot_trj_marker(wks, plot, xm, ym, angle, res_marker))

        if doDraw:
            ngl.draw(plot)
            res.nglDraw = True
        if doFrame:
            ngl.frame(wks)
            res.nglFrame = True

    return plot
Beispiel #4
0
def _plot_trj_marker(wks, plot, x, y, angle, res):
    ''' Plots a single arrow head onto the a trajectory plot

    pgon = _plot_trj_marker(wks, plot, x, y, angle, res)

    wks :              The identifier returned from calling Ngl.open_wks.

    x,y :              The X and Y coordinates of the arrow heads centre.

    xMarker, yMarker : X and Y coordinates in data coordinates of the marker
polygon

    angle:             angle relative to the x axis of the marker

    res:               Resource list using following special resources:

    Special resources:

    trjArrowDirection : can be 'pos' or 'neg' to select direction of the arrows

    trjArrowXShapeF   : Array containing the x coordinates of the arrow head
relative to the heads centre.

    trjArrowYShapeF   : Array containing the y  coordinates of the arrow head
relative to the heads centre.
    '''

    # get plot centre in data coordinates
    xMid, yMid = [(ngl.get_float(plot, "tr" + ax + "MaxF")
                   + ngl.get_float(plot, "tr" + ax + "MinF")) / 2.
                          for ax in "XY"]

    # rotate arrow
    if res.trjArrowDirection == "neg":
        angle = angle - np.pi

    xMarker = copy.deepcopy(res.trjArrowXShapeF)
    yMarker = copy.deepcopy(res.trjArrowYShapeF)

    # scale marker
    xMarker = xMarker * res.trjArrowXScaleF * res.trjArrowSizeF + xMid
    yMarker = yMarker * res.trjArrowYScaleF * res.trjArrowSizeF + yMid

    xMarker_ndc, yMarker_ndc = ngl.datatondc(plot, xMarker, yMarker)

    # move centre of mass to origin
    xMarker_ndc, yMarker_ndc = [xMarker_ndc - np.mean(xMarker_ndc),
                                yMarker_ndc - np.mean(yMarker_ndc)]
    # rotate marker
    xMarker_ndc, yMarker_ndc = [
                    np.cos(angle) * xMarker_ndc - np.sin(angle) * yMarker_ndc,
                    np.sin(angle) * xMarker_ndc + np.cos(angle) * yMarker_ndc]

    # shift to final position
    xOffset_ndc, yOffset_ndc = ngl.datatondc(plot, x, y)
    xMarker_ndc += xOffset_ndc
    yMarker_ndc += yOffset_ndc

    # convert back to coordinates
    xMarker, yMarker = ngl.ndctodata(plot, xMarker_ndc, yMarker_ndc)

    # filter attributes from res
    for attr in dir(res):
        if not attr[0:2] in ["gs", "__"] or attr[0:3] == "gsn":
            delattr(res, attr)

    return ngl.add_polygon(wks, plot, xMarker, yMarker, res)
Beispiel #5
0
def add_labels_lcm(wks,map,dlat,dlon):
  PI         = 3.14159
  RAD_TO_DEG = 180./PI

#-- determine whether we are in northern or southern hemisphere
  if (float(minlat) >= 0. and float(maxlat) > 0.):
     HEMISPHERE = "NH"
  else:
     HEMISPHERE = "SH"

#-- pick some "nice" values for the latitude labels.
  lat_values = np.arange(int(minlat),int(maxlat),10)
  lat_values = lat_values.astype(float)
  nlat       = len(lat_values)

#-- We need to get the slope of the left and right min/max longitude lines.
#-- Use NDC coordinates to do this.
  lat1_ndc = 0.
  lon1_ndc = 0.
  lat2_ndc = 0.
  lon2_ndc = 0.
  lon1_ndc,lat1_ndc = Ngl.datatondc(map,minlon,lat_values[0])
  lon2_ndc,lat2_ndc = Ngl.datatondc(map,minlon,lat_values[nlat-1])
  slope_lft         = (lat2_ndc-lat1_ndc)/(lon2_ndc-lon1_ndc)

  lon1_ndc,lat1_ndc = Ngl.datatondc(map,maxlon,lat_values[0])
  lon2_ndc,lat2_ndc = Ngl.datatondc(map,maxlon,lat_values[nlat-1])
  slope_rgt         = (lat2_ndc-lat1_ndc)/(lon2_ndc-lon1_ndc)
  
#-- set some text resources
  txres               = Ngl.Resources()
  txres.txFontHeightF = 0.01
  txres.txPosXF       = 0.1

#-- Loop through lat values, and attach labels to the left and right edges of
#-- the masked LC plot. The labels will be rotated to fit the line better.
  dum_lft       = []                            #-- assign arrays
  dum_rgt       = []                            #-- assign arrays
  lat_label_lft = []                            #-- assign arrays
  lat_label_rgt = []                            #-- assign arrays

  for n in range(0,nlat):
#-- left label
    if(HEMISPHERE == "NH"):
       rotate_val = -90.
       direction  = "N"
    else:
       rotate_val =  90.
       direction  = "S"

#-- add extra white space to labels
    lat_label_lft.append("{}~S~o~N~{}              ".format(str(np.abs(lat_values[n])),direction))
    lat_label_rgt.append("              {}~S~o~N~{}".format(str(np.abs(lat_values[n])),direction))
        
    txres.txAngleF = RAD_TO_DEG * np.arctan(slope_lft) + rotate_val
                             
    dum_lft.append(Ngl.add_text(wks,map,lat_label_lft[n],minlon,lat_values[n],txres))

#-- right label
    if(HEMISPHERE == "NH"):
       rotate_val =  90
    else:
       rotate_val = -90

    txres.txAngleF = RAD_TO_DEG * np.arctan(slope_rgt) + rotate_val

    dum_rgt.append(Ngl.add_text(wks,map,lat_label_rgt[n],maxlon,lat_values[n],txres))

#----------------------------------------------------------------------
# Now do longitude labels. These are harder because we're not adding
# them to a straight line.
# Loop through lon values, and attach labels to the bottom edge for
# northern hemisphere, or top edge for southern hemisphere.
#----------------------------------------------------------------------
  del(txres.txPosXF)
  txres.txPosYF = -5.0

#-- pick some "nice" values for the longitude labels
  lon_values = np.arange(int(minlon+10),int(maxlon-10),10).astype(float)
  lon_values = np.where(lon_values > 180, 360-lon_values, lon_values)
  nlon       = lon_values.size

  dum_bot    = []                            #-- assign arrays
  lon_labels = []                            #-- assign arrays

  if(HEMISPHERE == "NH"):
     lat_val    = minlat
  else:
     lat_val    = maxlat

  ctrl = "~C~"

  for n in range(0,nlon):
    if(lon_values[n] < 0):
       if(HEMISPHERE == "NH"):
          lon_labels.append("{}~S~o~N~W{}".format(str(np.abs(lon_values[n])),ctrl))
       else:
          lon_labels.append("{}{}~S~o~N~W".format(ctrl,str(np.abs(lon_values[n]))))
    elif(lon_values[n] > 0):
       if(HEMISPHERE == "NH"):
          lon_labels.append("{}~S~o~N~E{}".format(str(lon_values[n]),ctrl))
       else:
          lon_labels.append("{}{}~S~o~N~E".format(ctrl,str(lon_values[n])))
    else:
       if(HEMISPHERE == "NH"):
          lon_labels.append("{}0~S~o~N~{}".format(ctrl,ctrl))
       else:
          lon_labels.append("{}0~S~o~N~{}".format(ctrl,ctrl))

#-- For each longitude label, we need to figure out how much to rotate
#-- it, so get the approximate slope at that point.
    if(HEMISPHERE == "NH"):             #-- add labels to bottom of LC plot
       lon1_ndc,lat1_ndc = Ngl.datatondc(map, lon_values[n]-0.5, minlat)
       lon2_ndc,lat2_ndc = Ngl.datatondc(map, lon_values[n]+0.5, minlat)
       txres.txJust = "TopCenter"
    else:                               #-- add labels to top of LC plot
       lon1_ndc,lat1_ndc = Ngl.datatondc(map, lon_values[n]+0.5, maxlat)
       lon2_ndc,lat2_ndc = Ngl.datatondc(map, lon_values[n]-0.5, maxlat)
       txres.txJust = "BottomCenter"

    slope_bot = (lat1_ndc-lat2_ndc)/(lon1_ndc-lon2_ndc)
    txres.txAngleF  =  RAD_TO_DEG * np.arctan(slope_bot)
    
#-- attach to map
    dum_bot.append(Ngl.add_text(wks, map, str(lon_labels[n]), \
                                lon_values[n], lat_val, txres))
  return
Beispiel #6
0
wks_type = "png"
wks = Ngl.open_wks(wks_type, "datatondc1")

res = Ngl.Resources()
res.nglMaximize = False
res.vpXF = 0.1
res.vpYF = 0.9
res.vpHeightF = 0.8
res.vpWidthF = 0.8

xy = Ngl.xy(wks, x, y, res)

x_in = x
y_in = numpy.absolute(y)

x_out, y_out = Ngl.datatondc(xy, x_in, y_in)

#
#  Print out a table of data versus NDC values.
#
# for i in xrange(len(x_out)):
#   print("%4d  data: (%3.0f, %8.4f)  NDC: (%6.4f, %6.4f)" % \
#                  (i,x_in[i],y_in[i],x_out[i],y_out[i]))

#
#  Draw some markers on the curve in the above plot.
#
Ngl.draw(xy)  #  Redraw the plot to start with.

#
#  Then draw markers.