pingmapper 5.4.1__tar.gz → 5.4.2__tar.gz
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.
- {pingmapper-5.4.1 → pingmapper-5.4.2}/PKG-INFO +3 -2
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/class_portstarObj.py +164 -28
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/class_rectObj.py +55 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/class_sonObj.py +68 -1
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/class_sonObj_nadirgaptest.py +10 -1
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/main_readFiles.py +7 -3
- pingmapper-5.4.2/pingmapper/version.py +1 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper.egg-info/PKG-INFO +3 -2
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper.egg-info/SOURCES.txt +1 -0
- pingmapper-5.4.2/setup.py +50 -0
- pingmapper-5.4.1/pingmapper/version.py +0 -1
- {pingmapper-5.4.1 → pingmapper-5.4.2}/LICENSE +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/README.md +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/__init__.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/__main__.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/class_mapSubstrateObj.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/default_params.json +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/doWork.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/funcs_common.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/funcs_model.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/funcs_rectify.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/gui_main.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/main_mapSubstrate.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/main_rectify.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/nonGUI_batch_main.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/nonGui_main.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0926.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/processing_scripts/main_batchDirectory_2024-01-18_0929.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/scratch/funcs_pyhum_correct.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/scratch/main.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/scratch/main_batchDirectory.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/test_PINGMapper.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/test_dq_filter.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/test_time.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline_from_bankline.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/gen_centerline_trkpnts_fitspline_DRAFT.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/RawEGN_avg_predictions.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/00_substrate_logits_mosaic_transects.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/00_substrate_shps_mosaic_transects.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/01_gen_centerline_from_coverage.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/02_gen_summary_stamp_shps.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/04_combine_summary_shp_csv.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/05_gen_summary_shp_plots.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/06_compare_raw-egn_volume.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/08_raw-egn_hardReacheFreq_hist.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/09_raw-egn_PatchSize_density.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/summarize_project_substrate.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/export_coverage.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/main_mosaic_transects.py +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper.egg-info/dependency_links.txt +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper.egg-info/requires.txt +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper.egg-info/top_level.txt +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/pyproject.toml +0 -0
- {pingmapper-5.4.1 → pingmapper-5.4.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.4.
|
|
3
|
+
Version: 5.4.2
|
|
4
4
|
Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
|
|
5
5
|
Author: Daniel Buscombe
|
|
6
6
|
Author-email: Cameron Bodine <bodine.cs@gmail.email>
|
|
@@ -17,7 +17,7 @@ Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
|
17
17
|
Classifier: Topic :: Scientific/Engineering :: Oceanography
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Hydrology
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.6
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
23
|
Requires-Dist: pinginstaller<3,>=2
|
|
@@ -33,6 +33,7 @@ Requires-Dist: tensorflow<3,>=2.20; extra == "ml"
|
|
|
33
33
|
Requires-Dist: tf-keras<3,>=2.20; extra == "ml"
|
|
34
34
|
Requires-Dist: transformers<5,>=4.57; extra == "ml"
|
|
35
35
|
Dynamic: license-file
|
|
36
|
+
Dynamic: requires-python
|
|
36
37
|
|
|
37
38
|
# PING-Mapper
|
|
38
39
|
[)](https://pypi.org/project/pingmapper/)
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
import os, sys
|
|
34
|
+
import time
|
|
34
35
|
|
|
35
36
|
# Add 'pingmapper' to the path, may not need after pypi package...
|
|
36
37
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -1650,8 +1651,9 @@ class portstarObj(object):
|
|
|
1650
1651
|
return pd.Series(vals).rolling(window=window, center=True, min_periods=1).median().to_numpy()
|
|
1651
1652
|
|
|
1652
1653
|
def _flag_depth_outliers(depth, inst_depth=None, inst_depth_mult=None,
|
|
1653
|
-
|
|
1654
|
-
|
|
1654
|
+
resid_floor_m=0.5, jump_floor_m=0.5,
|
|
1655
|
+
iterative_jump=False, iterative_max_iter=64,
|
|
1656
|
+
iterative_jump_floor_m=None):
|
|
1655
1657
|
depth = np.asarray(depth, dtype=float)
|
|
1656
1658
|
flags = np.zeros(depth.shape, dtype=bool)
|
|
1657
1659
|
|
|
@@ -1690,7 +1692,11 @@ class portstarObj(object):
|
|
|
1690
1692
|
# back those runs until continuity is restored.
|
|
1691
1693
|
if iterative_jump:
|
|
1692
1694
|
work = depth.copy()
|
|
1693
|
-
|
|
1695
|
+
if iterative_jump_floor_m is None:
|
|
1696
|
+
iterative_jump_floor_m = jump_floor_m
|
|
1697
|
+
# Cap iterations so very large tracks do not degrade to near O(n^2)
|
|
1698
|
+
# behavior when many jump-like artifacts are present.
|
|
1699
|
+
max_iter = max(1, int(iterative_max_iter))
|
|
1694
1700
|
for _ in range(max_iter):
|
|
1695
1701
|
valid_work = np.isfinite(work) & (work > 0)
|
|
1696
1702
|
valid_idx = np.flatnonzero(valid_work)
|
|
@@ -1704,7 +1710,7 @@ class portstarObj(object):
|
|
|
1704
1710
|
|
|
1705
1711
|
step_center = np.nanmedian(step_vals)
|
|
1706
1712
|
step_mad = np.nanmedian(np.abs(step_vals - step_center))
|
|
1707
|
-
jump_thr = max(
|
|
1713
|
+
jump_thr = max(iterative_jump_floor_m, 6.0 * step_mad if np.isfinite(step_mad) else iterative_jump_floor_m)
|
|
1708
1714
|
|
|
1709
1715
|
diffs = np.abs(np.diff(work[valid_idx]))
|
|
1710
1716
|
bad_step_pos = np.flatnonzero(np.isfinite(diffs) & (diffs > jump_thr))
|
|
@@ -1756,15 +1762,31 @@ class portstarObj(object):
|
|
|
1756
1762
|
|
|
1757
1763
|
trk_df.reset_index().to_csv(trk_file, index=False, float_format='%.14f')
|
|
1758
1764
|
|
|
1765
|
+
depth_timer_start = time.perf_counter()
|
|
1766
|
+
depth_timer_last = depth_timer_start
|
|
1767
|
+
beam_pair = '{} / {}'.format(self.port.beamName, self.star.beamName)
|
|
1768
|
+
|
|
1769
|
+
def _depth_timing(label):
|
|
1770
|
+
nonlocal depth_timer_last
|
|
1771
|
+
now = time.perf_counter()
|
|
1772
|
+
print('\tDepth timing [{}] {}: {:.2f}s'.format(beam_pair, label, now - depth_timer_last))
|
|
1773
|
+
depth_timer_last = now
|
|
1774
|
+
|
|
1759
1775
|
# Load sonar metadata file
|
|
1760
1776
|
self.port._loadSonMeta()
|
|
1761
1777
|
portDF = self.port.sonMetaDF
|
|
1762
1778
|
self.star._loadSonMeta()
|
|
1763
1779
|
starDF = self.star.sonMetaDF
|
|
1780
|
+
_depth_timing('load metadata')
|
|
1764
1781
|
|
|
1765
1782
|
# Get all chunks
|
|
1766
1783
|
chunks = pd.unique(portDF['chunk_id'])
|
|
1767
1784
|
|
|
1785
|
+
# Track points invalidated during pre-smoothing QC so output metadata
|
|
1786
|
+
# reflects all flagged depth values, not only post-smoothing flags.
|
|
1787
|
+
portPreFlags = np.zeros(len(portDF), dtype=bool)
|
|
1788
|
+
starPreFlags = np.zeros(len(starDF), dtype=bool)
|
|
1789
|
+
|
|
1768
1790
|
if detectDep == 0:
|
|
1769
1791
|
def _depth_series(df):
|
|
1770
1792
|
# Some formats (e.g., Garmin RSD) may not include dep_m in metadata.
|
|
@@ -1786,6 +1808,36 @@ class portstarObj(object):
|
|
|
1786
1808
|
portInstDepth = np.where(portValid, portInstDepth, portMetaDepth)
|
|
1787
1809
|
starInstDepth = np.where(starValid, starInstDepth, starMetaDepth)
|
|
1788
1810
|
|
|
1811
|
+
# Flag outliers on raw instrument depth BEFORE smoothing so sharp
|
|
1812
|
+
# jumps (e.g. sonar lock-on to a false deep target) are caught on
|
|
1813
|
+
# the un-blurred signal rather than on the smoothed ramp they become
|
|
1814
|
+
# after savgol. NaNs are linearly filled so savgol has no gaps.
|
|
1815
|
+
def _fill_nans_linear(arr):
|
|
1816
|
+
nans = np.isnan(arr) | (arr <= 0)
|
|
1817
|
+
x = np.arange(len(arr))
|
|
1818
|
+
if nans.any() and (~nans).any():
|
|
1819
|
+
arr[nans] = np.interp(x[nans], x[~nans], arr[~nans])
|
|
1820
|
+
return arr
|
|
1821
|
+
|
|
1822
|
+
# Keep one-ping spike sensitivity, but require a much larger jump for
|
|
1823
|
+
# iterative run peeling so true depth regime changes are not over-flagged.
|
|
1824
|
+
portPreFlags = _flag_depth_outliers(
|
|
1825
|
+
portInstDepth,
|
|
1826
|
+
iterative_jump=True,
|
|
1827
|
+
iterative_max_iter=512,
|
|
1828
|
+
iterative_jump_floor_m=4.0,
|
|
1829
|
+
)
|
|
1830
|
+
starPreFlags = _flag_depth_outliers(
|
|
1831
|
+
starInstDepth,
|
|
1832
|
+
iterative_jump=True,
|
|
1833
|
+
iterative_max_iter=512,
|
|
1834
|
+
iterative_jump_floor_m=4.0,
|
|
1835
|
+
)
|
|
1836
|
+
portInstDepth[portPreFlags] = np.nan
|
|
1837
|
+
starInstDepth[starPreFlags] = np.nan
|
|
1838
|
+
portInstDepth = _fill_nans_linear(portInstDepth)
|
|
1839
|
+
starInstDepth = _fill_nans_linear(starInstDepth)
|
|
1840
|
+
|
|
1789
1841
|
if smthDep:
|
|
1790
1842
|
# print("\nSmoothing depth values...")
|
|
1791
1843
|
portInstDepth = savgol_filter(portInstDepth, 51, 3)
|
|
@@ -1818,6 +1870,7 @@ class portstarObj(object):
|
|
|
1818
1870
|
|
|
1819
1871
|
portDF['dep_m_adjBy'] = _format_depth_adjustment(portDF['pixM'])
|
|
1820
1872
|
starDF['dep_m_adjBy'] = _format_depth_adjustment(starDF['pixM'])
|
|
1873
|
+
_depth_timing('prepare instrument depth')
|
|
1821
1874
|
|
|
1822
1875
|
elif detectDep > 0:
|
|
1823
1876
|
# Prepare depth detection dictionaries
|
|
@@ -1904,12 +1957,15 @@ class portstarObj(object):
|
|
|
1904
1957
|
|
|
1905
1958
|
portDF['dep_m_adjBy'] = _format_depth_adjustment(portDF['pixM'])
|
|
1906
1959
|
starDF['dep_m_adjBy'] = _format_depth_adjustment(starDF['pixM'])
|
|
1960
|
+
_depth_timing('prepare detected depth')
|
|
1907
1961
|
|
|
1908
1962
|
# Outlier and jump filtering before interpolation.
|
|
1909
1963
|
# detectDep=0: continuity-only acoustic QC.
|
|
1910
1964
|
# detectDep=1/2: continuity QC plus instrument-depth proportional cap.
|
|
1911
1965
|
portArr = pd.to_numeric(portDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1912
1966
|
starArr = pd.to_numeric(starDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1967
|
+
portRawArr = portArr.copy()
|
|
1968
|
+
starRawArr = starArr.copy()
|
|
1913
1969
|
portInst = pd.to_numeric(portDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1914
1970
|
starInst = pd.to_numeric(starDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
1915
1971
|
|
|
@@ -1917,8 +1973,8 @@ class portstarObj(object):
|
|
|
1917
1973
|
starFlags = np.zeros(starArr.shape, dtype=bool)
|
|
1918
1974
|
|
|
1919
1975
|
if detectDep == 0:
|
|
1920
|
-
portFlags |= _flag_depth_outliers(portArr, iterative_jump=True)
|
|
1921
|
-
starFlags |= _flag_depth_outliers(starArr, iterative_jump=True)
|
|
1976
|
+
portFlags |= _flag_depth_outliers(portArr, iterative_jump=True, iterative_jump_floor_m=4.0)
|
|
1977
|
+
starFlags |= _flag_depth_outliers(starArr, iterative_jump=True, iterative_jump_floor_m=4.0)
|
|
1922
1978
|
elif detectDep in (1, 2):
|
|
1923
1979
|
portFlags |= _flag_depth_outliers(portArr, portInst, inst_depth_mult=3.0)
|
|
1924
1980
|
starFlags |= _flag_depth_outliers(starArr, starInst, inst_depth_mult=3.0)
|
|
@@ -1949,14 +2005,17 @@ class portstarObj(object):
|
|
|
1949
2005
|
portArr[portFlags] = np.nan
|
|
1950
2006
|
starArr[starFlags] = np.nan
|
|
1951
2007
|
portDF['dep_m'] = portArr
|
|
2008
|
+
portDF['dep_m_raw'] = portRawArr
|
|
1952
2009
|
starDF['dep_m'] = starArr
|
|
2010
|
+
starDF['dep_m_raw'] = starRawArr
|
|
2011
|
+
_depth_timing('outlier and jump filtering')
|
|
1953
2012
|
|
|
1954
2013
|
# Interpolate over nan's (and set zeros to nan)
|
|
1955
2014
|
portDep = portDF['dep_m'].to_numpy(copy=True)
|
|
1956
2015
|
starDep = starDF['dep_m'].to_numpy(copy=True)
|
|
1957
2016
|
|
|
1958
|
-
portInterp = np.isnan(portDep) | (portDep == 0)
|
|
1959
|
-
starInterp = np.isnan(starDep) | (starDep == 0)
|
|
2017
|
+
portInterp = np.isnan(portDep) | (portDep == 0) | portPreFlags
|
|
2018
|
+
starInterp = np.isnan(starDep) | (starDep == 0) | starPreFlags
|
|
1960
2019
|
|
|
1961
2020
|
portDep[portDep == 0] = np.nan
|
|
1962
2021
|
starDep[starDep == 0] = np.nan
|
|
@@ -1976,12 +2035,14 @@ class portstarObj(object):
|
|
|
1976
2035
|
starDep[nans] = 0
|
|
1977
2036
|
starDF['dep_m'] = starDep
|
|
1978
2037
|
starDF['dep_m_interp'] = starInterp.astype(np.uint8)
|
|
2038
|
+
_depth_timing('interpolate depth')
|
|
1979
2039
|
|
|
1980
2040
|
# Export to csv
|
|
1981
2041
|
portDF.to_csv(self.port.sonMetaFile, index=False, float_format='%.14f')
|
|
1982
2042
|
starDF.to_csv(self.star.sonMetaFile, index=False, float_format='%.14f')
|
|
1983
2043
|
_sync_trackline_depth(self.port, portDF)
|
|
1984
2044
|
_sync_trackline_depth(self.star, starDF)
|
|
2045
|
+
_depth_timing('write metadata and trackline')
|
|
1985
2046
|
|
|
1986
2047
|
try:
|
|
1987
2048
|
# Take average of both estimates to store with downlooking sonar csv
|
|
@@ -2003,6 +2064,9 @@ class portstarObj(object):
|
|
|
2003
2064
|
depDF['dep_m_adjBy'] = portDF['dep_m_adjBy']
|
|
2004
2065
|
depDF['dep_m_interp'] = portDF['dep_m_interp']
|
|
2005
2066
|
|
|
2067
|
+
_depth_timing('build return depth dataframe')
|
|
2068
|
+
print('\tDepth timing [{}] total: {:.2f}s'.format(beam_pair, time.perf_counter() - depth_timer_start))
|
|
2069
|
+
|
|
2006
2070
|
del portDF, starDF
|
|
2007
2071
|
gc.collect()
|
|
2008
2072
|
return depDF
|
|
@@ -2059,20 +2123,65 @@ class portstarObj(object):
|
|
|
2059
2123
|
self.star._loadSonMeta()
|
|
2060
2124
|
starDF = self.star.sonMetaDF
|
|
2061
2125
|
|
|
2062
|
-
|
|
2063
|
-
|
|
2126
|
+
def _depth_to_pixels(df, depth_col):
|
|
2127
|
+
depth = pd.to_numeric(df[depth_col], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2128
|
+
pix = pd.to_numeric(df['pixM'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2129
|
+
return np.divide(
|
|
2130
|
+
depth,
|
|
2131
|
+
pix,
|
|
2132
|
+
out=np.full(depth.shape, np.nan, dtype=float),
|
|
2133
|
+
where=np.isfinite(pix) & (pix != 0)
|
|
2134
|
+
)
|
|
2135
|
+
|
|
2136
|
+
def _pad_to_match(values, reference):
|
|
2137
|
+
diff = reference.shape[0] - values.shape[0]
|
|
2138
|
+
if diff > 0:
|
|
2139
|
+
values = np.append(values, reference[-diff:])
|
|
2140
|
+
return values
|
|
2141
|
+
|
|
2142
|
+
portCols = ['inst_dep_m', 'dep_m', 'pixM']
|
|
2143
|
+
starCols = ['inst_dep_m', 'dep_m', 'pixM']
|
|
2144
|
+
if 'dep_m_interp' in portDF.columns:
|
|
2145
|
+
portCols.append('dep_m_interp')
|
|
2146
|
+
if 'dep_m_raw' in portDF.columns:
|
|
2147
|
+
portCols.append('dep_m_raw')
|
|
2148
|
+
if 'dep_m_interp' in starDF.columns:
|
|
2149
|
+
starCols.append('dep_m_interp')
|
|
2150
|
+
if 'dep_m_raw' in starDF.columns:
|
|
2151
|
+
starCols.append('dep_m_raw')
|
|
2152
|
+
|
|
2153
|
+
portDF = portDF.loc[portDF['chunk_id'] == i, portCols]
|
|
2154
|
+
starDF = starDF.loc[starDF['chunk_id'] == i, starCols]
|
|
2155
|
+
|
|
2156
|
+
detectDepMode = int(getattr(self.port, 'detectDep', getattr(self.star, 'detectDep', -1)))
|
|
2064
2157
|
|
|
2065
2158
|
portInstDepth = pd.to_numeric(portDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2066
2159
|
portMetaDepth = pd.to_numeric(portDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2160
|
+
if not np.isfinite(portInstDepth).any():
|
|
2161
|
+
portInstDepth = portMetaDepth.copy()
|
|
2162
|
+
portDF = portDF.copy()
|
|
2163
|
+
portDF['inst_depth_plot'] = portInstDepth
|
|
2164
|
+
portInst = np.nan_to_num(_depth_to_pixels(portDF, 'inst_depth_plot'), nan=0.0)
|
|
2165
|
+
portAuto = _depth_to_pixels(portDF, 'dep_m')
|
|
2166
|
+
portRaw = _depth_to_pixels(portDF, 'dep_m_raw') if 'dep_m_raw' in portDF.columns else portAuto.copy()
|
|
2167
|
+
if 'dep_m_interp' in portDF.columns:
|
|
2168
|
+
portInterp = pd.to_numeric(portDF['dep_m_interp'], errors='coerce').fillna(0).to_numpy(dtype=np.uint8, copy=True).astype(bool)
|
|
2169
|
+
else:
|
|
2170
|
+
portInterp = np.zeros(portAuto.shape, dtype=bool)
|
|
2070
2171
|
|
|
2071
2172
|
starInstDepth = pd.to_numeric(starDF['inst_dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2072
2173
|
starMetaDepth = pd.to_numeric(starDF['dep_m'], errors='coerce').to_numpy(dtype=float, copy=True)
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2174
|
+
if not np.isfinite(starInstDepth).any():
|
|
2175
|
+
starInstDepth = starMetaDepth.copy()
|
|
2176
|
+
starDF = starDF.copy()
|
|
2177
|
+
starDF['inst_depth_plot'] = starInstDepth
|
|
2178
|
+
starInst = np.nan_to_num(_depth_to_pixels(starDF, 'inst_depth_plot'), nan=0.0)
|
|
2179
|
+
starAuto = _depth_to_pixels(starDF, 'dep_m')
|
|
2180
|
+
starRaw = _depth_to_pixels(starDF, 'dep_m_raw') if 'dep_m_raw' in starDF.columns else starAuto.copy()
|
|
2181
|
+
if 'dep_m_interp' in starDF.columns:
|
|
2182
|
+
starInterp = pd.to_numeric(starDF['dep_m_interp'], errors='coerce').fillna(0).to_numpy(dtype=np.uint8, copy=True).astype(bool)
|
|
2183
|
+
else:
|
|
2184
|
+
starInterp = np.zeros(starAuto.shape, dtype=bool)
|
|
2076
2185
|
|
|
2077
2186
|
# Ensure port/star same length
|
|
2078
2187
|
if (portAuto.shape[0] != starAuto.shape[0]):
|
|
@@ -2080,27 +2189,37 @@ class portstarObj(object):
|
|
|
2080
2189
|
sL = starAuto.shape[0]
|
|
2081
2190
|
# Add rows to shortest array from longest array
|
|
2082
2191
|
if (pL > sL):
|
|
2083
|
-
starAuto =
|
|
2084
|
-
starInst =
|
|
2192
|
+
starAuto = _pad_to_match(starAuto, portAuto)
|
|
2193
|
+
starInst = _pad_to_match(starInst, portInst)
|
|
2194
|
+
starRaw = _pad_to_match(starRaw, portRaw)
|
|
2195
|
+
starInterp = _pad_to_match(starInterp, portInterp)
|
|
2085
2196
|
else:
|
|
2086
|
-
portAuto =
|
|
2087
|
-
portInst =
|
|
2197
|
+
portAuto = _pad_to_match(portAuto, starAuto)
|
|
2198
|
+
portInst = _pad_to_match(portInst, starInst)
|
|
2199
|
+
portRaw = _pad_to_match(portRaw, starRaw)
|
|
2200
|
+
portInterp = _pad_to_match(portInterp, starInterp)
|
|
2088
2201
|
|
|
2089
2202
|
# Relocate depths relative to horizontal center of image
|
|
2090
2203
|
c = int(mergeSon.shape[1]/2)
|
|
2091
2204
|
|
|
2092
2205
|
portInst = c - portInst
|
|
2093
2206
|
portAuto = c - portAuto
|
|
2207
|
+
portRaw = c - portRaw
|
|
2094
2208
|
|
|
2095
2209
|
starInst = c + starInst
|
|
2096
2210
|
starAuto = c + starAuto
|
|
2211
|
+
starRaw = c + starRaw
|
|
2097
2212
|
|
|
2098
2213
|
# maybe flip???
|
|
2099
2214
|
portInst = np.flip(portInst)
|
|
2100
2215
|
portAuto = np.flip(portAuto)
|
|
2216
|
+
portRaw = np.flip(portRaw)
|
|
2217
|
+
portInterp = np.flip(portInterp)
|
|
2101
2218
|
|
|
2102
2219
|
starInst = np.flip(starInst)
|
|
2103
2220
|
starAuto = np.flip(starAuto)
|
|
2221
|
+
starRaw = np.flip(starRaw)
|
|
2222
|
+
starInterp = np.flip(starInterp)
|
|
2104
2223
|
|
|
2105
2224
|
#############
|
|
2106
2225
|
# Export Plot
|
|
@@ -2127,14 +2246,31 @@ class portstarObj(object):
|
|
|
2127
2246
|
outFile = os.path.join(outDir, projName+'_Bedpick_'+addZero+str(i)+tileFile)
|
|
2128
2247
|
|
|
2129
2248
|
plt.imshow(mergeSon, cmap='gray')
|
|
2130
|
-
if
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2249
|
+
if detectDepMode == 0:
|
|
2250
|
+
if acousticBed:
|
|
2251
|
+
portInstGood = np.where(~portInterp, portInst, np.nan)
|
|
2252
|
+
starInstGood = np.where(~starInterp, starInst, np.nan)
|
|
2253
|
+
portInstBad = np.where(portInterp, portInst, np.nan)
|
|
2254
|
+
starInstBad = np.where(starInterp, starInst, np.nan)
|
|
2255
|
+
portInterpDepth = np.where(portInterp, portAuto, np.nan)
|
|
2256
|
+
starInterpDepth = np.where(starInterp, starAuto, np.nan)
|
|
2257
|
+
|
|
2258
|
+
plt.plot(portInstGood, y, '-.', color='lime', lw=1, label='Instrument Depth (Good)')
|
|
2259
|
+
plt.plot(starInstGood, y, '-.', color='lime', lw=1)
|
|
2260
|
+
plt.plot(portInstBad, y, '-.', color='red', lw=1, label='Instrument Depth (Flagged)')
|
|
2261
|
+
plt.plot(starInstBad, y, '-.', color='red', lw=1)
|
|
2262
|
+
plt.plot(portInterpDepth, y, '-.', color='yellow', lw=1, label='Interpolated Depth')
|
|
2263
|
+
plt.plot(starInterpDepth, y, '-.', color='yellow', lw=1)
|
|
2264
|
+
del portInstGood, starInstGood, portInstBad, starInstBad, portInterpDepth, starInterpDepth
|
|
2265
|
+
else:
|
|
2266
|
+
if acousticBed:
|
|
2267
|
+
plt.plot(portInst, y, 'r-.', lw=1, label='Instrument Depth')
|
|
2268
|
+
plt.plot(starInst, y, 'r-.', lw=1)
|
|
2269
|
+
if autoBed:
|
|
2270
|
+
plt.plot(portAuto, y, 'b-.', lw=1, label='Auto Depth')
|
|
2271
|
+
plt.plot(starAuto, y, 'b-.', lw=1)
|
|
2272
|
+
|
|
2273
|
+
del portInst, starInst, portAuto, starAuto, portRaw, starRaw, portInterp, starInterp
|
|
2138
2274
|
|
|
2139
2275
|
plt.legend(loc = 'lower right', prop={'size':4}) # create the plot legend
|
|
2140
2276
|
plt.savefig(outFile, dpi=300, bbox_inches='tight')
|
|
@@ -2151,6 +2151,7 @@ class rectObj(sonObj):
|
|
|
2151
2151
|
|
|
2152
2152
|
# Open smoothed trackline/range extent file
|
|
2153
2153
|
trkMeta = pd.read_csv(trkMetaFile)
|
|
2154
|
+
trkMeta = self._sanitizeProjectedTrackMeta(trkMeta, wgs=wgs)
|
|
2154
2155
|
|
|
2155
2156
|
# Create geodataframe
|
|
2156
2157
|
gdf = gpd.GeoDataFrame(
|
|
@@ -2165,6 +2166,59 @@ class rectObj(sonObj):
|
|
|
2165
2166
|
del trkMetaFile
|
|
2166
2167
|
|
|
2167
2168
|
return
|
|
2169
|
+
|
|
2170
|
+
#===========================================================================
|
|
2171
|
+
def _sanitizeProjectedTrackMeta(self, trkMeta, wgs=False):
|
|
2172
|
+
|
|
2173
|
+
if wgs:
|
|
2174
|
+
return trkMeta
|
|
2175
|
+
|
|
2176
|
+
trkMeta = trkMeta.copy()
|
|
2177
|
+
|
|
2178
|
+
def _reproject_from_lonlat(df, lon_col, lat_col, x_col, y_col):
|
|
2179
|
+
if lon_col not in df.columns or lat_col not in df.columns:
|
|
2180
|
+
return df
|
|
2181
|
+
|
|
2182
|
+
lon = pd.to_numeric(df[lon_col], errors='coerce')
|
|
2183
|
+
lat = pd.to_numeric(df[lat_col], errors='coerce')
|
|
2184
|
+
valid_lonlat = lon.notna() & lat.notna()
|
|
2185
|
+
if not valid_lonlat.any():
|
|
2186
|
+
return df
|
|
2187
|
+
|
|
2188
|
+
need_xy = pd.Series(False, index=df.index)
|
|
2189
|
+
if x_col not in df.columns or y_col not in df.columns:
|
|
2190
|
+
need_xy[:] = True
|
|
2191
|
+
else:
|
|
2192
|
+
x = pd.to_numeric(df[x_col], errors='coerce')
|
|
2193
|
+
y = pd.to_numeric(df[y_col], errors='coerce')
|
|
2194
|
+
|
|
2195
|
+
# EPSG:326xx eastings should be positive and reasonably bounded.
|
|
2196
|
+
# Rebuild projected XY when stored values are missing or obviously invalid.
|
|
2197
|
+
need_xy = (
|
|
2198
|
+
x.isna() |
|
|
2199
|
+
y.isna() |
|
|
2200
|
+
(x <= 0) |
|
|
2201
|
+
(x > 1000000) |
|
|
2202
|
+
(y <= 0)
|
|
2203
|
+
) & valid_lonlat
|
|
2204
|
+
|
|
2205
|
+
if not need_xy.any():
|
|
2206
|
+
return df
|
|
2207
|
+
|
|
2208
|
+
geo = gpd.GeoDataFrame(
|
|
2209
|
+
df.loc[need_xy, [lon_col, lat_col]].copy(),
|
|
2210
|
+
geometry=gpd.points_from_xy(lon[need_xy], lat[need_xy]),
|
|
2211
|
+
crs='EPSG:4326',
|
|
2212
|
+
).to_crs(self.humDat['epsg'])
|
|
2213
|
+
|
|
2214
|
+
df.loc[need_xy, x_col] = geo.geometry.x.to_numpy()
|
|
2215
|
+
df.loc[need_xy, y_col] = geo.geometry.y.to_numpy()
|
|
2216
|
+
return df
|
|
2217
|
+
|
|
2218
|
+
trkMeta = _reproject_from_lonlat(trkMeta, 'trk_lons', 'trk_lats', 'trk_utm_es', 'trk_utm_ns')
|
|
2219
|
+
trkMeta = _reproject_from_lonlat(trkMeta, 'range_lons', 'range_lats', 'range_es', 'range_ns')
|
|
2220
|
+
|
|
2221
|
+
return trkMeta
|
|
2168
2222
|
|
|
2169
2223
|
#===========================================================================
|
|
2170
2224
|
def _exportCovShp(self,
|
|
@@ -2212,6 +2266,7 @@ class rectObj(sonObj):
|
|
|
2212
2266
|
# dfs = [df1, df2]
|
|
2213
2267
|
|
|
2214
2268
|
df1 = pd.read_csv(self.smthTrkFile)
|
|
2269
|
+
df1 = self._sanitizeProjectedTrackMeta(df1, wgs=wgs)
|
|
2215
2270
|
dfs = [df1]
|
|
2216
2271
|
|
|
2217
2272
|
filt = 0
|
|
@@ -260,6 +260,8 @@ class sonObj(object):
|
|
|
260
260
|
dq_src_utc_offset=0.0,
|
|
261
261
|
dq_target_utc_offset=0.0,
|
|
262
262
|
dq_time_offset=0.0,
|
|
263
|
+
filter_coord_outliers=True,
|
|
264
|
+
coord_iqr_scale=3.0,
|
|
263
265
|
):
|
|
264
266
|
'''
|
|
265
267
|
'''
|
|
@@ -271,6 +273,11 @@ class sonObj(object):
|
|
|
271
273
|
# print('len', len(sonDF))
|
|
272
274
|
# print(sonDF)
|
|
273
275
|
|
|
276
|
+
##############################
|
|
277
|
+
# GPS Coordinate Outlier Filter
|
|
278
|
+
if filter_coord_outliers:
|
|
279
|
+
sonDF = self._filterCoordOutliers(sonDF, iqr_scale=coord_iqr_scale)
|
|
280
|
+
|
|
274
281
|
#############################
|
|
275
282
|
# Do Heading Deviation Filter
|
|
276
283
|
if max_heading_dev > 0:
|
|
@@ -690,7 +697,16 @@ class sonObj(object):
|
|
|
690
697
|
if not filtCol in sonDF.columns:
|
|
691
698
|
sonDF[filtCol] = True
|
|
692
699
|
|
|
693
|
-
|
|
700
|
+
# Guard against bool/test toggles; only load when a real table is provided.
|
|
701
|
+
if isinstance(time_table, (bool, np.bool_)) or time_table is None:
|
|
702
|
+
return sonDF
|
|
703
|
+
if isinstance(time_table, str) and time_table.strip() == '':
|
|
704
|
+
return sonDF
|
|
705
|
+
|
|
706
|
+
if isinstance(time_table, pd.DataFrame):
|
|
707
|
+
time_table = time_table.copy()
|
|
708
|
+
else:
|
|
709
|
+
time_table = pd.read_csv(time_table)
|
|
694
710
|
|
|
695
711
|
for i, row in time_table.iterrows():
|
|
696
712
|
|
|
@@ -733,6 +749,57 @@ class sonObj(object):
|
|
|
733
749
|
|
|
734
750
|
return sonDF
|
|
735
751
|
|
|
752
|
+
# ======================================================================
|
|
753
|
+
def _filterCoordOutliers(self,
|
|
754
|
+
sonDF,
|
|
755
|
+
iqr_scale=3.0):
|
|
756
|
+
'''
|
|
757
|
+
Flag pings with extreme GPS coordinate outliers using the IQR method
|
|
758
|
+
on the lon and lat columns. For each coordinate field, pings that fall
|
|
759
|
+
outside Q1 - iqr_scale*IQR .. Q3 + iqr_scale*IQR are marked False
|
|
760
|
+
in the 'filter' column.
|
|
761
|
+
|
|
762
|
+
----------
|
|
763
|
+
Parameters
|
|
764
|
+
----------
|
|
765
|
+
sonDF : DataFrame
|
|
766
|
+
Ping metadata dataframe.
|
|
767
|
+
iqr_scale : float
|
|
768
|
+
Multiplier applied to the IQR to set the outlier fence.
|
|
769
|
+
Default 3.0 (flags only extreme outliers).
|
|
770
|
+
|
|
771
|
+
-------
|
|
772
|
+
Returns
|
|
773
|
+
-------
|
|
774
|
+
sonDF with 'filter' column updated.
|
|
775
|
+
'''
|
|
776
|
+
|
|
777
|
+
filtCol = 'filter'
|
|
778
|
+
|
|
779
|
+
if filtCol not in sonDF.columns:
|
|
780
|
+
sonDF[filtCol] = True
|
|
781
|
+
|
|
782
|
+
for coord_col in ['lon', 'lat']:
|
|
783
|
+
if coord_col not in sonDF.columns:
|
|
784
|
+
continue
|
|
785
|
+
|
|
786
|
+
vals = sonDF[coord_col]
|
|
787
|
+
q1 = vals.quantile(0.25)
|
|
788
|
+
q3 = vals.quantile(0.75)
|
|
789
|
+
iqr = q3 - q1
|
|
790
|
+
|
|
791
|
+
lower = q1 - iqr_scale * iqr
|
|
792
|
+
upper = q3 + iqr_scale * iqr
|
|
793
|
+
|
|
794
|
+
outlier_mask = (vals < lower) | (vals > upper)
|
|
795
|
+
n_flagged = outlier_mask.sum()
|
|
796
|
+
if n_flagged > 0:
|
|
797
|
+
print(f"\n _filterCoordOutliers: flagged {n_flagged} pings with {coord_col} outside "
|
|
798
|
+
f"[{lower:.6f}, {upper:.6f}]")
|
|
799
|
+
sonDF.loc[outlier_mask, filtCol] = False
|
|
800
|
+
|
|
801
|
+
return sonDF
|
|
802
|
+
|
|
736
803
|
# ======================================================================
|
|
737
804
|
def _filterAOI(self,
|
|
738
805
|
sonDF,
|
|
@@ -675,7 +675,16 @@ class sonObj(object):
|
|
|
675
675
|
if not filtCol in sonDF.columns:
|
|
676
676
|
sonDF[filtCol] = True
|
|
677
677
|
|
|
678
|
-
|
|
678
|
+
# Guard against bool/test toggles; only load when a real table is provided.
|
|
679
|
+
if isinstance(time_table, (bool, np.bool_)) or time_table is None:
|
|
680
|
+
return sonDF
|
|
681
|
+
if isinstance(time_table, str) and time_table.strip() == '':
|
|
682
|
+
return sonDF
|
|
683
|
+
|
|
684
|
+
if isinstance(time_table, pd.DataFrame):
|
|
685
|
+
time_table = time_table.copy()
|
|
686
|
+
else:
|
|
687
|
+
time_table = pd.read_csv(time_table)
|
|
679
688
|
|
|
680
689
|
for i, row in time_table.iterrows():
|
|
681
690
|
|
|
@@ -126,6 +126,8 @@ def read_master_func(logfilename='',
|
|
|
126
126
|
dq_src_utc_offset = 0.0,
|
|
127
127
|
dq_target_utc_offset = 0.0,
|
|
128
128
|
dq_time_offset = 0.0,
|
|
129
|
+
filter_coord_outliers = True,
|
|
130
|
+
coord_iqr_scale = 3.0,
|
|
129
131
|
tempC=10,
|
|
130
132
|
nchunk=500,
|
|
131
133
|
cropRange=0,
|
|
@@ -1025,7 +1027,7 @@ def read_master_func(logfilename='',
|
|
|
1025
1027
|
# For Filtering #
|
|
1026
1028
|
############################################################################
|
|
1027
1029
|
|
|
1028
|
-
if dq_table or max_heading_deviation > 0 or min_speed > 0 or max_speed > 0 or aoi or time_table:
|
|
1030
|
+
if dq_table or max_heading_deviation > 0 or min_speed > 0 or max_speed > 0 or aoi or time_table or filter_coord_outliers:
|
|
1029
1031
|
|
|
1030
1032
|
start_time = time.time()
|
|
1031
1033
|
|
|
@@ -1060,7 +1062,8 @@ def read_master_func(logfilename='',
|
|
|
1060
1062
|
son0 = portstar[maxRec]
|
|
1061
1063
|
df0 = son0._doSonarFiltering(max_heading_deviation, max_heading_distance, min_speed, max_speed, aoi, time_table,
|
|
1062
1064
|
dq_table, dq_time_field, dq_flag_field, dq_keep_values,
|
|
1063
|
-
dq_src_utc_offset, dq_target_utc_offset, dq_time_offset
|
|
1065
|
+
dq_src_utc_offset, dq_target_utc_offset, dq_time_offset,
|
|
1066
|
+
filter_coord_outliers=filter_coord_outliers, coord_iqr_scale=coord_iqr_scale)
|
|
1064
1067
|
|
|
1065
1068
|
# Add filter to other beam
|
|
1066
1069
|
son1 = portstar[minRec]
|
|
@@ -1110,7 +1113,8 @@ def read_master_func(logfilename='',
|
|
|
1110
1113
|
for son in downbeams:
|
|
1111
1114
|
df = son._doSonarFiltering(max_heading_deviation, max_heading_distance, min_speed, max_speed, aoi, time_table,
|
|
1112
1115
|
dq_table, dq_time_field, dq_flag_field, dq_keep_values,
|
|
1113
|
-
dq_src_utc_offset, dq_target_utc_offset, dq_time_offset
|
|
1116
|
+
dq_src_utc_offset, dq_target_utc_offset, dq_time_offset,
|
|
1117
|
+
filter_coord_outliers=filter_coord_outliers, coord_iqr_scale=coord_iqr_scale)
|
|
1114
1118
|
|
|
1115
1119
|
df = df[df['filter'] == True]
|
|
1116
1120
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '5.4.2'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pingmapper
|
|
3
|
-
Version: 5.4.
|
|
3
|
+
Version: 5.4.2
|
|
4
4
|
Summary: Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat
|
|
5
5
|
Author: Daniel Buscombe
|
|
6
6
|
Author-email: Cameron Bodine <bodine.cs@gmail.email>
|
|
@@ -17,7 +17,7 @@ Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
|
17
17
|
Classifier: Topic :: Scientific/Engineering :: Oceanography
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Hydrology
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.6
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
23
|
Requires-Dist: pinginstaller<3,>=2
|
|
@@ -33,6 +33,7 @@ Requires-Dist: tensorflow<3,>=2.20; extra == "ml"
|
|
|
33
33
|
Requires-Dist: tf-keras<3,>=2.20; extra == "ml"
|
|
34
34
|
Requires-Dist: transformers<5,>=4.57; extra == "ml"
|
|
35
35
|
Dynamic: license-file
|
|
36
|
+
Dynamic: requires-python
|
|
36
37
|
|
|
37
38
|
# PING-Mapper
|
|
38
39
|
[)](https://pypi.org/project/pingmapper/)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
DESCRIPTION = 'Open-source interface for processing recreation-grade side scan sonar datasets and reproducibly mapping benthic habitat'
|
|
5
|
+
LONG_DESCRIPTION = Path('README.md').read_text()
|
|
6
|
+
|
|
7
|
+
exec(open('pingmapper/version.py').read())
|
|
8
|
+
|
|
9
|
+
setup(
|
|
10
|
+
name="pingmapper",
|
|
11
|
+
version=__version__,
|
|
12
|
+
author="Cameron Bodine, Daniel Buscombe",
|
|
13
|
+
author_email="bodine.cs@gmail.email",
|
|
14
|
+
description=DESCRIPTION,
|
|
15
|
+
long_description=LONG_DESCRIPTION,
|
|
16
|
+
long_description_content_type='text/markdown',
|
|
17
|
+
packages=find_packages(),
|
|
18
|
+
data_files=[("pingmapper_config", ["pingmapper/default_params.json"])],
|
|
19
|
+
classifiers=[
|
|
20
|
+
"Development Status :: 5 - Production/Stable",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Topic :: Scientific/Engineering",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Oceanography",
|
|
27
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
28
|
+
"Topic :: Scientific/Engineering :: Hydrology"
|
|
29
|
+
],
|
|
30
|
+
keywords=[
|
|
31
|
+
"pingmapper",
|
|
32
|
+
"sonar",
|
|
33
|
+
"ecology",
|
|
34
|
+
"remotesensing",
|
|
35
|
+
"sidescan",
|
|
36
|
+
"sidescan-sonar",
|
|
37
|
+
"aquatic",
|
|
38
|
+
"humminbird",
|
|
39
|
+
"lowrance",
|
|
40
|
+
"gis",
|
|
41
|
+
"oceanography",
|
|
42
|
+
"limnology",],
|
|
43
|
+
python_requires=">=3.6",
|
|
44
|
+
install_requires=['pinginstaller', 'pingwizard', 'pingverter'],
|
|
45
|
+
project_urls={
|
|
46
|
+
"Issues": "https://github.com/CameronBodine/PINGMapper/issues",
|
|
47
|
+
"GitHub":"https://github.com/CameronBodine/PINGMapper",
|
|
48
|
+
"Homepage":"https://cameronbodine.github.io/PINGMapper/",
|
|
49
|
+
},
|
|
50
|
+
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '5.4.1'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/avg_predictions_Mussel_WBL.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/DRAFT_Workflows/testEXAMPLE_mosaic_logit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pingmapper-5.4.1 → pingmapper-5.4.2}/pingmapper/utils/Substrate_Summaries/03_gen_summary_shp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|