1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
- import pyxtf
- import numpy as np
- import matplotlib.pyplot as plt
- # Read the test file
- # Note that at this point, the header_7125 and header_7125_snippet is not implemented, which is why a warning is shown
- # The bathymetry and sonar headers are implemented, however - which can be read while ignoring the unimplemented packets
- test_file = "/home/ps/PycharmProjects/mines_rocks/data/JNCC2013_03BassSandRawAcousticssraw_data/BoxA/20130328042943L.xtf"
- (fh, p) = pyxtf.xtf_read(test_file)
- # This prints all the ctypes fields present
- print(fh)
- # The ChanInfo field is an array of XTFChanInfo objects
- # Note that the ChanInfo field always has a size of 6, even if the number of channels is less.
- # Use the fh.NumXChannels fields to calculate the number (the function xtf_channel_count does this)
- n_channels = fh.channel_count(verbose=True)
- actual_chan_info = [fh.ChanInfo[i] for i in range(0, n_channels)]
- print('Number of data channels: {}\n'.format(n_channels))
- # Print the first channel
- print(actual_chan_info[0])
- # Print the keys in the packets-dictionary
- print([key for key in p])
- # The returned packets is a Dict[XTFHeaderType, List[XTFClass]]
- # The values in the dict are lists of pings, of the class in question
- sonar_ch = p[pyxtf.XTFHeaderType.sonar] # type: List[pyxtf.XTFPingHeader]
- # Each element in the list is a ping (XTFPingHeader)
- # This retrieves the first ping in the file of the sonar type
- sonar_ch_ping1 = sonar_ch[0]
- # The properties in the header defines the attributes common for all subchannels
- # (e.g sonar often has port/stbd subchannels)
- print(sonar_ch_ping1)
- # The data and header for each subchannel is contained in the data and ping_chan_headers respectively.
- # The data is a list of numpy arrays (one for each subchannel)
- sonar_subchan0 = sonar_ch_ping1.data[0] # type: np.ndarray
- sonar_subchan1 = sonar_ch_ping1.data[1] # type: np.ndarray
- print(sonar_subchan0.shape)
- print(sonar_subchan1.shape)
- # Plot a signal-vie of both subchannels of the first ping
- fig, (ax1, ax2) = plt.subplots(2,1, figsize=(12,8))
- ax1.semilogy(np.arange(0, sonar_subchan0.shape[0]), sonar_subchan0)
- ax2.semilogy(np.arange(0, sonar_subchan1.shape[0]), sonar_subchan1)
- # Each subchannel has a XTFPingChanHeader,
- # which contains information that can change from ping to ping in each of the subchannels
- sonar_ping1_ch_header0 = sonar_ch_ping1.ping_chan_headers[0]
- print(sonar_ping1_ch_header0)
- # Concatenate the sonar data to produce a dense array/image
- # The function concatenate_channels concatenates all the individual pings for a channel, and returns it as a dense numpy array
- np_chan1 = pyxtf.concatenate_channel(p[pyxtf.XTFHeaderType.sonar], file_header=fh, channel=0, weighted=False)
- np_chan2 = pyxtf.concatenate_channel(p[pyxtf.XTFHeaderType.sonar], file_header=fh, channel=1, weighted=False)
- # Clip to range (max cannot be used due to outliers)
- # More robust methods are possible (through histograms / statistical outlier removal)
- upper_limit = 2 ** 14
- np_chan1.clip(0, upper_limit-1, out=np_chan1)
- np_chan2.clip(0, upper_limit-1, out=np_chan2)
- # The sonar data is logarithmic (dB), add small value to avoid log10(0)
- np_chan1 = np.log10(np_chan1 + 0.0001)
- np_chan2 = np.log10(np_chan2 + 0.0001)
- # Transpose so that the largest axis is horizontal
- np_chan1 = np_chan1 if np_chan1.shape[0] < np_chan1.shape[1] else np_chan1.T
- np_chan2 = np_chan2 if np_chan2.shape[0] < np_chan2.shape[1] else np_chan2.T
- # The following plots the waterfall-view in separate subplots
- fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12))
- ax1.imshow(np_chan1, cmap='gray', vmin=0, vmax=np.log10(upper_limit))
- ax2.imshow(np_chan2, cmap='gray', vmin=0, vmax=np.log10(upper_limit))
- plt.show()
|