Converting UDP data to acceleration

Going through the forums, I’ve found multiple instances of people asking about this, but each response was that obspy library would be updated to allow the UDP into a stream object. These comments were from mid-late 2019. I have not seen that option added to the obspy changelog. Has it been added yet?

If not, is there a simple way to take the UDP byte-stream and convert each data point from voltage count to acceleration? I understand there will be sensor-noise added, but I just need human readable numbers.

Thanks!

Hello Bluesummers, welcome to the community!

Our software RSUDP, developed here at Raspberry Shake, can convert a UDP stream straight to different plots, such as Velocity or Acceleration.

You can find the full documentation here: rsudp 1.0.1 — rsudp documentation

The software is fully customisable, so it could be what you are looking for.

Hi Stomrchaser, thanks for the reply! I apologize in advance that I have very little knowledge about seismography. I’ve been tasked with pulling in the data into an existing ecology, and making it available for other devs to use. It does not need plotted or displayed in any graph form at the moment.

My understanding is that rsudp gets installed and setup on the shake? If so, then that is not ideal for us, as we don’t own the shake that is casting to us. I’m sure we could work with the owners, but I’d much rather own the code on our end.

I’m really looking for a server-side solution, as we might have multiple shakes installed at some point and I’d like to keep their setup simple. On the server that I’m casting to, I can get the byte-stream and pick it apart and pull it into our database, however the voltage counts don’t mean much. Ideally, I’d like to just massage the raw data after it comes in to make it useful as acceleration/velocity.

I’ve been using ObsPy to grab the data (via IP using Client get_waveforms) and apply an inventory file, and I believe the numbers look correct, but I’d rather still get accel/velocity via UDP.

This is my test code. Each piece works, but I would like to marry the two methods together. Is there a way to apply the inventory to UDP?

import socket as s
import statistics
from obspy.core import UTCDateTime, Stream
from obspy import read_inventory
from obspy.clients.earthworm import Client
import time
import os

def main():
IPGet()
# UDPGet()

def IPGet():
‘’’
This will constantly query the rshake for waveform data and filter out the device-specific noise on
the sensors. However, get_waveforms lowest read time is in 1-second intervals.
‘’’

rs = Client(<rshake>, 16032)               # on obspy 1.2.0 and greater
inv = read_inventory('./R1A9C-no_location-dummyfile.xml')

stream = Stream()
channels = ['EHZ','ENN','ENE','ENZ']


while (True):

    calcStart = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time() - 1))
    start = UTCDateTime(calcStart)
    calcEnd = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    end = UTCDateTime(calcEnd)

    for ch in channels:
        trace = rs.get_waveforms('AM', 'R1A9C', '00', ch, start, end)
        stream += trace
    
    stream.attach_response(inv)
    stream.remove_response(output='ACC')

    for trace in stream:
        print (end, trace.stats.channel, max(abs(trace.data)))

def UDPGet():
‘’’
This will read a broadcasted UDP stream and split the incoming byte stream into chewable unit-less pieces

'''

host = <host>
port =<port>								# Port to bind to

HP = host + ":" + str(port)
print ("  Opening socket on (HOST:PORT) ", HP)

sock = s.socket(s.AF_INET, s.SOCK_DGRAM | s.SO_REUSEADDR)
sock.bind((host, port))

print ("Waiting for data on (HOST:PORT) ", HP)

while (True):							# loop forever
    bData, addr = sock.recvfrom(1024)	# wait to receive data

    # corrected = bData
    # corrected.attach_response(inv)
    # corrected.remove_resp(output='ACC', taper=0.5)
    # print(corrected)

    sData = bData.decode("utf-8")       # converting bytes to string
    lsData = sData.strip('}{').split(', ')  # converting string to list of strings

    print ("Sensor = ", lsData[0].strip("'"))
    print (" Time = ", lsData[1])

    ilsData = lsData[2:27]
    ilsData = [int(i) for i in ilsData]     # converting list of strings to list of integers
    print ("  Max = ", max(ilsData))
    print ("  Min = ", min(ilsData))
    print ("  Median = ", int(statistics.median(ilsData)))
    print ("  Average = ", int(statistics.mean(ilsData)))
    print ("  Deviation = ", int(statistics.stdev(ilsData)))

if name == “main”:
main()

Hello Bluesummers, some further info:

  1. RSUDP can be installed anywhere, on the Shake (though not recommended, because of the increased processing power needed for the software), or on any other computer on a LAN, or on any other computer in the world;
  2. The Shake itself needs to be configured, through the front-end config app rs.local, to forward UDP data to the machine where RSUDP is installed, designated by IP address. Since you will be managing some of the Shakes, as I understand, this would not be difficult to do;
  3. If, instead, you don’t want to use RSUDP, you can still forward UDP data to another machine and then, if you need specific processing for the data, we always encourage to write your own Python code (as you have already started to do) to ingest, process the data, and save the results to his own database.

Finally, this is our manual page regarding converting the voltage counts from the Shake to more recognizable units: Developer’s corner — Instructions on Setting Up Your Raspberry Shake You can use this as a starting poing.