apsg 1.3.0__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.
- AUTHORS.md +9 -0
- CHANGELOG.md +304 -0
- CONTRIBUTING.md +91 -0
- apsg/__init__.py +104 -0
- apsg/config.py +214 -0
- apsg/database/__init__.py +23 -0
- apsg/database/_alchemy.py +609 -0
- apsg/database/_sdbread.py +284 -0
- apsg/decorator/__init__.py +5 -0
- apsg/decorator/_decorator.py +43 -0
- apsg/feature/__init__.py +79 -0
- apsg/feature/_container.py +1808 -0
- apsg/feature/_geodata.py +702 -0
- apsg/feature/_paleomag.py +425 -0
- apsg/feature/_statistics.py +430 -0
- apsg/feature/_tensor2.py +550 -0
- apsg/feature/_tensor3.py +1108 -0
- apsg/helpers/__init__.py +28 -0
- apsg/helpers/_helper.py +7 -0
- apsg/helpers/_math.py +46 -0
- apsg/helpers/_notation.py +119 -0
- apsg/math/__init__.py +6 -0
- apsg/math/_matrix.py +406 -0
- apsg/math/_vector.py +590 -0
- apsg/pandas/__init__.py +27 -0
- apsg/pandas/_pandas_api.py +507 -0
- apsg/plotting/__init__.py +25 -0
- apsg/plotting/_fabricplot.py +563 -0
- apsg/plotting/_paleomagplots.py +71 -0
- apsg/plotting/_plot_artists.py +551 -0
- apsg/plotting/_projection.py +326 -0
- apsg/plotting/_roseplot.py +360 -0
- apsg/plotting/_stereogrid.py +332 -0
- apsg/plotting/_stereonet.py +992 -0
- apsg/shell.py +35 -0
- apsg-1.3.0.dist-info/AUTHORS.md +9 -0
- apsg-1.3.0.dist-info/METADATA +141 -0
- apsg-1.3.0.dist-info/RECORD +40 -0
- apsg-1.3.0.dist-info/WHEEL +4 -0
- apsg-1.3.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
SQLAlchemy API to access PySDB database
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
import contextlib
|
|
10
|
+
|
|
11
|
+
from apsg.feature._geodata import Lineation, Foliation, Pair
|
|
12
|
+
from apsg.feature._container import LineationSet, FoliationSet
|
|
13
|
+
|
|
14
|
+
from sqlalchemy import create_engine, event
|
|
15
|
+
from sqlalchemy.orm import sessionmaker
|
|
16
|
+
from sqlalchemy import Column, Float, ForeignKey, Integer, String, Table, Text, text
|
|
17
|
+
from sqlalchemy.orm import relationship
|
|
18
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
19
|
+
|
|
20
|
+
Base = declarative_base()
|
|
21
|
+
metadata = Base.metadata
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Meta(Base):
|
|
25
|
+
__tablename__ = "meta"
|
|
26
|
+
|
|
27
|
+
id = Column(Integer, primary_key=True)
|
|
28
|
+
name = Column(String(16), nullable=False)
|
|
29
|
+
value = Column(Text)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Site(Base):
|
|
33
|
+
__tablename__ = "sites"
|
|
34
|
+
|
|
35
|
+
id = Column(Integer, primary_key=True)
|
|
36
|
+
id_units = Column(ForeignKey("units.id"), nullable=False, index=True)
|
|
37
|
+
name = Column(String(16), nullable=False, server_default=text("''"))
|
|
38
|
+
x_coord = Column(Float, server_default=text("NULL"))
|
|
39
|
+
y_coord = Column(Float, server_default=text("NULL"))
|
|
40
|
+
description = Column(Text)
|
|
41
|
+
|
|
42
|
+
unit = relationship("Unit", back_populates="sites")
|
|
43
|
+
|
|
44
|
+
structdata = relationship("Structdata", back_populates="site")
|
|
45
|
+
|
|
46
|
+
def __repr__(self):
|
|
47
|
+
return "Site:{} ({})".format(self.name, self.unit.name)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
tagged = Table(
|
|
51
|
+
"tagged",
|
|
52
|
+
metadata,
|
|
53
|
+
Column("id", Integer, autoincrement=True),
|
|
54
|
+
Column("id_tags", Integer, ForeignKey("tags.id"), primary_key=True),
|
|
55
|
+
Column("id_structdata", Integer, ForeignKey("structdata.id"), primary_key=True),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Attached(Base):
|
|
60
|
+
__tablename__ = "attach"
|
|
61
|
+
|
|
62
|
+
id = Column(Integer, primary_key=True)
|
|
63
|
+
id_structdata_planar = Column(
|
|
64
|
+
ForeignKey("structdata.id"), nullable=False, index=True
|
|
65
|
+
)
|
|
66
|
+
id_structdata_linear = Column(
|
|
67
|
+
ForeignKey("structdata.id"), nullable=False, index=True
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def __repr__(self):
|
|
71
|
+
return "{} - {}".format(self.planar, self.linear)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Structdata(Base):
|
|
75
|
+
__tablename__ = "structdata"
|
|
76
|
+
|
|
77
|
+
id = Column(Integer, primary_key=True)
|
|
78
|
+
id_sites = Column(ForeignKey("sites.id"), nullable=False, index=True)
|
|
79
|
+
id_structype = Column(ForeignKey("structype.id"), nullable=False, index=True)
|
|
80
|
+
azimuth = Column(Float, nullable=False, server_default=text("0"))
|
|
81
|
+
inclination = Column(Float, nullable=False, server_default=text("0"))
|
|
82
|
+
description = Column(Text)
|
|
83
|
+
|
|
84
|
+
site = relationship("Site", back_populates="structdata")
|
|
85
|
+
structype = relationship("Structype", back_populates="structdata")
|
|
86
|
+
|
|
87
|
+
tags = relationship("Tag", secondary=tagged, back_populates="structdata")
|
|
88
|
+
|
|
89
|
+
attach_planar = relationship(
|
|
90
|
+
"Attached", backref="planar", primaryjoin=id == Attached.id_structdata_planar
|
|
91
|
+
)
|
|
92
|
+
attach_linear = relationship(
|
|
93
|
+
"Attached", backref="linear", primaryjoin=id == Attached.id_structdata_linear
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def __repr__(self):
|
|
97
|
+
return "{}:{:g}/{:g}".format(
|
|
98
|
+
self.structype.structure, self.azimuth, self.inclination
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class Structype(Base):
|
|
103
|
+
__tablename__ = "structype"
|
|
104
|
+
|
|
105
|
+
id = Column(Integer, primary_key=True)
|
|
106
|
+
pos = Column(Integer, nullable=False, server_default=text("0"))
|
|
107
|
+
structure = Column(String(16), nullable=False)
|
|
108
|
+
description = Column(Text)
|
|
109
|
+
structcode = Column(Integer, server_default=text("0"))
|
|
110
|
+
groupcode = Column(Integer, server_default=text("0"))
|
|
111
|
+
planar = Column(Integer, server_default=text("1"))
|
|
112
|
+
|
|
113
|
+
structdata = relationship("Structdata", back_populates="structype")
|
|
114
|
+
|
|
115
|
+
def __repr__(self):
|
|
116
|
+
return "Type:{}".format(self.structure)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class Tag(Base):
|
|
120
|
+
__tablename__ = "tags"
|
|
121
|
+
|
|
122
|
+
id = Column(Integer, primary_key=True)
|
|
123
|
+
pos = Column(Integer, nullable=False, server_default=text("0"))
|
|
124
|
+
name = Column(String(16), nullable=False)
|
|
125
|
+
description = Column(Text)
|
|
126
|
+
|
|
127
|
+
structdata = relationship("Structdata", secondary=tagged, back_populates="tags")
|
|
128
|
+
|
|
129
|
+
def __repr__(self):
|
|
130
|
+
return "Tag:{}".format(self.name)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class Unit(Base):
|
|
134
|
+
__tablename__ = "units"
|
|
135
|
+
|
|
136
|
+
id = Column(Integer, primary_key=True)
|
|
137
|
+
pos = Column(Integer, nullable=False, server_default=text("0"))
|
|
138
|
+
name = Column(String(60), nullable=False)
|
|
139
|
+
description = Column(Text)
|
|
140
|
+
|
|
141
|
+
sites = relationship("Site", back_populates="unit")
|
|
142
|
+
|
|
143
|
+
def __repr__(self):
|
|
144
|
+
return "Unit:{}".format(self.name)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def default_meta():
|
|
148
|
+
return dict(
|
|
149
|
+
version="3.1.0",
|
|
150
|
+
crs="EPSG:4326",
|
|
151
|
+
created=datetime.now().strftime("%d.%m.%Y %H:%M"),
|
|
152
|
+
updated=datetime.now().strftime("%d.%m.%Y %H:%M"),
|
|
153
|
+
accessed=datetime.now().strftime("%d.%m.%Y %H:%M"),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def default_initial_values():
|
|
158
|
+
return [
|
|
159
|
+
Structype(
|
|
160
|
+
pos=1,
|
|
161
|
+
structure="S",
|
|
162
|
+
description="Default planar feature",
|
|
163
|
+
structcode=35,
|
|
164
|
+
groupcode=13,
|
|
165
|
+
planar=1,
|
|
166
|
+
),
|
|
167
|
+
Structype(
|
|
168
|
+
pos=2,
|
|
169
|
+
structure="L",
|
|
170
|
+
description="Default linear feature",
|
|
171
|
+
structcode=78,
|
|
172
|
+
groupcode=13,
|
|
173
|
+
planar=0,
|
|
174
|
+
),
|
|
175
|
+
Unit(pos=1, name="Default", description="Default unit"),
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def before_commit_meta_update(session):
|
|
180
|
+
u = session.query(Meta).filter_by(name="updated").first()
|
|
181
|
+
u.value = datetime.now().strftime("%d.%m.%Y %H:%M")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def before_insert_pos_update(mapper, connection, target):
|
|
185
|
+
if target.pos is None:
|
|
186
|
+
t = str(mapper.persist_selectable)
|
|
187
|
+
query = "SELECT max({}.pos) FROM {}".format(t, t)
|
|
188
|
+
maxpos = connection.scalar(text(query))
|
|
189
|
+
if maxpos is None:
|
|
190
|
+
maxpos = 1
|
|
191
|
+
else:
|
|
192
|
+
maxpos += 1
|
|
193
|
+
target.pos = maxpos
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class SDBSession:
|
|
197
|
+
"""
|
|
198
|
+
SqlAlchemy interface to PySDB database
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
sdbfile (str): filename of PySDB database
|
|
202
|
+
|
|
203
|
+
Keyword Args:
|
|
204
|
+
create (bool): if True existing sdbfile will be deleted
|
|
205
|
+
and new database will be created
|
|
206
|
+
autocommit(bool): if True, each operation is autocommitted
|
|
207
|
+
|
|
208
|
+
Example:
|
|
209
|
+
>>> db = SDBSession('database.sdb', create=True)
|
|
210
|
+
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
def __init__(self, sdb_file, **kwargs):
|
|
214
|
+
if kwargs.get("create", False):
|
|
215
|
+
with contextlib.suppress(FileNotFoundError):
|
|
216
|
+
os.remove(sdb_file)
|
|
217
|
+
self.sdb_engine = create_engine("sqlite:///{}".format(sdb_file))
|
|
218
|
+
if kwargs.get("create", False):
|
|
219
|
+
metadata.create_all(self.sdb_engine)
|
|
220
|
+
sdb_Session = sessionmaker(bind=self.sdb_engine)
|
|
221
|
+
self.session = sdb_Session()
|
|
222
|
+
if kwargs.get("create", False):
|
|
223
|
+
meta = default_meta()
|
|
224
|
+
meta.update(kwargs.get("meta", {}))
|
|
225
|
+
self.session.add_all(default_initial_values())
|
|
226
|
+
self.session.add_all([Meta(name=n, value=v) for n, v in meta.items()])
|
|
227
|
+
self.session.commit()
|
|
228
|
+
self.autocommit = kwargs.get("autocommit", False)
|
|
229
|
+
# add listeners
|
|
230
|
+
event.listen(self.session, "before_commit", before_commit_meta_update)
|
|
231
|
+
event.listen(Unit, "before_insert", before_insert_pos_update)
|
|
232
|
+
event.listen(Structype, "before_insert", before_insert_pos_update)
|
|
233
|
+
event.listen(Tag, "before_insert", before_insert_pos_update)
|
|
234
|
+
|
|
235
|
+
def __repr__(self):
|
|
236
|
+
return self.info()
|
|
237
|
+
|
|
238
|
+
def info(self, data=False):
|
|
239
|
+
lines = []
|
|
240
|
+
lines.append(f"PySDB database version: {self.meta('version').value}")
|
|
241
|
+
lines.append(f"PySDB database CRS: {self.meta('crs').value}")
|
|
242
|
+
lines.append(f"PySDB database created: {self.meta('created').value}")
|
|
243
|
+
lines.append(f"PySDB database updated: {self.meta('created').value}")
|
|
244
|
+
lines.append(f"Number of sites: {self.session.query(Site).count()}")
|
|
245
|
+
lines.append(f"Number of units: {self.session.query(Unit).count()}")
|
|
246
|
+
lines.append(f"Number of structures: {self.session.query(Structype).count()}")
|
|
247
|
+
lines.append(
|
|
248
|
+
f"Number of measurements: {self.session.query(Structdata).count()}"
|
|
249
|
+
)
|
|
250
|
+
if data:
|
|
251
|
+
for s in self.structypes():
|
|
252
|
+
n = self.session.query(Structdata).filter_by(structype=s).count()
|
|
253
|
+
if n > 0:
|
|
254
|
+
lines.append(f"Number of {s.structure} measurements: {n}")
|
|
255
|
+
return "\n".join(lines)
|
|
256
|
+
|
|
257
|
+
def close(self):
|
|
258
|
+
"""
|
|
259
|
+
Close session
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
self.session.close()
|
|
263
|
+
|
|
264
|
+
def commit(self):
|
|
265
|
+
"""
|
|
266
|
+
commit session
|
|
267
|
+
|
|
268
|
+
"""
|
|
269
|
+
self.session.commit()
|
|
270
|
+
|
|
271
|
+
def rollback(self):
|
|
272
|
+
"""
|
|
273
|
+
rollback session
|
|
274
|
+
|
|
275
|
+
"""
|
|
276
|
+
self.session.rollback()
|
|
277
|
+
|
|
278
|
+
def meta(self, name, **kwargs):
|
|
279
|
+
"""
|
|
280
|
+
Insert, update or retrieve (when kwargs empty) Meta
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
name (str): meta name
|
|
284
|
+
|
|
285
|
+
Keyword Args:
|
|
286
|
+
value (str): meta value
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Meta
|
|
290
|
+
"""
|
|
291
|
+
meta = self.session.query(Meta).filter_by(name=name).first()
|
|
292
|
+
if kwargs:
|
|
293
|
+
if meta is None:
|
|
294
|
+
meta = Meta(name=name, **kwargs)
|
|
295
|
+
self.session.add(meta)
|
|
296
|
+
else:
|
|
297
|
+
self.session.query(Meta).filter_by(name=name).update(kwargs)
|
|
298
|
+
if self.autocommit:
|
|
299
|
+
self.commit()
|
|
300
|
+
return meta
|
|
301
|
+
|
|
302
|
+
def site(self, name, **kwargs):
|
|
303
|
+
"""
|
|
304
|
+
Insert, update or retrieve (when kwargs empty) Site
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
name (str): site name
|
|
308
|
+
|
|
309
|
+
Keyword Args:
|
|
310
|
+
x_coord (float): x coord or longitude
|
|
311
|
+
y_coord (float): y coord or latitude
|
|
312
|
+
description (str): site description
|
|
313
|
+
unit (Unit): unit instance (mus be provided)
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Site
|
|
317
|
+
"""
|
|
318
|
+
site = self.session.query(Site).filter_by(name=name).first()
|
|
319
|
+
if kwargs:
|
|
320
|
+
if site is None:
|
|
321
|
+
site = Site(name=name, **kwargs)
|
|
322
|
+
self.session.add(site)
|
|
323
|
+
else:
|
|
324
|
+
self.session.query(Site).filter_by(name=name).update(kwargs)
|
|
325
|
+
if self.autocommit:
|
|
326
|
+
self.commit()
|
|
327
|
+
return site
|
|
328
|
+
|
|
329
|
+
def unit(self, name, **kwargs):
|
|
330
|
+
"""
|
|
331
|
+
Insert, update or retrieve (when kwargs empty) Unit
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
name (str): unit name
|
|
335
|
+
|
|
336
|
+
Keyword Args:
|
|
337
|
+
description (str): unit description
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
Unit
|
|
341
|
+
"""
|
|
342
|
+
unit = self.session.query(Unit).filter_by(name=name).first()
|
|
343
|
+
if kwargs:
|
|
344
|
+
if unit is None:
|
|
345
|
+
unit = Unit(name=name, **kwargs)
|
|
346
|
+
self.session.add(unit)
|
|
347
|
+
else:
|
|
348
|
+
self.session.query(Unit).filter_by(name=name).update(kwargs)
|
|
349
|
+
if self.autocommit:
|
|
350
|
+
self.commit()
|
|
351
|
+
return unit
|
|
352
|
+
|
|
353
|
+
def tag(self, name, **kwargs):
|
|
354
|
+
"""
|
|
355
|
+
Insert, update or retrieve (when kwargs empty) Tag
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
name (str): tag name
|
|
359
|
+
|
|
360
|
+
Keyword Args:
|
|
361
|
+
description (str): tag description
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
Tag
|
|
365
|
+
"""
|
|
366
|
+
tag = self.session.query(Tag).filter_by(name=name).first()
|
|
367
|
+
if kwargs:
|
|
368
|
+
if tag is None:
|
|
369
|
+
tag = Tag(name=name, **kwargs)
|
|
370
|
+
self.session.add(tag)
|
|
371
|
+
else:
|
|
372
|
+
self.session.query(Tag).filter_by(name=name).update(kwargs)
|
|
373
|
+
if self.autocommit:
|
|
374
|
+
self.commit()
|
|
375
|
+
return tag
|
|
376
|
+
|
|
377
|
+
def structype(self, structure, **kwargs):
|
|
378
|
+
"""
|
|
379
|
+
Insert, update or retrieve (when kwargs empty) Structype
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
structure (str): label for structure
|
|
383
|
+
|
|
384
|
+
Keyword Args:
|
|
385
|
+
description (str): structype description
|
|
386
|
+
planar (int): 1 for planar 0 for linear
|
|
387
|
+
structcode (int): structcode (optional)
|
|
388
|
+
groupcode (int): groupcode (optional)
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
Structype
|
|
392
|
+
"""
|
|
393
|
+
structype = self.session.query(Structype).filter_by(structure=structure).first()
|
|
394
|
+
if kwargs:
|
|
395
|
+
if structype is None:
|
|
396
|
+
structype = Structype(structure=structure, **kwargs)
|
|
397
|
+
self.session.add(structype)
|
|
398
|
+
else:
|
|
399
|
+
self.session.query(Structype).filter_by(structure=structure).update(
|
|
400
|
+
kwargs
|
|
401
|
+
)
|
|
402
|
+
if self.autocommit:
|
|
403
|
+
self.commit()
|
|
404
|
+
return structype
|
|
405
|
+
|
|
406
|
+
def add_structdata(self, site, structype, azimuth, inclination, **kwargs):
|
|
407
|
+
"""
|
|
408
|
+
Add structdata to site
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
site (Site): site instance
|
|
412
|
+
structype (Structype): structype instance
|
|
413
|
+
azimuth (float): dip direction or plunge direction
|
|
414
|
+
inclination (float): dip or plunge
|
|
415
|
+
|
|
416
|
+
Keyword Args:
|
|
417
|
+
description (str): structdata description
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
Structdata
|
|
421
|
+
|
|
422
|
+
"""
|
|
423
|
+
data = Structdata(
|
|
424
|
+
site=site,
|
|
425
|
+
structype=structype,
|
|
426
|
+
azimuth=azimuth,
|
|
427
|
+
inclination=inclination,
|
|
428
|
+
**kwargs,
|
|
429
|
+
)
|
|
430
|
+
self.session.add(data)
|
|
431
|
+
if self.autocommit:
|
|
432
|
+
self.commit()
|
|
433
|
+
return data
|
|
434
|
+
|
|
435
|
+
def add_fol(self, site, structype, fol, **kwargs):
|
|
436
|
+
"""
|
|
437
|
+
Add Foliation to site
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
site (Site): site instance
|
|
441
|
+
structype (Structype): structype instance
|
|
442
|
+
fol (Foliation): foliation instance
|
|
443
|
+
|
|
444
|
+
Keyword Args:
|
|
445
|
+
description (str): structdata description
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
Structdata
|
|
449
|
+
|
|
450
|
+
"""
|
|
451
|
+
assert isinstance(
|
|
452
|
+
fol, Foliation
|
|
453
|
+
), "fol argument must be instance of Foliation class"
|
|
454
|
+
assert structype.planar, "structype must be planar"
|
|
455
|
+
azimuth, inclination = fol.geo
|
|
456
|
+
return self.add_structdata(site, structype, azimuth, inclination, **kwargs)
|
|
457
|
+
|
|
458
|
+
def add_lin(self, site, structype, lin, **kwargs):
|
|
459
|
+
"""
|
|
460
|
+
Add Lineation to site
|
|
461
|
+
|
|
462
|
+
Args:
|
|
463
|
+
site (Site): site instance
|
|
464
|
+
structype (Structype): structype instance
|
|
465
|
+
lin (Lineation): lineation instance
|
|
466
|
+
|
|
467
|
+
Keyword Args:
|
|
468
|
+
description (str): structdata description
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
Structdata
|
|
472
|
+
|
|
473
|
+
"""
|
|
474
|
+
assert isinstance(
|
|
475
|
+
lin, Lineation
|
|
476
|
+
), "lin argument must be instance of Lineation class"
|
|
477
|
+
assert not structype.planar, "structype must be linear"
|
|
478
|
+
azimuth, inclination = lin.geo
|
|
479
|
+
return self.add_structdata(site, structype, azimuth, inclination, **kwargs)
|
|
480
|
+
|
|
481
|
+
def attach(self, fol, lin):
|
|
482
|
+
"""
|
|
483
|
+
Add Lineation to site
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
fol (Foliation): foliation instance
|
|
487
|
+
lin (Lineation): lineation instance
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
Attached
|
|
491
|
+
|
|
492
|
+
"""
|
|
493
|
+
pair = Attached(planar=fol, linear=lin)
|
|
494
|
+
self.session.add(pair)
|
|
495
|
+
if self.autocommit:
|
|
496
|
+
self.commit()
|
|
497
|
+
return pair
|
|
498
|
+
|
|
499
|
+
def add_pair(self, pair, foltype, lintype, **kwargs):
|
|
500
|
+
"""
|
|
501
|
+
Add attached foliation and lineation to database
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
pair (Pair): pair instance
|
|
505
|
+
foltype (Structype): structype instance
|
|
506
|
+
lintype (Structype): structype instance
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
Attached
|
|
510
|
+
|
|
511
|
+
"""
|
|
512
|
+
assert isinstance(pair, Pair), "pair argument must be instance of Pair class"
|
|
513
|
+
kwargs["structype"] = foltype
|
|
514
|
+
fol = self.add_fol(pair.fol, **kwargs)
|
|
515
|
+
kwargs["structype"] = lintype
|
|
516
|
+
lin = self.add_lin(pair.lin, **kwargs)
|
|
517
|
+
return self.attach(fol, lin)
|
|
518
|
+
|
|
519
|
+
def sites(self, **kwargs):
|
|
520
|
+
"""
|
|
521
|
+
Retrieve Site or list of Sites based on criteria in kwargs
|
|
522
|
+
|
|
523
|
+
Keyword arguments are passed to sqlalchemy filter_by method
|
|
524
|
+
"""
|
|
525
|
+
if kwargs:
|
|
526
|
+
sites = self.session.query(Site).filter_by(**kwargs).all()
|
|
527
|
+
else:
|
|
528
|
+
sites = self.session.query(Site).all()
|
|
529
|
+
if len(sites) == 1:
|
|
530
|
+
return sites[0]
|
|
531
|
+
else:
|
|
532
|
+
return sites
|
|
533
|
+
|
|
534
|
+
def units(self, **kwargs):
|
|
535
|
+
"""
|
|
536
|
+
Retrieve Unit or list of Units based on criteria in kwargs
|
|
537
|
+
|
|
538
|
+
Keyword arguments are passed to sqlalchemy filter_by method
|
|
539
|
+
"""
|
|
540
|
+
if kwargs:
|
|
541
|
+
units = self.session.query(Unit).filter_by(**kwargs).all()
|
|
542
|
+
else:
|
|
543
|
+
units = self.session.query(Unit).all()
|
|
544
|
+
if len(units) == 1:
|
|
545
|
+
return units[0]
|
|
546
|
+
else:
|
|
547
|
+
return units
|
|
548
|
+
|
|
549
|
+
def structypes(self, **kwargs):
|
|
550
|
+
"""
|
|
551
|
+
Retrieve Structype or list of Structypes based on criteria in kwargs
|
|
552
|
+
|
|
553
|
+
Keyword arguments are passed to sqlalchemy filter_by method
|
|
554
|
+
"""
|
|
555
|
+
if kwargs:
|
|
556
|
+
structypes = self.session.query(Structype).filter_by(**kwargs).all()
|
|
557
|
+
else:
|
|
558
|
+
structypes = self.session.query(Structype).all()
|
|
559
|
+
if len(structypes) == 1:
|
|
560
|
+
return structypes[0]
|
|
561
|
+
else:
|
|
562
|
+
return structypes
|
|
563
|
+
|
|
564
|
+
def tags(self, **kwargs):
|
|
565
|
+
"""
|
|
566
|
+
Retrieve Tag or list of Tags based on criteria in kwargs
|
|
567
|
+
|
|
568
|
+
Keyword arguments are passed to sqlalchemy filter_by method
|
|
569
|
+
"""
|
|
570
|
+
if kwargs:
|
|
571
|
+
tags = self.session.query(Tag).filter_by(**kwargs).all()
|
|
572
|
+
else:
|
|
573
|
+
tags = self.session.query(Tag).all()
|
|
574
|
+
if len(tags) == 1:
|
|
575
|
+
return tags[0]
|
|
576
|
+
else:
|
|
577
|
+
return tags
|
|
578
|
+
|
|
579
|
+
def getset(self, structype, **kwargs):
|
|
580
|
+
"""Method to retrieve data from SDB database to ``FeatureSet``.
|
|
581
|
+
|
|
582
|
+
Args:
|
|
583
|
+
structype (str, Structype): structure or list of structures to retrieve
|
|
584
|
+
|
|
585
|
+
Keyword arguments are passed to sqlalchemy filter_by method
|
|
586
|
+
|
|
587
|
+
"""
|
|
588
|
+
if isinstance(structype, str):
|
|
589
|
+
structypes = (
|
|
590
|
+
self.session.query(Structype).filter_by(structure=structype).all()
|
|
591
|
+
)
|
|
592
|
+
assert len(structypes) == 1, f"There is no structure {structype} in db"
|
|
593
|
+
structype = structypes[0]
|
|
594
|
+
data = (
|
|
595
|
+
self.session.query(Structdata)
|
|
596
|
+
.filter_by(structype=structype, **kwargs)
|
|
597
|
+
.all()
|
|
598
|
+
)
|
|
599
|
+
if structype.planar:
|
|
600
|
+
res = FoliationSet(
|
|
601
|
+
[Foliation(v.azimuth, v.inclination) for v in data],
|
|
602
|
+
name=structype.structure,
|
|
603
|
+
)
|
|
604
|
+
else:
|
|
605
|
+
res = LineationSet(
|
|
606
|
+
[Lineation(v.azimuth, v.inclination) for v in data],
|
|
607
|
+
name=structype.structure,
|
|
608
|
+
)
|
|
609
|
+
return res
|