apsg 1.3.6__py3-none-any.whl → 1.3.8__py3-none-any.whl

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.
apsg/__init__.py CHANGED
@@ -158,6 +158,6 @@ __all__ = (
158
158
  "quicknet",
159
159
  )
160
160
 
161
- __version__ = "1.3.6"
161
+ __version__ = "1.3.8"
162
162
  __author__ = "Ondrej Lexa"
163
163
  __email__ = "lexa.ondrej@gmail.com"
apsg/database/__init__.py CHANGED
@@ -6,6 +6,7 @@ from apsg.database._alchemy import (
6
6
  Site,
7
7
  Structdata,
8
8
  Structype,
9
+ Attached,
9
10
  Tag,
10
11
  Unit,
11
12
  )
@@ -17,6 +18,7 @@ __all__ = (
17
18
  "Site",
18
19
  "Structdata",
19
20
  "Structype",
21
+ "Attached",
20
22
  "Tag",
21
23
  "Unit",
22
24
  "SDB",
apsg/database/_alchemy.py CHANGED
@@ -7,12 +7,13 @@ SQLAlchemy API to access PySDB database
7
7
  import os
8
8
  from datetime import datetime
9
9
  import contextlib
10
+ import warnings
10
11
 
11
- from apsg.feature._geodata import Lineation, Foliation, Pair
12
- from apsg.feature._container import LineationSet, FoliationSet
12
+ from apsg.feature._geodata import Lineation, Foliation, Pair, Fault
13
+ from apsg.feature._container import LineationSet, FoliationSet, PairSet, FaultSet
13
14
 
14
15
  from sqlalchemy import create_engine, event
15
- from sqlalchemy.orm import sessionmaker
16
+ from sqlalchemy.orm import sessionmaker, aliased
16
17
  from sqlalchemy import (
17
18
  Column,
18
19
  Float,
@@ -607,34 +608,175 @@ class SDBSession:
607
608
  else:
608
609
  return tags
609
610
 
610
- def getset(self, structype, **kwargs):
611
+ def getset(self, structype, site={}, unit={}, tag={}):
611
612
  """Method to retrieve data from SDB database to ``FeatureSet``.
612
613
 
613
614
  Args:
614
- structype (str, Structype): structure or list of structures to retrieve
615
-
616
- Keyword arguments are passed to sqlalchemy filter_by method
615
+ structype (str | Structype): structure to retrieve
616
+ site (dict): keyword args passed to filter site
617
+ unit (dict): keyword args passed to filter unit
618
+ tag (dict): keyword args passed to filter tag
617
619
 
618
620
  """
619
621
  if isinstance(structype, str):
620
- structypes = (
621
- self.session.query(Structype).filter_by(structure=structype).all()
622
+ dbstruct = (
623
+ self.session.query(Structype).filter_by(structure=structype).first()
622
624
  )
623
- assert len(structypes) == 1, f"There is no structure {structype} in db."
624
- structype = structypes[0]
625
- data = (
626
- self.session.query(Structdata)
627
- .filter_by(structype=structype, **kwargs)
628
- .all()
629
- )
630
- if structype.planar == 1:
631
- res = FoliationSet(
632
- [Foliation(v.azimuth, v.inclination) for v in data],
633
- name=structype.structure,
625
+ assert dbstruct is not None, f"There is no structure {structype} in db."
626
+ structype = dbstruct
627
+ if isinstance(structype, Structype):
628
+ data = (
629
+ self.session.query(Structdata)
630
+ .filter_by(structype=structype)
631
+ .join(Structdata.site)
632
+ .filter_by(**site)
633
+ .join(Site.unit)
634
+ .filter_by(**unit)
635
+ .join(Structdata.tags)
636
+ .filter_by(**tag)
637
+ .all()
634
638
  )
639
+ if structype.planar == 1:
640
+ res = FoliationSet(
641
+ [Foliation(v.azimuth, v.inclination) for v in data],
642
+ name=structype.structure,
643
+ )
644
+ else:
645
+ res = LineationSet(
646
+ [Lineation(v.azimuth, v.inclination) for v in data],
647
+ name=structype.structure,
648
+ )
649
+ return res
635
650
  else:
636
- res = LineationSet(
637
- [Lineation(v.azimuth, v.inclination) for v in data],
638
- name=structype.structure,
651
+ raise ValueError("structype argument must be string or Structype")
652
+
653
+ def getpairs(self, ptype, ltype, site={}, unit={}, ptag={}, ltag={}):
654
+ """Method to retrieve data from SDB database to ``PairSet``.
655
+
656
+ Args:
657
+ ptype (str | Structype): planar structure to retrieve
658
+ ltype (str | Structype): linear structure to retrieve
659
+
660
+ Keyword Args:
661
+ site (dict): keyword args passed to filter site
662
+ unit (dict): keyword args passed to filter unit
663
+ ptag (dict): keyword args passed to filter planar tag
664
+ ltag (dict): keyword args passed to filter linear tag
665
+
666
+ """
667
+ if isinstance(ptype, str):
668
+ dbstruct = self.session.query(Structype).filter_by(structure=ptype).first()
669
+ assert dbstruct is not None, f"There is no structure {ptype} in db."
670
+ ptype = dbstruct
671
+ if isinstance(ltype, str):
672
+ dbstruct = self.session.query(Structype).filter_by(structure=ltype).first()
673
+ assert dbstruct is not None, f"There is no structure {ltype} in db."
674
+ ltype = dbstruct
675
+ if isinstance(ptype, Structype) and isinstance(ltype, Structype):
676
+ AttachPlanar = aliased(Structdata)
677
+ AttachLinear = aliased(Structdata)
678
+ TagPlanar = aliased(Tag)
679
+ TagLinear = aliased(Tag)
680
+ data = (
681
+ self.session.query(Attached)
682
+ .join(AttachPlanar, Attached.planar)
683
+ .filter_by(structype=ptype)
684
+ .join(AttachLinear, Attached.linear)
685
+ .filter_by(structype=ltype)
686
+ .join(Structdata.site)
687
+ .filter_by(**site)
688
+ .join(Site.unit)
689
+ .filter_by(**unit)
690
+ .outerjoin(TagPlanar, AttachPlanar.tags)
691
+ .filter_by(**ptag)
692
+ .outerjoin(TagLinear, AttachLinear.tags)
693
+ .filter_by(**ltag)
694
+ .all()
639
695
  )
640
- return res
696
+ pairs = []
697
+ warnings.filterwarnings("error")
698
+ for v in data:
699
+ try:
700
+ pair = Pair(
701
+ v.planar.azimuth,
702
+ v.planar.inclination,
703
+ v.linear.azimuth,
704
+ v.linear.inclination,
705
+ )
706
+ pairs.append(pair)
707
+ except UserWarning:
708
+ print(
709
+ f"Too big misfit for pair {v.planar}-{v.linear} on {v.planar.site}"
710
+ )
711
+ warnings.resetwarnings()
712
+ res = PairSet(pairs, name=f"{ptype.structure}-{ltype.structure}")
713
+ return res
714
+ else:
715
+ raise ValueError("structype argument must be string or Structype")
716
+
717
+ def getfaults(self, ptype, ltype, sense, site={}, unit={}, ptag={}, ltag={}):
718
+ """Method to retrieve data from SDB database to ``FaultSet``.
719
+
720
+ Args:
721
+ ptype (str | Structype): planar structure to retrieve
722
+ ltype (str | Structype): linear structure to retrieve
723
+ sense (float or str): sense of movement +/-1 hanging-wall down/up. When str,
724
+ must be one of 's', 'd', 'n', 'r'.
725
+
726
+ Keyword Args:
727
+ site (dict): keyword args passed to filter site
728
+ unit (dict): keyword args passed to filter unit
729
+ ptag (dict): keyword args passed to filter planar tag
730
+ ltag (dict): keyword args passed to filter linear tag
731
+
732
+ """
733
+ if isinstance(ptype, str):
734
+ dbstruct = self.session.query(Structype).filter_by(structure=ptype).first()
735
+ assert dbstruct is not None, f"There is no structure {ptype} in db."
736
+ ptype = dbstruct
737
+ if isinstance(ltype, str):
738
+ dbstruct = self.session.query(Structype).filter_by(structure=ltype).first()
739
+ assert dbstruct is not None, f"There is no structure {ltype} in db."
740
+ ltype = dbstruct
741
+ if isinstance(ptype, Structype) and isinstance(ltype, Structype):
742
+ AttachPlanar = aliased(Structdata)
743
+ AttachLinear = aliased(Structdata)
744
+ TagPlanar = aliased(Tag)
745
+ TagLinear = aliased(Tag)
746
+ data = (
747
+ self.session.query(Attached)
748
+ .join(AttachPlanar, Attached.planar)
749
+ .filter_by(structype=ptype)
750
+ .join(AttachLinear, Attached.linear)
751
+ .filter_by(structype=ltype)
752
+ .join(Structdata.site)
753
+ .filter_by(**site)
754
+ .join(Site.unit)
755
+ .filter_by(**unit)
756
+ .outerjoin(TagPlanar, AttachPlanar.tags)
757
+ .filter_by(**ptag)
758
+ .outerjoin(TagLinear, AttachLinear.tags)
759
+ .filter_by(**ltag)
760
+ .all()
761
+ )
762
+ faults = []
763
+ warnings.filterwarnings("error")
764
+ for v in data:
765
+ try:
766
+ fault = Fault(
767
+ v.planar.azimuth,
768
+ v.planar.inclination,
769
+ v.linear.azimuth,
770
+ v.linear.inclination,
771
+ sense,
772
+ )
773
+ faults.append(fault)
774
+ except UserWarning:
775
+ print(
776
+ f"Too big misfit for pair {v.planar}-{v.linear} on {v.planar.site}"
777
+ )
778
+ warnings.resetwarnings()
779
+ res = FaultSet(faults, name=f"{ptype.structure}-{ltype.structure}")
780
+ return res
781
+ else:
782
+ raise ValueError("structype argument must be string or Structype")
@@ -1384,6 +1384,9 @@ class EllipseSet(FeatureSet):
1384
1384
 
1385
1385
  __feature_class__ = Ellipse
1386
1386
 
1387
+ def __repr__(self):
1388
+ return f"E2({len(self)}) {self.name}"
1389
+
1387
1390
  @property
1388
1391
  def S1(self) -> np.ndarray:
1389
1392
  """
@@ -1433,6 +1436,15 @@ class EllipseSet(FeatureSet):
1433
1436
  """
1434
1437
  return np.array([e.e12 for e in self])
1435
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
+
1436
1448
 
1437
1449
  class OrientationTensor2Set(EllipseSet):
1438
1450
  """
@@ -1441,6 +1453,9 @@ class OrientationTensor2Set(EllipseSet):
1441
1453
 
1442
1454
  __feature_class__ = OrientationTensor2
1443
1455
 
1456
+ def __repr__(self):
1457
+ return f"M2({len(self)}) {self.name}"
1458
+
1444
1459
 
1445
1460
  class EllipsoidSet(FeatureSet):
1446
1461
  """
@@ -1449,6 +1464,9 @@ class EllipsoidSet(FeatureSet):
1449
1464
 
1450
1465
  __feature_class__ = Ellipsoid
1451
1466
 
1467
+ def __repr__(self):
1468
+ return f"E({len(self)}) {self.name}"
1469
+
1452
1470
  @property
1453
1471
  def strength(self) -> np.ndarray:
1454
1472
  """
@@ -1675,6 +1693,15 @@ class EllipsoidSet(FeatureSet):
1675
1693
  """
1676
1694
  return np.array([e.MAD for e in self])
1677
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
+
1678
1705
 
1679
1706
  class OrientationTensor3Set(EllipsoidSet):
1680
1707
  """
@@ -1683,6 +1710,9 @@ class OrientationTensor3Set(EllipsoidSet):
1683
1710
 
1684
1711
  __feature_class__ = OrientationTensor3
1685
1712
 
1713
+ def __repr__(self):
1714
+ return f"M({len(self)}) {self.name}"
1715
+
1686
1716
 
1687
1717
  class ClusterSet(object):
1688
1718
  """
apsg/feature/_geodata.py CHANGED
@@ -412,8 +412,8 @@ class Fault(Pair):
412
412
  finc (float): dip of planar feature in degrees
413
413
  lazi (float): plunge direction of linear feature in degrees
414
414
  linc (float): plunge of linear feature in degrees
415
- sense (float or str): sense of movement +/11 hanging-wall down/up. When str,
416
- ,ust be one of 's', 'd', 'n', 'r'.
415
+ sense (float or str): sense of movement +/-1 hanging-wall down/up. When str,
416
+ must be one of 's', 'd', 'n', 'r'.
417
417
 
418
418
 
419
419
  Attributes:
@@ -1,32 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apsg
3
- Version: 1.3.6
3
+ Version: 1.3.8
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>
7
- License: MIT License
8
-
9
- APSG - The package for structural geologists.
10
- Copyright (c) 2015-2024, Ondrej Lexa
11
-
12
- Permission is hereby granted, free of charge, to any person obtaining a copy
13
- of this software and associated documentation files (the "Software"), to deal
14
- in the Software without restriction, including without limitation the rights
15
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
- copies of the Software, and to permit persons to whom the Software is
17
- furnished to do so, subject to the following conditions:
18
-
19
- The above copyright notice and this permission notice shall be included in all
20
- copies or substantial portions of the Software.
21
-
22
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
- SOFTWARE.
29
-
7
+ License-Expression: MIT
30
8
  Project-URL: Homepage, https://github.com/ondrolexa/apsg
31
9
  Project-URL: Documentation, https://apsg.readthedocs.io
32
10
  Project-URL: Repository, https://github.com/ondrolexa/apsg.git
@@ -35,7 +13,6 @@ Project-URL: Changelog, https://github.com/ondrolexa/apsg/blob/master/CHANGELOG.
35
13
  Keywords: structural geology,stereonet,orientation data
36
14
  Classifier: Development Status :: 4 - Beta
37
15
  Classifier: Intended Audience :: Science/Research
38
- Classifier: License :: OSI Approved :: MIT License
39
16
  Classifier: Operating System :: OS Independent
40
17
  Classifier: Programming Language :: Python :: 3
41
18
  Requires-Python: >=3.10
@@ -85,7 +62,7 @@ APSG is the package for structural geologists. It defines several new python cla
85
62
 
86
63
  ## :hammer_and_wrench: Requirements
87
64
 
88
- You need Python 3.9 or later to run APSG. The package requires [NumPy](https://numpy.org/) and [SciPy](https://www.scipy.org/),
65
+ You need Python 3.10 or later to run APSG. The package requires [NumPy](https://numpy.org/) and [SciPy](https://www.scipy.org/),
89
66
  [Matplotlib](https://matplotlib.org/), [SciPy](https://scipy.org/), [SQLAlchemy](https://www.sqlalchemy.org/)
90
67
  and [pandas](https://pandas.pydata.org/).
91
68
 
@@ -1,14 +1,14 @@
1
- apsg/__init__.py,sha256=er5PTmzLPoYoorvyKGhTjeyE6lVsLZr0nB5ariut94o,2849
1
+ apsg/__init__.py,sha256=scpdGQROB_0MMpP7k1n03UybD_I5pllVN4ARKNJWiUo,2849
2
2
  apsg/config.py,sha256=vwJZVqWQ2bXe4TNW3hzse-dIam3QBwNeFx5VJUhNjU8,4549
3
3
  apsg/shell.py,sha256=1D0PeB7qXzlpiOf2QYGo6OJlEVN1KJPYld1GEREBiFg,707
4
- apsg/database/__init__.py,sha256=7Rvcf1KBBBNhoM28ZlvQ01CkScQTroFkoS4d1kD55Ws,315
5
- apsg/database/_alchemy.py,sha256=geV3Q6ZLdGvjzxry7GTHHIQq6t_ccsUxZvuv13CLYFQ,19467
4
+ apsg/database/__init__.py,sha256=d9R2Yi52srrvKkObB5f3kAheJBOqZtn2QZp95uQVcxo,345
5
+ apsg/database/_alchemy.py,sha256=3cdFRqRVW5P0026qA20YL3cNwXHPfU_t-pbVyaPFzsY,25589
6
6
  apsg/database/_sdbread.py,sha256=lKvImHCFaxXr0wx5FnogVRp6bAPeaP01MDpUn_rH3Ek,11009
7
7
  apsg/decorator/__init__.py,sha256=fZ-dxpldQIk6-2JhVnCj-Tsl8bz2nvoGOyG7uXKvBfg,160
8
8
  apsg/decorator/_decorator.py,sha256=8TMSrcVvhU5UCbNMrnyrW3-65qo20_6N2ShtXd3bP-k,1194
9
9
  apsg/feature/__init__.py,sha256=XkyS-X8lUaXCVaXgoK0GETmTCCGqB1BmSwZRZG3blZQ,1733
10
- apsg/feature/_container.py,sha256=7RLkTnEwDDhm6c4jErQOTIPg5KBM46SLpcFlrtyZHvg,60812
11
- apsg/feature/_geodata.py,sha256=tjgPSKXyEOXiAN3iPeHpm8kpj__jI4ahtTpDuWhQNBE,24008
10
+ apsg/feature/_container.py,sha256=4RgiLNtLQPArHg8uvSlwesz9iLbaq513sH5mBTQqLKs,61682
11
+ apsg/feature/_geodata.py,sha256=GbKwF3Y6nCF4cqaR2VP7IrOL3SYFEjDx6iizFx0BiHE,24008
12
12
  apsg/feature/_paleomag.py,sha256=WIICUOEJGGFHbCDF0gbW7lMt10jI0el0UVhkbMH7XAs,14911
13
13
  apsg/feature/_statistics.py,sha256=WwBU2D7SyIHMpWnO7WFqbIpSkz6KUCT9xkG8oVzgskQ,13916
14
14
  apsg/feature/_tensor2.py,sha256=XzGuSU46RkeVHQu3pqKzgzf0cYZCgbs9eP_yfYa82SU,13451
@@ -30,9 +30,9 @@ apsg/plotting/_projection.py,sha256=ix67PwOU2WGjryEcsHlVIMpcVC9yxy45ycOV9k5x_Q8,
30
30
  apsg/plotting/_roseplot.py,sha256=Wq5NBCDZMUQWEioIC6hYAZzjDKZsiDIJtjk_vQzzCd8,13104
31
31
  apsg/plotting/_stereogrid.py,sha256=awh7MwN1WgszhOlr6UgR20wHQJ8u778-Tf_w1uflrV4,11869
32
32
  apsg/plotting/_stereonet.py,sha256=uHJXluFMkeaI4yzD9pGc4DIlgjZA01INySLKtUHLAlU,36624
33
- apsg-1.3.6.dist-info/licenses/LICENSE,sha256=lY0kfpVRrzcgVZq7pI6rLK5WYiUMWe0bdKpDelN6hk8,1120
34
- apsg-1.3.6.dist-info/METADATA,sha256=tD60lfw5Bi1DY0NlsQG6FEnKxv87Bukfz5a-_-jVdks,8047
35
- apsg-1.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- apsg-1.3.6.dist-info/entry_points.txt,sha256=SowP7_uRI0NJuzznKBXyM9BJcSwBxbXo6Iz5LUo9mEQ,42
37
- apsg-1.3.6.dist-info/top_level.txt,sha256=xWxwi0nqqOyKdmpsszfR-bmqnNpgVbhnLRuIKGJnaUM,5
38
- apsg-1.3.6.dist-info/RECORD,,
33
+ apsg-1.3.8.dist-info/licenses/LICENSE,sha256=lY0kfpVRrzcgVZq7pI6rLK5WYiUMWe0bdKpDelN6hk8,1120
34
+ apsg-1.3.8.dist-info/METADATA,sha256=QxiltKB0pms9_cNAg6UFXKrP9J_5xOzx6-R9WonUQfs,6715
35
+ apsg-1.3.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
+ apsg-1.3.8.dist-info/entry_points.txt,sha256=SowP7_uRI0NJuzznKBXyM9BJcSwBxbXo6Iz5LUo9mEQ,42
37
+ apsg-1.3.8.dist-info/top_level.txt,sha256=xWxwi0nqqOyKdmpsszfR-bmqnNpgVbhnLRuIKGJnaUM,5
38
+ apsg-1.3.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5