Package fieldpy :: Package plotting :: Module plot_tools
[hide private]
[frames] | no frames]

Source Code for Module fieldpy.plotting.plot_tools

  1  """This module is for producing standardized plots for: 
  2   
  3   - publications: functions starting with pub_ 
  4   
  5   - presentations: functions starting with pres_ 
  6   
  7   - internet: functions starting with net_ 
  8   
  9   - tools functions: starting with tool_ 
 10   
 11  Generally a function sets the P.rcParams to values suitable for the printing. 
 12   - this is probably not the most clever way of doing things, should 
 13     be done through the API 
 14   
 15  Some features cannot be done with P.rcParams and can be done with 
 16  seprarate functions. 
 17   
 18  For a description of the sizing of plot and fonts see 
 19  http://www.scipy.org/Cookbook/Matplotlib/LaTeX_Examples 
 20   
 21  Short help about Date ticking 
 22  ============================= 
 23  To set tick locations use:: 
 24      ax.xaxis.set_major_locator(plt.DayLocator()) 
 25  Possible date locators are:: 
 26      MinuteLocator: locate minutes 
 27      HourLocator: locate hours 
 28      DayLocator: locate specifed days of the month 
 29      WeekdayLocator: Locate days of the week, eg MO, TU 
 30      MonthLocator: locate months, eg 7 for july 
 31      YearLocator: locate years that are multiples of base 
 32      RRuleLocator: locate using a matplotlib.dates.rrulewrapper. The rrulewrapper is a simple wrapper around a dateutils.rrule (dateutil) which allow almost arbitrary date tick specifications. See rrule example. 
 33      AutoDateLocator: On autoscale, this class picks the best MultipleDateLocator to set the view limits and the tick locations. 
 34   
 35  More is found here: U{http://matplotlib.sourceforge.net/api/dates_api.html}. 
 36  Other non-date locators see: U{http://matplotlib.sourceforge.net/api/ticker_api.html} 
 37   
 38  And the formatting is done with:: 
 39      ax.xaxis.set_major_formatter(plt.DateFormatter('%d')) 
 40  where format string is:: 
 41      %a      Locale's abbreviated weekday name. 
 42      %A      Locale's full weekday name. 
 43      %b      Locale's abbreviated month name. 
 44      %B      Locale's full month name. 
 45      %c      Locale's appropriate date and time representation. 
 46      %d      Day of the month as a decimal number [01,31]. 
 47      %H      Hour (24-hour clock) as a decimal number [00,23]. 
 48      %I      Hour (12-hour clock) as a decimal number [01,12]. 
 49      %j      Day of the year as a decimal number [001,366]. 
 50      %m      Month as a decimal number [01,12]. 
 51      %M      Minute as a decimal number [00,59]. 
 52      %p      Locale's equivalent of either AM or PM.      (1) 
 53      %S      Second as a decimal number [00,61].      (2) 
 54      %U      Week number of the year (Sunday as the first day of the week) 
 55              as a decimal number [00,53]. All days in a new year preceding 
 56              the first Sunday are considered to be in week 0.      (3) 
 57      %w      Weekday as a decimal number [0(Sunday),6]. 
 58      %W      Week number of the year (Monday as the first day of the week) 
 59              as a decimal number [00,53]. All days in a new year preceding 
 60              the first Monday are considered to be in week 0.      (3) 
 61      %x      Locale's appropriate date representation. 
 62      %X      Locale's appropriate time representation. 
 63      %y      Year without century as a decimal number [00,99]. 
 64      %Y      Year with century as a decimal number. 
 65      %Z      Time zone characters if no time zone exists). 
 66      %%      A literal "%" character. 
 67  """ 
 68   
 69  import numpy as np 
 70  import string 
 71  import copy 
 72   
 73  # from matplotlib import rc 
 74  # rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']}) 
 75  # #rc('font',**{'family':'serif','serif':['Palatino', 'Computer Modern Roman']}) 
 76  # rc('text', usetex=True) 
 77   
 78  import matplotlib.widgets 
 79  import matplotlib.font_manager 
 80   
 81  import pylab as plt 
 82   
 83   
 84  #: in inches: 1 inch = 72.27pt (matplotlib works in inches) 
 85  pt_per_inch = 72.27 
 86   
 87  #: ditto 
 88  golden_mean = (np.sqrt(5)-1.0)/2.0         # Aesthetic ratio 
 89   
 90  #: for dashed lines 
 91  dashes = ['--', #    : dashed line 
 92            '-', #     : solid line 
 93            '-.', #   : dash-dot line 
 94            ':'] #    : dotted line 
 95   
 96   
97 -def pub_igs_rcparams():
98 """This function is used to set the rcParams for publications in the 99 Journal of Glaciology. 100 101 It returns some useful constans: 102 @return: column_width, column_height, two_column_width, dashes 103 """ 104 # some dimensions in latex points: 105 column_width_pt = 244.6937 #/showthe/columnwidth 106 column_width = column_width_pt/pt_per_inch 107 text_height_pt = 724.5 #/showthe/textheight 108 column_height = text_height_pt/pt_per_inch 109 text_width_pt = 506.45905 #/showthe/textwidth 110 two_column_width = text_width_pt/pt_per_inch 111 112 113 fig_size_one = [column_width,column_width*golden_mean] 114 fig_size_two = [two_column_width,two_column_width*golden_mean] 115 fig_size_full_hight_one = [column_width,column_height] 116 fig_size_full_hight_two = [two_column_width,column_height] 117 118 # figure out what font sizes you want and other parameters which are 119 # the same for all size plots: 120 font_big = 10 121 font_norm = 9 122 font_small = 7 123 line_thin = 0.1 124 line_medium = 0.3 125 line_norm = 0.5 126 params = {'backend': 'eps', 127 'font.size': font_norm, 128 'axes.labelsize': font_norm, 129 'text.fontsize': font_norm, 130 'legend.fontsize': font_norm, 131 'legend.linewidth': line_thin, 132 'xtick.labelsize': font_small, 133 'ytick.labelsize': font_small, 134 'lines.linewidth': line_norm, 135 'lines.color': 'k', 136 'grid.linewidth': line_thin, 137 'axes.linewidth': line_medium, 138 'font.family': 'sans-serif', 139 'font.serif': ['Times New Roman', 'Palatino', 'New Century Schoolbook', 'Bookman', 'Computer Modern Roman'], 140 'font.sans-serif': ['Arial', 'FreeSans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif'], #'Free Sans, Arial, Computer Modern Sans serif', #Optima, Helvetica, Avant Garde, Computer Modern Sans serif', 141 'font.monospace': ['Courier', 'Computer Modern Typewriter', 'Bitstream Vera Sans Mono'], 142 'figure.dpi': 300, 143 'savefig.dpi': 100, 144 'xtick.major.size': 3, 145 'xtick.minor.size': 1.5, 146 'ytick.major.size': 3, 147 'ytick.minor.size': 1.5, 148 'axes.titlesize': font_norm 149 } 150 151 plt.rcParams.update(params) 152 # use plt.rcdefaults() to restore defaults if needed 153 154 # # parameters which differ for different grapics 155 # param_one = {'figure.figsize': fig_size_one} 156 # param_two = {'figure.figsize': fig_size_two} 157 # param_full_hight_one = {'figure.figsize': fig_size_full_hight_one} 158 # param_full_hight_two = {'figure.figsize': fig_size_full_hight_two} 159 160 161 return column_width, column_height, two_column_width
162 163
164 -def pres_rcparams():
165 """This function is used to set the rcParams for latex-beamer 166 presentations. 167 168 It returns some useful constans: 169 @return: column_width, column_height, two_column_width, dashes 170 """ 171 # some dimensions in latex points: 172 column_width_pt = 307.28987 #/showthe/columnwidth 173 column_width = column_width_pt/pt_per_inch 174 text_height_pt = 200.# 249.80135 #/showthe/textheight 175 column_height = text_height_pt/pt_per_inch 176 text_width_pt = 307.28987 #/showthe/textwidth 177 two_column_width = text_width_pt/pt_per_inch 178 179 180 fig_size_one = [column_width,column_width*golden_mean] 181 fig_size_two = [two_column_width,two_column_width*golden_mean] 182 fig_size_full_hight_one = [column_width,column_height] 183 fig_size_full_hight_two = [two_column_width,column_height] 184 185 # figure out what font sizes you want and other parameters which are 186 # the same for all size plots: 187 font_big = 12 188 font_norm = 7 189 font_small = 6 190 line_thin = 1 191 line_norm = 2 192 params = {'backend': 'png', 193 'font.size': font_norm, 194 'axes.labelsize': font_norm, 195 'text.fontsize': font_norm, 196 'legend.fontsize': font_norm, 197 'legend.linewidth': line_thin, 198 'xtick.labelsize': font_norm, 199 'ytick.labelsize': font_norm, 200 'lines.linewidth': line_norm, 201 'grid.linewidth': line_thin, 202 'axes.linewidth': line_thin, 203 'font.family': 'sans-serif', 204 'font.serif': ['Times New Roman',' Palatino',' New Century Schoolbook',' Bookman',' Computer Modern Roman'], 205 'font.sans-serif': ['Arial', 'FreeSans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif'], #'Free Sans, Arial, Computer Modern Sans serif', #Optima, Helvetica, Avant Garde, Computer Modern Sans serif', 206 'font.cursive': ['Zapf Chancery'], 207 'font.monospace': ['Courier',' Computer Modern Typewriter'], 208 'figure.dpi': 300, 209 'xtick.major.size': 3, 210 'xtick.minor.size': 1, 211 'ytick.major.size': 3, 212 'ytick.minor.size': 1, 213 'savefig.dpi': 300, 214 'axes.titlesize': font_norm 215 } 216 217 # 'text.usetex': True } 218 plt.rcParams.update(params) 219 # use plt.rcdefaults() to restore defaults if needed 220 221 # # parameters which differ for different grapics 222 # param_one = {'figure.figsize': fig_size_one} 223 # param_two = {'figure.figsize': fig_size_two} 224 # param_full_hight_one = {'figure.figsize': fig_size_full_hight_one} 225 # param_full_hight_two = {'figure.figsize': fig_size_full_hight_two} 226 227 # now do some front checking 228 fp = matplotlib.font_manager.FontProperties() 229 print fp.get_family(), '\n', matplotlib.font_manager.fontManager.findfont(fp) 230 231 return column_width, column_height, two_column_width
232 233 234 235 # ---------------------------------------- 236 # helper functions 237
238 -def finish_up(filename, fig=None, subplot_adjust=None):
239 """This function finishes up a plot: 240 - adjust the linewidth of the minor ticks 241 - adjust the subplots if subplot_adjust is passed 242 - it *save* it to the filename. File type is determined by the 243 extension. 244 245 It sets the ticks to the width of the axes border 246 """ 247 linewidth = plt.rcParams['axes.linewidth'] 248 if fig is None: 249 fig = plt.gcf() 250 axs = fig.axes 251 if subplot_adjust is None: 252 subplot_adjust = {'left': 0.13, 253 'right': 0.95, 254 'bottom': 0.1, 255 'top': 0.95, 256 'wspace': None, 257 'hspace': None} 258 fig.subplots_adjust(**subplot_adjust) 259 for ax in axs: 260 # there is no get_xticklines methode for the minor ticks (in 261 # current matplotlib), so we need to get the list of lines 262 # ourselves: 263 xminortick_lines=[] 264 for minor_ticks in ax.xaxis.minorTicks: 265 xminortick_lines.append(minor_ticks.tick1line) 266 xminortick_lines.append(minor_ticks.tick2line) 267 yminortick_lines=[] 268 for minor_ticks in ax.yaxis.minorTicks: 269 yminortick_lines.append(minor_ticks.tick1line) 270 yminortick_lines.append(minor_ticks.tick2line) 271 plt.setp(ax.get_xticklines() + ax.get_yticklines() + 272 xminortick_lines + yminortick_lines, mew=linewidth) 273 274 plt.savefig(filename)
275
276 -def tool_no_legend_box(ax=None):
277 """Removes the legend from the passed list of axes. If no 278 arguments are passed, then plt.gcf().axes is used. 279 """ 280 281 if ax is None: 282 ax = plt.gcf().axes 283 # this removes the border around the legend labels: 284 # setp(legendframe, linewidth=0.0) might also be an option 285 286 for a in ax: 287 leg = a.axes.get_legend() 288 leg.draw_frame(False)
289
290 -def tool_touching_subplots(fig=None, top_ticklabels=False):
291 """Makes touching subplots and removes the xlabels in all but the 292 lowermost subplot. 293 294 @param fig: the figure containing the subplots. defaults to current 295 figure. 296 @param top_ticklabels: if true also do ticklabels at the top 297 """ 298 if fig is None: 299 fig = plt.gcf() 300 axs = copy.copy(fig.axes[:-1]) 301 if top_ticklabels: 302 axs[0].xaxis.tick_top() 303 axs = axs[1:] 304 fig.subplots_adjust(hspace=0) 305 for a in axs: 306 lab = a.get_xmajorticklabels() 307 lab.append(a.get_xminorticklabels()) 308 xlab = a.xaxis.get_label() 309 plt.setp(lab, visible=False) 310 plt.setp(xlab, visible=False)
311
312 -def tool_rotate_xlabels(ax=None, rotation=0):
313 """Rotates the xlabels of ax by rotation. 314 """ 315 if ax is None: 316 ax = plt.gca() 317 labels = ax.get_xticklabels() 318 plt.setp(labels, rotation=rotation)
319 # plt.setp(labels, verticalalignment='center') 320 321
322 -def tool_get_extent(plot_fn, *args, **kwargs):
323 """This function returns the extent of the axes when the figure is 324 closed. Useful for figuring out the extent on date plots without 325 hassel. 326 327 @param plot_fn: a function which does some plotting. does not 328 contain a plt.show() the arguments to plot_fn can 329 be passed in the following *args and **kwargs 330 """ 331 plot_fn(*args, **kwargs) 332 xlims = [] 333 ylims = [] 334 def resize(event): 335 xlims = [] 336 ylims = [] 337 for a in plt.gcf().axes: 338 xlims.append(a.get_xlim()) 339 ylims.append(a.get_ylim()) 340 print xlims, ylims
341 resize(None) 342 plt.connect('draw_event', resize) 343 plt.show() 344 return xlims, ylims 345
346 -def tool_get_coords(plot_fn, ax=None, *args, **kwargs):
347 """Returns the x&y coords from where you clicked. Does not respond 348 when zooming. 349 350 @param plot_fn: a function which does some plotting. does not 351 contain a plt.show() the arguments to plot_fn can 352 be passed in the following *args and **kwargs 353 @param ax: if not not current axes ought to be used. Pass the number of 354 the subplot. 355 """ 356 plot_fn(*args, **kwargs) 357 xcoord = [] 358 ycoord = [] 359 if ax is not None: 360 plt.axes(plt.gcf().axes[ax]) 361 def click(event): 362 # this is a trick to let you zoom and pan: 363 tb = plt.get_current_fig_manager().toolbar 364 # normal event inside axis. return coordinates. 365 if event.button==1 and event.inaxes and tb.mode == '': 366 print 'x,y = ', event.xdata, event.ydata 367 xcoord.append(event.xdata) 368 ycoord.append(event.ydata)
369 # otherwise it jumps about: 370 plt.gca().set_autoscale_on(False) 371 #register this function with the event handler 372 plt.connect('button_press_event', click) 373 # make different cursor 374 curs = matplotlib.widgets.Cursor(plt.gca(), color='black', useblit=True) 375 plt.show() 376 return xcoord, ycoord 377
378 -def tool_underlay_with_color( x_loc, color='g', axs=None , alpha=0.3):
379 """Underlays the axis in the list axs with a color rectangel. 380 381 @param x_loc: (x_min, x_max) the borders of the rectangel 382 @param color: 'g' the color 383 @param axs: [axes] default [plt.gcf().axes] 384 @param alpha: how solid the color is 385 386 @note: on twinx() plots the lines of the first plot will be covered. use 387 axs=axs[0:-1:2] when axs is the list of axes. 388 """ 389 if axs is None: 390 axs = plt.gcf().axes 391 for ax in axs: 392 plt.axes(ax) 393 ylim = ax.get_ylim() 394 xlim = ax.get_xlim() 395 x_vertices = [x_loc[0], x_loc[1], x_loc[1], x_loc[0]] 396 y_vertices = [ylim[0], ylim[0], ylim[1], ylim[1]] 397 plt.fill(x_vertices, y_vertices, facecolor=color, edgecolor=color, 398 hold=True) 399 #to preserve the limits: 400 ax.set_xlim(xlim) 401 ax.set_ylim(ylim)
402
403 -def tool_make_vert_lines( x_loc, axs=None , fmt='k-.'):
404 """Makes vertical lines at x_loc. 405 406 @param x_loc: (x_min, x_max) the borders of the rectangel 407 @param axs: [axes] default [plt.gcf().axes] 408 @param fmt: line style 409 410 @note: on twinx() plots the lines of the first plot will be covered. use 411 axs=axs[0:-1:2] when axs is the list of axes. 412 """ 413 if axs is None: 414 axs = plt.gcf().axes 415 for ax in axs: 416 plt.axes(ax) 417 ylim = ax.get_ylim() 418 xlim = ax.get_xlim() 419 y_vertices = np.array([ylim[0], ylim[1]]) 420 for x in x_loc: 421 x_vertices = np.array([x ,x]) 422 plt.plot(x_vertices, y_vertices, fmt, hold=True) 423 #to preserve the limits: 424 ax.set_xlim(xlim) 425 ax.set_ylim(ylim)
426
427 -def tool_adjust_ylabels(pos_factor=1, axs=None):
428 """Adjust the ylabels such that they align when there are several 429 subplots. Only works when the x-Axis are linked. 430 431 Note: it seems that all labels need to be either ascii or 432 unicode. a mix leads to misalignment. 433 434 @param pos_factor: controls the horizontal postion. default 1 means 435 same place as outermost label. < 1 more left, > 1 436 more right 437 @param axs: a list of axes. default plt.gcf().axes 438 """ 439 # we need to save it in order that the values are right 440 plt.savefig('/tmp/tmp_fig.eps') 441 if axs is None: 442 axs = plt.gcf().axes 443 axs_left = [ ax for ax in axs if ax.yaxis.label_position=='left'] 444 axs_right = [ ax for ax in axs if ax.yaxis.label_position=='right'] 445 labels_left = [ ax.yaxis.get_label() for ax in axs_left] 446 labels_right = [ ax.yaxis.get_label() for ax in axs_right] 447 xlims = axs[0].get_xlim() 448 loop_over = [x for x in [(axs_right, labels_right),(axs_left, labels_left)] if x!=([],[])] 449 for axs, labels in loop_over: 450 # get largest x-postion in identity coordates 451 # use ax.transAxes.inverse_xy_tup() to go to axes coord 452 x_pos = [ lab.get_position()[0] for lab in labels] 453 x_position = min(x_pos) * pos_factor 454 y_position= [ lab.get_position()[1] for lab in labels] 455 text = [ lab.get_text() for lab in labels] 456 fontsize = [ lab.get_fontsize() for lab in labels] 457 fontproperties = [ lab.get_font_properties() for lab in labels] 458 for n,ax in enumerate(axs): 459 # make the original ones disappear 460 plt.setp(labels[n], visible=False) 461 pos = ax.transAxes.inverted().transform((x_position,y_position[n])) 462 # and set new ones. for some strange reason i need only to 463 # take the x_pos transformed and not the y_pos??! 464 t = ax.text(pos[0], y_position[n], text[n], transform=ax.transAxes, rotation=90, 465 va='center', ha='center', fontsize=fontsize[n])
466 #t.set_fontproperties = fontproperties[n] 467 #, ha='center') this seem to have something to do with wonkey text alignement 468 #print t.get_horizontalalignment() 469 # print 'Text font: ' + t.get_fontname() 470 # print 'Text size: ' + str(t.get_fontsize()) 471 # print 'Xlabel font: ' + plt.gca().xaxis.get_label().get_fontname() 472 # print 'Xlabel size: ' + str(plt.gca().xaxis.get_label().get_fontsize()) 473 # print 'XTickLabel font: ' + plt.gca().get_xticklabels()[0].get_fontname() 474 # print 'XTickLabel size: ' + str(plt.gca().get_xticklabels()[0].get_fontsize()) 475 476
477 -def tool_label_subplots(axs=None, system='abc', pos='out_right', check_axes=True, start_value=0, 478 fontsize=None):
479 """This function labels all the subplots in a figure. The labels are 480 481 @param axs: axes of the subplots to act on. the order of the list 482 determines the order of the labeling. 483 @param system: labeling system: default 'abc', 'ABC' 484 @param pos: default: outside on the right (out_right), in_top_right or (x,y) in 485 figure coordinates. 486 @param check_axes: if only one axes, then don't label. default:True 487 """ 488 489 if axs is None: 490 axs = plt.gcf().axes 491 if len(axs)==1: 492 return 493 if fontsize is None: 494 fontsize = 12 #plt.rcParams['text.fontsize']#axs[-1].xaxis.get_majorticklabels()[0].get_fontsize() 495 if system=='abc': 496 labels = string.ascii_lowercase[start_value:] 497 elif system=='ABC': 498 labels = string.ascii_uppercase[start_value:] 499 if pos=='out_right': 500 pos_v = (1.02, 0) 501 elif pos=='in_top_right': 502 pos_v = (0.96, 0.9) 503 elif pos=='in_bottom_left': 504 pos_v = (0.04, 0.1) 505 else: 506 pos_v = pos 507 for n, ax in enumerate(axs): 508 ax.text(pos_v[0], pos_v[1], labels[n], transform=ax.transAxes, fontsize=fontsize)
509
510 -def tool_contour_remove_litte_ones(cs, num_points):
511 """Removes small contours with less than num_points. 512 513 @param cs: is a contour instance 514 @param num_points: min number of points 515 """ 516 for i, col in enumerate(cs.collections): 517 segs = col._segments 518 col.set_segments([seg for seg in segs if len(seg) > num_points])
519 520
521 -def tool_set_y_extent_and_ticks_of_subplots(y_extents, y_ticks, axs=None, minor=True):
522 """Sets the extents and ticks according to the entires in the corresponding lists. 523 524 @param y_extents: a list of y-extent tuples 525 526 @type y_ticks: list of lists containing B{floats} 527 @param y_ticks: the location of the yticks given for each axes. 528 529 @param axs: a list of axis (default: all axis in current figure) 530 531 @param minor: not sure 532 533 @note: 534 - the y_ticks need to be floats! 535 - set minor=False if using plt.twiny 536 """ 537 if axs is None: 538 axs = plt.gcf().axes 539 for n,ax in enumerate(axs): 540 if minor: 541 ax.yaxis.set_minor_locator( 542 plt.MultipleLocator(np.diff(y_ticks[n])[0]/2)) 543 ax.set_yticks(y_ticks[n]) 544 ax.set_ylim(y_extents[n])
545