pyrolite 0.0.14__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__init__.py +10 -0
  2. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/__init__.cpython-36.pyc +0 -0
  3. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/_version.cpython-36.pyc +0 -0
  4. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/alteration.cpython-36.pyc +0 -0
  5. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/classification.cpython-36.pyc +0 -0
  6. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/compositions.cpython-36.pyc +0 -0
  7. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/geochem.cpython-36.pyc +0 -0
  8. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/melts.cpython-36.pyc +0 -0
  9. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/norm.cpython-36.pyc +0 -0
  10. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/normalisation.cpython-36.pyc +0 -0
  11. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/plot.cpython-36.pyc +0 -0
  12. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/_version.py +21 -0
  13. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/alteration.py +66 -0
  14. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/classification.py +222 -0
  15. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__init__.py +9 -0
  16. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/__init__.cpython-36.pyc +0 -0
  17. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/aggregate.cpython-36.pyc +0 -0
  18. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/codata.cpython-36.pyc +0 -0
  19. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/impute.cpython-36.pyc +0 -0
  20. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/renorm.cpython-36.pyc +0 -0
  21. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/aggregate.py +391 -0
  22. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/codata.py +266 -0
  23. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/impute.py +82 -0
  24. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/renorm.py +40 -0
  25. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/compositions.py +524 -0
  26. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_CFB_Dataset_List.csv +42 -0
  27. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_Convergent_Dataset_List.csv +42 -0
  28. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OBFB_Dataset_List.csv +5 -0
  29. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OIB_Dataset_List.csv +49 -0
  30. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OceanicPlateau_Dataset_List.csv +18 -0
  31. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/contents.json +1 -0
  32. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-35.pyc +0 -0
  33. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-36.pyc +0 -0
  34. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/env.py +1063 -0
  35. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ba.modelfield +0 -0
  36. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Bs.modelfield +0 -0
  37. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.F.modelfield +0 -0
  38. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O1.modelfield +0 -0
  39. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O2.modelfield +0 -0
  40. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O3.modelfield +0 -0
  41. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Pc.modelfield +0 -0
  42. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ph.modelfield +0 -0
  43. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.R.modelfield +0 -0
  44. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S1.modelfield +0 -0
  45. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S2.modelfield +0 -0
  46. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S3.modelfield +0 -0
  47. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T1.modelfield +0 -0
  48. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T2.modelfield +0 -0
  49. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U1.modelfield +0 -0
  50. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U2.modelfield +0 -0
  51. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U3.modelfield +0 -0
  52. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.modelfields +0 -0
  53. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.nan.modelfield +0 -0
  54. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.none.modelfield +0 -0
  55. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS.clsf.gz +0 -0
  56. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/aphanitic.clsf.gz +0 -0
  57. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/gabbroic.clsf.gz +0 -0
  58. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/peralkalinity.clsf.gz +0 -0
  59. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/phaneritic.clsf.gz +0 -0
  60. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/ultramafic.clsf.gz +0 -0
  61. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/CH_PalmeONeill2014.csv +95 -0
  62. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DDMM_WorkmanHart2005.csv +105 -0
  63. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DMM_WorkmanHart2005.csv +105 -0
  64. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DM_SaltersStrake2004.csv +95 -0
  65. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/EDMM_WorkmanHart2005.csv +105 -0
  66. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/PM_PalmeONeill2014.csv +95 -0
  67. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/timescale/geotimescale_spans.csv +180 -0
  68. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/geochem.py +821 -0
  69. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/melts.py +92 -0
  70. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__init__.py +10 -0
  71. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/__init__.cpython-36.pyc +0 -0
  72. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/db.cpython-36.pyc +0 -0
  73. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/ions.cpython-36.pyc +0 -0
  74. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/mineral.cpython-36.pyc +0 -0
  75. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/sites.cpython-36.pyc +0 -0
  76. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/db.py +88 -0
  77. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/ions.py +78 -0
  78. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/mineral.py +587 -0
  79. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/sites.py +134 -0
  80. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/norm.py +224 -0
  81. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/normalisation.py +204 -0
  82. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/plot.py +514 -0
  83. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__init__.py +13 -0
  84. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/__init__.cpython-36.pyc +0 -0
  85. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/database.cpython-36.pyc +0 -0
  86. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/env.cpython-36.pyc +0 -0
  87. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/general.cpython-36.pyc +0 -0
  88. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/georoc.cpython-36.pyc +0 -0
  89. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/math.cpython-36.pyc +0 -0
  90. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/melts.cpython-36.pyc +0 -0
  91. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multip.cpython-36.pyc +0 -0
  92. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multiprocessing.cpython-36.pyc +0 -0
  93. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/pd.cpython-36.pyc +0 -0
  94. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/plot.cpython-36.pyc +0 -0
  95. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/skl.cpython-36.pyc +0 -0
  96. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/spatial.cpython-36.pyc +0 -0
  97. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/text.cpython-36.pyc +0 -0
  98. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/time.cpython-36.pyc +0 -0
  99. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/wfs.cpython-36.pyc +0 -0
  100. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/database.py +88 -0
  101. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/env.py +81 -0
  102. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/general.py +266 -0
  103. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/georoc.py +444 -0
  104. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/math.py +371 -0
  105. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/melts.py +397 -0
  106. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multip.py +29 -0
  107. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multiprocessing.py +29 -0
  108. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/pd.py +214 -0
  109. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/plot.py +345 -0
  110. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/skl.py +847 -0
  111. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/spatial.py +91 -0
  112. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/text.py +207 -0
  113. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/time.py +224 -0
  114. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/wfs.py +10 -0
  115. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/PKG-INFO +61 -0
  116. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/SOURCES.txt +83 -0
  117. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/dependency_links.txt +1 -0
  118. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/requires.txt +47 -0
  119. ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/top_level.txt +1 -0
@@ -0,0 +1,345 @@
1
+ import os
2
+ from copy import copy
3
+ from types import MethodType
4
+ from pathlib import Path
5
+ import numpy as np
6
+ import pandas as pd
7
+ from scipy import interpolate
8
+ from scipy.stats.kde import gaussian_kde
9
+ from scipy.spatial import ConvexHull
10
+ import matplotlib.pyplot as plt
11
+ import matplotlib.colors as colors
12
+ import matplotlib.lines as mlines
13
+ import matplotlib.patches as patches
14
+ from mpl_toolkits.axes_grid1 import make_axes_locatable
15
+ import matplotlib.axes as matax
16
+ from matplotlib.transforms import Bbox
17
+ import logging
18
+
19
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
20
+ logger = logging.getLogger()
21
+
22
+
23
+ def add_legend_items(ax):
24
+
25
+ handles_original = []
26
+ handles_original += ax.lines + ax.patches + ax.collections + ax.containers
27
+ # support parasite axes:
28
+ if hasattr(ax, "parasites"):
29
+ for axx in ax.parasites:
30
+ handles_original += (
31
+ axx.lines + axx.patches + axx.collections + axx.containers
32
+ )
33
+ handles, labels = [], []
34
+ for handle in handles_original:
35
+ label = handle.get_label()
36
+ if label and not label.startswith("_"):
37
+ handles.append(handle)
38
+ labels.append(label)
39
+
40
+
41
+ def modify_legend_handles(ax, **kwargs):
42
+ """
43
+ Modify the handles of a legend based for a single axis.
44
+
45
+ Parameters
46
+ ----------
47
+ ax: matplotlib.axes.Axes
48
+ Axis for which to obtain modifed legend handles.
49
+ kwargs:
50
+ Keyword arguments to be passed to the handles.
51
+
52
+ Returns
53
+ -------
54
+ tuple
55
+ Handles, labels to be passed to a legend call.
56
+ """
57
+ hndls, labls = ax.get_legend_handles_labels()
58
+ _hndls = []
59
+ for h in hndls:
60
+ _h = copy(h)
61
+ print(_h, dir(_h))
62
+ _h.update(kwargs)
63
+ _hndls.append(_h)
64
+ return _hndls, labls
65
+
66
+
67
+ def add_colorbar(mappable, **kwargs):
68
+ """
69
+ Adds a colorbar to a given mappable object.
70
+
71
+ Source: http://joseph-long.com/writing/colorbars/
72
+
73
+ Parameters
74
+ ----------
75
+ mappable :
76
+ The Image, ContourSet, etc. to which the colorbar applies.
77
+
78
+ Returns
79
+ ----------
80
+ colorbar: matplotlib.colorbar.Colorbar
81
+ """
82
+ ax = kwargs.get("ax", None)
83
+ if hasattr(mappable, "axes"):
84
+ ax = ax or mappable.axes
85
+ elif hasattr(mappable, "ax"):
86
+ ax = ax or mappable.ax
87
+
88
+ position = kwargs.pop("position", "right")
89
+ size = kwargs.pop("size", "5%")
90
+ pad = kwargs.pop("pad", 0.05)
91
+
92
+ fig = ax.figure
93
+ divider = make_axes_locatable(ax)
94
+ cax = divider.append_axes(position, size=size, pad=pad)
95
+ return fig.colorbar(mappable, cax=cax, **kwargs)
96
+
97
+
98
+ def ABC_to_tern_xy(ABC):
99
+ (A, B, C) = ABC
100
+ T = A + B + C
101
+ A_n, B_n, C_n = np.divide(A, T), np.divide(B, T), np.divide(C, T)
102
+ xdata = 100.0 * (
103
+ (C_n / np.sin(np.pi / 3) + A_n / np.tan(np.pi / 3.0)) * np.sin(np.pi / 3.0)
104
+ )
105
+ ydata = 100.0 * (2.0 / (3.0 ** 0.5)) * A_n * np.sin(np.pi / 3.0)
106
+ return xdata, ydata
107
+
108
+
109
+ def tern_heatmapcoords(data, scale=10, bins=10):
110
+ # this appears to cause problems for ternary density diagrams
111
+ x, y = ABC_to_tern_xy(data)
112
+ xydata = np.vstack((x, y))
113
+ k = gaussian_kde(xydata)
114
+
115
+ tridata = dict()
116
+ step = scale // bins
117
+ for i in np.arange(0, scale + 1, step):
118
+ for j in np.arange(0, scale + 1 - i, step):
119
+ datacoord = i, j
120
+ # datacoord = i+0.5*step, j+0.5*step
121
+ tridata[(i, j)] = np.float(k(np.vstack(datacoord)))
122
+
123
+ return tridata
124
+
125
+
126
+ def proxy_rect(**kwargs):
127
+ """
128
+ Generates a legend proxy for a filled region.
129
+
130
+ Returns
131
+ ----------
132
+ rect: matplotlib.patches.Rectangle
133
+ """
134
+ return patches.Rectangle((0, 0), 1, 1, **kwargs)
135
+
136
+
137
+ def proxy_line(**kwargs):
138
+ """
139
+ Generates a legend proxy for a line region.
140
+
141
+ Returns
142
+ ----------
143
+ line: matplotlib.lines.Line2D
144
+ """
145
+ return mlines.Line2D(range(1), range(1), **kwargs)
146
+
147
+
148
+ def draw_vector(v0, v1, ax=None, **kwargs):
149
+ """
150
+ Plots an arrow represnting the direction and magnitue of a principal
151
+ component on a biaxial plot.
152
+
153
+ Todo: update for ternary plots.
154
+
155
+ Modified after Jake VanderPlas' Python Data Science Handbook
156
+ https://jakevdp.github.io/PythonDataScienceHandbook/ \
157
+ 05.09-principal-component-analysis.html
158
+ """
159
+ ax = ax
160
+ arrowprops = dict(arrowstyle="->", linewidth=2, shrinkA=0, shrinkB=0)
161
+ arrowprops.update(kwargs)
162
+ ax.annotate("", v1, v0, arrowprops=arrowprops)
163
+
164
+
165
+ def vector_to_line(
166
+ mu: np.array, vector: np.array, variance: float, spans: int = 4, expand: int = 10
167
+ ):
168
+ """
169
+ Creates an array of points representing a line along a vector - typically
170
+ for principal component analysis.
171
+
172
+ Modified after Jake VanderPlas' Python Data Science Handbook
173
+ https://jakevdp.github.io/PythonDataScienceHandbook/05.09-principal-component-analysis.html
174
+ """
175
+ length = np.sqrt(variance)
176
+ parts = np.linspace(-spans, spans, expand * 2 * spans + 1)
177
+ line = length * np.dot(parts[:, np.newaxis], vector[np.newaxis, :]) + mu
178
+ line = length * parts.reshape(parts.shape[0], 1) * vector + mu
179
+ return line
180
+
181
+
182
+ def plot_2dhull(ax, data, splines=False, s=0, **plotkwargs):
183
+ """
184
+ Plots a 2D convex hull around an array of xy data points.
185
+ """
186
+ chull = ConvexHull(data, incremental=True)
187
+ x, y = data[chull.vertices].T
188
+ if not splines:
189
+ lines = ax.plot(np.append(x, [x[0]]), np.append(y, [y[0]]), **plotkwargs)
190
+ else:
191
+ # https://stackoverflow.com/questions/33962717/interpolating-a-closed-curve-using-scipy
192
+ tck, u = interpolate.splprep([x, y], per=True, s=s)
193
+ xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck)
194
+ lines = ax.plot(xi, yi, **plotkwargs)
195
+ return lines
196
+
197
+
198
+ def nan_scatter(xdata, ydata, ax=None, axes_width=0.2, **kwargs):
199
+ """
200
+ Scatter plot with additional marginal axes to plot data for which data is partially
201
+ missing. Additional keyword arguments are passed to matplotlib.
202
+
203
+ Parameters
204
+ -----------
205
+ xdata : np.ndarray | pd.Series
206
+ X data
207
+ ydata: np.ndarray | pd.Series
208
+ Y data
209
+ ax : matplotlib.axes.Axes
210
+ Axes on which to plot.
211
+ axes_width : float
212
+ Width of the marginal axes.
213
+ """
214
+ if ax is None:
215
+ fig, ax = plt.subplots(1)
216
+
217
+ ax.scatter(xdata, ydata, **kwargs)
218
+
219
+ if hasattr(ax, "divider"): # Don't rebuild axes
220
+ div = ax.divider
221
+ nanaxx = div.nanaxx
222
+ nanaxy = div.nanaxy
223
+ else: # Build axes
224
+ ax.yaxis.set_tick_params(labelleft=False, left=False)
225
+ ax.xaxis.set_tick_params(labelbottom=False, bottom=False)
226
+ ax.spines["top"].set_visible(False)
227
+ ax.spines["right"].set_visible(False)
228
+
229
+ div = make_axes_locatable(ax)
230
+ ax.divider = div
231
+
232
+ nanaxx = div.append_axes("bottom", axes_width, pad=0, sharex=ax)
233
+ div.nanaxx = nanaxx
234
+ nanaxx.invert_yaxis()
235
+ nanaxx.yaxis.set_visible(False)
236
+ nanaxx.spines["left"].set_visible(False)
237
+ nanaxx.spines["right"].set_visible(False)
238
+ nanaxx.set_facecolor("none")
239
+
240
+ nanaxy = div.append_axes("left", axes_width, pad=0, sharey=ax)
241
+ div.nanaxy = nanaxy
242
+ nanaxy.invert_xaxis()
243
+ nanaxy.xaxis.set_visible(False)
244
+ nanaxy.spines["top"].set_visible(False)
245
+ nanaxy.spines["bottom"].set_visible(False)
246
+ nanaxy.set_facecolor("none")
247
+
248
+ nanxdata = xdata[(np.isnan(ydata) & np.isfinite(xdata))]
249
+ nanydata = ydata[(np.isnan(xdata) & np.isfinite(ydata))]
250
+
251
+ yminmax = np.nanmin(ydata), np.nanmax(ydata)
252
+ no_ybins = 50
253
+ ybinwidth = (np.nanmax(ydata) - np.nanmin(ydata)) / no_ybins
254
+ ybins = np.linspace(np.nanmin(ydata), np.nanmax(ydata) + ybinwidth, no_ybins)
255
+
256
+ nanaxy.hist(nanydata, bins=ybins, orientation="horizontal", **kwargs)
257
+ nanaxy.scatter(
258
+ 10 * np.ones_like(nanydata) + 5 * np.random.randn(len(nanydata)),
259
+ nanydata,
260
+ zorder=-1,
261
+ **kwargs
262
+ )
263
+
264
+ xminmax = np.nanmin(xdata), np.nanmax(xdata)
265
+ no_xbins = 50
266
+ xbinwidth = (np.nanmax(xdata) - np.nanmin(xdata)) / no_xbins
267
+ xbins = np.linspace(np.nanmin(xdata), np.nanmax(xdata) + xbinwidth, no_xbins)
268
+
269
+ nanaxx.hist(nanxdata, bins=xbins, **kwargs)
270
+ nanaxx.scatter(
271
+ nanxdata,
272
+ 10 * np.ones_like(nanxdata) + 5 * np.random.randn(len(nanxdata)),
273
+ zorder=-1,
274
+ **kwargs
275
+ )
276
+
277
+ return ax
278
+
279
+
280
+ def save_figure(
281
+ figure, save_at="", name="fig", save_fmts=["png"], output=False, **kwargs
282
+ ):
283
+ """
284
+ Save a figure at a specified location in a number of formats.
285
+ """
286
+ default_config = dict(dpi=600, bbox_inches="tight", transparent=True)
287
+ config = default_config.copy()
288
+ config.update(kwargs)
289
+ for fmt in save_fmts:
290
+ out_filename = os.path.join(save_at, name + "." + fmt)
291
+ if output:
292
+ print("Saving " + out_filename)
293
+ figure.savefig(out_filename, format=fmt, **config)
294
+
295
+
296
+ def save_axes(ax, save_at="", name="fig", save_fmts=["png"], pad=0.0, **kwargs):
297
+ """
298
+ Save either a single or multiple axes (from a single figure) based on their
299
+ extent. Uses the save_figure procedure to save at a specific location using
300
+ a number of formats.
301
+ """
302
+ # Check if axes is a single axis or list of axes
303
+
304
+ if isinstance(ax, matax.Axes):
305
+ extent = get_full_extent(ax, pad=pad)
306
+ figure = ax.figure
307
+ else:
308
+ extent_items = []
309
+ for a in ax:
310
+ extent_items.append(get_full_extent(a, pad=pad))
311
+ figure = axes[0].figure
312
+ extent = Bbox.union([item for item in extent_items])
313
+ save_figure(
314
+ figure,
315
+ bbox_inches=extent,
316
+ save_at=save_at,
317
+ name=name,
318
+ save_fmts=save_fmts,
319
+ **kwargs
320
+ )
321
+
322
+
323
+ def get_full_extent(ax, pad=0.0):
324
+ """Get the full extent of an axes, including axes labels, tick labels, and
325
+ titles. Text objects are first drawn to define the extents."""
326
+ fig = ax.figure
327
+ fig.canvas.draw()
328
+ renderer = fig.canvas.renderer
329
+
330
+ items = [ax]
331
+
332
+ if len(ax.get_title()):
333
+ items += [ax.title]
334
+
335
+ for a in [ax.xaxis, ax.yaxis]:
336
+ if len(a.get_label_text()):
337
+ items += [a.label]
338
+
339
+ for t_lb in [ax.get_xticklabels(), ax.get_yticklabels()]:
340
+ if np.array([len(i.get_text()) > 0 for i in t_lb]).any():
341
+ items += t_lb
342
+
343
+ bbox = Bbox.union([item.get_window_extent(renderer) for item in items])
344
+ full_extent = bbox.expanded(1.0 + pad, 1.0 + pad)
345
+ return full_extent.transformed(ax.figure.dpi_scale_trans.inverted())