compass-lib 0.0.1__py3-none-any.whl → 0.0.3__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.
- compass_lib/__init__.py +115 -3
- compass_lib/commands/__init__.py +2 -1
- compass_lib/commands/convert.py +225 -32
- compass_lib/commands/encrypt.py +115 -0
- compass_lib/commands/geojson.py +118 -0
- compass_lib/commands/main.py +4 -2
- compass_lib/constants.py +84 -0
- compass_lib/enums.py +309 -65
- compass_lib/errors.py +86 -0
- compass_lib/geo_utils.py +47 -0
- compass_lib/geojson.py +1024 -0
- compass_lib/interface.py +332 -0
- compass_lib/io.py +246 -0
- compass_lib/models.py +251 -0
- compass_lib/plot/__init__.py +28 -0
- compass_lib/plot/models.py +265 -0
- compass_lib/plot/parser.py +610 -0
- compass_lib/project/__init__.py +36 -0
- compass_lib/project/format.py +158 -0
- compass_lib/project/models.py +494 -0
- compass_lib/project/parser.py +638 -0
- compass_lib/survey/__init__.py +24 -0
- compass_lib/survey/format.py +284 -0
- compass_lib/survey/models.py +160 -0
- compass_lib/survey/parser.py +842 -0
- compass_lib/validation.py +74 -0
- compass_lib-0.0.3.dist-info/METADATA +60 -0
- compass_lib-0.0.3.dist-info/RECORD +31 -0
- {compass_lib-0.0.1.dist-info → compass_lib-0.0.3.dist-info}/WHEEL +1 -3
- compass_lib-0.0.3.dist-info/entry_points.txt +8 -0
- compass_lib/parser.py +0 -282
- compass_lib/section.py +0 -18
- compass_lib/shot.py +0 -21
- compass_lib-0.0.1.dist-info/METADATA +0 -268
- compass_lib-0.0.1.dist-info/RECORD +0 -14
- compass_lib-0.0.1.dist-info/entry_points.txt +0 -5
- compass_lib-0.0.1.dist-info/top_level.txt +0 -1
- {compass_lib-0.0.1.dist-info → compass_lib-0.0.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Validation utilities for Compass data.
|
|
3
|
+
|
|
4
|
+
This module provides validation functions for station names and other
|
|
5
|
+
data elements based on Compass format specifications.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import calendar
|
|
9
|
+
import re
|
|
10
|
+
from re import Pattern
|
|
11
|
+
|
|
12
|
+
# Station name pattern: printable ASCII characters (0x21-0x7F), no spaces
|
|
13
|
+
# The original Compass spec limited to 12 chars, but modern files often exceed this
|
|
14
|
+
# We allow any length but still require valid printable ASCII
|
|
15
|
+
STATION_NAME_PATTERN: Pattern[str] = re.compile(r"^[\x21-\x7f]+$")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def is_valid_station_name(name: str) -> bool:
|
|
19
|
+
"""Check if a station name is valid.
|
|
20
|
+
|
|
21
|
+
Valid station names:
|
|
22
|
+
- 1 or more characters (no upper limit enforced)
|
|
23
|
+
- Printable ASCII only (0x21-0x7F)
|
|
24
|
+
- No spaces or control characters
|
|
25
|
+
|
|
26
|
+
Note: The original Compass format limited station names to 12 characters,
|
|
27
|
+
but many modern Compass files use longer names. This validation accepts
|
|
28
|
+
any length to ensure compatibility with real-world data.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
name: Station name to validate
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
True if valid, False otherwise
|
|
35
|
+
"""
|
|
36
|
+
if not name:
|
|
37
|
+
return False
|
|
38
|
+
return bool(STATION_NAME_PATTERN.match(name))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def validate_station_name(name: str) -> None:
|
|
42
|
+
"""Validate a station name, raising an error if invalid.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
name: Station name to validate
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
ValueError: If the station name is invalid
|
|
49
|
+
"""
|
|
50
|
+
if not is_valid_station_name(name):
|
|
51
|
+
# Escape non-printable characters for error message
|
|
52
|
+
escaped = ""
|
|
53
|
+
for char in name:
|
|
54
|
+
if ord(char) < 0x20 or ord(char) > 0x7F:
|
|
55
|
+
escaped += f"\\x{ord(char):02x}"
|
|
56
|
+
else:
|
|
57
|
+
escaped += char
|
|
58
|
+
msg = f"Invalid station name: {escaped}"
|
|
59
|
+
raise ValueError(msg)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def days_in_month(month: int, year: int) -> int:
|
|
63
|
+
"""Get the number of days in a month, accounting for leap years.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
month: Month (1-12)
|
|
67
|
+
year: Year
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Number of days in the month
|
|
71
|
+
"""
|
|
72
|
+
# monthrange returns (weekday_of_first_day, num_days_in_month)
|
|
73
|
+
_, num_days = calendar.monthrange(year, month)
|
|
74
|
+
return num_days
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: compass_lib
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: Compass Parser Library.
|
|
5
|
+
Keywords: cave,survey,karst
|
|
6
|
+
Author-email: Jonathan Dekhtiar <jonathan@dekhtiar.com>
|
|
7
|
+
Maintainer-email: Jonathan Dekhtiar <jonathan@dekhtiar.com>
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Intended Audience :: Information Technology
|
|
14
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: geojson>=3.2,<4
|
|
24
|
+
Requires-Dist: orjson>=3.10,<3.12
|
|
25
|
+
Requires-Dist: pydantic>=2.12,<2.13
|
|
26
|
+
Requires-Dist: pydantic-extra-types>=2.11,<3.0
|
|
27
|
+
Requires-Dist: pyIGRF14==1.0.4
|
|
28
|
+
Requires-Dist: pyproj>=3.7.1,<3.8
|
|
29
|
+
Requires-Dist: utm>=0.8.1,<0.9
|
|
30
|
+
Requires-Dist: cryptography>=44.0.0,<47.0.0 ; extra == "test"
|
|
31
|
+
Requires-Dist: python-dotenv>=1.0.0,<2.0.0 ; extra == "test"
|
|
32
|
+
Requires-Dist: deepdiff>=7.0,<9.0 ; extra == "test"
|
|
33
|
+
Requires-Dist: pytest>=8.0.0,<10.0.0 ; extra == "test"
|
|
34
|
+
Requires-Dist: pytest-cov>=5.0.0,<8.0.0 ; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-dotenv>=0.5.0,<1.0.0 ; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-env>=1.1.3,<2.0.0 ; extra == "test"
|
|
37
|
+
Requires-Dist: pytest-runner>=6.0.0,<7.0.0 ; extra == "test"
|
|
38
|
+
Requires-Dist: pytest-ordering>=0.6,<1.0.0 ; extra == "test"
|
|
39
|
+
Requires-Dist: parameterized>=0.9.0,<0.10 ; extra == "test"
|
|
40
|
+
Project-URL: Bug Reports, https://github.com/OpenSpeleo/pytool_compass_lib/issues
|
|
41
|
+
Project-URL: Homepage, https://pypi.org/project/compass-lib/
|
|
42
|
+
Project-URL: Source, https://github.com/OpenSpeleo/pytool_compass_lib
|
|
43
|
+
Provides-Extra: test
|
|
44
|
+
|
|
45
|
+
# Compass Python Lib
|
|
46
|
+
|
|
47
|
+
## Conversion commands:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install in dev mod
|
|
51
|
+
pip install -e ".[dev,test]"
|
|
52
|
+
|
|
53
|
+
# Install latest stable version
|
|
54
|
+
pip install compass_lib
|
|
55
|
+
|
|
56
|
+
# run some commands
|
|
57
|
+
compass convert --input_file=./tests/artifacts/fulford.dat --output_file=fulford.json --format=json --overwrite
|
|
58
|
+
compass convert --input_file=./tests/artifacts/random.dat --output_file=random.json --format=json --overwrite
|
|
59
|
+
```
|
|
60
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
compass_lib/__init__.py,sha256=GmS4B4rae0P8zy4-givpmeyFUSqKRJ8WEERgxro9Gxs,3594
|
|
2
|
+
compass_lib/constants.py,sha256=TApFKLFXywSS_iFx_UBBO9mQhjW2-1f8Wsu0J-Mr-rU,3144
|
|
3
|
+
compass_lib/enums.py,sha256=PgIOhqb6qUBHZhZpVaZfQ_qG6DCp2nfQD4SghM-lAoM,9667
|
|
4
|
+
compass_lib/errors.py,sha256=0D5jCIroPdRX2oVx1PK_lotYKDdjc_94jeFKQhW8pBE,2473
|
|
5
|
+
compass_lib/geo_utils.py,sha256=5KKHKNIGOXrV3dTGbaLbGY4j7EajFXf0bcKFsDyJ0Sg,1409
|
|
6
|
+
compass_lib/geojson.py,sha256=yROsA_J19Afkx-_i3E2TFL2Qi28uAhhAfjLWmpzDoFA,34289
|
|
7
|
+
compass_lib/interface.py,sha256=GcM2yRD39dpy94brTIpJD-Z5DSlmBjpuu6dkTsHpyoI,10576
|
|
8
|
+
compass_lib/io.py,sha256=xU8JYg0gQK6FrpvEQHqXHCBotIWNVJP2Iu1MidgBbQ8,6506
|
|
9
|
+
compass_lib/models.py,sha256=vXQ-kJZVFRmUsNV3-8bsdTC48hLmkuoOIsIco8_al9Y,7036
|
|
10
|
+
compass_lib/validation.py,sha256=tfLn3MNblpQ7vb0TDeimEQV_zeNkLMT8NY0xCdUQFOo,2176
|
|
11
|
+
compass_lib/commands/__init__.py,sha256=kHsx7hB3ivV6wfdRn1KkhlbVPkLcaGsMLXOdgZhKU3Q,79
|
|
12
|
+
compass_lib/commands/convert.py,sha256=RZ3ZFd83yAb2pgso6oaRRtHjEHMSojsaoKmo4RX6fcs,8501
|
|
13
|
+
compass_lib/commands/encrypt.py,sha256=dD5IspbWPnjFjiFDa5RBkfgrQzG_5VglPKGqIOk_Uf8,3189
|
|
14
|
+
compass_lib/commands/geojson.py,sha256=kRgukxnGJIFvFod9odJFaMBZE6BK0I3polNZyBx9G9s,3554
|
|
15
|
+
compass_lib/commands/main.py,sha256=rce8oDfTwZdR5oKVQggNeGn8geIldPRbjvqRucwnFAI,775
|
|
16
|
+
compass_lib/plot/__init__.py,sha256=YXIKLAJSmHtIxiZNxCkDJLR3ud8Dgeea7pKrchB_NtY,953
|
|
17
|
+
compass_lib/plot/models.py,sha256=OEbSibClG95Jo-rDET2chAcfuE0qLsfnj522WW3jmtY,7815
|
|
18
|
+
compass_lib/plot/parser.py,sha256=K3YK-CVXCxAUhLQpi95CajPvWCWOwv41d05Whylysxg,19294
|
|
19
|
+
compass_lib/project/__init__.py,sha256=qdYdBCdEP669a4zT3r7xHm6qDGquf52hkeMyKzXMx_c,1312
|
|
20
|
+
compass_lib/project/format.py,sha256=uxSNG97yzwfUZpV7uYS8n6q0cZEzfSuKi8igBhZwKGY,5033
|
|
21
|
+
compass_lib/project/models.py,sha256=Z3qDggeEV_SEoO5ky5Wjrc7ZmyNdxnTSolNSIpoyQb0,15033
|
|
22
|
+
compass_lib/project/parser.py,sha256=YV3_qUMNbd_enql_5BKcU8jithltTzSmdhbgpSBNvIU,21733
|
|
23
|
+
compass_lib/survey/__init__.py,sha256=9BfBbW0luUr1ldNI4joD1WuZpTH7wuQ2lsdyMw-ppYY,784
|
|
24
|
+
compass_lib/survey/format.py,sha256=L5DPPe3riTknro2a_V70n-jkdJOkp9wK6TX0KbMjrPM,8655
|
|
25
|
+
compass_lib/survey/models.py,sha256=YRch52D0kBf9SxQ5RIhbvIy09-Yt2AtNeNRugJd7K_c,5258
|
|
26
|
+
compass_lib/survey/parser.py,sha256=xvBi3jr1Hgq3rzRzWTYJFQaAHpv7jFtD-QBeyhmAjhM,27402
|
|
27
|
+
compass_lib-0.0.3.dist-info/entry_points.txt,sha256=VhEdfsIVxwPerPEyPYms1IIJ6r4UOeCgPagV2BMzUd8,216
|
|
28
|
+
compass_lib-0.0.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
29
|
+
compass_lib-0.0.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
30
|
+
compass_lib-0.0.3.dist-info/METADATA,sha256=9oGhJp4nt62bUfzsDLYJgujs7c-kVELSR7Nc1k1kEv8,2393
|
|
31
|
+
compass_lib-0.0.3.dist-info/RECORD,,
|
compass_lib/parser.py
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
import datetime
|
|
5
|
-
import hashlib
|
|
6
|
-
import json
|
|
7
|
-
from typing import Optional, Union
|
|
8
|
-
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
from compass_lib.enums import ShotFlag
|
|
11
|
-
|
|
12
|
-
from compass_lib.section import SurveySection
|
|
13
|
-
from compass_lib.shot import SurveyShot
|
|
14
|
-
|
|
15
|
-
from functools import cached_property
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import dataclasses
|
|
19
|
-
from dataclasses import dataclass
|
|
20
|
-
|
|
21
|
-
# ============================== CompassFileFormat ============================== #
|
|
22
|
-
|
|
23
|
-
# _formatFormat(): string {
|
|
24
|
-
# const {
|
|
25
|
-
# displayAzimuthUnit,
|
|
26
|
-
# displayLengthUnit,
|
|
27
|
-
# displayLrudUnit,
|
|
28
|
-
# displayInclinationUnit,
|
|
29
|
-
# lrudOrder,
|
|
30
|
-
# shotMeasurementOrder,
|
|
31
|
-
# hasBacksights,
|
|
32
|
-
# lrudAssociation,
|
|
33
|
-
# } = this
|
|
34
|
-
# return `${inverseAzimuthUnits[displayAzimuthUnit]}${
|
|
35
|
-
# inverseLengthUnits[displayLengthUnit]
|
|
36
|
-
# }${inverseLengthUnits[displayLrudUnit]}${
|
|
37
|
-
# inverseInclinationUnits[displayInclinationUnit]
|
|
38
|
-
# }${lrudOrder
|
|
39
|
-
# .map(i => inverseLrudItems[i])
|
|
40
|
-
# .join('')}${shotMeasurementOrder
|
|
41
|
-
# .map(i => inverseShotMeasurementItems[i])
|
|
42
|
-
# .join('')}${hasBacksights ? 'B' : 'N'}${
|
|
43
|
-
# lrudAssociation != null ? inverseStationSides[lrudAssociation] : ''
|
|
44
|
-
# }`
|
|
45
|
-
# }
|
|
46
|
-
|
|
47
|
-
@dataclass
|
|
48
|
-
class CompassFileFormat:
|
|
49
|
-
displayAzimuthUnit: str
|
|
50
|
-
displayLengthUnit: str
|
|
51
|
-
displayLrudUnit: str
|
|
52
|
-
displayInclinationUnit: str
|
|
53
|
-
lrudOrder: str
|
|
54
|
-
shotMeasurementOrder: str
|
|
55
|
-
hasBacksights: str
|
|
56
|
-
lrudAssociation: str
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def from_str(cls, input):
|
|
60
|
-
return cls(
|
|
61
|
-
displayAzimuthUnit="",
|
|
62
|
-
displayLengthUnit="",
|
|
63
|
-
displayLrudUnit="",
|
|
64
|
-
displayInclinationUnit="",
|
|
65
|
-
lrudOrder="",
|
|
66
|
-
shotMeasurementOrder="",
|
|
67
|
-
hasBacksights="",
|
|
68
|
-
lrudAssociation="",
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class EnhancedJSONEncoder(json.JSONEncoder):
|
|
74
|
-
def default(self, obj):
|
|
75
|
-
|
|
76
|
-
if dataclasses.is_dataclass(obj):
|
|
77
|
-
return dataclasses.asdict(obj)
|
|
78
|
-
|
|
79
|
-
if isinstance(obj, datetime.date):
|
|
80
|
-
return obj.isoformat()
|
|
81
|
-
|
|
82
|
-
if isinstance(obj, ShotFlag):
|
|
83
|
-
return obj.value
|
|
84
|
-
|
|
85
|
-
return super().default(obj)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class CompassParser:
|
|
89
|
-
SEPARATOR = "\f" # Form_feed: https://www.ascii-code.com/12
|
|
90
|
-
END_OF_FILE = "\x1A" # Substitute: https://www.ascii-code.com/26
|
|
91
|
-
|
|
92
|
-
def __init__(self, filepath: str) -> None:
|
|
93
|
-
|
|
94
|
-
self._filepath = Path(filepath)
|
|
95
|
-
|
|
96
|
-
if not self.filepath.is_file():
|
|
97
|
-
raise FileNotFoundError(f"File not found: {filepath}")
|
|
98
|
-
|
|
99
|
-
# Ensure at least that the file type is valid
|
|
100
|
-
_ = self._data
|
|
101
|
-
|
|
102
|
-
# =================== Data Loading =================== #
|
|
103
|
-
|
|
104
|
-
@cached_property
|
|
105
|
-
def _data(self):
|
|
106
|
-
|
|
107
|
-
with self.filepath.open(mode="r") as f:
|
|
108
|
-
data = f.read()
|
|
109
|
-
|
|
110
|
-
return [
|
|
111
|
-
activity.strip()
|
|
112
|
-
for activity in data.split(CompassParser.SEPARATOR)
|
|
113
|
-
if CompassParser.END_OF_FILE not in activity
|
|
114
|
-
]
|
|
115
|
-
|
|
116
|
-
# =================== File Properties =================== #
|
|
117
|
-
|
|
118
|
-
def __repr__(self) -> str:
|
|
119
|
-
repr = f"[CompassSurveyFile {self.filetype.upper()}] `{self.filepath}`:"
|
|
120
|
-
# for key in self._KEY_MAP.keys():
|
|
121
|
-
# if key.startswith("_"):
|
|
122
|
-
# continue
|
|
123
|
-
# repr += f"\n\t- {key}: {getattr(self, key)}"
|
|
124
|
-
# repr += f"\n\t- shots: Total Shots: {len(self.shots)}"
|
|
125
|
-
# repr += f"\n\t- hash: {self.hash}"
|
|
126
|
-
return repr
|
|
127
|
-
|
|
128
|
-
@cached_property
|
|
129
|
-
def __hash__(self):
|
|
130
|
-
# return hashlib.sha256(self._as_binary()).hexdigest()
|
|
131
|
-
return hashlib.sha256("0".encode()).hexdigest()
|
|
132
|
-
|
|
133
|
-
@property
|
|
134
|
-
def hash(self):
|
|
135
|
-
return self.__hash__
|
|
136
|
-
|
|
137
|
-
# =============== Descriptive Properties =============== #
|
|
138
|
-
|
|
139
|
-
@property
|
|
140
|
-
def filepath(self):
|
|
141
|
-
return self._filepath
|
|
142
|
-
|
|
143
|
-
@property
|
|
144
|
-
def filetype(self):
|
|
145
|
-
return self.filepath.suffix[1:]
|
|
146
|
-
# try:
|
|
147
|
-
# return ArianeFileType.from_str(self.filepath.suffix[1:])
|
|
148
|
-
# except ValueError as e:
|
|
149
|
-
# raise TypeError(e) from e
|
|
150
|
-
|
|
151
|
-
@property
|
|
152
|
-
def lstat(self):
|
|
153
|
-
return self.filepath.lstat()
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def date_created(self):
|
|
157
|
-
return self.lstat.st_ctime
|
|
158
|
-
|
|
159
|
-
@property
|
|
160
|
-
def date_last_modified(self):
|
|
161
|
-
return self.lstat.st_mtime
|
|
162
|
-
|
|
163
|
-
@property
|
|
164
|
-
def date_last_opened(self):
|
|
165
|
-
return self.lstat.st_atime
|
|
166
|
-
|
|
167
|
-
# =================== Data Processing =================== #
|
|
168
|
-
|
|
169
|
-
@cached_property
|
|
170
|
-
def data(self):
|
|
171
|
-
sections = []
|
|
172
|
-
for activity in self._data:
|
|
173
|
-
entries = activity.splitlines()
|
|
174
|
-
|
|
175
|
-
cave_name = entries[0].strip()
|
|
176
|
-
|
|
177
|
-
if "SURVEY NAME: " not in entries[1]:
|
|
178
|
-
raise RuntimeError
|
|
179
|
-
survey_name = entries[1].split(":")[-1].strip()
|
|
180
|
-
|
|
181
|
-
date_str, comment_str = entries[2].split(" ", maxsplit=1)
|
|
182
|
-
|
|
183
|
-
if "SURVEY DATE: " not in date_str:
|
|
184
|
-
raise RuntimeError
|
|
185
|
-
date = date_str.split(":")[-1].strip()
|
|
186
|
-
|
|
187
|
-
if "COMMENT:" not in comment_str:
|
|
188
|
-
raise RuntimeError
|
|
189
|
-
survey_comment = comment_str.split(":")[-1].strip()
|
|
190
|
-
|
|
191
|
-
if "SURVEY TEAM:" != entries[3].strip():
|
|
192
|
-
raise RuntimeError
|
|
193
|
-
|
|
194
|
-
surveyors = [suveyor.strip() for suveyor in entries[4].split(",") if suveyor.strip() != ""]
|
|
195
|
-
|
|
196
|
-
if "DECLINATION:" not in entries[5]:
|
|
197
|
-
raise RuntimeError
|
|
198
|
-
if "FORMAT:" not in entries[5]:
|
|
199
|
-
raise RuntimeError
|
|
200
|
-
if "CORRECTIONS:" not in entries[5]:
|
|
201
|
-
raise RuntimeError
|
|
202
|
-
|
|
203
|
-
_, declination_str, _, format_str, _, correct_A, correct_B, correct_C = entries[5].split()
|
|
204
|
-
|
|
205
|
-
shots = list()
|
|
206
|
-
for shot in entries[9:]:
|
|
207
|
-
shot_data = shot.split(maxsplit=9)
|
|
208
|
-
from_id, to_id, length, bearing, incl, left, up, down, right = shot_data[:9]
|
|
209
|
-
|
|
210
|
-
try:
|
|
211
|
-
flags_comment = shot_data[9]
|
|
212
|
-
|
|
213
|
-
flag_regex = rf"({ShotFlag.__start_token__}([{''.join(ShotFlag._value2member_map_.keys())}]*){ShotFlag.__end_token__})*(.*)"
|
|
214
|
-
_, flag_str, comment = re.search(flag_regex, flags_comment).groups()
|
|
215
|
-
|
|
216
|
-
flags = [ShotFlag._value2member_map_[f] for f in flag_str] if flag_str else None
|
|
217
|
-
|
|
218
|
-
except IndexError:
|
|
219
|
-
flags = None
|
|
220
|
-
comment = None
|
|
221
|
-
|
|
222
|
-
shots.append(SurveyShot(
|
|
223
|
-
from_id=from_id,
|
|
224
|
-
to_id=to_id,
|
|
225
|
-
length=float(length),
|
|
226
|
-
bearing=float(bearing),
|
|
227
|
-
inclination=float(incl),
|
|
228
|
-
left=float(left),
|
|
229
|
-
up=float(up),
|
|
230
|
-
down=float(down),
|
|
231
|
-
right=float(right),
|
|
232
|
-
flags=sorted(set(flags), key=lambda f: f.value) if flags else None,
|
|
233
|
-
comment=comment.strip() if comment else None
|
|
234
|
-
))
|
|
235
|
-
|
|
236
|
-
section = SurveySection(
|
|
237
|
-
cave_name=cave_name,
|
|
238
|
-
survey_name=survey_name,
|
|
239
|
-
date=datetime.datetime.strptime(date, "%m %d %Y").date(),
|
|
240
|
-
comment=survey_comment,
|
|
241
|
-
surveyors=surveyors,
|
|
242
|
-
declination=float(declination_str),
|
|
243
|
-
format=format_str,
|
|
244
|
-
correction=(float(correct_A), float(correct_B), float(correct_C)),
|
|
245
|
-
shots=shots
|
|
246
|
-
)
|
|
247
|
-
sections.append(section)
|
|
248
|
-
|
|
249
|
-
return sections
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
# =================== Export Formats =================== #
|
|
253
|
-
|
|
254
|
-
def to_json(self, filepath: Optional[Union[str, Path]] = None) -> str:
|
|
255
|
-
json_str = json.dumps(self.data, indent=4, sort_keys=True, cls=EnhancedJSONEncoder)
|
|
256
|
-
|
|
257
|
-
if filepath is not None:
|
|
258
|
-
with open(filepath, mode="w") as file:
|
|
259
|
-
file.write(json_str)
|
|
260
|
-
|
|
261
|
-
return json_str
|
|
262
|
-
|
|
263
|
-
# ==================== Public APIs ====================== #
|
|
264
|
-
|
|
265
|
-
@cached_property
|
|
266
|
-
def shots(self):
|
|
267
|
-
return []
|
|
268
|
-
# return [
|
|
269
|
-
# SurveyShot(data=survey_shot)
|
|
270
|
-
# for survey_shot in self._KEY_MAP.fetch(self._shots_list, "_shots")
|
|
271
|
-
# ]
|
|
272
|
-
|
|
273
|
-
@cached_property
|
|
274
|
-
def sections(self):
|
|
275
|
-
return []
|
|
276
|
-
# section_map = dict()
|
|
277
|
-
# for shot in self.shots:
|
|
278
|
-
# try:
|
|
279
|
-
# section_map[shot.section].add_shot(shot)
|
|
280
|
-
# except KeyError:
|
|
281
|
-
# section_map[shot.section] = SurveySection(shot=shot)
|
|
282
|
-
# return list(section_map.values())
|
compass_lib/section.py
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
|
|
3
|
-
from datetime import date
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from compass_lib.shot import SurveyShot
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@dataclass
|
|
9
|
-
class SurveySection:
|
|
10
|
-
cave_name: str
|
|
11
|
-
survey_name: str
|
|
12
|
-
date: date
|
|
13
|
-
comment: str
|
|
14
|
-
surveyors: list[str]
|
|
15
|
-
declination: float
|
|
16
|
-
format: str
|
|
17
|
-
correction: tuple[float, float, float]
|
|
18
|
-
shots: list[SurveyShot]
|
compass_lib/shot.py
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
|
|
5
|
-
from compass_lib.enums import ShotFlag
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
8
|
-
class SurveyShot:
|
|
9
|
-
# FROM TO LENGTH BEARING INC LEFT UP DOWN RIGHT FLAGS COMMENTS
|
|
10
|
-
# A1 A2 21.75 63.50 -28.00 2.60 2.60 2.60 2.60#
|
|
11
|
-
from_id: str
|
|
12
|
-
to_id: str
|
|
13
|
-
length: float
|
|
14
|
-
bearing: float
|
|
15
|
-
inclination: float
|
|
16
|
-
left: float
|
|
17
|
-
up: float
|
|
18
|
-
down: float
|
|
19
|
-
right: float
|
|
20
|
-
flags: list[ShotFlag]
|
|
21
|
-
comment: str
|