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,514 @@
1
+ import pandas as pd
2
+ import pandas_flavor as pf
3
+ from scipy.stats.kde import gaussian_kde
4
+ import matplotlib.pyplot as plt
5
+ from matplotlib.ticker import MaxNLocator
6
+ import numpy as np
7
+ import ternary
8
+ from .util.pd import to_frame
9
+ from .util.math import on_finite
10
+ from .util.plot import ABC_to_tern_xy, tern_heatmapcoords, add_colorbar
11
+ from .util.general import iscollection
12
+ from .geochem import common_elements, REE, get_radii
13
+ import logging
14
+
15
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
16
+ logger = logging.getLogger(__name__)
17
+
18
+ DEFAULT_CONT_COLORMAP = plt.cm.viridis
19
+ DEFAULT_DISC_COLORMAP = plt.cm.tab10
20
+
21
+
22
+ @pf.register_series_method
23
+ @pf.register_dataframe_method
24
+ def spiderplot(
25
+ df, components: list = None, ax=None, plot=True, fill=False, indexes=None, **kwargs
26
+ ):
27
+ """
28
+ Plots spidergrams for trace elements data. Additional keyword arguments are
29
+ passed to matplotlib.
30
+
31
+ By using separate lines and scatterplots, values between two missing
32
+ items are still presented. Might be able to speed up the lines
33
+ with a matplotlib.collections.LineCollection.
34
+
35
+ Parameters
36
+ ----------
37
+ df: pandas DataFrame
38
+ Dataframe from which to draw data.
39
+ components: list, None
40
+ Elements or compositional components to plot.
41
+ ax: Matplotlib AxesSubplot, None
42
+ The subplot to draw on.
43
+ plot: boolean, True
44
+ Whether to plot lines and markers.
45
+ fill:
46
+ Whether to add a patch representing the full range.
47
+ """
48
+ kwargs = kwargs.copy()
49
+ try:
50
+ assert plot or fill
51
+ except:
52
+ msg = "Please select to either plot values or fill between ranges."
53
+ raise AssertionError(msg)
54
+
55
+ df = to_frame(df)
56
+
57
+ if components is None:
58
+ components = [el for el in common_elements() if el in df.columns]
59
+
60
+ assert len(components) != 0
61
+
62
+ sty = {}
63
+
64
+ # Color ----------------------------------------------------------
65
+
66
+ variable_colors = False
67
+ color = kwargs.get("color") or kwargs.get("c")
68
+ norm = kwargs.pop("norm", None)
69
+ if color is not None:
70
+ if iscollection(color):
71
+ sty["c"] = color
72
+ variable_colors = True
73
+ else:
74
+ sty["color"] = color
75
+
76
+ _c = sty.pop("c", None)
77
+
78
+ cmap = kwargs.get("cmap", None)
79
+ if isinstance(cmap, str):
80
+ cmap = plt.get_cmap(cmap)
81
+
82
+ if (_c is not None) and (cmap is not None):
83
+ if norm is not None:
84
+ _c = [norm(c) for c in _c]
85
+ _c = [cmap(c) for c in _c]
86
+
87
+ sty["alpha"] = kwargs.get("alpha") or kwargs.get("a") or 1.0
88
+
89
+ # ---------------------------------------------------------------------
90
+
91
+ ax = ax or plt.subplots(1, figsize=(len(components) * 0.3, 4))[1]
92
+
93
+ if indexes is None:
94
+ indexes = np.arange(len(components))
95
+ ax.set_xticks(indexes)
96
+ ax.set_xticklabels(components, rotation=60)
97
+
98
+ if fill:
99
+ mins = df.loc[:, components].min(axis=0)
100
+ maxs = df.loc[:, components].max(axis=0)
101
+ plycol = ax.fill_between(indexes, mins, maxs, **sty)
102
+ # Use the first (typically only) element for color
103
+ if (sty.get("color") is None) and (sty.get("c") is None):
104
+ sty["color"] = plycol.get_facecolor()[0]
105
+
106
+ sty["marker"] = kwargs.get("marker", None) or "D"
107
+
108
+ # Use the default color cycling to provide a single color
109
+ if sty.get("color") is None and _c is None:
110
+ sty["color"] = next(ax._get_lines.prop_cycler)["color"]
111
+
112
+ if plot:
113
+ ls = ax.plot(indexes, df.loc[:, components].T.values.astype(np.float), **sty)
114
+ if variable_colors:
115
+ for l, c in zip(ls, _c):
116
+ l.set_color(c)
117
+
118
+ sty["s"] = kwargs.get("markersize") or kwargs.get("s") or 5.0
119
+ if (sty.get("color") is None) and (_c is None):
120
+ sty["color"] = ls[0].get_color()
121
+
122
+ sty["label"] = kwargs.pop("label", None)
123
+ # For the scatter, the number of points > the number of series
124
+ # Need to check if this is the case, and create equivalent
125
+
126
+ if _c is not None:
127
+ cshape = np.array(_c).shape
128
+ if cshape != df.loc[:, components].shape:
129
+ # expand it across the columns
130
+ _c = np.tile(_c, (len(components), 1))
131
+
132
+ sc = ax.scatter(
133
+ np.tile(indexes, (df.loc[:, components].index.size, 1)).T,
134
+ df.loc[:, components].T.values.astype(np.float),
135
+ **sty,
136
+ )
137
+
138
+ ax.set_yscale("log")
139
+ ax.set_xlabel("Element")
140
+
141
+ unused_keys = [i for i in kwargs if i not in list(sty.keys())]
142
+ if len(unused_keys):
143
+ logger.info("Styling not yet implemented for:{}".format(unused_keys))
144
+
145
+ return ax
146
+
147
+
148
+ @pf.register_series_method
149
+ @pf.register_dataframe_method
150
+ def REE_radii_plot(df=None, ax=None, **kwargs):
151
+ """
152
+ Creates an axis for a REE diagram with ionic radii along the x axis.
153
+
154
+ Parameters
155
+ -----------
156
+ ax : matplotlib.axes.Axes
157
+ Optional designation of axes to reconfigure.
158
+ """
159
+ if ax is not None:
160
+ fig = ax.figure
161
+ ax = ax
162
+ else:
163
+ fig, ax = plt.subplots()
164
+
165
+ ree = REE()
166
+ radii = np.array(get_radii(ree))
167
+
168
+ if df is not None:
169
+ if any([i in df.columns for i in ree]):
170
+ reedata = df.loc[:, ree]
171
+ reedata.spiderplot(ax=ax, indexes=radii, **kwargs)
172
+
173
+ _ax = ax.twiny()
174
+ ax.set_yscale("log")
175
+ ax.set_xlim((0.99 * radii.min(), 1.01 * radii.max()))
176
+ _ax.set_xlim(ax.get_xlim())
177
+ _ax.set_xticks(radii)
178
+ _ax.set_xticklabels(ree)
179
+ _ax.set_xlabel("Element")
180
+ ax.axhline(1.0, ls="--", c="k", lw=0.5)
181
+ ax.set_ylabel(" $\mathrm{X / X_{Reference}}$")
182
+ ax.set_xlabel("Ionic Radius ($\mathrm{\AA}$)")
183
+
184
+ return ax
185
+
186
+
187
+ @pf.register_series_method
188
+ @pf.register_dataframe_method
189
+ def ternaryplot(df, components: list = None, ax=None, clockwise=True, **kwargs):
190
+ """
191
+ Plots scatter ternary diagrams, using a wrapper around the
192
+ python-ternary library (gh.com/marcharper/python-ternary).
193
+ Additional keyword arguments arepassed to matplotlib.
194
+
195
+ Parameters
196
+ ----------
197
+ df: pandas DataFrame
198
+ Dataframe from which to draw data.
199
+ components: list, None
200
+ Elements or compositional components to plot.
201
+ ax: Matplotlib AxesSubplot, None
202
+ The subplot to draw on.
203
+ """
204
+ kwargs = kwargs.copy()
205
+ df = to_frame(df)
206
+
207
+ try:
208
+ if not df.columns.size == 3:
209
+ assert len(components) == 3
210
+
211
+ if components is None:
212
+ components = df.columns.values
213
+ except:
214
+ msg = "Suggest components or provide a slice of the dataframe."
215
+ raise AssertionError(msg)
216
+
217
+ # Some default values
218
+ scale = kwargs.pop("scale", None) or 100.0
219
+ figsize = kwargs.pop("size", None) or 8.0
220
+ gridsize = kwargs.pop("gridsize", None) or 10.0
221
+ fontsize = kwargs.pop("fontsize", None) or 10.0
222
+
223
+ sty = {}
224
+ sty["marker"] = kwargs.pop("marker", None) or "D"
225
+ sty["color"] = kwargs.pop("color", None) or kwargs.pop("c", None) or "0.5"
226
+ sty["label"] = kwargs.pop("label", None)
227
+ sty["alpha"] = kwargs.pop("alpha", None) or kwargs.pop("a", None) or 1.0
228
+
229
+ ax = ax or plt.subplots(1, figsize=(figsize, figsize * 3 ** 0.5 * 0.5))[1]
230
+ d1 = ax.__dict__.copy()
231
+
232
+ # Checking if there's already a ternary axis
233
+ tax = getattr(ax, "tax", None) or ternary.figure(ax=ax, scale=scale)[1]
234
+
235
+ # Set attribute for future reference
236
+ ax.tax = tax
237
+ points = (
238
+ df.loc[:, components].div(df.loc[:, components].sum(axis=1), axis=0).values
239
+ * scale
240
+ )
241
+ if points.any():
242
+ tax.scatter(points, **sty)
243
+
244
+ if sty["label"] is not None:
245
+ tax.legend(frameon=False)
246
+
247
+ # Check if there's already labels
248
+ if not len(tax._labels.keys()):
249
+ tax.left_axis_label(components[2], fontsize=fontsize)
250
+ tax.bottom_axis_label(components[0], fontsize=fontsize)
251
+ tax.right_axis_label(components[1], fontsize=fontsize)
252
+
253
+ tax.gridlines(multiple=gridsize, color="k", alpha=0.5)
254
+ tax.ticks(axis="lbr", linewidth=1, clockwise=clockwise, multiple=gridsize)
255
+ tax.boundary(linewidth=1.0)
256
+ ax.spines["top"].set_visible(False)
257
+ ax.spines["right"].set_visible(False)
258
+ ax.spines["bottom"].set_visible(False)
259
+ ax.spines["left"].set_visible(False)
260
+ ax.get_xaxis().set_ticks([])
261
+ ax.get_yaxis().set_ticks([])
262
+
263
+ return ax
264
+
265
+
266
+ @pf.register_series_method
267
+ @pf.register_dataframe_method
268
+ def densityplot(
269
+ df,
270
+ components: list = None,
271
+ ax=None,
272
+ mode="density",
273
+ coverage_scale=1.1,
274
+ logspace=False,
275
+ contour=False,
276
+ extent=None,
277
+ **kwargs
278
+ ):
279
+ """
280
+ Plots density plot diagrams. Should work for either binary components (X-Y)
281
+ or in a ternary plot. Some additional keyword arguments are passed to
282
+ matplotlib.
283
+
284
+ Todo:
285
+ Split logscales for x and y (currently only for log-log)
286
+
287
+ Parameters
288
+ ----------
289
+ df: pandas DataFrame
290
+ Dataframe from which to draw data.
291
+ components: list, None
292
+ Elements or compositional components to plot.
293
+ ax: Matplotlib AxesSubplot, None
294
+ The subplot to draw on.
295
+ mode: str, 'density'
296
+ Different modes used here: ['density', 'hexbin', 'hist2d']
297
+ coverage_scale: float, 1.1
298
+ Scale the area over which the density plot is drawn.
299
+ logspace: {False, True}
300
+ Whether to use a logspaced grid. Note that values strickly >0 are
301
+ required.
302
+ contour: {False, True}
303
+ Whether to add density contours to the plot.
304
+ """
305
+ kwargs = kwargs.copy()
306
+ df = to_frame(df)
307
+ try:
308
+ if df.columns.size not in [2, 3]:
309
+ assert len(components) in [2, 3]
310
+
311
+ if components is None:
312
+ components = df.columns.values
313
+ except:
314
+ msg = "Suggest components or provide a slice of the dataframe."
315
+ raise AssertionError(msg)
316
+
317
+ figsize = kwargs.pop("figsize", 8.0)
318
+ fontsize = kwargs.pop("fontsize", 12.0)
319
+ linewidths = kwargs.pop("linewidths", None)
320
+ linestyles = kwargs.pop("linestyles", None)
321
+
322
+ colorbar = kwargs.pop("colorbar", False)
323
+
324
+ ax = ax or plt.subplots(1, figsize=(figsize, figsize * 3 ** 0.5 * 0.5))[1]
325
+ background_color = ax.patch.get_facecolor() # consider alpha here
326
+ nbins = kwargs.pop("bins", 20)
327
+ cmap = kwargs.pop("cmap", DEFAULT_CONT_COLORMAP)
328
+ if isinstance(cmap, str):
329
+ cmap = plt.get_cmap(cmap)
330
+ cmap.set_under(color=background_color)
331
+
332
+ exp = (coverage_scale - 1) / 2
333
+ data = df.loc[:, components].values
334
+
335
+ if data.any():
336
+ # Data can't be plotted if there's any nans, so we can exclude these
337
+ data = data[(np.isfinite(data).all(axis=1)), :]
338
+ if len(components) == 2: # binary
339
+ x, y = data.T
340
+ if extent is not None:
341
+ xmin, xmax, ymin, ymax = extent
342
+ else:
343
+ xmin, xmax = (
344
+ on_finite(x, np.min) * (1.0 - exp),
345
+ on_finite(x, np.max) * (1.0 + exp),
346
+ ) # 120% range
347
+ ymin, ymax = (
348
+ on_finite(y, np.min) * (1.0 - exp),
349
+ on_finite(y, np.max) * (1.0 + exp),
350
+ ) # 120% range
351
+ if not logspace:
352
+ xstep = (xmax - xmin) / nbins
353
+ ystep = (ymax - ymin) / nbins
354
+ else:
355
+ xstep = (xmax / xmin) / nbins
356
+ ystep = (ymax / ymin) / nbins
357
+
358
+ plotextent = extent or (xmin, xmax, ymin, ymax)
359
+
360
+ if mode == "hexbin":
361
+ vmin = kwargs.pop("vmin", 0)
362
+ if logspace:
363
+ # extent values are exponents (i.e. 3 -> 10**3)
364
+ hex_extent = (
365
+ np.log(xmin / xstep),
366
+ np.log(xmax * xstep),
367
+ np.log(ymin / ystep),
368
+ np.log(ymax * ystep),
369
+ )
370
+ mappable = ax.hexbin(
371
+ x,
372
+ y,
373
+ gridsize=nbins,
374
+ cmap=cmap,
375
+ extent=hex_extent,
376
+ xscale="log",
377
+ yscale="log",
378
+ **kwargs,
379
+ )
380
+ else:
381
+ hex_extent = (
382
+ xmin - xstep,
383
+ xmax + xstep,
384
+ ymin - ystep,
385
+ ymax + ystep,
386
+ )
387
+ mappable = ax.hexbin(
388
+ x, y, gridsize=nbins, cmap=cmap, extent=hex_extent, **kwargs
389
+ )
390
+ cbarlabel = "Frequency"
391
+
392
+ elif mode == "hist2d":
393
+ vmin = kwargs.pop("vmin", 0)
394
+ if logspace:
395
+ assert ((xmin / xstep) > 0.0) and ((ymin / ystep) > 0.0)
396
+ xe = np.logspace(
397
+ np.log(xmin / xstep), np.log(xmax * xstep), nbins + 1
398
+ )
399
+ ye = np.logspace(
400
+ np.log(ymin / ystep), np.log(ymax * ystep), nbins + 1
401
+ )
402
+ else:
403
+ xe = np.linspace(xmin - xstep, xmax + xstep, nbins + 1)
404
+ ye = np.linspace(ymin - ystep, ymax + ystep, nbins + 1)
405
+
406
+ range = [[plotextent[0], plotextent[1]], [plotextent[2], plotextent[3]]]
407
+ h, xe, ye, im = ax.hist2d(
408
+ x, y, bins=[xe, ye], range=range, cmap=cmap, **kwargs
409
+ )
410
+ mappable = im
411
+ cbarlabel = "Frequency"
412
+
413
+ elif mode == "density":
414
+ shading = kwargs.pop("shading", None) or "flat"
415
+ kdedata = data.T
416
+ # Can't have nans or infs
417
+ # kdedata = kdedata[:, (np.isfinite(kdedata).all(axis=0))]
418
+
419
+ if logspace:
420
+ assert xmin > 0.0 and ymin > 0.0
421
+ # Generate grid in logspace
422
+ _xs = np.linspace(np.log(xmin), np.log(xmax), nbins + 1)
423
+ _ys = np.linspace(np.log(ymin), np.log(ymax), nbins + 1)
424
+ xi, yi = np.meshgrid(_xs, _ys)
425
+ # Generate KDE in logspace
426
+ k = gaussian_kde(np.log(kdedata))
427
+ zi = k(np.vstack([xi.flatten(), yi.flatten()]))
428
+ # Revert coordinates bacl to non-log space
429
+ xi, yi = np.exp(xi), np.exp(yi)
430
+ assert np.isfinite(xi).all() and np.isfinite(yi).all()
431
+ else:
432
+ xi, yi = np.mgrid[
433
+ xmin : xmax : nbins * 1j, ymin : ymax : nbins * 1j
434
+ ]
435
+ k = gaussian_kde(kdedata)
436
+ zi = k(np.vstack([xi.flatten(), yi.flatten()]))
437
+
438
+ vmin = kwargs.pop("vmin", 0.02 * np.nanmax(zi)) # 2% max height
439
+ if contour:
440
+ levels = kwargs.pop("levels", None)
441
+
442
+ if levels is None:
443
+ levels = MaxNLocator(nbins=10).tick_values(zi.min(), zi.max())
444
+ elif isinstance(levels, int):
445
+ levels = MaxNLocator(nbins=levels).tick_values(
446
+ zi.min(), zi.max()
447
+ )
448
+
449
+ mappable = ax.contourf(
450
+ xi,
451
+ yi,
452
+ zi.reshape(xi.shape),
453
+ extent=extent,
454
+ levels=levels,
455
+ vmin=vmin,
456
+ **kwargs,
457
+ )
458
+
459
+ ax.contour(
460
+ xi,
461
+ yi,
462
+ zi.reshape(xi.shape),
463
+ extent=extent,
464
+ linewidths=linewidths,
465
+ linestyles=linestyles,
466
+ vmin=vmin,
467
+ **kwargs,
468
+ )
469
+ else:
470
+ mappable = ax.pcolormesh(
471
+ xi,
472
+ yi,
473
+ zi.reshape(xi.shape),
474
+ cmap=cmap,
475
+ shading=shading,
476
+ vmin=vmin,
477
+ **kwargs,
478
+ )
479
+ mappable.set_edgecolor(background_color)
480
+ mappable.set_linestyle("None")
481
+ mappable.set_lw(0.0)
482
+
483
+ cbarlabel = "Kernel Density Estimate"
484
+
485
+ if colorbar:
486
+ cbkwargs = kwargs.copy()
487
+ cbkwargs["label"] = cbarlabel
488
+ add_colorbar(mappable, **cbkwargs)
489
+
490
+ if extent:
491
+ ax.axis(extent)
492
+ else:
493
+ ax.axis((xmin, xmax, ymin, ymax))
494
+
495
+ ax.set_xlabel(components[0], fontsize=fontsize)
496
+ ax.set_ylabel(components[1], fontsize=fontsize)
497
+
498
+ elif len(components) == 3: # ternary
499
+ scale = kwargs.pop("scale", None) or 100.0
500
+ empty_df = pd.DataFrame(columns=df.columns)
501
+ heatmapdata = tern_heatmapcoords(data.T, scale=nbins, bins=nbins)
502
+ ternaryplot(empty_df, ax=ax, components=components, scale=scale)
503
+ tax = ax.tax
504
+ if mode == "hexbin":
505
+ style = "hexagonal"
506
+ else:
507
+ style = "triangular"
508
+ tax.heatmap(
509
+ heatmapdata, scale=scale, style=style, colorbar=colorbar, **kwargs
510
+ )
511
+ else:
512
+ pass
513
+ plt.tight_layout()
514
+ return ax
@@ -0,0 +1,13 @@
1
+ # from .general import *
2
+ # from .pd import *
3
+ # from .plot import *
4
+ # from .text import *
5
+ # from .time import *
6
+ # from .math import *
7
+ # from .georoc import *
8
+ # from .database import *
9
+ # from .env import *
10
+ # from .multip import *
11
+ # from .spatial import *
12
+ # from .wfs import *
13
+ # from .skl import *
@@ -0,0 +1,88 @@
1
+ import os, sys
2
+ from pathlib import Path
3
+ import re
4
+ import struct
5
+ import subprocess
6
+ from subprocess import Popen, PIPE
7
+ import shlex
8
+ from contextlib import contextmanager
9
+ import getpass
10
+ import pyodbc, psycopg2, sqlite3
11
+ from psycopg2 import ProgrammingError as PGProgrammingError
12
+ from sqlite3 import Error as SQLiteError
13
+ from sqlite3 import OperationalError as SQLOperationalError
14
+ from pyodbc import DatabaseError as PyODBCDatabaseError
15
+ from pyodbc import ProgrammingError as PyODBCProgrammingError
16
+ from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
17
+ import logging
18
+ from .text import *
19
+
20
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
21
+ logger = logging.getLogger()
22
+
23
+
24
+ def check_access_driver():
25
+ return [x for x in pyodbc.drivers() if x.startswith("Microsoft Access Driver")]
26
+
27
+
28
+ def bitness():
29
+ bitness = struct.calcsize("P") * 8
30
+ return "{} bit".format(bitness)
31
+
32
+
33
+ @contextmanager
34
+ def open_db_connection(
35
+ connection_params,
36
+ commit=False,
37
+ encoding="utf-8",
38
+ short_decoding="utf-8",
39
+ wide_decoding="utf-16",
40
+ backend=pyodbc,
41
+ ):
42
+ """
43
+ Todo: Implement pooled connections.
44
+ http://initd.org/psycopg/docs/pool.html
45
+
46
+ https://github.com/mkleehammer/pyodbc/wiki/Unicode
47
+ """
48
+ if isinstance(connection_params, str):
49
+ connection = backend.connect(connection_params)
50
+ elif isinstance(connection_params, dict):
51
+ connection = backend.connect(**connection_params)
52
+ else:
53
+ raise NotImplementedError
54
+
55
+ if backend.__name__ == "pyodbc":
56
+ connection.autocommit = False
57
+ connection.setencoding(encoding)
58
+ connection.setdecoding(pyodbc.SQL_CHAR, encoding=short_decoding)
59
+ connection.setdecoding(pyodbc.SQL_WCHAR, encoding=wide_decoding)
60
+
61
+ cursor = connection.cursor()
62
+
63
+ def rollback(crsr):
64
+ try:
65
+ try:
66
+ crsr.execute("ROLLBACK;")
67
+ except SQLOperationalError:
68
+ print("No transaction to rollback.")
69
+ except PyODBCProgrammingError as err:
70
+ print("ROLLBACK not supported.")
71
+
72
+ try:
73
+ yield connection, cursor
74
+ except PyODBCDatabaseError as err:
75
+ error, = err.args
76
+ sys.stderr.write(error.message)
77
+ rollback(cursor)
78
+ raise err
79
+ else:
80
+ if commit:
81
+ try:
82
+ cursor.execute("COMMIT;")
83
+ except SQLOperationalError:
84
+ print("No active transaction to commit.")
85
+ else:
86
+ rollback(cursor)
87
+ finally:
88
+ connection.close()