箭头符号演示

新的花式箭头工具的箭头绘制示例。

代码由此人贡献: Rob Knight < rob@spot.colorado.edu >

用法:

箭头符号图示例

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. rates_to_bases = {'r1': 'AT', 'r2': 'TA', 'r3': 'GA', 'r4': 'AG', 'r5': 'CA',
  4. 'r6': 'AC', 'r7': 'GT', 'r8': 'TG', 'r9': 'CT', 'r10': 'TC',
  5. 'r11': 'GC', 'r12': 'CG'}
  6. numbered_bases_to_rates = {v: k for k, v in rates_to_bases.items()}
  7. lettered_bases_to_rates = {v: 'r' + v for k, v in rates_to_bases.items()}
  8. def add_dicts(d1, d2):
  9. """Adds two dicts and returns the result."""
  10. result = d1.copy()
  11. result.update(d2)
  12. return result
  13. def make_arrow_plot(data, size=4, display='length', shape='right',
  14. max_arrow_width=0.03, arrow_sep=0.02, alpha=0.5,
  15. normalize_data=False, ec=None, labelcolor=None,
  16. head_starts_at_zero=True,
  17. rate_labels=lettered_bases_to_rates,
  18. **kwargs):
  19. """Makes an arrow plot.
  20. Parameters:
  21. data: dict with probabilities for the bases and pair transitions.
  22. size: size of the graph in inches.
  23. display: 'length', 'width', or 'alpha' for arrow property to change.
  24. shape: 'full', 'left', or 'right' for full or half arrows.
  25. max_arrow_width: maximum width of an arrow, data coordinates.
  26. arrow_sep: separation between arrows in a pair, data coordinates.
  27. alpha: maximum opacity of arrows, default 0.8.
  28. **kwargs can be anything allowed by a Arrow object, e.g.
  29. linewidth and edgecolor.
  30. """
  31. plt.xlim(-0.5, 1.5)
  32. plt.ylim(-0.5, 1.5)
  33. plt.gcf().set_size_inches(size, size)
  34. plt.xticks([])
  35. plt.yticks([])
  36. max_text_size = size * 12
  37. min_text_size = size
  38. label_text_size = size * 2.5
  39. text_params = {'ha': 'center', 'va': 'center', 'family': 'sans-serif',
  40. 'fontweight': 'bold'}
  41. r2 = np.sqrt(2)
  42. deltas = {
  43. 'AT': (1, 0),
  44. 'TA': (-1, 0),
  45. 'GA': (0, 1),
  46. 'AG': (0, -1),
  47. 'CA': (-1 / r2, 1 / r2),
  48. 'AC': (1 / r2, -1 / r2),
  49. 'GT': (1 / r2, 1 / r2),
  50. 'TG': (-1 / r2, -1 / r2),
  51. 'CT': (0, 1),
  52. 'TC': (0, -1),
  53. 'GC': (1, 0),
  54. 'CG': (-1, 0)}
  55. colors = {
  56. 'AT': 'r',
  57. 'TA': 'k',
  58. 'GA': 'g',
  59. 'AG': 'r',
  60. 'CA': 'b',
  61. 'AC': 'r',
  62. 'GT': 'g',
  63. 'TG': 'k',
  64. 'CT': 'b',
  65. 'TC': 'k',
  66. 'GC': 'g',
  67. 'CG': 'b'}
  68. label_positions = {
  69. 'AT': 'center',
  70. 'TA': 'center',
  71. 'GA': 'center',
  72. 'AG': 'center',
  73. 'CA': 'left',
  74. 'AC': 'left',
  75. 'GT': 'left',
  76. 'TG': 'left',
  77. 'CT': 'center',
  78. 'TC': 'center',
  79. 'GC': 'center',
  80. 'CG': 'center'}
  81. def do_fontsize(k):
  82. return float(np.clip(max_text_size * np.sqrt(data[k]),
  83. min_text_size, max_text_size))
  84. A = plt.text(0, 1, '$A_3$', color='r', size=do_fontsize('A'),
  85. **text_params)
  86. T = plt.text(1, 1, '$T_3$', color='k', size=do_fontsize('T'),
  87. **text_params)
  88. G = plt.text(0, 0, '$G_3$', color='g', size=do_fontsize('G'),
  89. **text_params)
  90. C = plt.text(1, 0, '$C_3$', color='b', size=do_fontsize('C'),
  91. **text_params)
  92. arrow_h_offset = 0.25 # data coordinates, empirically determined
  93. max_arrow_length = 1 - 2 * arrow_h_offset
  94. max_head_width = 2.5 * max_arrow_width
  95. max_head_length = 2 * max_arrow_width
  96. arrow_params = {'length_includes_head': True, 'shape': shape,
  97. 'head_starts_at_zero': head_starts_at_zero}
  98. ax = plt.gca()
  99. sf = 0.6 # max arrow size represents this in data coords
  100. d = (r2 / 2 + arrow_h_offset - 0.5) / r2 # distance for diags
  101. r2v = arrow_sep / r2 # offset for diags
  102. # tuple of x, y for start position
  103. positions = {
  104. 'AT': (arrow_h_offset, 1 + arrow_sep),
  105. 'TA': (1 - arrow_h_offset, 1 - arrow_sep),
  106. 'GA': (-arrow_sep, arrow_h_offset),
  107. 'AG': (arrow_sep, 1 - arrow_h_offset),
  108. 'CA': (1 - d - r2v, d - r2v),
  109. 'AC': (d + r2v, 1 - d + r2v),
  110. 'GT': (d - r2v, d + r2v),
  111. 'TG': (1 - d + r2v, 1 - d - r2v),
  112. 'CT': (1 - arrow_sep, arrow_h_offset),
  113. 'TC': (1 + arrow_sep, 1 - arrow_h_offset),
  114. 'GC': (arrow_h_offset, arrow_sep),
  115. 'CG': (1 - arrow_h_offset, -arrow_sep)}
  116. if normalize_data:
  117. # find maximum value for rates, i.e. where keys are 2 chars long
  118. max_val = 0
  119. for k, v in data.items():
  120. if len(k) == 2:
  121. max_val = max(max_val, v)
  122. # divide rates by max val, multiply by arrow scale factor
  123. for k, v in data.items():
  124. data[k] = v / max_val * sf
  125. def draw_arrow(pair, alpha=alpha, ec=ec, labelcolor=labelcolor):
  126. # set the length of the arrow
  127. if display == 'length':
  128. length = max_head_length + data[pair] / sf * (max_arrow_length -
  129. max_head_length)
  130. else:
  131. length = max_arrow_length
  132. # set the transparency of the arrow
  133. if display == 'alpha':
  134. alpha = min(data[pair] / sf, alpha)
  135. # set the width of the arrow
  136. if display == 'width':
  137. scale = data[pair] / sf
  138. width = max_arrow_width * scale
  139. head_width = max_head_width * scale
  140. head_length = max_head_length * scale
  141. else:
  142. width = max_arrow_width
  143. head_width = max_head_width
  144. head_length = max_head_length
  145. fc = colors[pair]
  146. ec = ec or fc
  147. x_scale, y_scale = deltas[pair]
  148. x_pos, y_pos = positions[pair]
  149. plt.arrow(x_pos, y_pos, x_scale * length, y_scale * length,
  150. fc=fc, ec=ec, alpha=alpha, width=width,
  151. head_width=head_width, head_length=head_length,
  152. **arrow_params)
  153. # figure out coordinates for text
  154. # if drawing relative to base: x and y are same as for arrow
  155. # dx and dy are one arrow width left and up
  156. # need to rotate based on direction of arrow, use x_scale and y_scale
  157. # as sin x and cos x?
  158. sx, cx = y_scale, x_scale
  159. where = label_positions[pair]
  160. if where == 'left':
  161. orig_position = 3 * np.array([[max_arrow_width, max_arrow_width]])
  162. elif where == 'absolute':
  163. orig_position = np.array([[max_arrow_length / 2.0,
  164. 3 * max_arrow_width]])
  165. elif where == 'right':
  166. orig_position = np.array([[length - 3 * max_arrow_width,
  167. 3 * max_arrow_width]])
  168. elif where == 'center':
  169. orig_position = np.array([[length / 2.0, 3 * max_arrow_width]])
  170. else:
  171. raise ValueError("Got unknown position parameter %s" % where)
  172. M = np.array([[cx, sx], [-sx, cx]])
  173. coords = np.dot(orig_position, M) + [[x_pos, y_pos]]
  174. x, y = np.ravel(coords)
  175. orig_label = rate_labels[pair]
  176. label = r'$%s_{_{\mathrm{%s}}}$' % (orig_label[0], orig_label[1:])
  177. plt.text(x, y, label, size=label_text_size, ha='center', va='center',
  178. color=labelcolor or fc)
  179. for p in sorted(positions):
  180. draw_arrow(p)
  181. # test data
  182. all_on_max = dict([(i, 1) for i in 'TCAG'] +
  183. [(i + j, 0.6) for i in 'TCAG' for j in 'TCAG'])
  184. realistic_data = {
  185. 'A': 0.4,
  186. 'T': 0.3,
  187. 'G': 0.5,
  188. 'C': 0.2,
  189. 'AT': 0.4,
  190. 'AC': 0.3,
  191. 'AG': 0.2,
  192. 'TA': 0.2,
  193. 'TC': 0.3,
  194. 'TG': 0.4,
  195. 'CT': 0.2,
  196. 'CG': 0.3,
  197. 'CA': 0.2,
  198. 'GA': 0.1,
  199. 'GT': 0.4,
  200. 'GC': 0.1}
  201. extreme_data = {
  202. 'A': 0.75,
  203. 'T': 0.10,
  204. 'G': 0.10,
  205. 'C': 0.05,
  206. 'AT': 0.6,
  207. 'AC': 0.3,
  208. 'AG': 0.1,
  209. 'TA': 0.02,
  210. 'TC': 0.3,
  211. 'TG': 0.01,
  212. 'CT': 0.2,
  213. 'CG': 0.5,
  214. 'CA': 0.2,
  215. 'GA': 0.1,
  216. 'GT': 0.4,
  217. 'GC': 0.2}
  218. sample_data = {
  219. 'A': 0.2137,
  220. 'T': 0.3541,
  221. 'G': 0.1946,
  222. 'C': 0.2376,
  223. 'AT': 0.0228,
  224. 'AC': 0.0684,
  225. 'AG': 0.2056,
  226. 'TA': 0.0315,
  227. 'TC': 0.0629,
  228. 'TG': 0.0315,
  229. 'CT': 0.1355,
  230. 'CG': 0.0401,
  231. 'CA': 0.0703,
  232. 'GA': 0.1824,
  233. 'GT': 0.0387,
  234. 'GC': 0.1106}
  235. if __name__ == '__main__':
  236. from sys import argv
  237. d = None
  238. if len(argv) > 1:
  239. if argv[1] == 'full':
  240. d = all_on_max
  241. scaled = False
  242. elif argv[1] == 'extreme':
  243. d = extreme_data
  244. scaled = False
  245. elif argv[1] == 'realistic':
  246. d = realistic_data
  247. scaled = False
  248. elif argv[1] == 'sample':
  249. d = sample_data
  250. scaled = True
  251. if d is None:
  252. d = all_on_max
  253. scaled = False
  254. if len(argv) > 2:
  255. display = argv[2]
  256. else:
  257. display = 'length'
  258. size = 4
  259. plt.figure(figsize=(size, size))
  260. make_arrow_plot(d, display=display, linewidth=0.001, edgecolor=None,
  261. normalize_data=scaled, head_starts_at_zero=True, size=size)
  262. plt.show()

下载这个示例