# First let's create some data
npoints = 50
X = numpy.arrayrange(npoints, dtype='d')
X = X / float(npoints) * 2. * numpy.pi

Y1 = numpy.ma.sin(X)
Y2 = numpy.ma.cos(X)
Y3 = numpy.ma.tan(X)

# Now the real grace thing, plot the 2 on one graph and the diff on
# another graph

from genutil import xmgrace  # first we need to import xmgrace module

x = xmgrace.init()  # create our xmgrace object

# First let's set our graphs area
# graph 0, exist by default, but we need to add 1 graph, therefore:
x.add_graph()  # adds one graph to our graph list (x.Graph)

# Let's change the orientation of the page to portrait
x.portrait()

# Now let's set the area of graph 0
x.Graph[0].vymin = .55  # starts at 55% of the page
x.Graph[0].vymax = .9   # stops at 90% of the page
x.Graph[0].vxmin = .1  # starts at 10% of the page
x.Graph[0].vxmax = .75   # stops at 75% of the page
# and the area of graph 1
x.Graph[1].vymin = .1  # starts at 10% of the page
Exemple #2
0
TEMPDIR = './'

# First let's create some data
npoints=50
X=numpy.ma.arrayrange(npoints,dtype=numpy.float)
X=X/float(npoints)*2.*numpy.pi

Y1=numpy.ma.sin(X)
Y2=numpy.ma.cos(X)
Y3=numpy.ma.tan(X)

# Now the real grace thing, plot the 2 on one graph and the diff on another graph

from genutil import xmgrace # first we need to import xmgrace module

x=xmgrace.init() # create our xmgrace object

# First let's set our graphs area
# graph 0, exist by default, but we need to add 1 graph, therefore:
x.add_graph() # adds one graph to our graph list (x.Graph)

# Let's change the orientation of the page to portrait
x.portrait()

# Now let's set the area of graph 0
x.Graph[0].vymin=.55  # starts at 55% of the page
x.Graph[0].vymax=.9   # stops at 90% of the page
x.Graph[0].vxmin=.1  # starts at 10% of the page
x.Graph[0].vxmax=.75   # stops at 75% of the page
# and the area of graph 1
x.Graph[1].vymin=.1 # starts at 10% of the page
def genBarDiagrams(var, path, hours, outpath=None, bargap=0.28, barwidth=0.8,
                                                             yticdiff=0.25):
    """
    :func:`genBarDiagrams`: It should generate the least directory hierarichy
        structure of season statiscore in the plotsgraphspath by score name.
        It will plots score values in xmgrace as bar diagram and save it
        inside the appropirate directory, by reading the nc file of the
        appropirate process season Region statiscore files path.

        It should plot for all the vars of that statiscore nc files.

    Inputs : var is the variable name. If var is 'all' means, then it should
             plot the bar diagram for all the available variables in the passed
             path nc or xml file.

             path is an absolute nc or xml file path.

             outpath is the path to store the images. If it is None means, it
             should create the least (plotname)directory in the current
             directory path itself and save it.

             bargap is the value of the gap ratio in between each bars of each
             threshold in xaxis of score bar diagram.

             barwidth is the width of the each bar in xaxis of the score
             bar diagram.

             yticdiff is the difference of the tic levels in y axis of the
             bar diagram.


    Written By : Dileep Kumar.R, Arulalan.T

    Updated on : 28.09.2011

    """

    f = cdms2.open(path)
    filelist = path.split('/')[-1].split('_')
    seamon = filelist[-3].upper()
    # modelname
    modelname = filelist[-1].split('.')[0].upper()
    # year
    year = filelist[-2]
    # region
    regionName = filelist[-4]
    allvars = None
    if var == 'all':
        # var is all. So we have to take all the vars from passed ncpath.
        allvars = [var for var in f.listvariable() if not var.startswith('bounds')]
    else:
        if isinstance(var, list):
            allvars = var
        else:
            allvars = [var]

    if not outpath:
        # get the current workig directory
        outpath = os.getcwd()

    # setting some intelligent to set xaxis values and its labels depends on
    # no of threshold dynamically
    xdic = {}
    xval = []
    sno = 0
    i = 0
    while(i< len(threshold)):
        if sno % 2:
            # set xaxis threshold string
            xdic[sno] = str(threshold[i])
            i += 1
            xval.append(sno)
        else:
            # set xaxis empty string
            xdic[sno] = ''
        # end of if sno % 2:
        sno += 1
    # end of while(i< len(threshold)):
    # set final xaxis empty string
    xdic[sno] = ''
    # xaxis numpy value
    xval = numpy.array(xval)
    # xlist to set xaxis scales min, max value in xmgrace
    xlist = xdic.keys()
    xlist.sort()

    # make hours as int type and do sort
    hours = [int(hr) for hr in hours]
    hours.sort()
    # calculation and generating x axis shift alignments scales for
    # multiple hours bar for single threshold.
    # i.e. setting gap b/w each vertical bar for all the threshold(xaxis)bars
    rem = len(hours) / 2
    leng = rem * bargap
    bar_shift_list = numpy.arange(-leng, leng + bargap, bargap)
    bar_shift_list = [round(shift, 3) for shift in bar_shift_list]
    if len(hours) < len(bar_shift_list):
        centerindex = len(bar_shift_list) / 2
        bar_shift_list.remove(bar_shift_list[centerindex])
    # end of if len(hours) < len(bar_shift_list):

    # make fcst hour name in legend
    legendNames = []
    for hr in hours:
        day = hr / 24.0
        # keep as float if day is not 24's multiple
        if not hr % 24.0:
            day = int(day)
        day = 'D' + str(day)
        legendNames.append(day)
    # end of for hr in hours:

    # colorList is the list of colors of different bars corresponds
    # to forcast hours
    colorList = ['black', 'red', 'green', 'orange', 'maroon', 'blue', '	turquoise']
    org_yticdiff = yticdiff
    for varName in allvars:
        scoreName = varName.upper()
        # make reduce the yaxis tic lables for some scores
        if scoreName in ['ODR']:
            org_yticdiff = yticdiff
            yticdiff = yticdiff * 2
        else:
            # for other scores maintain the function definition value for
            # yticdiff variable
            yticdiff = org_yticdiff
        # create plot name directory if it is not exists
        scoreNamePath = createDirsIfNotExists(outpath, scoreName)
        # get the score data
        score = f(varName)

        try:
            title_string = score.long_name
        except:
            title_string = score.id

        # for condition checking purpose we get the data alone.
        nscore = numpy.array(score)

        # setting y axis min and max values depends upon the min, max of score
        if (numpy.min(nscore) < 0):
            Y_axis_min = int(numpy.min(nscore)) - yticdiff
        else:
            Y_axis_min = 0
        # end of if (numpy.min(nscore) < 0):
        if (numpy.max(nscore) > 1):
            Y_axis_max = int(numpy.max(nscore)) + 1
        else:
            Y_axis_max = 1
        # end of if (numpy.max(nscore) > 1):

        # setting y axis lables dynamically by find round max of score
        if Y_axis_max >= 1e+20:
            Y_second_max = numutils.nextmax(nscore)
            ydicmax = round(Y_second_max, 2)
        else:
            # change the max level into next to make good view in y axis
            Y_axis_max = Y_axis_max + yticdiff
            ydicmax = Y_axis_max
        ydicmax = (ydicmax-(ydicmax % yticdiff)) + yticdiff
        # get the min value of score
        ydicmin = nscore.min()

        if ydicmin < 0:
            if ydicmin == -1e+20:
                ydicmin = numutils.nextmin(nscore)
            # -ve value
            # adjust min value by rounding w.r.t yticdiff
            Y_axis_min = (ydicmin-(ydicmin % yticdiff)) - yticdiff
        else:
            Y_axis_min = 0
        Y_second_min = ydicmin
        # generate the ydic values
        ydicval = numpy.arange(Y_axis_min, ydicmax + yticdiff, yticdiff)

        ydic = {}
        for val in ydicval:
            ydic[val] = str(val)
        # setting some intelligent to set infinity in y axis label with
        # one interval after the second max of y axis
        if Y_axis_max >= (1e+20) or Y_axis_min <= (-1e+20):
            # setting infinity value
            ydicindex = ydic.keys()
            ydicindex.sort()
            for y in ydicindex:
                if y >= Y_second_max:
                    Y_axis_max = y + yticdiff
                    # add one more y axis label at next to next max val
                    # of yaxis scale
                    ydic[Y_axis_max] = str(Y_axis_max)
                    # set yaxis max val in yaxis lable for infinity case
                    Y_axis_max += yticdiff
                    # break
                # end of if y >= Y_second_max:
                if y <= Y_second_min:
                    Y_axis_min = y - yticdiff
                    # add one more y axis label at next to next max val
                    # of yaxis scale
                    ydic[Y_axis_min] = str(Y_axis_min)
                    # set yaxis max val in yaxis lable for infinity case
                    Y_axis_min -= yticdiff
                # end of if y >= Y_second_max:
            # end of for y in ydicindex:
            # change the y axis max val label by 'Infinity' for 1e+20 val in
            # score value
            ydic[Y_axis_max] = 'Infinity'
            ydic[Y_axis_min] = '-Infinity'
        # end of if Y_axis_max >= (1e+20):

        x = xmgrace.init()
        x.Graph[0].vymin = .20
        x.Graph[0].vymax = .90
        x.Graph[0].vxmin = .15
        x.Graph[0].vxmax = .88
        x.Graph[0].bar_hgap = 1
        x.Graph[0].status = 'on'

        x.Graph[0].title = title_string + ' ' + modelname + ' ' + year
        x.Graph[0].stitle = regions.get(regionName) + ' ' + seamon
        # ymin for graph 0
        x.Graph[0].yaxis.min = Y_axis_min
        # ymax for graph 0
        x.Graph[0].yaxis.max = Y_axis_max
        # Main tick every unit
        x.Graph[0].yaxis.tick.inc = 1
        # 4 sub in between, 1 every .25 units
        x.Graph[0].yaxis.tick.minor_ticks = 1
        x.Graph[0].yaxis.bar.status = 'on'
        # setting min value of x axis
        x.Graph[0].xaxis.min = xlist[0]
        # setting max value of x axis
        x.Graph[0].xaxis.max = xlist[-1]

        x.Graph[0].xaxis.tick.spec.loc = xdic
        x.Graph[0].xaxis.tick.label.char_size = .6
        x.Graph[0].xaxis.tick.orientation = 'out'
        x.Graph[0].xaxis.label = 'Rainfall Threshold (cm)'
        x.Graph[0].yaxis.tick.spec.loc = ydic
        x.Graph[0].yaxis.tick.label.char_size = .6
        x.Graph[0].yaxis.tick.orientation = 'out'

        x.Graph[0].yaxis.label = title_string
        x.Graph[0].legend.char_size = .7
        x.Graph[0].legend.x = .9  # Legend at 90% in x
        x.Graph[0].legend.y = .8  # Legend at 80% in y

        for setno in range(len(hours)):
            if setno != 0:
                x.add_set(0)
            # set bar type
            x.Graph[0].Set[setno].type = 'bar'
            # Set width of bar
            #x.Graph[0].Set[setno].symbol.size = 1.03
            x.Graph[0].Set[setno].symbol.size = barwidth
            # Set Color
            x.Graph[0].Set[setno].fill.color = colorList[setno]
            # Switch offing the line which connected on all the bars top edge
            x.Graph[0].Set[setno].line.type = 0
            # Setting the legend
            x.Graph[0].Set[setno].legend = legendNames[setno]
            # add the bar_shift_list elements to all the element of threshold
            xshiftval = xval + bar_shift_list[setno]
            # x axis values
            xshiftval = numpy.ma.array(xshiftval)
            # y axis values
            yval = numpy.ma.array(score(fcsthour = hours[setno])).squeeze()
            # Some statistical score takes values -1e+20, for plotting itmakes
            # some problem, threfore we are going to change -1e+20 as 0
            # (Theoriticaly it is not correct)
            # yval = numpy.ma.where(yval !=-1e+20, yval, 0)
            yval = numpy.ma.where(yval !=-1e+20, yval, Y_axis_min)
            # plot in xmgrace in the corresponding set of graph
            x.plot(yval, xshiftval, G = 0, S = setno)
            x.update()
        # end of for setno in range(len(hours)):

        output_filename = "%s_%s_of_%s_Region_%s_%s.jpg" % (modelname,
                                        scoreName, regionName, seamon, year)
        output_filename = scoreNamePath + '/' + output_filename
        x.jpeg(output_filename, color = 'color', quality = 80, dpi = 300,
                                         smoothing = 0, baseline = 'off')
    # end of for var in allvars:
    f.close()
Exemple #4
0
def phase2d(xdata, ydata, sxyphase, dmin=None, dmax=None, colors=['red'],
            tcomment='', bcomment='', lcomment='', rcomment='',
            title='Phase Diagram', stitle1='', stitle2='', ctitle='Weak',
            pposition1=None, pdirection='anticlock', plocation='in', mintick=0):
    """
    phase2d : This will allow user to plot the 2 dimensional line plot in
              circular path among 8 phases. Also named as phase space diagram.

    Inputs:
        xdata : single dimensional xaxis dataset.
                eg : normalized pc1 time series
        ydata : single dimensional yaxis dataset.
                eg : normalized pc2 time series
                Both xdata & ydata should be continous time series dataset.

        xdata.id and ydata.id will be set as xaxis & yaxis label.

        dmin : data min - xaxis and yaxis minimum scale/label value.
               It must be -ve.
        dmin : data max - xaxis and yaxis maximum scale/label value.
               It must be +ve.
               By default both dmin, dmax takes as None. If it is None, then
               this function will automatically find out the min & max from
               the xdata & ydata. Finally set dmin = -dmax. So that we will
               get squared region.

        colors : phase line colors. It should be eithre string or list of
                 colors. If it is string or single color list, the it will
                 apply that color through out the data line in the graph.
                 If user passed it as list of colors (more than one colors)
                 then it will apply those colors to the available months data
                 set. So make sure that your colorlist and available months
                 length should be same.

        tcomment : Top Comment
        bcomment : Bottom Comment
        lcomment : Left Comment
        rcomment : Right Comment
        title : Title of the diagram
        stitle1 : Sub Title 1 - By default it will draw string as start year
                  and end year from the xdata.
        stitle2 : Sub Title 2 - By default it will draw string as season of
                  available months (from startmonth to endmonth).
                  User can overwrite the stitle1 & stitle2 strings.
        ctitle : Centred Title or text inside the circle.

        sxyphase : start x, y phase - start x,y points of xdata, ydata phase
                   number. So user can pass the phase number of the starting
                   points of the whole data (xdata, ydata). With depends upon
                   pdirection it will be draw the phase name over the 8
                   half quadrants of the graph. User no need to pass phase
                   numbers for the whole datasets (xdata, ydata). Just pass
                   the first or start day of season phase alone. User can use
                   pposition1 argument also instead of sxyphase argument.
                   No default argument takes place here. So user must pass
                   argument to this sxyphase arg. If user need to use
                   pposition1 arg, then they must pass None to this sxyphase
                   argument.

        pposition1 : phase position 1 - Lets understand the distribution of
                    8 phases. Lets consider from 0 to 45 degree region as
                    phase position 1 (pposition1).From 45 to 90 degree region
                    as phase position 2(pposition2) and so on. So if we walk
                    in anti-clock wise direction we will endup with pposition8
                    in the region of 315 to 360 degree.
                        User can pass argument to pposition1 as integer from
                    1 to 8. So whatever user passed in the pposition1 phase
                    number, that phase no string will be draw within in range
                    from 0 to 45 degree.
                       eg : pposition1=5 . i.e. phase name 'PHASE 5' will be
                            drawn in the 0 to 45 degree region of the graph.

                       By default it takes None argument.

                    ..note:: User can not use both sxyphase and pposition1
                             args. Can be used either sxyphase or pposition1
                             only.

        pdirection : phase direction - It can be either 'clock' or 'anticlock'
                     It will determine what is the phase number in the
                     pposition2, pposition3, ..., pposition8 w.r.t the input
                     of pposition1 argument or sxyphase and clock/anticlock
                     direction.
                     eg 1: pposition1 = 5, pdirection = 'anticlock'
                       pposition1=5, pposition2=6, pposition3=7, pposition4=8,
                       pposition5=1, pposition6=2, pposition7=3, pposition8=4.

                     i.e. w.r.t pposition1 as 5 and pdirection as 'anticlock'
                          the phase names of the rest phase positions are
                        determined as increment trend of pnames in ppositions.

                   eg 2: pposition1 = 5, pdirection = 'clock'
                       pposition1=5, pposition2=4, pposition3=3, pposition4=2,
                       pposition5=1, pposition6=8, pposition7=7, pposition8=6.

                     i.e. w.r.t pposition1 as 5 and pdirection as 'clock'
                          the phase names of the rest phase positions are
                        determined as decrement trend of pnames in ppositions.

                     same examples we can play with sxyphase also.

        plocation : It takes input as 'in/inside/out/outside'. If it is
                    'in' or 'inside', then the phase name/number will be drawn
                    inside the squared graph itself.
                    If it is 'out' or 'outside', then the phase name/number
                    will be drawn outside the squared graph.
        mintick : minor ticks count. By default it takes as 0. user can pass 4
                  also.

    Methods Used : _sortMonths, getTimeAxisMonths, getHalfQuadrantOfCircle

    Return :
        It should return the 'x' of the xmgrace object which has plotted the
        data with this MJO args. User can either save it into ps, pdf, etc.,
        or modify/update further.

    Author : Arulalan.T

    Date : 20.02.2013

    License : GPL V3

    """

    if sxyphase and pposition1:
        raise ValueError("pass either sxyphase or pposition1 argument.\
                                                Dont pass both args!")
    if not sxyphase and not pposition1:
        raise ValueError("You must pass either sxyphase or pposition1 argument")
    if sxyphase:
        if not isinstance(sxyphase, int):
            raise ValueError("sxyphase argument must be integer type")
        if sxyphase < 1 or sxyphase > 8:
            raise ValueError("sxyphase argument must be within 1 to 8 only!")
    elif pposition1:
        if not isinstance(pposition1, int):
            raise ValueError("pposition1 argument must be integer type")
        if pposition1 < 1 or pposition1 > 8:
            raise ValueError("pposition1 argument must be within 1 to 8 only!")

    # create our xmgrace object
    x = xmgrace.init()
    x.portrait()

    # Now let's set the area of graph 0
    x.Graph[0].vymin = .20  # starts at 55% of the page
    x.Graph[0].vymax = .75   # stops at 90% of the page
    x.Graph[0].vxmin = .15  # starts at 10% of the page
    x.Graph[0].vxmax = .90   # stops at 75% of the page

    if not (dmin and dmax):
        # user not passed the data min & data max values.
        # So what, lets find it !
        xmin, xmax = min(xdata), max(xdata)
        ymin, ymax = min(ydata), max(ydata)
        dmin = min([xmin, ymin])
        dmax = max([xmax, ymax])
        if abs(dmin) == abs(dmax):
            dmax = round(dmax) + 1
        else:
            dmax = round(max([abs(dmin), abs(dmax)])) + 1
        # end of if abs(umin) == abs(umax):
        dmin = -dmax
    # end of if not (min and max):

    # ok now let's set the min ans max for the Y axis
    x.Graph[0].yaxis.min = dmin  # ymin for graph 0
    x.Graph[0].yaxis.max = dmax  # ymax for graph 0

    # Now let's set the tick marks for Graph 0
    x.Graph[0].yaxis.tick.inc = 1   # Main tick every unit
    x.Graph[0].yaxis.tick.minor_ticks = mintick

    # ok now let's set the min ans max for the X axis
    x.Graph[0].xaxis.min = dmin  # xmin for graph 0
    x.Graph[0].xaxis.max = dmax  # xmax for graph 0

    # Now let's set the tick marks for Graph 0
    x.Graph[0].xaxis.tick.inc = 1  # Main tick every unit
    x.Graph[0].xaxis.tick.minor_ticks = mintick

    for setno in range(4):
        if setno != 0:
            # adding set to graph 0 to add lines
            x.add_set(graph=0)
        # end of if setno != 0:
        # First let's set the line width, style, color
        x.Graph[0].Set[setno].line.linewidth = 1
        x.Graph[0].Set[setno].line.color = 'black'
        x.Graph[0].Set[setno].line.linestyle = 'solid'
    # end of for setno in range(4):

    # line co-ordinates points
    p1 = [0, 0]
    p2 = [dmin, dmax]
    p3 = [dmax, dmin]
    # line x, y co-ordinates
    lines1 = [p1, p2, p2, p2]
    lines2 = [p2, p1, p2, p3]
    # plotting + and x cross lines to connect all the corners of the graph.
    x.plot(lines1, xs=lines2)

    # adding set to graph 0 to add the centred circle
    csetno = setno + 1
    x.add_set(graph=0)
    # set centred circle properties
    x.Graph[0].Set[csetno].symbol.type = 1
    # circle should follow its path on these conditions/points
    # (x=1, y=0),(x=-1, y=0),(x=0,y=1),(x=0,y=-1).
    # We set size of the circle according to the above rules!
    x.Graph[0].Set[csetno].symbol.size = 9.175
    x.Graph[0].Set[csetno].symbol.color = 'black'
    x.Graph[0].Set[csetno].symbol.fcolor = 'white'
    x.Graph[0].Set[csetno].symbol.linestyle = 1
    x.Graph[0].Set[csetno].symbol.linewidth = 1
    # plotting the centred circle
    x.plot([[0]], G=0, S=csetno)

    # to point the starting day of event, set its x, y, color properties
    start_x = 0
    start_y = 0
    start_clr = 'red'

    # plot type
    if isinstance(colors, str):
        ptype = 'single'
        start_clr = colors
    elif (isinstance(colors, (list, tuple)) and len(colors) == 1):
        ptype = 'single'
        start_clr = colors[0]
    elif len(colors) > 1:
        ptype = 'multi'
        avlColors = colors
    # end of if isinstance(colors, str):

    if ptype == 'single':
        csetno = csetno + 1
        x.add_set(graph=0)
        # set the line properties color & inter points color, size
        x.Graph[0].Set[csetno].line.linewidth = 1
        x.Graph[0].Set[csetno].line.color = start_clr
        x.Graph[0].Set[csetno].line.linestyle = 'solid'
        x.Graph[0].Set[csetno].symbol.type = 1
        x.Graph[0].Set[csetno].symbol.size = 0.125
        x.Graph[0].Set[csetno].symbol.color = start_clr
        # plotting the xdata, ydata in circle manner
        x.plot(ydata, xs=xdata, G=0, S=csetno)
        # to point the starting day of event by filled color square symbol
        # set its start_x, start_y
        start_x = xdata[0]
        start_y = ydata[0]

    elif ptype == 'multi':
        # available months in dictionary format contains years, month string
        # and dates
        xtimeAxis = xdata.getTime()
        ytimeAxis = ydata.getTime()
        if xtimeAxis[:].tolist() != ytimeAxis[:].tolist():
            raise ValueError("xdata (%s), ydata (%s) time axis are not same!"
                                                     % (xdata.id, ydata.id))
        # end of if xtimeAxis[:].tolist() != ytimeAxis[:].tolist():
        cdutil.setAxisTimeBoundsDaily(xtimeAxis)
        avlMonths = timobj.getTimeAxisMonths(xtimeAxis)
        avlMonthsList = []

        for year in avlMonths:
            months = avlMonths[year].keys()
            # sort the month string
            months = timobj._sortMonths(months)
            for mon in months:
                avlMonthsList.append((mon, avlMonths[year][mon]))
            # end of for mon in months:
        # end of for year in avlMonths:

        # innter lock connection months
        conMonths = []
        # now lets do innter lock connection between months last & first date
        preMonthLastDate = None
        for idx, (mon, (fdate, ldate)) in enumerate(avlMonthsList):
            if idx == 0:
                conMonths.append((mon, (fdate, ldate)))
            else:
                # previous month's last date as first day of this month &
                # this month last date for the purpose of continous line plot
                # while changing colors for different months.
                conMonths.append((mon, (preMonthLastDate, ldate)))
            # end of if idx == 0:
            preMonthLastDate = ldate
        # end of for idx, fdate, ldate in enumerate(avlMonthsList):
        # make memory free
        del avlMonths, avlMonthsList

        # month string x position to indicate below the graph with
        # corresponding line color
        monx = 0.4
        for montime, colr in zip(conMonths, avlColors):
            # get the month name string
            mon = montime[0]
            # month first last component time object date
            monFLDate = montime[1]
            # get the current month pc1 and pc2 data
            pc1 = xdata(time=monFLDate)
            pc2 = ydata(time=monFLDate)
            if monx == 0.4:
                # do it only one time, assign the first day of first month to
                # start_x, start_y, color to point the starting day of event
                # by filled color square symbol
                start_x = pc1[0]
                start_y = pc2[0]
                # set the starting color as begining of multi color list
                start_clr = colr
            # end of if monx == 0.4:
            csetno = csetno + 1
            x.add_set(graph=0)
            # set the line properties color & inter points color, size
            # for this month dataset
            x.Graph[0].Set[csetno].line.linewidth = 1
            x.Graph[0].Set[csetno].line.color = colr
            x.Graph[0].Set[csetno].line.linestyle = 'solid'
            x.Graph[0].Set[csetno].symbol.type = 1
            x.Graph[0].Set[csetno].symbol.size = 0.125
            x.Graph[0].Set[csetno].symbol.color = colr
            # plotting the xdata, ydata in circle manner
            x.plot(pc2, xs=pc1, G=0, S=csetno)
            # darw the month string with same as color of that month line
            # color to indicate monthly event
            x.add_string(monx, 0.09, mon[:3], color=colr,
                            char_size=0.6, rot=0, just=14)
            # increment the month string position
            monx += 0.05
        # end of for mon, colr in zip(conMonths, avlColors):
    else:
        raise ValueError("Wrong plot '%s' type has passed. \
                          Pass either 'single' or 'multi'" % ptype)
    # end of if ptype == 'single':

    # adding set to draw a small square symbol at the begining of the season.
    # it must be square symbol only. Becuause we can not plot this symbol
    # out side of the graph, using viewport.
    csetno = csetno + 1
    x.add_set(graph=0)
    x.Graph[0].Set[csetno].symbol.type = 2  # 'square' type
    x.Graph[0].Set[csetno].symbol.size = 0.45
    x.Graph[0].Set[csetno].symbol.color = start_clr
    x.Graph[0].Set[csetno].symbol.fcolor = start_clr
    x.plot([[start_y]], [[start_x]], G=0, S=csetno)

    # Since we can not use viewport to plot the symbol to indicate what the
    # above square symbol meant to be, here we are using add_box function to
    # draw a small square below the graph with text 'Start day of season'.
    x.add_box(0.75, 0.158, 0.758, 0.164, color=start_clr, fillcolor=start_clr)
    # drawing the text behind to the above small square box
    x.add_string(0.83, 0.16, 'Start day of season', color='black',
                                    char_size=0.6, rot=0, just=14)
    # draw the xdata id as xaxis label
    x.add_string(0.53, 0.16, xdata.id, color='black', char_size=0.7,
                                                     rot=0, just=14)
    # draw the ydata id as yaxis label
    x.add_string(0.10, 0.48, ydata.id, color='black', char_size=0.7,
                                                    rot=90, just=14)
    # draw the bottom comment
    x.add_string(0.53, 0.13, bcomment, color='blue', char_size=1.3,
                                                     rot=0, just=14)
    # draw the top comment
    x.add_string(0.53, 0.81, tcomment, color='blue', char_size=1.3,
                                                     rot=0, just=14)
    # draw the left comment
    x.add_string(0.06, 0.48, lcomment, color='blue', char_size=1.3,
                                                    rot=90, just=14)
    # draw the right comment
    x.add_string(0.97, 0.48, rcomment, color='blue', char_size=1.3,
                                                   rot=270, just=14)

    # phase quadrant/positions no, and its x, y coordinate points to draw
    # phase name inside the graph
    phases_loc_in = ((1, (2.5, 1)), (2, (1, 3.5)), (3, (-2, 3.5)),
                  (4, (-3.5, 1)), (5, (-3.5, -1)), (6, (-2, -3.5)),
                  (7, (1, -3.5)), (8, (2.5, -1)))
    # phase quadrant/positions no, its x, y coordinate points to draw
    # phase name and its rotation(direction) outside the graph
    phases_loc_out = ((1, (4.25, 2.5), 270), (2, (1, 4.25), 0),
        (3, (-2, 4.25), 0), (4, (-4.5, 1.5), 90), (5, (-4.5, -2.5), 90),
        (6, (-2, -4.65), 0), (7, (1, -4.65), 0), (8, (4.25, -1.5), 270))

    # general phase sequence
    phase_sequence = range(1, 9)

    if sxyphase:
        # passed start x, y points of xdata, ydata phase name/number.
        # assign the above phase name/number of start x, y points
        # of xdata, ydata
        pos = sxyphase
        # get the actual half quadrant of the circle of the start x, y points
        # of xdata, ydata. subtract 1 for python index access of list.
        hq = trig.getHalfQuadrantOfCircle(start_x, start_y) - 1
        # reorder the phase_sequence w.r.t starting x,y points of xdata,ydata
        phase_sequence = phase_sequence[hq:] + phase_sequence[:hq]
    elif pposition1:
        # passed phase name/number of pposition1 or first positive half
        # quadrant of the circle region phase name/number
        # assign the first position phase number as passed by user arg
        pos = pposition1
    # end of if sxyphase:

    phases_name = {}
    if pdirection in ['clock', 1]:
        # for clock wise phase increment should be -ve w.r.t phase positions
        inc = -1
    elif pdirection in ['aclock', 'anticlock', -1]:
        # for anti-clock wise phase increment should be +ve w.r.t
        # phase positions
        inc = 1
    else:
        raise ValueError("Wrong pdirection '%s' has passed.\
                pass either 'clock' or 'anticlock'" % pdirection)
    # end of if pdirection in ['clock', 1]:

    # loop through phase positions from 1 to 8.
    for phase_position in phase_sequence:
        # assign the phase name to the corresponding phase position as per
        # user input for the pposition1.
        phases_name[phase_position] = 'PHASE ' + str(pos)
        # if phase name is reached 8, then next phase name should be 1 in
        # case of anticlock wise direction. inc will take care of the below
        # pos = 0 to convert pos = 1.
        if pos == 8 and inc == 1: pos = 0
        # if phase name is reached 1, then next phase name should be 8 in
        # case of clock wise direction. inc will take care of the below
        # pos = 9 to convert pos = 8.
        if pos == 1 and inc == -1: pos = 9
        # either increment or decrement w.r.t clock/anticlock wise direction
        pos += inc
    # end of for phase_position in phase_sequence:

    # draw strings/names of 8 phases inside/outside of the graph
    if plocation in ['in', 'inside']:
        for (idx, (px, py)) in phases_loc_in:
            pname = phases_name[idx]
            # to plot the string w.r.t some x, y position justification
            # must be 0 and location type must be world.
            x.add_string(px, py, pname, color='black',
                         char_size=0.8, rot=0, just=0)
            # make the loctype as world to recently added string
            # (i.e. the above string added)
            x.String[-1].loctype = 'world'
        # end of for (idx, (px, py)) in phases_loc:
    elif plocation in ['out', 'outside']:
        for (idx, (px, py), r) in phases_loc_out:
            pname = phases_name[idx]
            # to plot the string outside with rotation
            x.add_string(px, py, pname, color='black',
                         char_size=0.8, rot=r, just=0)
            x.String[-1].loctype = 'world'
        # end of for (idx, (px, py), r) in phases_loc_out:
    else:
        raise ValueError("Wrong plocation '%s' has passed.\
                    pass either 'in' or 'out'" % plocation)
    # end of if plocation in ['in', 'inside']:

    # set the subtitle1 as year if user not passed
    st1x = 0.76
    if not stitle1:
        if ptype == 'single':
            taxis = xdata.getTime().asComponentTime()
            syear, eyear = taxis[0].year, taxis[-1].year
            # make memory free
            del taxis
        elif ptype == 'multi':
            syear, eyear = conMonths[0][1][0].year, conMonths[-1][1][0].year
        # end of if ptype == 'single':
        stitle1 = 'Year : %d' % syear
        if syear < eyear:
            stitle1 += ' to %d' % eyear
            st1x = 0.795
    # end of if not stitle1:

    # set the subtitle2 as season months if user not passed
    if not stitle2:
        if ptype == 'single':
            taxis = xdata.getTime().asComponentTime()
            smon = cdutil.getMonthString(taxis[0].month)
            emon = cdutil.getMonthString(taxis[-1].month)
            # make memory free
            del taxis
            stitle2 = 'Season : %s to %s' % (smon.capitalize()[:3],
                                             emon.capitalize()[:3])
        elif ptype == 'multi':
            stitle2 = 'Season : %s to %s' % (conMonths[0][0].capitalize()[:3],
                                         conMonths[-1][0].capitalize()[:3])
    # end of if not stitle2:
    # draw the title, subtitle1 and subtitle2
    x.add_string(0.52, 0.9, title, color='black', char_size=1.5, rot=0, just=14)
    x.add_string(st1x, 0.86, stitle1, color='black', char_size=0.8, rot=0, just=14)
    x.add_string(0.8, 0.84, stitle2, color='black', char_size=0.8, rot=0, just=14)
    # draw the centred title / circle title
    x.add_string(0, 0, ctitle, color='black', char_size=0.8, rot=0, just=14)
    x.String[-1].loctype = 'world'
    # update the x to plot all the strings
    x.update()
    return x
Exemple #5
0
def genBarDiagrams(var,
                   path,
                   hours,
                   outpath=None,
                   bargap=0.28,
                   barwidth=0.8,
                   yticdiff=0.25):
    """
    :func:`genBarDiagrams`: It should generate the least directory hierarichy
        structure of season statiscore in the plotsgraphspath by score name.
        It will plots score values in xmgrace as bar diagram and save it
        inside the appropirate directory, by reading the nc file of the
        appropirate process season Region statiscore files path.

        It should plot for all the vars of that statiscore nc files.

    Inputs : var is the variable name. If var is 'all' means, then it should
             plot the bar diagram for all the available variables in the passed
             path nc or xml file.

             path is an absolute nc or xml file path.

             outpath is the path to store the images. If it is None means, it
             should create the least (plotname)directory in the current
             directory path itself and save it.

             bargap is the value of the gap ratio in between each bars of each
             threshold in xaxis of score bar diagram.

             barwidth is the width of the each bar in xaxis of the score
             bar diagram.

             yticdiff is the difference of the tic levels in y axis of the
             bar diagram.


    Written By : Dileep Kumar.R, Arulalan.T

    Updated on : 28.09.2011

    """

    f = cdms2.open(path)
    filelist = path.split('/')[-1].split('_')
    seamon = filelist[-3].upper()
    # modelname
    modelname = filelist[-1].split('.')[0].upper()
    # year
    year = filelist[-2]
    # region
    regionName = filelist[-4]
    allvars = None
    if var == 'all':
        # var is all. So we have to take all the vars from passed ncpath.
        allvars = [
            var for var in f.listvariable() if not var.startswith('bounds')
        ]
    else:
        if isinstance(var, list):
            allvars = var
        else:
            allvars = [var]

    if not outpath:
        # get the current workig directory
        outpath = os.getcwd()

    # setting some intelligent to set xaxis values and its labels depends on
    # no of threshold dynamically
    xdic = {}
    xval = []
    sno = 0
    i = 0
    while (i < len(threshold)):
        if sno % 2:
            # set xaxis threshold string
            xdic[sno] = str(threshold[i])
            i += 1
            xval.append(sno)
        else:
            # set xaxis empty string
            xdic[sno] = ''
        # end of if sno % 2:
        sno += 1
    # end of while(i< len(threshold)):
    # set final xaxis empty string
    xdic[sno] = ''
    # xaxis numpy value
    xval = numpy.array(xval)
    # xlist to set xaxis scales min, max value in xmgrace
    xlist = xdic.keys()
    xlist.sort()

    # make hours as int type and do sort
    hours = [int(hr) for hr in hours]
    hours.sort()
    # calculation and generating x axis shift alignments scales for
    # multiple hours bar for single threshold.
    # i.e. setting gap b/w each vertical bar for all the threshold(xaxis)bars
    rem = len(hours) / 2
    leng = rem * bargap
    bar_shift_list = numpy.arange(-leng, leng + bargap, bargap)
    bar_shift_list = [round(shift, 3) for shift in bar_shift_list]
    if len(hours) < len(bar_shift_list):
        centerindex = len(bar_shift_list) / 2
        bar_shift_list.remove(bar_shift_list[centerindex])
    # end of if len(hours) < len(bar_shift_list):

    # make fcst hour name in legend
    legendNames = []
    for hr in hours:
        day = hr / 24.0
        # keep as float if day is not 24's multiple
        if not hr % 24.0:
            day = int(day)
        day = 'D' + str(day)
        legendNames.append(day)
    # end of for hr in hours:

    # colorList is the list of colors of different bars corresponds
    # to forcast hours
    colorList = [
        'black', 'red', 'green', 'orange', 'maroon', 'blue', '	turquoise'
    ]
    org_yticdiff = yticdiff
    for varName in allvars:
        scoreName = varName.upper()
        # make reduce the yaxis tic lables for some scores
        if scoreName in ['ODR']:
            org_yticdiff = yticdiff
            yticdiff = yticdiff * 2
        else:
            # for other scores maintain the function definition value for
            # yticdiff variable
            yticdiff = org_yticdiff
        # create plot name directory if it is not exists
        scoreNamePath = createDirsIfNotExists(outpath, scoreName)
        # get the score data
        score = f(varName)

        try:
            title_string = score.long_name
        except:
            title_string = score.id

        # for condition checking purpose we get the data alone.
        nscore = numpy.array(score)

        # setting y axis min and max values depends upon the min, max of score
        if (numpy.min(nscore) < 0):
            Y_axis_min = int(numpy.min(nscore)) - yticdiff
        else:
            Y_axis_min = 0
        # end of if (numpy.min(nscore) < 0):
        if (numpy.max(nscore) > 1):
            Y_axis_max = int(numpy.max(nscore)) + 1
        else:
            Y_axis_max = 1
        # end of if (numpy.max(nscore) > 1):

        # setting y axis lables dynamically by find round max of score
        if Y_axis_max >= 1e+20:
            Y_second_max = numutils.nextmax(nscore)
            ydicmax = round(Y_second_max, 2)
        else:
            # change the max level into next to make good view in y axis
            Y_axis_max = Y_axis_max + yticdiff
            ydicmax = Y_axis_max
        ydicmax = (ydicmax - (ydicmax % yticdiff)) + yticdiff
        # get the min value of score
        ydicmin = nscore.min()

        if ydicmin < 0:
            if ydicmin == -1e+20:
                ydicmin = numutils.nextmin(nscore)
            # -ve value
            # adjust min value by rounding w.r.t yticdiff
            Y_axis_min = (ydicmin - (ydicmin % yticdiff)) - yticdiff
        else:
            Y_axis_min = 0
        Y_second_min = ydicmin
        # generate the ydic values
        ydicval = numpy.arange(Y_axis_min, ydicmax + yticdiff, yticdiff)

        ydic = {}
        for val in ydicval:
            ydic[val] = str(val)
        # setting some intelligent to set infinity in y axis label with
        # one interval after the second max of y axis
        if Y_axis_max >= (1e+20) or Y_axis_min <= (-1e+20):
            # setting infinity value
            ydicindex = ydic.keys()
            ydicindex.sort()
            for y in ydicindex:
                if y >= Y_second_max:
                    Y_axis_max = y + yticdiff
                    # add one more y axis label at next to next max val
                    # of yaxis scale
                    ydic[Y_axis_max] = str(Y_axis_max)
                    # set yaxis max val in yaxis lable for infinity case
                    Y_axis_max += yticdiff
                    # break
                # end of if y >= Y_second_max:
                if y <= Y_second_min:
                    Y_axis_min = y - yticdiff
                    # add one more y axis label at next to next max val
                    # of yaxis scale
                    ydic[Y_axis_min] = str(Y_axis_min)
                    # set yaxis max val in yaxis lable for infinity case
                    Y_axis_min -= yticdiff
                # end of if y >= Y_second_max:
            # end of for y in ydicindex:
            # change the y axis max val label by 'Infinity' for 1e+20 val in
            # score value
            ydic[Y_axis_max] = 'Infinity'
            ydic[Y_axis_min] = '-Infinity'
        # end of if Y_axis_max >= (1e+20):

        x = xmgrace.init()
        x.Graph[0].vymin = .20
        x.Graph[0].vymax = .90
        x.Graph[0].vxmin = .15
        x.Graph[0].vxmax = .88
        x.Graph[0].bar_hgap = 1
        x.Graph[0].status = 'on'

        x.Graph[0].title = title_string + ' ' + modelname + ' ' + year
        x.Graph[0].stitle = regions.get(regionName) + ' ' + seamon
        # ymin for graph 0
        x.Graph[0].yaxis.min = Y_axis_min
        # ymax for graph 0
        x.Graph[0].yaxis.max = Y_axis_max
        # Main tick every unit
        x.Graph[0].yaxis.tick.inc = 1
        # 4 sub in between, 1 every .25 units
        x.Graph[0].yaxis.tick.minor_ticks = 1
        x.Graph[0].yaxis.bar.status = 'on'
        # setting min value of x axis
        x.Graph[0].xaxis.min = xlist[0]
        # setting max value of x axis
        x.Graph[0].xaxis.max = xlist[-1]

        x.Graph[0].xaxis.tick.spec.loc = xdic
        x.Graph[0].xaxis.tick.label.char_size = .6
        x.Graph[0].xaxis.tick.orientation = 'out'
        x.Graph[0].xaxis.label = 'Rainfall Threshold (cm)'
        x.Graph[0].yaxis.tick.spec.loc = ydic
        x.Graph[0].yaxis.tick.label.char_size = .6
        x.Graph[0].yaxis.tick.orientation = 'out'

        x.Graph[0].yaxis.label = title_string
        x.Graph[0].legend.char_size = .7
        x.Graph[0].legend.x = .9  # Legend at 90% in x
        x.Graph[0].legend.y = .8  # Legend at 80% in y

        for setno in range(len(hours)):
            if setno != 0:
                x.add_set(0)
            # set bar type
            x.Graph[0].Set[setno].type = 'bar'
            # Set width of bar
            #x.Graph[0].Set[setno].symbol.size = 1.03
            x.Graph[0].Set[setno].symbol.size = barwidth
            # Set Color
            x.Graph[0].Set[setno].fill.color = colorList[setno]
            # Switch offing the line which connected on all the bars top edge
            x.Graph[0].Set[setno].line.type = 0
            # Setting the legend
            x.Graph[0].Set[setno].legend = legendNames[setno]
            # add the bar_shift_list elements to all the element of threshold
            xshiftval = xval + bar_shift_list[setno]
            # x axis values
            xshiftval = numpy.ma.array(xshiftval)
            # y axis values
            yval = numpy.ma.array(score(fcsthour=hours[setno])).squeeze()
            # Some statistical score takes values -1e+20, for plotting itmakes
            # some problem, threfore we are going to change -1e+20 as 0
            # (Theoriticaly it is not correct)
            # yval = numpy.ma.where(yval !=-1e+20, yval, 0)
            yval = numpy.ma.where(yval != -1e+20, yval, Y_axis_min)
            # plot in xmgrace in the corresponding set of graph
            x.plot(yval, xshiftval, G=0, S=setno)
            x.update()
        # end of for setno in range(len(hours)):

        output_filename = "%s_%s_of_%s_Region_%s_%s.jpg" % (
            modelname, scoreName, regionName, seamon, year)
        output_filename = scoreNamePath + '/' + output_filename
        x.jpeg(output_filename,
               color='color',
               quality=80,
               dpi=300,
               smoothing=0,
               baseline='off')
    # end of for var in allvars:
    f.close()