Metrics describing shaking intensity (rsudp)

As you might have seen in my other posts I’m deploying on a LoRa network and through some testing my expected bandwidth is 15-50 kbits/second. While it appears the waveform will be near impossible to transmit in a raw format, I’d like to use rsudp to transmit metrics describing shaking such as magnitude. Is this currently possible using existing functionality?

This would mean running rsudp on the Pi locally which also brings up my next question: will it be too demanding for its CPU? If yes, I may just write my own application.

If you have any suggestions on compressing that raw data to shrink it down to a necessary bandwidth I’m all ears.


Managed to get an answer on this from a seismologist. For our use case we’re going to sample peak amplitude and average amplitude over a specified time period (1 second?) and also calculate the RMS. This is for each sensor on the 4D. Open to suggestions if anyone else has some ideas around this.


that sounds a lot like “Real-time Seismic Amplitude Measurement” (RSAM), a common tool in volcanology:

rsudp is an open-source project: feel free to contribute a new consumer module for this.


1 Like

Thanks and yes contributing a new module might be a faster way to do it since rsdup already handles the waveform natively :slight_smile: I’ll give it a look

1 Like

more source code examples:


1 Like

I played around with rsudp code last night, it seems adapting the Alarm consumer is going to be the fastest path to implementing RSAM. Some questions for you on the implementation:

  • Can I chain the output of one consumer to another? E.g. apply RSAM then use Forward consumer to send it out?
  • If the answer above is “no”, is it preferable to duplicate Forward functionality in the RSAM class?
  • Does the Alarm consumer only process one channel at a time? Or does the dimensionality of the array change depending on the channels selected to be processed?
obstart =[0].stats.endtime - timedelta(seconds=self.lta)	# obspy time
self.raw = self.raw.slice(starttime=obstart)		# slice the stream to the specified length (seconds variable) =	# slice the stream to the specified length (seconds variable)
  • Is the above code, controlled by the lta variable, the piece that is collecting a window of packets over specified time interval?
  • Where is self.raw being used?
  • Does the dimensionality of the array change in the def _filter function if a filter is not applied or all channels are selected?

Thanks I think I have a high-level understanding of the code need some answers on these items before proceeding.

1 Like

Hi Justin, I just saw your pull request (thank you, that was very speedy!) and will be reviewing it shortly. To answer your questions:

I think best practice would be to create a sub-sub consumer that would forward only the output of the RSAM consumer. Although both the RSAM and the forwarding operations require very little computation/execution time, so I think they could be combined into a single thread.

See above. I think this is an acceptable solution.

Yes, it is only designed to monitor one channel. Future iterations could have it monitor more than one, but I still need to think about how that could be achieved.

Yes, this keeps the size of the Stream object to the length of lta.

When deconvolving a stream, rsudp always works from raw data instead of doubly deconvolving previously deconvolved data. self.raw is the destination for incoming raw data in Counts, which is then deconvolved to if deconvolution is turned on.

The dimensionality does not change. However, as you’ve probably noticed, this function is applied on every loop when the trigger is running. Perhaps it’s more confusing than not, but I thought it would be more readable if the logic to determine whether there was a filter being applied would be better inside that function than in the run() function.

1 Like