def __init__(self, q=False, interval=5, cha='HZ', deconv=False, fwaddr=False, fwport=False, fwformat='LITE', quiet=False, testing=False, *args, **kwargs): """ Initializes the RSAM analysis thread. """ super().__init__() self.sender = 'RSAM' self.alive = True self.testing = testing self.quiet = quiet # suppresses printing of transmission stats self.stn = rs.stn self.fwaddr = fwaddr self.fwport = fwport self.fwformat = fwformat.upper() self.sock = False self.interval = interval self.default_ch = 'HZ' self.args = args self.kwargs = kwargs self.raw = rs.Stream() self.stream = rs.Stream() self.units = 'counts' self._set_deconv(deconv) self._set_channel(cha) self.rsam = [1, 1, 1] if q: self.queue = q else: printE('no queue passed to the consumer thread! We will exit now!', self.sender) sys.stdout.flush() self.alive = False sys.exit() printM('Starting.', self.sender)
def __init__(self, q, data_dir, testing=False, debug=False, cha='all'): """ Initialize the process """ super().__init__() self.sender = 'Write' self.alive = True self.testing = testing self.debug = debug if self.testing: self.debug = True self.queue = q self.stream = rs.Stream() self.outdir = os.path.join(data_dir, 'data') self.outfiles = [] self.chans = [] helpers.set_channels(self, cha) printM('Writing channels: %s' % self.chans, self.sender) self.numchns = rs.numchns self.stime = 1 / rs.sps self.inv = rs.inv printM('Starting.', self.sender)
def __init__(self, q, sta=5, lta=30, thresh=1.6, reset=1.55, bp=False, debug=True, cha='HZ', sound=False, deconv=False, testing=False, *args, **kwargs): """ Initializing the alert thread with parameters to set up the recursive STA-LTA trigger, filtering, and the channel used for listening. """ super().__init__() self.sender = 'Alert' self.alive = True self.testing = testing self.queue = q self.default_ch = 'HZ' self.sta = sta self.lta = lta self.thresh = thresh self.reset = reset self.debug = debug self.args = args self.kwargs = kwargs self.raw = rs.Stream() self.stream = rs.Stream() self._set_channel(cha) self.sps = rs.sps self.inv = rs.inv self.stalta = np.ndarray(1) self.maxstalta = 0 self.units = 'counts' self._set_deconv(deconv) self.exceed = False self.sound = sound self._set_filt(bp) self._print_filt()
def __init__(self, q): """ Initializes the custom code execution thread. """ super().__init__() self.sender = 'Testing' self.alive = True self.queue = q self.stream = rs.Stream() self.cha = rs.chns printW('Starting test consumer.', sender=self.sender, announce=False)
def __init__(self, q, debug=False, cha='all'): """ Initialize the process """ super().__init__() self.sender = 'Write' self.alive = True self.queue = q self.stream = rs.Stream() self.outdir = rsudp.data_dir self.debug = debug self.chans = [] helpers.set_channels(self, cha) printM('Writing channels: %s' % self.chans, self.sender) self.numchns = rs.numchns self.stime = 1 / rs.sps self.inv = rs.inv printM('Starting.', self.sender)
def __init__(self, q=False, debug=False, cha='all'): """ Initialize the process """ super().__init__() self.sender = 'Write' self.alive = True if q: self.queue = q else: printM('ERROR: no queue passed to consumer! Thread will exit now!', self.sender) sys.stdout.flush() sys.exit() self.stream = RS.Stream() self.outdir = rsudp.data_dir self.debug = debug self.chans = [] cha = RS.chns if (cha == 'all') else cha cha = list(cha) if isinstance(cha, str) else cha l = RS.chns for c in l: n = 0 for uch in cha: if (uch.upper() in c) and (c not in str(self.chans)): self.chans.append(c) n += 1 if len(self.chans) < 1: self.chans = RS.chns printM('Writing channels: %s' % self.chans, self.sender) self.numchns = RS.numchns self.stime = 1 / RS.sps self.inv = RS.inv self.alarm = False printM('Starting.', self.sender)
def __init__(self, q=False, debug=False): """ Initialize the process """ super().__init__() self.sender = 'Write' self.alive = True if q: self.queue = q else: printM('ERROR: no queue passed to consumer! Thread will exit now!', self.sender) sys.stdout.flush() sys.exit() self.stream = RS.Stream() self.refcha = None self.outdir = rsudp.data_dir self.debug = debug self.numchns = RS.numchns self.stime = 1/RS.sps self.inv = RS.inv self.alarm = False printM('Starting.', self.sender)
def test(): ''' .. versionadded:: 0.4.3 Set up tests, run modules, report test results. For a list of tests run, see :py:mod:`rsudp.test`. ''' global TESTFILE hlp_txt = ''' ########################################### ## R A S P B E R R Y S H A K E ## ## Testing Module ## ## by Ian Nesbitt ## ## GNU GPLv3 2020 ## ## ## ## Test settings with archived Shake ## ## data to determine optimal ## ## configuration. ## ## ## ## Requires: ## ## - numpy, obspy, matplotlib 3 ## ## ## ########################################### Usage: rs-test [ OPTIONS ] where OPTIONS := { -h | --help display this help message -f | --file=default or /path/to/data/file specify the path to a seismic data file -s | --settings=/path/to/settings/json specify the path to a JSON-formatted settings file -b | --no-plot "blind mode", used when there is no display -q | --no-sound "quiet mode", used when there is no audio device/ffmpeg } rs-test with no arguments will start the test with default settings and the data file at %s ''' % (TESTFILE) test_mode(True) settings = H.default_settings(verbose=False) settings_are_default = True plot = True quiet = False customfile = False try: opts = getopt.getopt( sys.argv[1:], 'hf:s:bq', ['help', 'file=', 'settings=', 'no-plot', 'no-sound'])[0] except Exception as e: print(COLOR['red'] + 'ERROR: %s' % e + COLOR['white']) print(hlp_txt) exit(1) for o, a in opts: # parse options and arguments if o in ('-h', '--help'): print(hlp_txt) exit(0) if o in ('-f', '--file='): ''' The data file. ''' a = os.path.expanduser(a) if os.path.exists(a): try: out = '%s.txt' % (a) packetize(inf=a, outf=out, testing=True) TESTFILE = out customfile = True # using a custom miniseed file for testing except Exception as e: print(hlp_txt) print(COLOR['red'] + 'ERROR: %s' % e + COLOR['white']) exit(1) if o in ('-s', '--settings='): ''' Dump the settings to a file, specified after the `-d` flag, or `-d default` to let the software decide where to put it. ''' settings_loc = os.path.abspath(os.path.expanduser(a)).replace( '\\', '/') if os.path.exists(settings_loc): settings = H.read_settings(settings_loc) settings_are_default = False else: print(COLOR['red'] + 'ERROR: could not find settings file at %s' % (a) + COLOR['white']) exit(1) if o in ('-b', '--no-plot'): plot = False if o in ('-q', '--no-sound'): quiet = True if not customfile: # we are just using the default miniseed file packetize(inf=TESTFILE + '.ms', outf=TESTFILE, testing=True) T.TEST['n_internet'][1] = T.is_connected('www.google.com') if settings_are_default: settings = T.make_test_settings(settings=settings, inet=T.TEST['n_internet'][1]) T.TEST['p_log_dir'][1] = T.logdir_permissions() T.TEST['p_log_file'][1] = start_logging(testing=True) T.TEST['p_log_std'][1] = add_debug_handler(testing=True) T.TEST['p_output_dirs'][1] = init_dirs( os.path.expanduser(settings['settings']['output_dir'])) T.TEST['p_data_dir'][1] = T.datadir_permissions( os.path.expanduser(settings['settings']['output_dir'])) T.TEST['p_screenshot_dir'][1] = T.ss_permissions( os.path.expanduser(settings['settings']['output_dir'])) settings = T.cancel_tests(settings, MPL, plot, quiet) try: run(settings, debug=True) # client test ctest = 'client test' if (T.TEST['c_miniseed'] and WRITER): printM('Merging and testing MiniSEED file(s)...', sender=ctest) try: ms = rs.Stream() for outfile in WRITER.outfiles: if os.path.exists(outfile): T.TEST['c_miniseed'][1] = True ms = ms + rs.read(outfile) dn, fn = os.path.dirname(outfile), os.path.basename( outfile) os.replace(outfile, os.path.join(dn, 'test.' + fn)) else: raise FileNotFoundError('MiniSEED file not found: %s' % outfile) printM('Renamed test file(s).', sender=ctest) printM(ms.merge().__str__()) except Exception as e: printE(e) T.TEST['c_miniseed'][1] = False except Exception as e: printE(traceback.format_exc(), announce=False) printE('Ending tests.', sender=SENDER, announce=False) time.sleep(0.5) TESTQUEUE.put(b'ENDTEST') printW('Test finished.', sender=SENDER, announce=False) print() code = 0 printM('Test results:') for i in T.TEST: printM('%s: %s' % (T.TEST[i][0], T.TRANS[T.TEST[i][1]])) if not T.TEST[i][1]: # if a test fails, change the system exit code to indicate an error occurred code = 1 _xit(code)
def __init__(self, sta=5, lta=30, thresh=1.6, reset=1.55, bp=False, debug=True, cha='HZ', win_ovr=False, q=False, func=None, sound=False, deconv=False, *args, **kwargs): """ Initialize the alert thread with parameters to set up the recursive STA-LTA trigger, filtering, the function that is executed upon trigger activation, and the channel used for listening. :param float sta: short term average (STA) duration in seconds :param float lta: long term average (LTA) duration in seconds :param float thresh: threshold for STA/LTA trigger :type bp: :py:class:`bool` or :py:class:`list` :param bp: bandpass filter parameters :param func func: threshold for STA/LTA trigger :param bool debug: threshold for STA/LTA trigger :param str cha: listening channel (defaults to [S,E]HZ) """ super().__init__() self.sender = 'Alert' self.alive = True if q: self.queue = q else: printM('ERROR: no queue passed to consumer! Thread will exit now!', self.sender) sys.stdout.flush() sys.exit() self.default_ch = 'HZ' self.sta = sta self.lta = lta self.thresh = thresh self.reset = reset self.func = func self.win_ovr = win_ovr self.debug = debug self.args = args self.kwargs = kwargs self.raw = RS.Stream() self.stream = RS.Stream() cha = self.default_ch if (cha == 'all') else cha self.cha = cha if isinstance(cha, str) else cha[0] self.sps = RS.sps self.inv = RS.inv self.stalta = np.ndarray(1) self.maxstalta = 0 self.deconv = deconv if (deconv == 'ACC') or (deconv == 'VEL') or ( deconv == 'DISP') else False if self.deconv and RS.inv: deconv = deconv.upper() self.units = 'Acceleration (m/s$^2$)' if (self.deconv == 'ACC') else False self.units = 'Velocity (m/s)' if (self.deconv == 'VEL') else self.units self.units = 'Displacement (m)' if (self.deconv == 'DISP') else self.units printM('Signal deconvolution set to %s' % (self.deconv), self.sender) else: self.units = 'Voltage counts' self.deconv = False printM('Alert stream units are %s' % (self.units), self.sender) self.alarm = False self.exceed = False self.sound = sound if bp: self.freqmin = bp[0] self.freqmax = bp[1] self.freq = 0 if (bp[0] <= 0) and (bp[1] >= (self.sps / 2)): self.filt = False elif (bp[0] > 0) and (bp[1] >= (self.sps / 2)): self.filt = 'highpass' self.freq = bp[0] desc = 'low corner %s' % (bp[0]) elif (bp[0] <= 0) and (bp[1] <= (self.sps / 2)): self.filt = 'lowpass' self.freq = bp[1] else: self.filt = 'bandpass' else: self.filt = False if self.cha not in str(RS.chns): printM( 'ERROR: Could not find channel %s in list of channels! Please correct and restart.' % self.cha, self.sender) sys.exit(2) if (os.name in 'nt') and (not callable(self.func)) and (not self.win_ovr): printM( 'ERROR: Using Windows with custom alert code! Your code MUST have UNIX/Mac newline characters!' ) printM( ' Please use a conversion tool like dos2unix to convert line endings' ) printM( ' (https://en.wikipedia.org/wiki/Unix2dos) to make your code file' ) printM(' readable to the Python interpreter.') printM( ' Once you have done that, please set "win_override" to true' ) printM(' in the settings file.') printM( ' (see also footnote [1] on this page: https://docs.python.org/3/library/functions.html#id2)' ) printM('THREAD EXITING, please correct and restart!', self.sender) sys.exit(2) else: pass listen_ch = '?%s' % self.cha printM( 'Starting Alert trigger with sta=%ss, lta=%ss, and threshold=%s on channel=%s' % (self.sta, self.lta, self.thresh, listen_ch), self.sender) if self.filt == 'bandpass': printM( 'Alert stream will be %s filtered from %s to %s Hz' % (self.filt, self.freqmin, self.freqmax), self.sender) elif self.filt in ('lowpass', 'highpass'): modifier = 'below' if self.filt in 'lowpass' else 'above' printM( 'Alert stream will be %s filtered %s %s Hz' % (self.filt, modifier, self.freq), self.sender)
def __init__(self, q, cha='all', seconds=30, spectrogram=True, fullscreen=False, kiosk=False, deconv=False, screencap=False, alert=True): """ Initialize the plot process. """ super().__init__() self.sender = 'Plot' self.alive = True self.alarm = False # don't touch this self.alarm_reset = False # don't touch this if MPL == False: sys.stdout.flush() sys.exit() if QT == False: printW( 'Running on %s machine, using Tk instead of Qt' % (platform.machine()), self.sender) self.queue = q self.master_queue = None # careful with this, this goes directly to the master consumer. gets set by main thread. self.stream = rs.Stream() self.raw = rs.Stream() self.stn = rs.stn self.net = rs.net self.chans = [] helpers.set_channels(self, cha) printM('Plotting %s channels: %s' % (len(self.chans), self.chans), self.sender) self.totchns = rs.numchns self.seconds = seconds self.pkts_in_period = rs.tr * rs.numchns * self.seconds # theoretical number of packets received in self.seconds self.spectrogram = spectrogram self._set_deconv(deconv) self.per_lap = 0.9 self.fullscreen = fullscreen self.kiosk = kiosk self.num_chans = len(self.chans) self.delay = rs.tr if (self.spectrogram) else 1 self.delay = 0.5 if (self.chans == ['SHZ']) else self.delay self.screencap = screencap self.save_timer = 0 self.save_pct = 0.7 self.save = [] self.events = 0 self.event_text = ' - detected events: 0' if alert else '' self.last_event = [] self.last_event_str = False # plot stuff self.bgcolor = '#202530' # background self.fgcolor = '0.8' # axis and label color self.linecolor = '#c28285' # seismogram color printM('Starting.', self.sender)
def __init__(self, cha='all', q=False, seconds=30, spectrogram=False, fullscreen=False, kiosk=False, qt=qt, deconv=False, screencap=False, alert=False): """ Initialize the plot process """ super().__init__() self.sender = 'Plot' self.alive = True self.alarm = False if mpl == False: sys.stdout.flush() sys.exit() if qt == False: printM( 'WARNING: Running on %s machine, using Tk instead of Qt' % (platform.machine()), self.sender) if q: self.queue = q else: printM('ERROR: no queue passed to consumer! Thread will exit now!', self.sender) sys.stdout.flush() sys.exit() printM('Starting.', self.sender) self.stream = RS.Stream() self.raw = RS.Stream() self.stn = RS.stn self.net = RS.net self.chans = [] cha = RS.chns if (cha == 'all') else cha cha = list(cha) if isinstance(cha, str) else cha l = RS.chns for c in l: n = 0 for uch in cha: if (uch.upper() in c) and (c not in str(self.chans)): self.chans.append(c) n += 1 if len(self.chans) < 1: self.chans = RS.chns printM('Plotting channels: %s' % self.chans, self.sender) self.totchns = RS.numchns self.seconds = seconds self.pkts_in_period = RS.tr * RS.numchns * self.seconds # theoretical number of packets received in self.seconds self.spectrogram = spectrogram self.deconv = deconv if (deconv == 'ACC') or (deconv == 'VEL') or ( deconv == 'DISP') or (deconv == 'CHAN') else False if self.deconv and RS.inv: deconv = deconv.upper() if self.deconv in 'ACC': self.units = 'Acceleration' self.unit = 'm/s$^2$' if self.deconv in 'VEL': self.units = 'Velocity' self.unit = 'm/s' if self.deconv in 'DISP': self.units = 'Displacement' self.unit = 'm' if self.deconv in 'CHAN': self.units = 'channel-specific' self.unit = 'counts' printM('Signal deconvolution set to %s' % (self.deconv), self.sender) else: self.units = 'Voltage counts' self.unit = ' counts' self.deconv = False printM('Seismogram units are %s' % (self.units), self.sender) self.per_lap = 0.9 self.fullscreen = fullscreen self.kiosk = kiosk self.qt = qt self.num_chans = len(self.chans) self.delay = RS.tr if (self.spectrogram) else 1 self.screencap = screencap self.save_timer = 0 self.save_pct = 0.7 self.save = [] self.events = 0 self.event_text = ' - detected events: 0' if alert else '' self.last_event = [] self.last_event_str = False # plot stuff self.bgcolor = '#202530' # background self.fgcolor = '0.8' # axis and label color self.linecolor = '#c28285' # seismogram color self.figimage = False