1
|
|
|
#!/usr/bin/env python |
2
|
|
|
# -*- coding: utf-8 -*- |
3
|
1 |
|
import os, sys |
4
|
1 |
|
import getopt |
5
|
1 |
|
from obspy import read |
6
|
1 |
|
from datetime import timedelta |
7
|
1 |
|
from rsudp.test import TEST |
8
|
1 |
|
from rsudp.helpers import lesser_multiple |
9
|
|
|
|
10
|
|
|
|
11
|
1 |
|
SMP = { |
12
|
|
|
0.01: 25, |
13
|
|
|
0.02: 50, |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
|
17
|
1 |
|
def get_samps(stream): |
18
|
|
|
''' |
19
|
|
|
Return the number of samples to place in each packet. |
20
|
|
|
This number is based on the sampling frequency of the data in question. |
21
|
|
|
|
22
|
|
|
Raspberry Shake data is sent to the UDP port either in packets of 25 |
23
|
|
|
(for sampling frequency of 100 Hz) or 50 (for frequency of 50 Hz). |
24
|
|
|
|
25
|
|
|
This is hardcoded and will not change for the foreseeable future, |
26
|
|
|
which means that it can be used to determine the variety of sensor used |
27
|
|
|
(50 Hz is the original versions of RS1D). |
28
|
|
|
|
29
|
|
|
:param obspy.core.stream.Stream stream: Stream object to calculate samples per packet for |
30
|
|
|
|
31
|
|
|
:rtype: int |
32
|
|
|
:return: the number of samples per packet (either 25 or 50) |
33
|
|
|
''' |
34
|
1 |
|
try: |
35
|
1 |
|
return SMP[stream[0].stats.delta] |
36
|
|
|
except KeyError as e: |
37
|
|
|
raise KeyError('Sampling frequency of %s is not supported. Is this Raspberry Shake data?' % (e)) |
38
|
|
|
|
39
|
|
|
|
40
|
1 |
|
def cutoff_calc(stream): |
41
|
|
|
''' |
42
|
|
|
Return the number of samples that will be transcribed to UDP packet formatted ascii text. |
43
|
|
|
Iterates over each trace in the stream to make this calculation. |
44
|
|
|
|
45
|
|
|
:param obspy.core.stream.Stream stream: Stream object to calculate number of samples from |
46
|
|
|
|
47
|
|
|
:rtype: int, int |
48
|
|
|
:return: 1) the number of samples to transcribe, 2) the number of samples in each packet |
49
|
|
|
''' |
50
|
1 |
|
samps = get_samps(stream) |
51
|
1 |
|
c = lesser_multiple(len(stream[0].data), base=samps) |
52
|
1 |
|
for t in stream: |
53
|
1 |
|
n = lesser_multiple(len(t.data), base=samps) |
54
|
1 |
|
if n < c: |
55
|
|
|
c = n |
56
|
1 |
|
return c, samps |
57
|
|
|
|
58
|
|
|
|
59
|
1 |
|
def packetize(inf, outf, testing=False): |
60
|
|
|
''' |
61
|
|
|
Reads a seismic data file and converts it to ascii text. |
62
|
|
|
|
63
|
|
|
:param str inf: the input data file to convert |
64
|
|
|
:param str outf: where to write the output file |
65
|
|
|
''' |
66
|
1 |
|
if os.path.isfile(os.path.expanduser(inf)): |
67
|
1 |
|
stream = read(inf) |
68
|
1 |
|
cutoff, samps = cutoff_calc(stream) |
69
|
1 |
|
n = 0 |
70
|
1 |
|
time = stream[0].stats.starttime |
71
|
|
|
|
72
|
1 |
|
with open(outf, 'w') as f: |
73
|
1 |
|
for i in range(0, int(cutoff/samps)): |
74
|
1 |
|
ptime = time + timedelta(seconds=stream[0].stats.delta*n) |
75
|
1 |
|
for t in stream: |
76
|
1 |
|
data = '' |
77
|
1 |
|
chan = t.stats.channel |
78
|
1 |
|
for j in range(n, n+samps): |
79
|
1 |
|
data += ', %s' % t.data[j] |
80
|
1 |
|
line = "{'%s', %.3f%s}%s" % (chan, ptime.timestamp, data, os.linesep) |
81
|
1 |
|
f.write(line) |
82
|
1 |
|
n += samps |
83
|
|
|
|
84
|
1 |
|
f.write('TERM%s' % (os.linesep)) |
85
|
|
|
|
86
|
1 |
|
print('Data written to %s' % outf) |
87
|
1 |
|
if testing: |
88
|
1 |
|
TEST['x_packetize'][1] = True |
89
|
|
|
else: |
90
|
|
|
print('Input file does not exist: %s' % inf) |
91
|
|
|
|
92
|
|
|
|
93
|
1 |
|
def main(): |
94
|
|
|
''' |
95
|
|
|
This function reads command line arguments, then calls |
96
|
|
|
:py:func:`rsudp.packetize.packetize` with those arguments. |
97
|
|
|
''' |
98
|
|
|
inf, outf = False, False |
99
|
|
|
opts = getopt.getopt(sys.argv[1:], 'i:o:', |
100
|
|
|
['in=', 'out=',] |
101
|
|
|
)[0] |
102
|
|
|
|
103
|
|
|
for opt, arg in opts: |
104
|
|
|
if opt in ('-i', '--in='): |
105
|
|
|
inf = arg |
106
|
|
|
if opt in ('-o', '--out='): |
107
|
|
|
outf = arg |
108
|
|
|
if inf and outf: |
109
|
|
|
packetize(inf=inf, outf=outf) |
110
|
|
|
else: |
111
|
|
|
print('Usage: packetize.py -i infile.ms -o testdata') |
112
|
|
|
|
113
|
|
|
if __name__ == '__main__': |
114
|
|
|
main() |