Changeset 1542 in lmdz_wrf for trunk


Ignore:
Timestamp:
Apr 26, 2017, 12:11:53 AM (8 years ago)
Author:
lfita
Message:

Adding `draw_bar_time': Function to plot a bar char figure with multiple sources and time axis

Location:
trunk/tools
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/documentation/plotting/gallery.html

    r1540 r1542  
    1919      <A HREF="2Dshad_line_time.html"><IMG SRC="figs/hus-ps_vert-sec_shad-line_time.png" ALT="2D shadow line time" STYLE="float:left;width:200px;height:200px" TARGET="value"></IMG></A>
    2020      <A HREF="draw_bar.html"><IMG SRC="figs/bar_rain_CRU-NCEP_norm.png" ALT="bar char plot" STYLE="float:left;width:200px;height:200px" TARGET="value"></IMG></A>
     21      <A HREF="bar_time.html"><IMG SRC="figs/bar_time_rain_CRU-NCEP_DJFmean_norm.png" ALT="bar char plot time" STYLE="float:left;width:200px;height:200px" TARGET="value"></IMG></A>
    2122      <A HREF="barbs.html"><IMG SRC="figs/wind_barbs_2001111003_wss.png" ALT="wind-barbs" STYLE="float:left;width:200px;height:200px" TARGET="value"></IMG></A>
    2223      <A HREF="barbs.html"><IMG SRC="figs/wind_barbs_2001111003_uw.png" ALT="wind-barbs" STYLE="float:left;width:200px;height:200px" TARGET="value"></IMG></A>
  • trunk/tools/documentation/plotting/plotting.html

    r1540 r1542  
    1515      <A CLASS="lc" HREF="2Dshad_line_time.html" TARGET="value">2D shadow line time</A><BR>
    1616      <A CLASS="lc" HREF="draw_bar.html" TARGET="value">bar</A><BR>
     17      <A CLASS="lc" HREF="bar_time.html" TARGET="value">bar_time</A><BR>
    1718      <A CLASS="lc" HREF="barbs.html" TARGET="value">barbs</A><BR>
    1819      <A CLASS="lc" HREF="basins.html" TARGET="value">ORCHIDEE's basins</A><BR>
  • trunk/tools/drawing.py

    r1540 r1542  
    4444## e.g. # drawing.py -o draw_basins -f routing.nc -S '-5,5,42.,52.:l:rainbow,auto,auto:1,1000:True:True:True:ORCDHIEE|river-basins:png:basins_named:True' -v nav_lon,nav_lat,trip,basins
    4545## e.g. # drawing.py -o draw_river_desc -f river_desc.nc -S 'Y|lat|lat|-1,X|lon|lon|-1:red,green:Blues:cyl,l:ORCDHIEE|rivers:png:0:or_rivers:True' -v Amazon,Parana
    46 ## e.g. #drawing.py -f forcing_Amazonia.nc,forcing_Amazonia.nc -o draw_2lines_time -S 'tstep:Excts:Excts:exct,5,y;%Y:x:tas,wss:r,b:2.:-,-:None:,;,:WFD!forcing!evolution!at!Amazonia:year:0|12:../LaTeX/figs/forcing_Amazonia_tas-wss:png:yes' -v Tair,Wind
    47 ## e.g. #drawing.py -o draw_bar -f 'Forcing_rainstats_OKstomate_CRUNCEP_spinup_SESA_norm_meanstd_stat2.nc;time_counter,0@12@1;time_counter;rainnorm:Forcing_rainstats_OKstomate_CRUNCEP_spinup_SACZ_norm_meanstd_stat2.nc;time_counter,0@12@1;time_counter;rainnorm' -S 'Stringlist,%s,January@Feburary@March@Arpil@May@June@July@August@September@October@November@December,25,pretty,auto,auto,auto:time!since!1958-01-01:pr:y:seconds:mmd-1:SESA,SACZ:#AA0000,#0000AA:1000000.:normalized!evolution!of!precipitaion!with!CRU-NCEP!forcing:0|10:png:bar_rain_CRU-NCEP_norm:yes'
     46## e.g. # drawing.py -f forcing_Amazonia.nc,forcing_Amazonia.nc -o draw_2lines_time -S 'tstep:Excts:Excts:exct,5,y;%Y:x:tas,wss:r,b:2.:-,-:None:,;,:WFD!forcing!evolution!at!Amazonia:year:0|12:../LaTeX/figs/forcing_Amazonia_tas-wss:png:yes' -v Tair,Wind
     47## e.g. # drawing.py -o draw_bar -f 'Forcing_rainstats_OKstomate_CRUNCEP_spinup_SESA_norm_meanstd_stat2.nc;time_counter,0@12@1;time_counter;rainnorm:Forcing_rainstats_OKstomate_CRUNCEP_spinup_SACZ_norm_meanstd_stat2.nc;time_counter,0@12@1;time_counter;rainnorm' -S 'Stringlist,%s,January@Feburary@March@Arpil@May@June@July@August@September@October@November@December,25,pretty,auto,auto,auto:time!since!1958-01-01:pr:y:seconds:mmd-1:SESA,SACZ:#AA0000,#0000AA:1000000.:normalized!evolution!of!precipitaion!with!CRU-NCEP!forcing:0|10:png:bar_rain_CRU-NCEP_norm:yes'
     48## e.g. # drawing.py -o draw_bar_time -f 'Forcing_rainstats_OKstomate_CRUNCEP_spinup_SESA_DJFmean_norm_meanstd_stat2.nc;time_centered,-1;time_centered;rainnorm:Forcing_rainstats_OKstomate_CRUNCEP_spinup_SACZ_DJFmean_norm_meanstd_stat2.nc;time_centered,-1;time_centered;rainnorm' -S 'auto;pr;1;y;None;year|seconds!since!1958-01-01!00:00:00|exct,5,y|%Y;SESA,SACZ;#AA0000,#0000AA;10000000.;normalized!evolution!of!DJFmean!of!precipitaion!with!CRU-NCEP!forcing;0|10;png;bar_time_rain_CRU-NCEP_DJFmean_norm;yes'
     49
    4850
    4951
     
    8183# draw_2lines_time: Function to plot two time-lines in different axes (x/x2 or y/y2)
    8284# draw_bar: Function to plot a bar char figure with multiple sources
     85# draw_bar_time: Function to plot a bar char figure with multiple sources and time axis
    8386# draw_barbs: Function to plot wind barbs
    8487# draw_basins: Function to plot river basins with their discharge vector and basins id (from 'routing.nc')
     
    112115  'draw_2D_shad_cont', 'draw_2D_shad_2cont', 'draw_2D_shad_cont_time',               \
    113116  'draw_2D_shad_line',                                                               \
    114   'draw_2D_shad_line_time', 'draw_bar', 'draw_barbs', 'draw_basins',                 \
     117  'draw_2D_shad_line_time', 'draw_bar', 'draw_bar_time', 'draw_barbs',               \
     118   'draw_basins',                                                                    \
    115119  'draw_2lines', 'draw_2lines_time', 'draw_lines', 'draw_lines_time',                \
    116120  'draw_Neighbourghood_evol',                                                        \
     
    65766580    return
    65776581
     6582def draw_bar_time(ncfile, values):
     6583    """ Function to plot a bar char figure with multiple sources and time-axis
     6584      ncfile = ':' list of [filen];[dimslice];[tvarn];[yvarn]
     6585        [filen]: name of the file
     6586        [dimslice]: '|' list of [dimn],[dimrange]
     6587          [dimn]: name of the dimension
     6588          [dimrange]: range for the slice
     6589            * [integer]: which value of the dimension
     6590            * -1: all along the dimension
     6591            * -9: last value of the dimension
     6592            * [beg]@[end]@[inc] slice from [beg] to [end] every [inc]
     6593            * NOTE, no dim name all the dimension size
     6594        [tvarn]: name of the variable time
     6595        [yvarn]: name of the variable to use for the values
     6596      values = [dimxyfmt];[yaxislab];[yunits];[aval];[rangevals];[timevals];
     6597          [labels];[colors];[wdth];[graphtit];[legvalues];[kindfig];[fign];[close]
     6598        [dimxyfmt]=[dxs],[dxf],[Ndx],[ordx],[dys],[dyf],[Ndy],[ordy]: format of the values at each
     6599            axis (or single 'auto' for 'auto','auto')
     6600          [dxs]: style of x-axis ('auto' for 'pretty')
     6601            'Nfix', values computed at even 'Ndx'
     6602            'Stringlist', a given list of strings
     6603            'Vfix', values computed at even 'Ndx' increments
     6604            'pretty', values computed following aprox. 'Ndx' at 'pretty' intervals (2.,2.5,4,5,10)
     6605          [dxf]: format of the labels at the x-axis
     6606          [Ndx]: Number of ticks at the x-axis (for 'Stringlist', '@' list of labels)
     6607          [ordx]: angle of orientation of ticks at the x-axis ('auto' for horizontal)
     6608          [dys]: style of y-axis ('auto' for 'pretty')
     6609          [dyf]: format of the labels at the y-axis
     6610          [Ndy]: Number of ticks at the y-axis
     6611          [ordy]: angle of orientation of ticks at the y-axis ('auto' for horizontal)
     6612        [yaxislab]: Label for the y-axis ('!' for spaces)
     6613        [yunits]: units of the y-label
     6614        [aval]: which acis should be used for the values ('x' or 'y')
     6615        [rangevals]: Range of the axis with the values (singel 'None' for 'auto','auto')
     6616         [vmin],[vmax]: minimum and maximum values
     6617           'auto': the computed minimumm or maximum of the values 
     6618        [timevals]: [timen]|[units]|[kind]|[tfmt] time labels characteristics
     6619          [timen]; name of the time variable
     6620          [units]; units string according to CF conventions ([tunits] since
     6621            [YYYY]-[MM]-[DD] [[HH]:[MI]:[SS]], '!' for spaces)
     6622          [kind]; kind of output
     6623            'Nval': according to a given number of values as 'Nval',[Nval]
     6624            'exct': according to an exact time unit as 'exct',[tunit];
     6625              tunit= [Nunits],[tu]; [tu]= 'c': centuries, 'y': year, 'm': month,
     6626               'w': week, 'd': day, 'h': hour, 'i': minute, 's': second,
     6627               'l': milisecond
     6628          [tfmt]; desired format
     6629        [labels]: ',' list of labels for the legend ('None' for no-labels)
     6630        [colors]: ',' list of colors (single value same color, 'auto' automatic)
     6631        [wdth]: width of the bars
     6632        [graphtit]: title of the figure '!' for spaces
     6633        [legvalues]=[locleg]|[fontsize]:
     6634          [locleg]: location of the legend (0, autmoatic)
     6635            1: 'upper right', 2: 'upper left', 3: 'lower left', 4: 'lower right',
     6636            5: 'right', 6: 'center left', 7: 'center right', 8: 'lower center',
     6637            9: 'upper center', 10: 'center'
     6638          [fontsize]: font size for the legend (auto for 12)
     6639        [kindfig]: kind of output figure (png, pdf, ps)
     6640        [fign]: name of the figure (without extension)
     6641        [close]: whether figure should be close or not
     6642    """
     6643    fname = 'draw_bar_time'
     6644
     6645    if values == 'h':
     6646        print fname + '____________________________________________________________'
     6647        print draw_bar_time.__doc__
     6648        quit()
     6649
     6650    expectargs = '[dimxyfmt];[yaxislab];[yunits];[aval];[rangevals];[timevals];' +   \
     6651      '[labels];[colors];[wdth];[graphtit];[legvalues];[kindfig];[fign];[close]'
     6652    drw.check_arguments(fname,values,expectargs,';')
     6653
     6654    dimxyfmt = values.split(';')[0]
     6655    yaxislab = values.split(';')[1].replace('!',' ')
     6656    yunits = values.split(';')[2]
     6657    aval = values.split(';')[3]
     6658    rangevals = values.split(';')[4]
     6659    timevals = values.split(';')[5]
     6660    labels = gen.str_list(values.split(';')[6], ',')
     6661    colors = gen.str_list(values.split(';')[7], ',')
     6662    wdth = np.float(values.split(';')[8])
     6663    graphtit = values.split(';')[9].replace('!',' ')
     6664    legvalues = values.split(';')[10]
     6665    kindfig = values.split(';')[11]
     6666    fign = values.split(';')[12]
     6667    close = gen.Str_Bool(values.split(';')[13])
     6668
     6669    # files and values
     6670    filedvs = ncfile.split(':')
     6671    tvals = []
     6672    yvals = []
     6673
     6674    # time-values
     6675    expectargs = '[timen]|[units]|[kind]|[tfmt]'
     6676    drw.check_arguments('timevals: '+fname,timevals,expectargs,'|')
     6677
     6678    timen = timevals.split('|')[0].replace('!',' ')
     6679    timeunit = timevals.split('|')[1].replace('!',' ')
     6680    timekind = timevals.split('|')[2]
     6681    timefmt = timevals.split('|')[3]
     6682
     6683    for fdv in filedvs:
     6684        filen = fdv.split(';')[0]
     6685        dimrange = fdv.split(';')[1]
     6686        tvarn = fdv.split(';')[2]
     6687        yvarn = fdv.split(';')[3]
     6688
     6689        if not os.path.isfile(filen):
     6690            print errormsg
     6691            print '  ' + fname + ': file "' + filen + '" does not exist !!'
     6692            quit(-1)
     6693
     6694        onc = NetCDFFile(filen, 'r')
     6695        if not onc.variables.has_key(tvarn):
     6696            print errormsg
     6697            print '  ' + fname + ': file "' + filen + "' does not have variable '" + \
     6698              tvarn + "' for the time-values !!"
     6699            print '    available ones:', onc.variables.keys()
     6700            onc.close()
     6701            quit(-1)
     6702        if not onc.variables.has_key(yvarn):
     6703            print errormsg
     6704            print '  ' + fname + ': file "' + filen + "' does not have variable '" + \
     6705              yvarn + "' for the y-values !!"
     6706            print '    available ones:', onc.variables.keys()
     6707            onc.close()
     6708            quit(-1)
     6709
     6710        otvar = onc.variables[tvarn]
     6711        oyvar = onc.variables[yvarn]
     6712        tvs, tdims = ncvar.slice_variable(otvar, dimrange.replace(',',':'))
     6713        yvs, ydims = ncvar.slice_variable(oyvar, dimrange.replace(',',':'))
     6714        tunitsvar = otvar.units
     6715
     6716        if len(tvs.shape) != 1:
     6717            print errormsg
     6718            print '  ' + fname + ': provided slice:', dimrange, "for variable '" +   \
     6719              tvarn + "' does not provide a rank-1 value !!"
     6720            print '    resultant shape:', tvs.shape, 'dimensions:', tdims, 'fix it!!'
     6721            quit(-1)
     6722        if len(yvs.shape) != 1:
     6723            print errormsg
     6724            print '  ' + fname + ': provided slice:', dimrange, "for variable '" +   \
     6725              yvarn + "' does not provide a rank-1 value !!"
     6726            print '    resultant shape:', yvs.shape, 'dimensions:', ydims, 'fix it!!'
     6727            quit(-1)
     6728
     6729        uvd = timeunit
     6730        tunitsec = timeunit.split(' ')
     6731        if len(tunitsec) == 4:
     6732            refdate = tunitsec[2][0:4]+tunitsec[2][5:7]+tunitsec[2][8:10] +          \
     6733              tunitsec[3][0:2] + tunitsec[3][3:5] + tunitsec[3][6:8]
     6734        else:
     6735            refdate = tunitsec[2][0:4]+tunitsec[2][5:7]+tunitsec[2][8:10] +          \
     6736              '000000'
     6737        tunitsval = tunitsec[0]
     6738        # Referring all times to the same reference time!
     6739        reftvals = gen.coincident_CFtimes(tvs, timeunit, tunitsvar)
     6740
     6741        tvals.append(list(reftvals))
     6742        yvals.append(list(yvs))
     6743
     6744        onc.close()
     6745
     6746    # Times
     6747    mintval = np.min(tvals)
     6748    maxtval = np.max(tvals)
     6749
     6750    dtvals = (maxtval - mintval)/10
     6751    dti = mintval
     6752    dte = maxtval
     6753    tvalsticks = np.arange(dti, dte, dtvals)
     6754
     6755    dtiS = drw.datetimeStr_conversion(str(dti) + ',' + timeunit, 'cfTime',           \
     6756     'Y/m/d H-M-S')
     6757    dteS = drw.datetimeStr_conversion(str(dte) + ',' + timeunit, 'cfTime',           \
     6758     'Y/m/d H-M-S')
     6759
     6760    print '  ' + fname + ': plotting from: ' + dtiS + ' to ' + dteS
     6761
     6762    timepos, timelabels = drw.CFtimes_plot(tvalsticks, timeunit, timekind, timefmt)
     6763
     6764    # ranges
     6765    if rangevals == 'None':
     6766        valmin = np.min(yvals)
     6767        valmax = np.max(yvals)
     6768    else:
     6769        valmin = np.float(rangevals.split(',')[0])
     6770        valmax = np.float(rangevals.split(',')[1])
     6771        if valmin != 'auto': valmin = np.min(yvals)
     6772        if valmax != 'auto': valmax = np.max(yvals)
     6773    yrange = [valmin, valmax]
     6774
     6775    xstyl, xaxf, Nxax, xaxor, ystyl, yaxf, Nyax, yaxor = drw.format_axes(dimxyfmt,',')
     6776    xaxis = [xstyl, xaxf, Nxax, xaxor]
     6777    yaxis = [ystyl, yaxf, Nyax, yaxor]
     6778
     6779    # Legend
     6780    legloc, legsiz = drw.legend_values(legvalues,'|')
     6781
     6782    dyu = yunits
     6783
     6784    drw.plot_bars_time(tvals, yvals, timepos, timelabels, yaxis, dyu, aval, yrange,  \
     6785     timen, yaxislab, labels, colors, wdth, graphtit, legloc, legsiz, kindfig, fign, \
     6786     close)
     6787
     6788    return
     6789
    65786790#quit()
    65796791
     
    65986810  'draw_2D_shad_cont_time',                                                          \
    65996811  'draw_2D_shad_line', 'draw_2D_shad_line_time', 'draw_2lines', 'draw_2lines_time',  \
    6600   'draw_bar', 'draw_lines',                                                          \
     6812  'draw_bar', 'draw_bar_time', 'draw_lines',                                         \
    66016813  'draw_lines_time', 'draw_points', 'draw_Taylor', 'draw_topo_geogrid_boxes',        \
    66026814  'draw_trajectories', 'draw_vals_trajectories', 'variable_values']
     
    66566868    elif oper == 'draw_bar':
    66576869        draw_bar(opts.ncfile, opts.values)
     6870    elif oper == 'draw_bar_time':
     6871        draw_bar_time(opts.ncfile, opts.values)
    66586872    elif oper == 'draw_barbs':
    66596873        draw_barbs(opts.ncfile, opts.values, opts.varname)
  • trunk/tools/drawing_tools.py

    r1539 r1542  
    93009300    return
    93019301
     9302def plot_bars_time(xvalues, yvalues, tpos, tlabs, yaxv, dimyu, valaxis, valrange, xlabel, \
     9303  ylabel, labels, cols, width, gtit, lloc, lsiz, kfig, figname, ifclose):
     9304    """ Function to plot a bar plot with multiple columns
     9305      xvalues= list with the values along the x-ais
     9306      yvalues= list with the values along the y-ais
     9307      tpos= position of the time-ticks
     9308      tlabs= labels of the time-ticks
     9309      yaxv= values at the axis y
     9310      dimyu= units at the axis y
     9311      valaxis= which axis holds the values 'x' or 'y'
     9312      valrange= range of the axis with values
     9313      xlabel= label at the x-axis
     9314      ylabel= label at the y-axis
     9315      labels= list of labels for legend (None for no legend)
     9316      cols= list of colors for the bars (single value for the same, 'auto' for automatic)
     9317      width= size of the column
     9318      gtit= title of the figure
     9319      lloc= location of the legend (0, autmoatic)
     9320        1: 'upper right', 2: 'upper left', 3: 'lower left', 4: 'lower right',
     9321        5: 'right', 6: 'center left', 7: 'center right', 8: 'lower center',
     9322        9: 'upper center', 10: 'center'
     9323      lsiz= font size of the legend
     9324      kfig= kind of output: pdf, png, ps
     9325      figname= name of the figure
     9326      ifclose= whether figure should be closed
     9327    """
     9328    fname = 'plot_bars'
     9329
     9330    Nvalues = len(xvalues)
     9331
     9332    dyn = valrange[0]
     9333    dyx = valrange[1]
     9334
     9335    axstyles = ['pretty', 'Nfix', 'Stringlist', 'Vfix']
     9336    if yaxv[0] == 'pretty':
     9337        dimyt = np.array(gen.pretty_int(dyn,dyx,yaxv[2]))
     9338        dimyl = np.array(dimyt, dtype=str)
     9339    elif yaxv[0] == 'Nfix':
     9340        dimyt = np.arange(0.,1.,1./(yaxv[2]+1))
     9341        dimyl = np.arange(0.,1.,1./varsv.shape[0])
     9342        axytype='fixpixel'
     9343    elif yaxv[0] == 'Vfix':
     9344        dynvfix = int(dyn/yaxv[2])
     9345        dimyt = np.arange(dynvfix*xaxv[2],dyx,yaxv[2])
     9346        axytype='data'
     9347    else:
     9348        print errormsg
     9349        print '  ' + fname + ": x-xais style '" + xaxv[0] + "' not ready !!"
     9350        print '    available ones: ', axstyles
     9351        quit(-1)
     9352
     9353    colvs = []
     9354    if len(cols) == 1:
     9355        if cols[0] == 'auto':
     9356            colvs = colorsauto[0:Nvalues+1]
     9357        else:
     9358            for ic in range(Nvalues): colvs.append(cols[0])
     9359    else:
     9360        colvs = cols
     9361   
     9362    for iv in range(Nvalues):
     9363        xvls = xvalues[iv]
     9364        Lvalues = len(xvls)
     9365        dxmean = np.mean(np.array(xvls[1:Lvalues])-np.array(xvls[0:Lvalues-1]))
     9366        if dxmean < width*Nvalues:
     9367            print warnmsg
     9368            print '  ' + fname + ': mean distance among x-values:', dxmean,         \
     9369              'is smaller than the total number of bars with the given witdh (',    \
     9370              width, '):', width*Nvalues
     9371            print '    reduce widht of the column, should not be larger than:',     \
     9372              dxmean/Nvalues
     9373        if width*Nvalues < 0.1*dxmean:
     9374            print warnmsg
     9375            print '  ' + fname + ': mean distance among x-values:', dxmean,         \
     9376              'is 100-times larger than the total number of bars with the given ' + \
     9377              'witdh (', width, '):', width*Nvalues
     9378            print '    increase widht of the column, should not be smaller than:',  \
     9379              0.1*dxmean
     9380
     9381        # Relative position of the column respect the xtick
     9382        if np.mod(Nvalues,2) == 0:
     9383            xrel = width*(iv - Nvalues/2.)
     9384        else:
     9385            xrel = width*(iv - (Nvalues-1)/2.)
     9386
     9387        xrels = xrel*np.ones((Lvalues),dtype=np.float)
     9388
     9389        if valaxis == 'x':
     9390            if labels is not None:
     9391                plt.barh(xvls+xrels, yvalues[iv], height=width, color=colvs[iv],     \
     9392                  label=labels[iv])
     9393            else:
     9394                plt.barh(xvls+xrels, yvalues[iv], height=width, color=colvs[iv])
     9395        else:
     9396            if labels is not None:
     9397                plt.bar(xvls+xrels, yvalues[iv], width=width, color=colvs[iv],       \
     9398                  label=labels[iv])
     9399            else:
     9400                plt.bar(xvls+xrels, yvalues[iv], width=width, color=colvs[iv])
     9401 
     9402    if valaxis == 'x':
     9403        plt.xticks(dimyt, dimyl, rotation=yaxv[3])
     9404        plt.yticks(tpos, tlabs, rotation=0)
     9405        plt.xlabel(ylabel + ' (' + units_lunits(dimyu) + ')')
     9406        plt.ylabel(gen.latex_text(xlabel))
     9407        plt.xlim(dyn, dyx)
     9408    else:
     9409        plt.xticks(tpos, tlabs)
     9410        plt.yticks(dimyt, list(dimyl), rotation=yaxv[3])
     9411        plt.xlabel(gen.latex_text(xlabel))
     9412        plt.ylabel(ylabel + ' (' + units_lunits(dimyu) + ')')
     9413        plt.ylim(dyn, dyx)
     9414
     9415    if labels is not None:
     9416        plt.legend(loc=lloc, prop={'size':lsiz})
     9417
     9418    plt.title(gen.latex_text(gtit))
     9419   
     9420    output_kind(kfig, figname, ifclose)
     9421
     9422    return
     9423
     9424
Note: See TracChangeset for help on using the changeset viewer.