PISM, A Parallel Ice Sheet Model stable 0.4.1779

test/vnreport.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 ## @package vnreport
00004 ## Plots error graphs using \c pismv of \c vfnow.py report files.
00005 ## 
00006 ## Has two command-line options: -i specifies a \c pismv report file to use, \c
00007 ## -t selects tests to plot. Use "-t all" to plot error graphs using all the
00008 ## error reports saved in a file given with -i.
00009 ## 
00010 ## For example:
00011 ## \verbatim
00012 ## vnreport.py -i r1084.nc -t G,B
00013 ## \endverbatim
00014 ## will use \c r1084.nc and plot tests "G" and "B".
00015 
00016 from pylab import close, figure, clf, hold, plot, xlabel, ylabel, xticks, yticks, axis, legend, title, grid, show, savefig
00017 from numpy import array, polyfit, polyval, log10, floor, ceil, unique
00018 #from matplotlib.font_manager import FontProperties
00019 import getopt
00020 import sys
00021 
00022 try:
00023     from netCDF4 import Dataset as NC
00024 except:
00025     from netCDF3 import Dataset as NC
00026 
00027 def plot_errors(nc, x, vars, testname, plot_title, filename = None):
00028     # This mask lets us choose data corresponding to a particular test:
00029     test = array(map(chr, nc.variables['test'][:]))
00030     mask = (test == testname)
00031 
00032     # If we have less than 2 points to plot, then bail.
00033     if (sum(mask) < 2):
00034         print "Skipping Test %s %s (not enough data to plot)" % (testname, plot_title)
00035         return
00036 
00037     # Get the independent variable and transform it. Note that everywhere here
00038     # I assume that neither dx (dy, dz) nor errors can be zero or negative.
00039     dx = nc.variables[x][mask]
00040     dim = log10(dx)
00041     
00042     figure(figsize=(10,6));clf();hold(True)
00043 
00044     colors = ['red', 'blue', 'green', 'black', 'brown', 'cyan']
00045     for (v,c) in zip(vars,colors):
00046         # Get a particular variable, transform and fit a line through it:
00047         data = log10(nc.variables[v][mask])
00048         p = polyfit(dim, data, 1)
00049 
00050         # Try to get the long_name, use short_name if it fails:
00051         try:
00052             name = nc.variables[v].long_name
00053         except:
00054             name = v
00055 
00056         # Create a label for the independent variable:
00057         if (x == "dx"):
00058             dim_name = "\Delta x"
00059         if (x == "dy"):
00060             dim_name = "\Delta y"
00061         if (x == "dz"):
00062             dim_name = "\Delta z"
00063         if (x == "dzb"):
00064             dim_name = "\Delta z_{bed}"
00065 
00066         # Variable label:
00067         var_label = "%s, $O(%s^{%1.2f})$" % (name, dim_name, p[0])
00068 
00069         # Plot errors and the linear fit:
00070         plot(dim, data, label=var_label, marker='o', color=c)
00071         plot(dim, polyval(p, dim), ls="--", color=c)
00072 
00073     # Shrink axes, then expand vertically to have integer powers of 10:
00074     axis('tight')
00075     _,_,ymin,ymax = axis()
00076     axis(ymin = floor(ymin), ymax = ceil(ymax))
00077 
00078     # Switch to km if dx (dy, dz) are big:
00079     units = nc.variables[x].units
00080     if (dx.min() > 1000.0 and (units == "meters")):
00081         dx = dx / 1000.0
00082         units = "km"
00083     # Round grid spacing in x-ticks:
00084     xticks(dim, map(lambda(x): "%d" % x, dx))
00085     xlabel("$%s$ (%s)" % (dim_name, units))
00086 
00087     # Use default (figured out by matplotlib) locations, but change labels for y-ticks:
00088     loc,_ = yticks()
00089     yticks(loc, map(lambda(x) : "$10^{%1.1f}$" % x, loc))
00090 
00091     # Make sure that all variables given have the same units:
00092     try:
00093         ylabels = array(map(lambda(x): nc.variables[x].units, vars))
00094         if (any(ylabels != ylabels[0])):
00095             print "Incompatible units!"
00096         else:
00097             ylabel(ylabels[0])
00098     except:
00099         pass
00100 
00101     # Legend, grid and the title:
00102     legend(loc='best', borderpad=1, labelspacing = 0.5, handletextpad = 0.75, handlelength = 0.02)
00103     #  prop = FontProperties(size='smaller'),
00104     grid(True)
00105     title("Test %s %s (%s)" % (testname, plot_title, nc.source))
00106 
00107     if (filename):
00108         savefig(filename)
00109 
00110 def plot_tests(nc, list_of_tests):
00111     for test_name in list_of_tests:
00112         # thickness, volume and eta errors:
00113         if test_name in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'L']:
00114             plot_errors(nc, 'dx', ["maximum_thickness", "average_thickness"], test_name, "ice thickness errors")
00115             plot_errors(nc, 'dx', ["relative_volume"], test_name, "relative ice volume errors")
00116             plot_errors(nc, 'dx', ["relative_max_eta"], test_name, r"relative max $\eta$ errors")
00117 
00118         # errors that are reported for test E only:
00119         if (test_name == 'E'):
00120             plot_errors(nc, 'dx', ["maximum_basal_velocity", "average_basal_velocity"], 'E' , r"basal velocity errors")
00121             plot_errors(nc, 'dx', ["maximum_basal_u", "maximum_basal_v"], 'E' , "basal velocity (ub and vb) errors")
00122             plot_errors(nc, 'dx', ["relative_basal_velocity"], 'E', "relative basal velocity errors")
00123 
00124         # F and G temperature, sigma and velocity errors:
00125         if test_name in ['F', 'G']:
00126             plot_errors(nc, 'dx', ["maximum_sigma", "average_sigma"],
00127                         test_name, "strain heating errors")
00128             plot_errors(nc, 'dx', ["maximum_temperature", "average_temperature",
00129                                    "maximum_basal_temperature", "average_basal_temperature"],
00130                         test_name, "ice temperature errors")
00131 
00132             plot_errors(nc, 'dx', ["maximum_surface_velocity", "maximum_surface_w"],
00133                         test_name, "maximum ice surface velocity errors")
00134             plot_errors(nc, 'dx', ["average_surface_velocity", "average_surface_w"],
00135                         test_name, "average ice surface velocity errors")
00136 
00137 
00138         # test I: plot only the u component
00139         if test_name == 'I':
00140             plot_errors(nc, 'dy', ["relative_velocity"],
00141                         test_name, "relative velocity errors")
00142             plot_errors(nc, 'dy', ["maximum_u", "average_u"],
00143                         test_name, "velocity errors")
00144             
00145         # tests J and M:
00146         if test_name in ['J', 'M']:
00147             plot_errors(nc, 'dx', ["relative_velocity"],
00148                         test_name, "relative velocity errors")
00149             plot_errors(nc, 'dx', ["maximum_velocity", "maximum_u", "average_u", "maximum_v", "average_v"],
00150                         test_name, "velocity errors")
00151 
00152         # test K temperature errors:
00153         if (test_name == 'K'):
00154             plot_errors(nc, 'dz', ["maximum_temperature", "average_temperature",
00155                                    "maximum_bedrock_temperature", "average_bedrock_temperature"],
00156                         'K', "temperature errors")
00157 
00158         # test O temperature and basal melt rate errors:
00159         if (test_name == 'O'):
00160             plot_errors(nc, 'dz', ["maximum_temperature", "average_temperature",
00161                                    "maximum_bedrock_temperature", "average_bedrock_temperature"],
00162                         'K', "temperature errors")
00163             plot_errors(nc, 'dz', ["maximum_basal_melt_rate"],
00164                         'O', "basal melt rate errors")
00165 
00166 def print_help():
00167     print """Usage:
00168 -i            specifies an input file, a result of running pismv (or vfnow.py)
00169                 with the -report_file option
00170 -t,--tests=   specifies a comma-separated list of tests. Use '-t all'
00171                 to plot all the tests available in the -i file.
00172 --help        prints this message
00173 """
00174 
00175 tests_to_plot = None
00176 input = None
00177 try:
00178     opts, args = getopt.getopt(sys.argv[1:], "i:t:", ["tests=", "help"])
00179     for opt, arg in opts:
00180         if opt in ["-t", "--tests"]:
00181             tests_to_plot = arg.split(',')
00182         if opt == "-i":
00183             input = arg
00184         if opt == "--help":
00185             print_help()
00186             sys.exit(0)
00187     if input:
00188         nc = NC(input, 'r')
00189         available_tests = unique(array(map(chr, nc.variables['test'][:])))
00190 
00191         if len(available_tests) == 1:
00192             if tests_to_plot == None:
00193                 tests_to_plot = available_tests
00194         else:
00195             if (tests_to_plot == None):
00196                 print """Please choose tests to plot using the -t option.
00197 (Input file %s has reports for tests %s available.)""" % (input, str(available_tests))
00198                 sys.exit(0)
00199 
00200         if (tests_to_plot[0] == "all"):
00201             tests_to_plot = available_tests
00202 
00203         close('all')
00204         plot_tests(nc, tests_to_plot)
00205         try:
00206             # show() will break if we didn't plot anything
00207             show()
00208         except:
00209             pass
00210     else:
00211         print_help()
00212 except getopt.GetoptError:
00213     print "Processing command-line options failed."
00214     print_help()
00215     sys.exit(1)
00216 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines