pingverter 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Cameron Bodine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.1
2
+ Name: pingverter
3
+ Version: 0.1.0
4
+ Summary: A Python-based converter for sonar logs used in PINGMapper
5
+ Author: Cameron Bodine
6
+ Author-email: bodine.cs@gmail.email
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.6
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+
14
+ # PINGVerter
15
+ A Python-based convertor for sonar logs
@@ -0,0 +1,2 @@
1
+ # PINGVerter
2
+ A Python-based convertor for sonar logs
@@ -0,0 +1,6 @@
1
+
2
+ from .humminbird_class import hum
3
+ from .lowrance_class import low
4
+ from .converter import hum2pingmapper, low2pingmapper, low2hum
5
+ from . import _version
6
+ __version__ = _version.get_versions()['version']
@@ -0,0 +1,255 @@
1
+
2
+ import os, sys
3
+ from pingverter import hum, low
4
+ import time, datetime
5
+ import pandas as pd
6
+ from glob import glob
7
+
8
+ from joblib import Parallel, delayed, cpu_count
9
+
10
+ # =========================================================
11
+ # Humminbird to PINGMapper
12
+ # =========================================================
13
+
14
+ def hum2pingmapper(input: str, out_dir: str, nchunk: int=500, tempC: float=10, exportUnknown: bool=False):
15
+ '''
16
+
17
+ '''
18
+ # Make sure input exists
19
+ assert os.path.isfile(input), "{} does not exist.".format(input)
20
+
21
+ # Create the class
22
+ humminbird = hum(humFile=input, nchunk=nchunk, exportUnknown=exportUnknown)
23
+
24
+ # Store temperatue
25
+ humminbird.tempC = float(tempC)/10
26
+
27
+ #################
28
+ # Decode DAT File
29
+ #################
30
+
31
+ start_time = time.time()
32
+ print("\nGetting DAT Metadata...")
33
+ print(input)
34
+ humminbird._getHumDatStruct()
35
+
36
+ # Read in the humdat data
37
+ if humminbird.isOnix == 0:
38
+ humminbird._getHumdat()
39
+
40
+ # Determine epsg code and transformation (if we can, ONIX doesn't have
41
+ ## lat/lon in DAT, so will determine at a later processing step).
42
+ humminbird._getEPSG()
43
+ else:
44
+ humminbird._decodeOnix()
45
+
46
+ # Create 'meta' directory if it doesn't exist
47
+ metaDir = os.path.join(out_dir, 'meta')
48
+ try:
49
+ os.mkdir(metaDir)
50
+ except:
51
+ pass
52
+ humminbird.metaDir = metaDir #Store metadata directory in sonObj
53
+
54
+ # Save DAT metadata to file (csv)
55
+ outFile = os.path.join(metaDir, 'DAT_meta.csv') # Specify file directory & name
56
+ pd.DataFrame.from_dict(humminbird.humDat, orient='index').T.to_csv(outFile, index=False) # Export DAT df to csv
57
+ humminbird.datMetaFile = outFile # Store metadata file path in sonObj
58
+ del outFile
59
+
60
+ print("\nDone!")
61
+ print("Time (s):", round(time.time() - start_time, ndigits=1))
62
+
63
+ #####################################
64
+ # Generate sonar file meta/attributes
65
+ #####################################
66
+
67
+ # Find available SON files
68
+ sonFiles = glob(os.path.join(humminbird.sonFile, '*.SON'))
69
+
70
+ # Determine which sonar beams are present (B000,B001,..)
71
+ chanAvail = {}
72
+ for s in sonFiles:
73
+ beam = os.path.split(s)[-1].split('.')[0] #Get beam number (B000,B001,..)
74
+ chanAvail[beam] = s
75
+ del s, beam
76
+
77
+ humminbird.chanAvail = chanAvail
78
+
79
+ # Store sonar file meta in humminbird object
80
+ ## Dictionary of dictionaries
81
+ beamMeta = humminbird.beamMeta = {}
82
+ for chan, file in chanAvail.items():
83
+
84
+ beamMeta[chan] = {}
85
+
86
+ # Get beam name
87
+ beamMeta[chan]['beamName'] = humminbird._getBeamName(chan)
88
+
89
+ beamMeta[chan]['beam'] = chan
90
+ beamMeta[chan]['sonFile'] = file
91
+
92
+ # Output csv name
93
+ csv = '{}_{}_{}'.format(chan, beamMeta[chan]['beamName'], 'meta.csv')
94
+ beamMeta[chan]['metaCSV'] = os.path.join(metaDir, csv)
95
+
96
+
97
+ ##############################################################
98
+ # Determine ping header structure (varies by Humminbird model)
99
+ ##############################################################
100
+ start_time = time.time()
101
+ print("\nGetting Header Structure...")
102
+
103
+
104
+ gotHeader = False # Flag indicating if length of header is found
105
+
106
+ for beam, meta in beamMeta.items():
107
+
108
+ # Get SON file
109
+ son = meta['sonFile']
110
+
111
+ # Count headbytes
112
+ headbytes = humminbird._cntHead(son)
113
+
114
+ if headbytes > 0: # Header length found
115
+ print("Header Length: {}".format(headbytes))
116
+ gotHeader = True
117
+
118
+ # Add headbytes to humminbird object
119
+ humminbird.frame_header_size = headbytes
120
+
121
+ break
122
+
123
+
124
+ # Consider adding decodeHeadStruct() function back into PINGVerter....
125
+
126
+
127
+ if not gotHeader:
128
+ sys.exit("\n#####\nERROR: Out of SON files... \n"+
129
+ "Unable to determine header length.")
130
+
131
+
132
+ #############################################
133
+ # Get the SON header structure and attributes
134
+ #############################################
135
+
136
+ humminbird._getHeadStruct()
137
+
138
+ ##################
139
+ # Parse son header
140
+ ##################
141
+
142
+ _ = Parallel(n_jobs = len(beamMeta), verbose=10 )(delayed(humminbird._parsePingHeader)(meta['sonFile'], meta['metaCSV']) for beam, meta in beamMeta.items())
143
+
144
+ print("\nDone!")
145
+ print("Time (s):", round(time.time() - start_time, ndigits=1))
146
+
147
+ return humminbird
148
+
149
+
150
+ # =========================================================
151
+ # Lowrance to PINGMapper
152
+ # =========================================================
153
+
154
+ def low2pingmapper(low_file: str, out_dir: str):
155
+
156
+ return
157
+
158
+
159
+ # =========================================================
160
+ # Lowrance to Humminbird
161
+ # =========================================================
162
+
163
+ def low2hum(input: str, output: str):
164
+
165
+ # Make sure input exists
166
+ assert os.path.isfile(input), "{} does not exist.".format(input)
167
+
168
+ # Create the classes
169
+ lowrance = low(input)
170
+ humminbird = hum(output)
171
+
172
+ # Make output files
173
+ humminbird._makeOutFiles()
174
+
175
+ # Start the decode
176
+ start_time = time.time()
177
+ print('\n\nDecoding Lowrance File...')
178
+
179
+ # Get Lowrance file length
180
+ lowrance._getFileLen()
181
+
182
+ # Parse file header
183
+ lowrance._parseFileHeader()
184
+
185
+ # Parse ping headers (attributes)
186
+ lowrance._parsePingHeader()
187
+
188
+ # Convert ping attributes to known units
189
+ lowrance._convertPingAttributes()
190
+
191
+ # lowrance.header_dat.to_csv('lowrance_test.csv')
192
+
193
+ print("Time (s):", round(time.time() - start_time, ndigits=1))
194
+
195
+ #######################
196
+ # Convert to Humminbird
197
+ #######################
198
+
199
+ start_time = time.time()
200
+ print('\n\nConverting to Humminbird...')
201
+
202
+ # Convert to Humminbird attributes
203
+ humminbird._convertLowHeader(lowrance)
204
+
205
+ # Drop unknown beams
206
+ humminbird._removeUnknownBeams()
207
+
208
+ # Split sidescan, if necessary
209
+ beams = humminbird.header_dat['beam'].unique()
210
+ if 5 in beams:
211
+ humminbird._splitLowSS()
212
+ flip_port = True
213
+ else:
214
+ flip_port = False
215
+
216
+ # Recalculate record number
217
+ humminbird._recalcRecordNum()
218
+
219
+ # humminbird.header_dat.to_csv('hum_converted.csv')
220
+
221
+ # Get necessary data for DAT file
222
+ humminbird._convertLowDAT(lowrance)
223
+
224
+ # Write DAT to file
225
+ humminbird._writeDAT()
226
+
227
+ # Save b001 and b002
228
+ beams = humminbird.header_dat['beam'].unique()
229
+
230
+ if 0 in beams:
231
+ humminbird._writeSonfromLow(0, lowrance.frame_header_size, lowrance.path)
232
+
233
+ if 1 in beams:
234
+ humminbird._writeSonfromLow(1, lowrance.frame_header_size, lowrance.path)
235
+
236
+ if 2 in beams:
237
+ humminbird._writeSonfromLow(2, lowrance.frame_header_size, lowrance.path, flip_port)
238
+
239
+ if 3 in beams:
240
+ humminbird._writeSonfromLow(3, lowrance.frame_header_size, lowrance.path)
241
+
242
+ if 4 in beams:
243
+ humminbird._writeSonfromLow(4, lowrance.frame_header_size, lowrance.path)
244
+
245
+ # Split b005 (lowrance sidescan) into port (2) and star (3)
246
+
247
+
248
+ humminbird.header_dat.to_csv('hum_converted.csv')
249
+
250
+ print("Time (s):", round(time.time() - start_time, ndigits=1))
251
+
252
+ return
253
+
254
+
255
+