apsg 1.3.5__tar.gz → 1.3.7__tar.gz

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 (45) hide show
  1. {apsg-1.3.5/src/apsg.egg-info → apsg-1.3.7}/PKG-INFO +2 -8
  2. {apsg-1.3.5 → apsg-1.3.7}/pyproject.toml +1 -10
  3. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/__init__.py +1 -1
  4. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/config.py +0 -1
  5. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/database/_sdbread.py +1 -1
  6. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_container.py +39 -1
  7. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_roseplot.py +36 -35
  8. {apsg-1.3.5 → apsg-1.3.7/src/apsg.egg-info}/PKG-INFO +2 -8
  9. {apsg-1.3.5 → apsg-1.3.7}/src/apsg.egg-info/requires.txt +1 -7
  10. {apsg-1.3.5 → apsg-1.3.7}/LICENSE +0 -0
  11. {apsg-1.3.5 → apsg-1.3.7}/README.md +0 -0
  12. {apsg-1.3.5 → apsg-1.3.7}/setup.cfg +0 -0
  13. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/database/__init__.py +0 -0
  14. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/database/_alchemy.py +0 -0
  15. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/decorator/__init__.py +0 -0
  16. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/decorator/_decorator.py +0 -0
  17. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/__init__.py +0 -0
  18. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_geodata.py +0 -0
  19. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_paleomag.py +0 -0
  20. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_statistics.py +0 -0
  21. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_tensor2.py +0 -0
  22. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/feature/_tensor3.py +0 -0
  23. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/helpers/__init__.py +0 -0
  24. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/helpers/_helper.py +0 -0
  25. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/helpers/_math.py +0 -0
  26. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/helpers/_notation.py +0 -0
  27. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/math/__init__.py +0 -0
  28. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/math/_matrix.py +0 -0
  29. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/math/_vector.py +0 -0
  30. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/pandas/__init__.py +0 -0
  31. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/pandas/_pandas_api.py +0 -0
  32. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/__init__.py +0 -0
  33. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_fabricplot.py +0 -0
  34. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_paleomagplots.py +0 -0
  35. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_plot_artists.py +0 -0
  36. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_projection.py +0 -0
  37. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_stereogrid.py +0 -0
  38. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/plotting/_stereonet.py +0 -0
  39. {apsg-1.3.5 → apsg-1.3.7}/src/apsg/shell.py +0 -0
  40. {apsg-1.3.5 → apsg-1.3.7}/src/apsg.egg-info/SOURCES.txt +0 -0
  41. {apsg-1.3.5 → apsg-1.3.7}/src/apsg.egg-info/dependency_links.txt +0 -0
  42. {apsg-1.3.5 → apsg-1.3.7}/src/apsg.egg-info/entry_points.txt +0 -0
  43. {apsg-1.3.5 → apsg-1.3.7}/src/apsg.egg-info/top_level.txt +0 -0
  44. {apsg-1.3.5 → apsg-1.3.7}/tests/test_apsg.py +0 -0
  45. {apsg-1.3.5 → apsg-1.3.7}/tests/test_tensors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apsg
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary: APSG - The package for structural geologists
5
5
  Author-email: Ondrej Lexa <lexa.ondrej@gmail.com>
6
6
  Maintainer-email: Ondrej Lexa <lexa.ondrej@gmail.com>
@@ -59,14 +59,8 @@ Requires-Dist: ipykernel; extra == "docs"
59
59
  Requires-Dist: nbsphinx; extra == "docs"
60
60
  Requires-Dist: autodocsumm; extra == "docs"
61
61
  Provides-Extra: dev
62
- Requires-Dist: pytest; extra == "dev"
62
+ Requires-Dist: apsg[docs,extra,tests]; extra == "dev"
63
63
  Requires-Dist: black; extra == "dev"
64
- Requires-Dist: sphinx; extra == "dev"
65
- Requires-Dist: sphinx_rtd_theme; extra == "dev"
66
- Requires-Dist: readthedocs-sphinx-search; extra == "dev"
67
- Requires-Dist: ipykernel; extra == "dev"
68
- Requires-Dist: nbsphinx; extra == "dev"
69
- Requires-Dist: autodocsumm; extra == "dev"
70
64
  Dynamic: license-file
71
65
 
72
66
  <img src="https://ondrolexa.github.io/apsg/apsg_banner.svg" alt="APSG logo" width="300px"/>
@@ -28,16 +28,7 @@ docs = [
28
28
  "nbsphinx",
29
29
  "autodocsumm",
30
30
  ]
31
- dev = [
32
- "pytest",
33
- "black",
34
- "sphinx",
35
- "sphinx_rtd_theme",
36
- "readthedocs-sphinx-search",
37
- "ipykernel",
38
- "nbsphinx",
39
- "autodocsumm",
40
- ]
31
+ dev = ["apsg[extra,tests,docs]", "black"]
41
32
 
42
33
  [project.urls]
43
34
  Homepage = "https://github.com/ondrolexa/apsg"
@@ -158,6 +158,6 @@ __all__ = (
158
158
  "quicknet",
159
159
  )
160
160
 
161
- __version__ = "1.3.5"
161
+ __version__ = "1.3.7"
162
162
  __author__ = "Ondrej Lexa"
163
163
  __email__ = "lexa.ondrej@gmail.com"
@@ -138,7 +138,6 @@ apsg_conf = dict(
138
138
  ),
139
139
  roseplot_default_kwargs=dict(
140
140
  bins=36,
141
- axial=True,
142
141
  density=True,
143
142
  arrowness=0.95,
144
143
  rwidth=1,
@@ -10,7 +10,7 @@ from apsg.feature._geodata import Lineation, Foliation
10
10
  from apsg.feature._container import LineationSet, FoliationSet
11
11
 
12
12
 
13
- class SDB(object):
13
+ class SDB:
14
14
  """
15
15
  sqlite3 based read-only interface to PySDB database
16
16
 
@@ -142,6 +142,14 @@ class Vector2Set(FeatureSet):
142
142
  """Return array of direction angles"""
143
143
  return np.asarray([e.direction for e in self]).T
144
144
 
145
+ def to_vec2(self):
146
+ """Return ``Vector2Set`` object with all data converted to ``Vector2``."""
147
+ return Vector2Set([Vector2(e) for e in self], name=self.name)
148
+
149
+ def to_dir2(self):
150
+ """Return ``Direction2Set`` object with all data converted to ``Direction``."""
151
+ return Direction2Set([Direction(e) for e in self], name=self.name)
152
+
145
153
  def proj(self, vec):
146
154
  """Return projections of all features in ``Vector2Set`` onto vector."""
147
155
  return type(self)([e.project() for e in self], name=self.name)
@@ -1376,6 +1384,9 @@ class EllipseSet(FeatureSet):
1376
1384
 
1377
1385
  __feature_class__ = Ellipse
1378
1386
 
1387
+ def __repr__(self):
1388
+ return f"E2({len(self)}) {self.name}"
1389
+
1379
1390
  @property
1380
1391
  def S1(self) -> np.ndarray:
1381
1392
  """
@@ -1425,6 +1436,15 @@ class EllipseSet(FeatureSet):
1425
1436
  """
1426
1437
  return np.array([e.e12 for e in self])
1427
1438
 
1439
+ def transform(self, F):
1440
+ """Return transformation of all features ``EllipseSet`` by matrix 'F'.
1441
+
1442
+ Args:
1443
+ F: Transformation matrix. Array-like value e.g. ``DeformationGradient3``
1444
+
1445
+ """
1446
+ return type(self)([e.transform(F) for e in self], name=self.name)
1447
+
1428
1448
 
1429
1449
  class OrientationTensor2Set(EllipseSet):
1430
1450
  """
@@ -1433,6 +1453,9 @@ class OrientationTensor2Set(EllipseSet):
1433
1453
 
1434
1454
  __feature_class__ = OrientationTensor2
1435
1455
 
1456
+ def __repr__(self):
1457
+ return f"M2({len(self)}) {self.name}"
1458
+
1436
1459
 
1437
1460
  class EllipsoidSet(FeatureSet):
1438
1461
  """
@@ -1441,6 +1464,9 @@ class EllipsoidSet(FeatureSet):
1441
1464
 
1442
1465
  __feature_class__ = Ellipsoid
1443
1466
 
1467
+ def __repr__(self):
1468
+ return f"E({len(self)}) {self.name}"
1469
+
1444
1470
  @property
1445
1471
  def strength(self) -> np.ndarray:
1446
1472
  """
@@ -1667,6 +1693,15 @@ class EllipsoidSet(FeatureSet):
1667
1693
  """
1668
1694
  return np.array([e.MAD for e in self])
1669
1695
 
1696
+ def transform(self, F):
1697
+ """Return transformation of all features ``EllipsoidSet`` by matrix 'F'.
1698
+
1699
+ Args:
1700
+ F: Transformation matrix. Array-like value e.g. ``DeformationGradient3``
1701
+
1702
+ """
1703
+ return type(self)([e.transform(F) for e in self], name=self.name)
1704
+
1670
1705
 
1671
1706
  class OrientationTensor3Set(EllipsoidSet):
1672
1707
  """
@@ -1675,6 +1710,9 @@ class OrientationTensor3Set(EllipsoidSet):
1675
1710
 
1676
1711
  __feature_class__ = OrientationTensor3
1677
1712
 
1713
+ def __repr__(self):
1714
+ return f"M({len(self)}) {self.name}"
1715
+
1678
1716
 
1679
1717
  class ClusterSet(object):
1680
1718
  """
@@ -1752,7 +1790,7 @@ class ClusterSet(object):
1752
1790
  """
1753
1791
 
1754
1792
  self.method = kwargs.get("method", self.method)
1755
- if issubclass(self.__feature_class__, (Axial2, Axial3)):
1793
+ if issubclass(self.data.__feature_class__, (Axial2, Axial3)):
1756
1794
  self.Z = linkage(self.pdist, method=self.method, metric=angle_metric_axial)
1757
1795
  else:
1758
1796
  self.Z = linkage(self.pdist, method=self.method, metric=angle_metric)
@@ -1,12 +1,13 @@
1
1
  import pickle
2
2
 
3
- import numpy as np
4
3
  import matplotlib.pyplot as plt
5
- from scipy.stats import vonmises, circmean
4
+ import numpy as np
5
+ from scipy.stats import circmean, vonmises
6
6
 
7
7
  from apsg.config import apsg_conf
8
- from apsg.plotting._plot_artists import RosePlotArtistFactory
9
8
  from apsg.feature import feature_from_json
9
+ from apsg.math._vector import Axial2, Axial3
10
+ from apsg.plotting._plot_artists import RosePlotArtistFactory
10
11
 
11
12
  __all__ = ["RosePlot"]
12
13
 
@@ -20,7 +21,6 @@ class RosePlot(object):
20
21
  title_kws (dict): dictionary of keyword arguments passed to matplotlib suptitle
21
22
  method.
22
23
  bins (int): Number of bins. Default 36
23
- axial (bool): Directional data are axial. Defaut True
24
24
  density (bool): Use density instead of counts. Default False
25
25
  pdf (bool): Plot Von Mises density function instead histogram. Default False
26
26
  pdf_res (int): Resolution of pdf. Default 901
@@ -245,7 +245,7 @@ class RosePlot(object):
245
245
  width = 2 * np.pi / self._kwargs["bins"]
246
246
  legend = kwargs.pop("legend")
247
247
  for arg in args:
248
- if self._kwargs["axial"]:
248
+ if issubclass(arg.__feature_class__, (Axial2, Axial3)):
249
249
  ang = np.concatenate((arg.direction % 360, (arg.direction + 180) % 360))
250
250
  weights = np.concatenate((abs(arg), abs(arg)))
251
251
  else:
@@ -279,7 +279,7 @@ class RosePlot(object):
279
279
  ang = arg.direction % 360
280
280
  # weights = abs(arg)
281
281
  radii = np.zeros_like(theta)
282
- if self._kwargs["axial"]:
282
+ if issubclass(arg.__feature_class__, (Axial2, Axial3)):
283
283
  for a in ang:
284
284
  radii += (
285
285
  vonmises.pdf(theta, self._kwargs["kappa"], loc=np.radians(a))
@@ -308,32 +308,21 @@ class RosePlot(object):
308
308
  bottom = bottom + radii
309
309
 
310
310
  def _muci(self, *args, **kwargs):
311
- ang = np.radians(np.concatenate([arg.direction for arg in args]))
312
311
  conflevel = kwargs.pop("confidence_level")
313
312
  n_resamples = kwargs.pop("n_resamples")
314
- # calculate mean and CI
315
- if self._kwargs["axial"]:
316
- mu = circmean(2 * ang) / 2
317
- ang_shift = ang + np.pi / 2 - mu
318
- bsmu = [
319
- circmean(np.random.choice(2 * ang_shift, size=len(ang_shift)))
320
- for i in range(n_resamples)
321
- ]
322
- low = np.percentile(bsmu, 100 - conflevel) / 2 + mu - np.pi / 2
323
- high = np.percentile(bsmu, conflevel) / 2 + mu - np.pi / 2
324
- else:
325
- mu = circmean(ang)
326
- ang_shift = ang + np.pi - mu
327
- bsmu = [
328
- circmean(np.random.choice(ang_shift, size=len(ang_shift)))
329
- for i in range(n_resamples)
330
- ]
331
- low = np.percentile(bsmu, (100 - conflevel) / 2) + mu - np.pi
332
- high = np.percentile(bsmu, 100 - (100 - conflevel) / 2) + mu - np.pi
333
- radii = []
334
313
  for arg in args:
314
+ radii = []
335
315
  p = 0
336
- if self._kwargs["axial"]:
316
+ ang = np.radians(arg.direction)
317
+ if issubclass(arg.__feature_class__, (Axial2, Axial3)):
318
+ mu = circmean(2 * ang) / 2
319
+ ang_shift = ang + np.pi / 2 - mu
320
+ bsmu = [
321
+ circmean(np.random.choice(2 * ang_shift, size=len(ang_shift)))
322
+ for i in range(n_resamples)
323
+ ]
324
+ low = np.percentile(bsmu, 100 - conflevel) / 2 + mu - np.pi / 2
325
+ high = np.percentile(bsmu, conflevel) / 2 + mu - np.pi / 2
337
326
  for a in arg.direction:
338
327
  p += vonmises.pdf(mu, self._kwargs["kappa"], loc=np.radians(a)) / 2
339
328
  p += (
@@ -341,16 +330,28 @@ class RosePlot(object):
341
330
  / 2
342
331
  )
343
332
  else:
333
+ mu = circmean(ang)
334
+ ang_shift = ang + np.pi - mu
335
+ bsmu = [
336
+ circmean(np.random.choice(ang_shift, size=len(ang_shift)))
337
+ for i in range(n_resamples)
338
+ ]
339
+ low = np.percentile(bsmu, (100 - conflevel) / 2) + mu - np.pi
340
+ high = np.percentile(bsmu, 100 - (100 - conflevel) / 2) + mu - np.pi
344
341
  for a in arg.direction:
345
342
  p += vonmises.pdf(mu, self._kwargs["kappa"], loc=np.radians(a))
346
343
  radii.append(p / len(arg))
347
- if self._kwargs["scaled"]:
348
- radii = np.sqrt(radii)
349
- mur = 1.1 * sum(radii)
350
- ci_angles = np.linspace(low, high, int(5 * np.degrees(high - low)))
351
- self.ax.plot([mu, mu + np.pi], [mur, mur], **kwargs)
352
- self.ax.plot(ci_angles, mur * np.ones_like(ci_angles), **kwargs)
353
- self.ax.plot(ci_angles + np.pi, mur * np.ones_like(ci_angles), **kwargs)
344
+ if self._kwargs["scaled"]:
345
+ radii = np.sqrt(radii)
346
+ mur = 1.1 * sum(radii)
347
+ ci_angles = np.linspace(low, high, int(5 * np.degrees(high - low)))
348
+ if issubclass(arg.__feature_class__, (Axial2, Axial3)):
349
+ self.ax.plot([mu, mu + np.pi], [mur, mur], **kwargs)
350
+ self.ax.plot(ci_angles, mur * np.ones_like(ci_angles), **kwargs)
351
+ self.ax.plot(ci_angles + np.pi, mur * np.ones_like(ci_angles), **kwargs)
352
+ else:
353
+ self.ax.plot([0, mu], [0, mur], **kwargs)
354
+ self.ax.plot(ci_angles, mur * np.ones_like(ci_angles), **kwargs)
354
355
 
355
356
 
356
357
  def roseartist_from_json(obj_json):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apsg
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary: APSG - The package for structural geologists
5
5
  Author-email: Ondrej Lexa <lexa.ondrej@gmail.com>
6
6
  Maintainer-email: Ondrej Lexa <lexa.ondrej@gmail.com>
@@ -59,14 +59,8 @@ Requires-Dist: ipykernel; extra == "docs"
59
59
  Requires-Dist: nbsphinx; extra == "docs"
60
60
  Requires-Dist: autodocsumm; extra == "docs"
61
61
  Provides-Extra: dev
62
- Requires-Dist: pytest; extra == "dev"
62
+ Requires-Dist: apsg[docs,extra,tests]; extra == "dev"
63
63
  Requires-Dist: black; extra == "dev"
64
- Requires-Dist: sphinx; extra == "dev"
65
- Requires-Dist: sphinx_rtd_theme; extra == "dev"
66
- Requires-Dist: readthedocs-sphinx-search; extra == "dev"
67
- Requires-Dist: ipykernel; extra == "dev"
68
- Requires-Dist: nbsphinx; extra == "dev"
69
- Requires-Dist: autodocsumm; extra == "dev"
70
64
  Dynamic: license-file
71
65
 
72
66
  <img src="https://ondrolexa.github.io/apsg/apsg_banner.svg" alt="APSG logo" width="300px"/>
@@ -5,14 +5,8 @@ sqlalchemy
5
5
  pandas
6
6
 
7
7
  [dev]
8
- pytest
8
+ apsg[docs,extra,tests]
9
9
  black
10
- sphinx
11
- sphinx_rtd_theme
12
- readthedocs-sphinx-search
13
- ipykernel
14
- nbsphinx
15
- autodocsumm
16
10
 
17
11
  [docs]
18
12
  sphinx
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes