%matplotlib inline
APSG defines several new python classes to easily manage, analyze and visualize orientation structural geology data. Base class Vec3
is derived from numpy.array
class and offers several new method which will be explained in following examples.
APSG module could be imported either into own name space or into active one for easier interactive work
from apsg import *
settings['figsize'] = (10, 8)
Instance of vector object Vec3
could be created from any iterable object as list, tuple or array
u = Vec3([1, -2, 3])
v = Vec3([-2, 1, 1])
For common vector operation we can use standard mathematical operators or special methods using dot notation
u + v
u - v
3*u - 2*v
Its magnitude or length is most commonly defined as its Euclidean norm and could be calculated using abs
abs(v)
abs(u + v)
For dot product we can use multiplication operator *
or dot
method
u*v
u.dot(v)
For cross product we can use operator **
or method cross
u**v
u.cross(v)
To project vector u
onto vector v
we can use method proj
u.proj(v)
To find angle (in degrees) between to vectors we use method angle
u.angle(v)
Method rotate
provide possibility to rotate vector around another vector. For example, to rotate vector u
around vector v
for 45°
u.rotate(v, 45)
To work with orientation data in structural geology, APSG provide two classes derived from Vec3
class. There is Fol
class to represent planar features by planes and Lin
class to represent linear feature by lines. Both classes provide all Vec3
methods, but they differ in way how instance is created and how some operations are calculated, as structural geology data are commonly axial in nature.
To create instance of Lin
or Fol
class, we have to provide dip direction and dip, both in degrees
Lin(120, 60), Fol(216, 62)
or we can create instance from Vec3
object using aslin
and asfol
properties
u.aslin, u.asfol
To find angle between two linear or planar features we can use method angle
l1 = Lin(110, 40)
l2 = Lin(160, 30)
l1.angle(l2)
p1 = Fol(330, 50)
p2 = Fol(250, 40)
p1.angle(p2)
We can use cross product to construct planar feature defined by two linear features
l1**l2
or to construct linear feature defined as intersection of two planar features
p1**p2
Cross product of planar and linear features could be used to construct plane defined by linear feature and normal of planar feature
l2**p2
or to find perpendicular linear feature on given plane
p2**l2
To rotate structural features we can use method rotate
p2.rotate(l2, 45)
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.
To create instance of Pair
class, we have to provide dip direction and dip of planar and linear feature, both in degrees
p = Pair(120, 40, 162, 28)
p
p.misfit
Planar and linear features are accessible using fol
and lin
properties
p.fol, p.lin
To rotate Pair
instance we can use rotate
method
p.rotate(Lin(45, 10), 60)
Instantiation of Fault
class is similar, we just have to provide argument to define sense of movement
f = Fault(120, 60, 110, 58, -1) # -1 for normal fault
f
Note the change in sense of movement after Fault
rotation
f.rotate(Lin(45, 10), 60)
To find rotation axis and angle between two Pair
instances
pr = p.rotate(Lin(45, 10), 60)
F = p.H(pr)
axis, angle = F.axisangle
print('Rotation axis: {}'.format(axis.aslin))
print('Rotation angle: {:g}°'.format(angle))
For simple fault analyses Fault
class also provide p
, t
, m
and d
properties to get PT-axes, kinematic plane and dihedra separation plane
f.p, f.t, f.m, f.d
Group
class serve as a homogeneous container for Lin
, Fol
and Vec3
objects. It allows grouping of features either for visualization or batch analysis
g = Group([Lin(120,60), Lin(116,50), Lin(132,45), Lin(90,60), Lin(84,52)], name='L1')
g
To simplify interactive group creation, you can use function G
g = G('120 60 116 50 132 45 90 60 84 52', name='L1')
g
Method len
returns number of features in group
len(g)
Most of the Lin
, Fol
and Vec3
methods could be used for Group
as well. For example, to measure angles between all features in group and another feature, we can use method angle
g.angle(Lin(110,50))
To rotate all features in group around another feature, we can use method rotate
gr = g.rotate(Lin(150, 30), 45)
To show data in list you can use data
property
gr.data
Property R
gives mean or resultant of all features in group. Note that Lin
and Fol
are axial in nature, so resultant vector is not reliable. You can use ortensor
property.
g.R
Group
class offers several methods to infer spherical statistics as spherical variance, Fisher's statistics, confidence cones on data etc.
g.var
g.fisher_stats
g.delta
To calculate orientation tensor of all features in group, we can use ortensor
property.
g.ortensor
Tensor
metaclass represents 3x3 tensor quantities used commonly in structural geology analysis. Eigenvalues and eigenvectors could be obtained by methods eigenvals
and eigenvects
. Eigenvectors could be also represented by linear or planar features using properties eigenlins
and eigenfols
. Several properties are implemented, e.g. E1
, E2
and E3
for individual eigenvalues, Woodcock's shape
and strength
, k
, K
, d
and D
for Flinn's and Ramsay symmetries and intensities, lode
for Lode's parameter etc. For more check documentation.
Ortensor
class represents orientation tensor of set of planar or linear features. In adition to Tensor
properties, properties to describe orientation distribution are also impleneted, e.g. Vollmer's P
, G
, R
and B
indexes, Intensity
for Lisle intensity index and MAD
for approximate angular deviation from plane or line.
ot = Ortensor(g)
ot.eigenvals
ot.eigenvects.data
ot.eigenlins.data
ot.eigenfols.data
ot.strength, ot.shape
ot.k, ot.d
ot.K, ot.D
ot.P, ot.G, ot.R
Ellipsoid
class could be used to represents either ellipsoid objects or strain ellipsoid. It could be instantiated from DefGrad
(represents Finger tensor), principal axes or directly from 3x3 matrix-like object.
E = Ellipsoid.from_axes(x=4, y=3, z=1)
E
F = DefGrad.from_comp(xx=2, xy=2, yz=2, zz=0.5)
E = Ellipsoid.from_defgrad(F)
E
E.eigenlins.data
E.eigenfols.data
Any Fol
, Lin
, Group
, Tensor
object could be visualized as plane, line or pole in stereographic projection using StereoNet
class
s = StereoNet()
s.plane(Fol(150, 40))
s.pole(Fol(150, 40))
s.line(Lin(112, 30))
s.show()
When StereoNet
class instance is created with arguments, they are immidiatelly plotted. Most of the objects provided by APSG could be plotted. Here we use the Group
object and principal planes and lines of Ortensor
:
StereoNet(g, ot);
A small circles (or cones) could be plotted as well
s = StereoNet()
g = Group.randn_lin(mean=Lin(40, 15))
s.line(g, 'k.')
s.cone(g.R, g.fisher_stats['a95'], 'r') # confidence cone on resultant
s.cone(g.R, g.fisher_stats['csd'], 'g') # confidence cone on 63% of data
s.show()
To make density contours plots, a contour
and contourf
methods are available
s = StereoNet()
g = Group.randn_lin(mean=Lin(40, 20))
s.contourf(g, 8, legend=True, sigma=2)
s.line(g, 'g.')
s.show()
Except Group
, APSG provides PairSet
and FaultSet
classes to store Pair
or Fault
datasets. It can be inicialized by passing list of Pair
or Fault
objects as argument or use class methods from_array
or from_csv
p = PairSet([Pair(120, 30, 165, 20),
Pair(215, 60, 280,35),
Pair(324, 70, 35, 40)])
p.misfit
StereoNet(p);
StereoNet
has two special methods to visualize fault data. Method fault
produce classical Angelier plot
f = FaultSet([Fault(170, 60, 182, 59, -1),
Fault(210, 55, 195, 53, -1),
Fault(10, 60, 15, 59, -1),
Fault(355, 48, 22, 45, -1)])
s = StereoNet()
s.fault(f)
s.line(f.p, label='P-axes')
s.line(f.t, label='T-axes')
s.plane(f.m, label='M-planes')
s.show()
hoeppner
method produce Hoeppner diagram and must be invoked from StereoNet
instance
s = StereoNet()
s.hoeppner(f, label=repr(f))
s.show()
Note that fault
method is used, when data are passed directly to StereoNet
instance
f = Fault(120, 60, 110, 58, -1)
StereoNet(f, f.m, f.d, f.p, f.t);
StereoGrid
class allows to visualize any scalar field on StereoNet. Internally it is used for plotting contour diagrams, but it exposes apply_func
method to calculate scalar field by any user-defined function. Function must accept three element numpy.array
as first argument passed from grid points of StereoGrid
.
Following example defines function to calculate resolved shear stress on plane from given stress tensor. StereoGrid
is used to calculate this value over all directions and finally values are plotted by StereoNet
S = Stress([[-10, 2, -3],[2, -5, 1], [-3, 1, 2]])
d = StereoGrid()
d.apply_func(S.shear_stress)
s = StereoNet()
s.contourf(d, 10, legend=True)
s.show()
The FaultSet
provide also amgmech
method which provide access to Angelier dihedra method. Results are stored in StereoGrid
. Default behavior is to calculate counts (positive in extension, negative in compression)
f = FaultSet.examples('MELE')
StereoNet(f.angmech());
Setting method to 'probability', maximum likelihood estimate is calculated.
f = FaultSet.examples('MELE')
StereoNet(f.angmech(method='probability'));
Tensor-type objects (Ortensor
, Ellipsoid
) could be visualized in several specialized plots. FlinnPlot
class provide classical Flinn's deformation diagram, RamsayPlot
class provide Ramsay modification of Flinn's deformation diagram, VollmerPlot
class provide triangular fabric plot (Vollmer, 1989) and HsuPlot
class provide Hsu fabric diagram using natural strains.
g1 = Group.examples('B2')
g2 = Group.examples('B4')
g3 = Group.uniform_lin(name='Uniform')
FlinnPlot(g1, g2, g3);
RamsayPlot(g1, g2, g3);
VollmerPlot(g1, g2, g3);
HsuPlot(g1, g2, g3);
All fabric plots has path
method which accepts list of Tensor
objects plotted as line.
L = VelGrad.from_comp(xx=-2, zz=2)
Eevol = [E.transform(L.defgrad(t/50)) for t in range(50)]
r = FlinnPlot()
r.path(Eevol)
r.plot(E, 'ro')
r.show()
L = VelGrad.from_comp(xx=-2, zz=2)
Eevol = [E.transform(L.defgrad(t/50)) for t in range(50)]
r = RamsayPlot()
r.path(Eevol)
r.plot(E, 'ro')
r.show()
ot = g3.ortensor
otevol = [g3.transform(L.defgrad(t/50)).ortensor for t in range(50)]
f = VollmerPlot()
f.path(otevol)
f.plot(ot, 'ro')
f.show()
L = VelGrad.from_comp(xx=-2, zz=2)
Eevol = [E.transform(L.defgrad(t/50)) for t in range(50)]
r = HsuPlot()
r.path(Eevol)
r.plot(E, 'ro')
r.show()