gsolve 5.6.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.
- gsolve/__init__.py +38 -0
- gsolve/__main__.py +190 -0
- gsolve/core/__init__.py +0 -0
- gsolve/core/_summary_functions.py +57 -0
- gsolve/core/_typing.py +120 -0
- gsolve/core/data.py +657 -0
- gsolve/core/excel_io.py +250 -0
- gsolve/core/utils.py +962 -0
- gsolve/core/xr_accessor.py +491 -0
- gsolve/core/xr_methods.py +269 -0
- gsolve/gsolve_algorithms.py +354 -0
- gsolve/gsolve_outputs.py +451 -0
- gsolve/meter_conversion.py +551 -0
- gsolve/observations.py +1668 -0
- gsolve/reductions/__init__.py +3 -0
- gsolve/reductions/anomalies.py +544 -0
- gsolve/reductions/corrections.py +858 -0
- gsolve/reductions/terrain_corrections.py +1595 -0
- gsolve/reports.py +393 -0
- gsolve/scintrex.py +817 -0
- gsolve/sites.py +921 -0
- gsolve/tide/__init__.py +6 -0
- gsolve/tide/earth_tide.py +1188 -0
- gsolve/tide/ocean_load.py +727 -0
- gsolve-5.6.0.dist-info/METADATA +110 -0
- gsolve-5.6.0.dist-info/RECORD +28 -0
- gsolve-5.6.0.dist-info/WHEEL +4 -0
- gsolve-5.6.0.dist-info/licenses/LICENSE +189 -0
gsolve/__init__.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib.metadata as _im
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _im.version("gsolve")
|
|
7
|
+
except _im.PackageNotFoundError:
|
|
8
|
+
__version__ = "5.6.0" # pragma: no cover
|
|
9
|
+
|
|
10
|
+
from gsolve.meter_conversion import LaCosteRombergDialConverter
|
|
11
|
+
from gsolve.observations import GravityObservations, GravitySurvey
|
|
12
|
+
from gsolve.reductions.anomalies import GravityAnomalies
|
|
13
|
+
from gsolve.reductions.corrections import (
|
|
14
|
+
GravityCorrectionParameters,
|
|
15
|
+
GravityCorrectionProvider,
|
|
16
|
+
)
|
|
17
|
+
from gsolve.reductions.terrain_corrections import (
|
|
18
|
+
TerrainCorrectionData,
|
|
19
|
+
TerrainCorrectionParameters,
|
|
20
|
+
TerrainCorrector,
|
|
21
|
+
)
|
|
22
|
+
from gsolve.reports import GSolveReport
|
|
23
|
+
from gsolve.sites import GravitySites, ReferenceGravity
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"GravityObservations",
|
|
27
|
+
"GravitySurvey",
|
|
28
|
+
"GravitySites",
|
|
29
|
+
"ReferenceGravity",
|
|
30
|
+
"LaCosteRombergDialConverter",
|
|
31
|
+
"GSolveReport",
|
|
32
|
+
"GravityCorrectionProvider",
|
|
33
|
+
"GravityCorrectionParameters",
|
|
34
|
+
"GravityAnomalies",
|
|
35
|
+
"TerrainCorrectionParameters",
|
|
36
|
+
"TerrainCorrector",
|
|
37
|
+
"TerrainCorrectionData",
|
|
38
|
+
]
|
gsolve/__main__.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# GSolve - gravity processing software.
|
|
2
|
+
# Copyright (c) 2026 Earth Sciences New Zealand.
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
# SPDX-License-Identifier: GPLv3
|
|
16
|
+
|
|
17
|
+
# Copyright (c) 2025 Earth Sciences New Zealand.
|
|
18
|
+
import argparse
|
|
19
|
+
|
|
20
|
+
from gsolve import GravitySurvey, LaCosteRombergDialConverter, ReferenceGravity
|
|
21
|
+
from gsolve.reports import GSolveReport
|
|
22
|
+
from gsolve.tide.earth_tide import LongmanTidalCorrection
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def parse_args(*args: str) -> argparse.Namespace:
|
|
26
|
+
__app_name__ = "gsolve-cli"
|
|
27
|
+
args_parser = argparse.ArgumentParser(
|
|
28
|
+
prog=__app_name__,
|
|
29
|
+
description=(
|
|
30
|
+
f"{__app_name__} - CLI utility to process relative gravimetric measurements"
|
|
31
|
+
),
|
|
32
|
+
epilog=None,
|
|
33
|
+
add_help=False,
|
|
34
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Input parameters
|
|
38
|
+
input = args_parser.add_argument_group("Input")
|
|
39
|
+
|
|
40
|
+
input.add_argument(
|
|
41
|
+
"-is",
|
|
42
|
+
"--input-survey",
|
|
43
|
+
action="store",
|
|
44
|
+
required=True,
|
|
45
|
+
metavar="file",
|
|
46
|
+
help=(
|
|
47
|
+
"[Required] Input survey .xlsx-file name with gravimeter readings "
|
|
48
|
+
"and site information."
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Optional parameters
|
|
53
|
+
input.add_argument(
|
|
54
|
+
"-ref",
|
|
55
|
+
"--reference",
|
|
56
|
+
action="store",
|
|
57
|
+
metavar="file",
|
|
58
|
+
default=None,
|
|
59
|
+
help="[Optional] Input file with reference gravity. Default: None",
|
|
60
|
+
)
|
|
61
|
+
input.add_argument(
|
|
62
|
+
"-ct",
|
|
63
|
+
"--conversion-table-file",
|
|
64
|
+
action="store",
|
|
65
|
+
metavar="file",
|
|
66
|
+
default=None,
|
|
67
|
+
help="[Optional] Input file with conversion table. Default: None",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Output parameter
|
|
71
|
+
output = args_parser.add_argument_group("Output")
|
|
72
|
+
|
|
73
|
+
output.add_argument(
|
|
74
|
+
"-or",
|
|
75
|
+
"--output-report",
|
|
76
|
+
action="store",
|
|
77
|
+
required=True,
|
|
78
|
+
metavar="file",
|
|
79
|
+
help=(
|
|
80
|
+
"[Required] Output report .xlsx-file name with adjusted gravity "
|
|
81
|
+
"and observations values."
|
|
82
|
+
),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Processing options
|
|
86
|
+
proc = args_parser.add_argument_group("Processing options")
|
|
87
|
+
|
|
88
|
+
proc.add_argument(
|
|
89
|
+
"-m",
|
|
90
|
+
"--method",
|
|
91
|
+
type=int,
|
|
92
|
+
action="store",
|
|
93
|
+
default=2,
|
|
94
|
+
choices=range(1, 4),
|
|
95
|
+
metavar="value",
|
|
96
|
+
help="[Optional] Absolute gravity constrain method: {1, 2, 3}. Default: 2",
|
|
97
|
+
)
|
|
98
|
+
proc.add_argument(
|
|
99
|
+
"-cf",
|
|
100
|
+
"--calibration-factor",
|
|
101
|
+
action="store",
|
|
102
|
+
metavar="value",
|
|
103
|
+
type=float,
|
|
104
|
+
default=1,
|
|
105
|
+
help="[Optional] Define calibration factor. Default: 1.0",
|
|
106
|
+
)
|
|
107
|
+
proc.add_argument(
|
|
108
|
+
"-pc",
|
|
109
|
+
"--percentile-clipping",
|
|
110
|
+
type=float,
|
|
111
|
+
default=100,
|
|
112
|
+
metavar="value",
|
|
113
|
+
help="[Optional] Clip data by percentile value. Default: 100",
|
|
114
|
+
)
|
|
115
|
+
proc.add_argument(
|
|
116
|
+
"--use-loops",
|
|
117
|
+
action="store_true",
|
|
118
|
+
default=False,
|
|
119
|
+
help="[Optional] Use individual loops in the adjustment process. Default: False",
|
|
120
|
+
)
|
|
121
|
+
proc.add_argument(
|
|
122
|
+
"--calculate-calibration-factor",
|
|
123
|
+
action="store_true",
|
|
124
|
+
default=False,
|
|
125
|
+
help="[Optional] Claculate calibration factor. Default: False",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Help function
|
|
129
|
+
args_parser.add_argument(
|
|
130
|
+
"-h", "--help", action="help", help="Show help message and exit"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if args:
|
|
134
|
+
return args_parser.parse_args(args=args)
|
|
135
|
+
return args_parser.parse_args()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def processing(args: argparse.Namespace) -> None:
|
|
139
|
+
# Read survey information
|
|
140
|
+
survey = GravitySurvey.from_excel(fname=args.input_survey)
|
|
141
|
+
|
|
142
|
+
# Read in list reference (i.e. absolute) stations
|
|
143
|
+
if args.reference is not None:
|
|
144
|
+
ref_sites = ReferenceGravity.from_csv(csv_file=args.reference)
|
|
145
|
+
# set stations with known reference gravity values
|
|
146
|
+
survey.set_reference_gravity(ref_grav=ref_sites)
|
|
147
|
+
|
|
148
|
+
# Convert gravimeter readings
|
|
149
|
+
if args.conversion_table_file is not None:
|
|
150
|
+
g106converter = LaCosteRombergDialConverter.from_csv(
|
|
151
|
+
fname=args.conversion_table_file
|
|
152
|
+
)
|
|
153
|
+
# apply dial conversion to convert values to mGal.
|
|
154
|
+
survey.apply_dial_to_mgal(converter=g106converter)
|
|
155
|
+
|
|
156
|
+
# Apply calibration factor
|
|
157
|
+
survey.set_calibration_factor(calibration_factor=args.calibration_factor)
|
|
158
|
+
|
|
159
|
+
# Calculate the earth tide correction
|
|
160
|
+
survey.apply_earth_tide_correction(tide_corrector=LongmanTidalCorrection())
|
|
161
|
+
|
|
162
|
+
# Calculate corrected gravity
|
|
163
|
+
survey.calculate_tide_corrected_gravity()
|
|
164
|
+
|
|
165
|
+
# Perform adjustment
|
|
166
|
+
results = survey.solve_lstsq(
|
|
167
|
+
method=args.method,
|
|
168
|
+
use_loops=args.use_loops,
|
|
169
|
+
calculate_calibration_factor=args.calculate_calibration_factor,
|
|
170
|
+
percentile_clipping=args.percentile_clipping,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Save output files
|
|
174
|
+
output_report = args.output_report
|
|
175
|
+
report = GSolveReport(
|
|
176
|
+
observations=survey.observations, sites=survey.sites, results=results
|
|
177
|
+
)
|
|
178
|
+
report.to_excel(filename=output_report)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def main() -> None:
|
|
182
|
+
try:
|
|
183
|
+
args = parse_args()
|
|
184
|
+
processing(args)
|
|
185
|
+
except Exception as e:
|
|
186
|
+
print(e)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
main()
|
gsolve/core/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# GSolve - gravity processing software.
|
|
2
|
+
# Copyright (c) 2026 Earth Sciences New Zealand.
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
# SPDX-License-Identifier: GPLv3
|
|
16
|
+
|
|
17
|
+
# Copyright (c) 2025 Earth Sciences New Zealand.
|
|
18
|
+
|
|
19
|
+
"""Funtions used in generating summary statistics for various GSolve classes."""
|
|
20
|
+
|
|
21
|
+
import pandas as _pd
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def stdev_ugal(x: _pd.Series) -> float:
|
|
25
|
+
return round(x.std() * 1000, 2)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def range_ugal(x: _pd.Series) -> float:
|
|
29
|
+
return round((x.max() - x.min()) * 1000, 2)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def n(x: _pd.Series) -> int:
|
|
33
|
+
return x.size
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def n_inactive(x: _pd.Series) -> int:
|
|
37
|
+
return x.eq(False).sum()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def n_sites(x: _pd.Series) -> int:
|
|
41
|
+
return x.nunique()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def starttime_utc(x: _pd.Series) -> _pd.Timestamp:
|
|
45
|
+
return x.min()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def endtime_utc(x: _pd.Series) -> _pd.Timestamp:
|
|
49
|
+
return x.max()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def duration_hr(x: _pd.Series) -> float:
|
|
53
|
+
return round((x.max() - x.min()).total_seconds() / 3600, 2)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def in_loops(x: _pd.Series) -> str:
|
|
57
|
+
return ",".join(sorted(x.unique()))
|
gsolve/core/_typing.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# GSolve - gravity processing software.
|
|
2
|
+
# Copyright (c) 2026 Earth Sciences New Zealand.
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
# SPDX-License-Identifier: GPLv3
|
|
16
|
+
|
|
17
|
+
# Copyright (c) 2025 Earth Sciences New Zealand.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import datetime
|
|
23
|
+
from collections.abc import Callable, Hashable, Mapping, Sequence
|
|
24
|
+
from os import PathLike
|
|
25
|
+
from typing import Any, Literal, Protocol, TypeAlias, Union, runtime_checkable
|
|
26
|
+
|
|
27
|
+
import numpy as np
|
|
28
|
+
import pandas as pd
|
|
29
|
+
import xarray as xr
|
|
30
|
+
from numpy.typing import ArrayLike, NDArray
|
|
31
|
+
from pandas import DataFrame, DatetimeIndex, Index, Series, Timestamp
|
|
32
|
+
from pandas.api.typing import NaTType
|
|
33
|
+
from pylab import ndarray
|
|
34
|
+
|
|
35
|
+
# from pandas.api.typing.aliases import TimedeltaConvertibleTypes
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"AllowedTimestampResolution",
|
|
39
|
+
"AllowedTimestampRoundingMethods",
|
|
40
|
+
"IfWorkbookExists",
|
|
41
|
+
"IfSheetExists",
|
|
42
|
+
"GSolveSolverMethod",
|
|
43
|
+
"GSolveSolverReturn",
|
|
44
|
+
"Renamer",
|
|
45
|
+
"DatetimeScalar",
|
|
46
|
+
"DatetimeArray",
|
|
47
|
+
"DatetimeScalarOrArray",
|
|
48
|
+
"FilePath",
|
|
49
|
+
"DatasetOrArray",
|
|
50
|
+
"ArrayOrCoords",
|
|
51
|
+
"Points2D",
|
|
52
|
+
"Points3D",
|
|
53
|
+
"TCorrDistanceMaskType",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
# Aliases by gsolve for various functions arguments
|
|
57
|
+
AllowedTimestampResolution: TypeAlias = Literal[
|
|
58
|
+
"year", "month", "day", "hour", "minute", "second", "microsecond", "nanosecond"
|
|
59
|
+
]
|
|
60
|
+
AllowedTimestampRoundingMethods: TypeAlias = Literal["round", "floor", "ceil"]
|
|
61
|
+
|
|
62
|
+
IfWorkbookExists: TypeAlias = Literal["error", "replace", "append"]
|
|
63
|
+
IfSheetExists: TypeAlias = Literal["error", "replace", "new"]
|
|
64
|
+
|
|
65
|
+
GSolveSolverMethod: TypeAlias = Literal[1, 2, 3]
|
|
66
|
+
|
|
67
|
+
GSolveSolverReturn: TypeAlias = tuple[
|
|
68
|
+
NDArray, NDArray, NDArray, NDArray, NDArray, float | np.float64 | None, NDArray
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
FilePath: TypeAlias = str | PathLike
|
|
72
|
+
|
|
73
|
+
# The following type aliases are copied/adapted from pandas to ensure
|
|
74
|
+
# function parameters are compatible with pandas methods they are passed to
|
|
75
|
+
|
|
76
|
+
Renamer: TypeAlias = Union[Mapping[Any, Hashable], Callable[[Any], Hashable]]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
DateTimeConvertibleTypes: TypeAlias = Union[
|
|
80
|
+
str,
|
|
81
|
+
int,
|
|
82
|
+
float,
|
|
83
|
+
datetime.timedelta,
|
|
84
|
+
list,
|
|
85
|
+
tuple,
|
|
86
|
+
range,
|
|
87
|
+
ArrayLike,
|
|
88
|
+
Index,
|
|
89
|
+
Series,
|
|
90
|
+
]
|
|
91
|
+
DatetimeScalar: TypeAlias = (
|
|
92
|
+
int | float | str | datetime.date | np.datetime64 | pd.Timestamp
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
DatetimeArray: TypeAlias = list | tuple | ndarray | Series | Index | DatetimeIndex
|
|
96
|
+
DatetimeScalarOrArray: TypeAlias = DatetimeScalar | DatetimeArray
|
|
97
|
+
|
|
98
|
+
TimedeltaScalar: TypeAlias = str | int | float | pd.Timedelta | datetime.timedelta
|
|
99
|
+
|
|
100
|
+
SiteIDArray: TypeAlias = Sequence[str] | Series | Index | NDArray[np.str_]
|
|
101
|
+
FloatArray: TypeAlias = Sequence[float] | Series | Index | NDArray[np.floating]
|
|
102
|
+
StringArray: TypeAlias = Sequence[str] | Series | Index | NDArray[np.str_]
|
|
103
|
+
BoolArray: TypeAlias = Sequence[bool] | Series | Index | NDArray[np.bool_]
|
|
104
|
+
|
|
105
|
+
# aliases used in terrain correction
|
|
106
|
+
DatasetOrArray: TypeAlias = xr.DataArray | xr.Dataset
|
|
107
|
+
ArrayOrCoords: TypeAlias = DatasetOrArray | Sequence[ArrayLike]
|
|
108
|
+
Points2D: TypeAlias = tuple[FloatArray, FloatArray]
|
|
109
|
+
Points3D: TypeAlias = tuple[FloatArray, FloatArray, FloatArray]
|
|
110
|
+
TCorrDistanceMaskType: TypeAlias = Literal["radial", "rectangular"]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# protocols for select Gsolve classes
|
|
114
|
+
@runtime_checkable
|
|
115
|
+
class SitesLike(Protocol):
|
|
116
|
+
data: pd.DataFrame
|
|
117
|
+
|
|
118
|
+
def get_points(
|
|
119
|
+
self, xcol: str, ycol: str, zcol: str
|
|
120
|
+
) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]: ...
|