APSG tutorial - Part 1

APSG defines several new python classes to easily manage, analyze and visualize orientation structural geology data. There are several classes to work with orientation data, namely Vector3 for vectorial data and Lineation, Foliation for axial data

Basic usage

APSG module could be imported either into own name space or into active one for easier interactive work.

[1]:
from apsg import *

Basic operations with vectors in 2D and 3D

Instance of vector object Vector3 could be created by passing 3 arguments correspondig to 3 components to function vec:

[2]:
u = vec(1, -2, 3)
v = vec(-2, 1, 1)

Alternative ways to create vector is to pass single iterable object as list, tuple or array, or to provide geological orientation according to APSG notation (default is direction of dip and dip angle for planar and trend and plunge for linear features)

[3]:
coords = (-2, 2, 3)
a = vec(coords)
b = vec(120, 60)
print(a, b)
Vector3(-2, 2, 3) Vector3(-0.25, 0.433, 0.866)

The instance of 2D vector Vector2 could be created passing 2 arguments correspondig to 2 components or single iterable with components to function vec2:

[4]:
k = vec2(1, 1)
coords = (-1, 2)
l = vec2(coords)
print(k, l)
Vector2(1, 1) Vector2(-1, 2)

Alternatively, single argument is interpreted as direction in degrees (0-top, 90-right, 180-down, 270-left)

[5]:
m = 5 * vec2(120)
m
[5]:
Vector2(-2.5, 4.33)

For common vector operation we can use standard mathematical operators or special methods using dot notation

[6]:
u + v
[6]:
Vector3(-1, -1, 4)
[7]:
u - v
[7]:
Vector3(3, -3, 2)
[8]:
3*u - 2*v
[8]:
Vector3(7, -8, 7)

Its magnitude or length is most commonly defined as its Euclidean norm and could be calculated using abs

[9]:
abs(v)
[9]:
2.449489742783178
[10]:
abs(u + v)
[10]:
4.242640687119285

For dot product we can use dot method or operator @

[11]:
u.dot(v)
[11]:
-1
[12]:
u @ v
[12]:
-1.0

For cross product we can method cross

[13]:
u.cross(v)
[13]:
Vector3(-5, -7, -3)

To project vector u onto vector v we can use method proj

[14]:
u.proj(v)
[14]:
Vector3(0.333, -0.167, -0.167)

To find angle (in degrees) between to vectors we use method angle

[15]:
u.angle(v)
[15]:
96.26395271992722

Method rotate provide possibility to rotate vector around another vector. For example, to rotate vector u around vector v for 45°

[16]:
u.rotate(v, 45)
[16]:
Vector3(2.248, 0.558, 2.939)

Classes Lineation and Foliation

To work with orientation data in structural geology, APSG provide two classes, Foliation class to represent planar features and Lineation class to represent linear features. Both classes support all Vector3 methods and operators, but it should be noted, that dot and angle respect their axial nature, i.e. angle between two lineations cant’t be bigger than 90 degrees.

To create instance of Lineation or Foliation, we can use functions lin and fol. Arguments have similar syntax to vec3.

[17]:
lin(120, 60), fol(216, 62)
[17]:
(L:120/60, S:216/62)

We can also cast Vector3 instance to Foliation or Lineation

[18]:
lin(u), fol(u)
[18]:
(L:297/53, S:117/37)

Vector methods for Lineation and Foliation

To find angle between two linear or planar features we can use method angle

[19]:
l1 = lin(110, 40)
l2 = lin(160, 30)
l1.angle(l2)
[19]:
41.59741268003547
[20]:
p1 = fol(330, 50)
p2 = fol(250, 40)
p1.angle(p2)
[20]:
54.69639932197533

We can use cross product to construct planar feature defined by two linear features

[21]:
l1.cross(l2)
[21]:
S:113/40

or to construct linear feature defined by intersection of two planar features

[22]:
p1.cross(p2)
[22]:
L:278/36

Cross product of planar and linear features could be used to construct plane defined by linear feature and normal of planar feature

[23]:
l2.cross(p2)
[23]:
S:96/53

or to find perpendicular linear feature on given plane

[24]:
p2.cross(l2)
[24]:
L:276/37

To rotate structural features we can use method rotate

[25]:
p2.rotate(l2, 45)
[25]:
S:269/78

Classes Pair and Fault

To work with paired orientation data like foliations and lineations or fault data in structural geology, APSG provide two base Pair class and derived Fault class. Both classes are instantiated providing dip direction and dip of planar and linear measurements, which are automatically orthogonalized. If misfit is too high, warning is raised. The Fault class expects one more argument providing sense of movement information, either 1 or -1 for normal/reverse movement.

To create instance of Pair, we have to pass two arguments for planar and two argumets for linear features following geological notation to function pair:

[26]:
p = pair(120, 40, 162, 28)
p
[26]:
P:118/39-163/30
[27]:
p.misfit
[27]:
3.5623168411508175

Planar and linear features are accessible using fol and lin properties

[28]:
p.fol, p.lin
[28]:
(S:118/39, L:163/30)

To rotate Pair instance we can use rotate method

[29]:
p.rotate(lin(45, 10), 60)
[29]:
P:314/83-237/61

Instantiation of Fault class is similar, we just have to provide argument to define sense of movement

[30]:
f = fault(120, 60, 110, 58, 1)  # 1 for normal fault
f
[30]:
F:120/59-110/59 +

Note the change in sense of movement after Fault rotation

[31]:
f.rotate(lin(45, 10), 60)
[31]:
F:312/62-340/59 -

For simple fault analyses Fault class also provide p, t, m and d properties to get PT-axes, kinematic plane and dihedra separation plane

[32]:
f.p, f.t, f.m, f.d
[32]:
(L:315/75, L:116/14, S:27/85, S:290/31)

Class Cone

General feature type to store small or great circles as cone. It could be defined by axis, secant and revolving angle or by axis and apical angle The revolving angle is by default 360° defining full cone. For segments of small circles, the revolving angle could be different.

[33]:
c = cone(lin(140, 50), lin(140, 75))
c
[33]:
C:140/50 [25]

To create small circle segment, you can provide revolving angle

[34]:
c = cone(lin(90, 70), lin(45,30), 115)

The tips of small circle segments could be obtained from cone property secant and rotated_secant

[35]:
lin(c.secant), lin(c.rotated_secant)
[35]:
(L:45/30, L:137/30)

To define cone using apical angle, use axis amd number arguments. Note, that revolving angle is 360 by default

[36]:
c = cone(lin(140, 50), 25)
c
[36]:
C:140/50 [25]
[37]:
c.revangle
[37]:
360.0

Feature sets

APSG provide several classes to process, analyze and visualize the sets of data. There are e.g. vecset, linset and folset classes to store group of vec, lin and fol objects. All these feature sets are created from homogeneous list of data with optional name atribute.

[38]:
v = vecset([vec(120,60), vec(116,50), vec(132,45), vec(90,60), vec(84,52)], name='Vectors')
v
[38]:
V3(5) Vectors
[39]:
l = linset([lin(120,60), lin(116,50), lin(132,45), lin(90,60), lin(84,52)], name='Lineations')
l
[39]:
L(5) Lineations
[40]:
f = folset([fol(120,60), fol(116,50), fol(132,45), fol(90,60), fol(84,52)], name='Foliations')
f
[40]:
S(5) Foliations

To simplify interactive group creation, you can use function G

[41]:
g = G([lin(120,60), lin(116,50), lin(132,45), lin(90,60), lin(84,52)], name='L1')
g
[41]:
L(5) L1

Method len returns number of features in group

[42]:
len(v)
[42]:
5

Most of the vec, lin and fol methods could be used for feature sets as well. For example, to measure angles between all features in group and another feature, we can use method angle:

[43]:
l.angle(lin(110,50))
[43]:
array([11.49989817,  3.85569115, 15.61367789, 15.11039885, 16.3947936 ])

To rotate all features in group around another feature, we can use method rotate

[44]:
lr = l.rotate(lin(150, 30), 45)

To show data in list you can use data property

[45]:
l.data
[45]:
(L:120/60, L:116/50, L:132/45, L:90/60, L:84/52)
[46]:
lr.data
[46]:
(L:107/35, L:113/26, L:126/30, L:93/26, L:94/18)

Function R returns resultant of all features in set. Note that Lineation and Foliation are axial in nature, so resultant vector is not reliable. Check the orientation tensor anlysis below.

[47]:
v.R()
[47]:
Vector3(-0.941, 2.649, 3.993)
[48]:
lin(v.R())
[48]:
L:110/55

There is several methods to infer spherical statistics as spherical variance, Fisher’s statistics, confidence cones on data etc.

[49]:
l.var()
[49]:
0.02337168447438498
[50]:
v.fisher_statistics()
[50]:
{'k': 34.22945405911087, 'a95': 13.26402990511733, 'csd': 13.844747281750971}
[51]:
v.fisher_cone_a95()
[51]:
C:110/55 [13.264]
[52]:
v.fisher_cone_csd()
[52]:
C:110/55 [13.8447]
[53]:
v.delta()
[53]:
12.411724720740516
[54]:
v.rdegree()
[54]:
95.32566310512297

To calculate orientation tensor of all features in group, we can use ortensor method.

[55]:
v.ortensor()
[55]:
OrientationTensor3
[[ 0.074 -0.096 -0.143]
 [-0.096  0.284  0.421]
 [-0.143  0.421  0.642]]
(S1:0.977, S2:0.201, S3:0.0758)
[ ]: