def test_get_tr_data(serial_mock, raw): sw = SpotWave(serial_mock) lines = [ b"TRAI = 1 T=43686000 NS=13\n", b"TRAI=2 T=43686983 NS=27\n", b"\n", ] data = [np.arange(samples, dtype=np.int16) for samples in (13, 27)] binary_data = [arr.tobytes() for arr in data] serial_mock.readline.side_effect = lines serial_mock.read.side_effect = binary_data tr_data = sw.get_tr_data(raw=raw) assert tr_data[0].trai == 1 assert tr_data[0].time == pytest.approx(43686000 / 2e6) assert tr_data[0].samples == 13 assert tr_data[0].raw == raw if raw: assert_allclose(tr_data[0].data, data[0]) else: assert_allclose(tr_data[0].data, data[0] * ADC_TO_VOLTS) assert tr_data[1].trai == 2 assert tr_data[1].time == pytest.approx(43686983 / 2e6) assert tr_data[1].samples == 27 assert tr_data[1].raw == raw if raw: assert_allclose(tr_data[1].data, data[1]) else: assert_allclose(tr_data[1].data, data[1] * ADC_TO_VOLTS)
def main(): port = SpotWave.discover()[0] with SpotWave(port) as sw: # apply settings sw.set_continuous_mode(True) sw.set_cct(0) sw.set_status_interval(0) sw.set_tr_enabled(True) sw.set_tr_decimation(4) # 2 MHz / 4 = 500 kHz sw.set_ddt(100_000) # 100 ms * 500 kHz = 50.000 samples sw.set_filter(50e3, 200e3, 4) # 50-200 kHz bandpass # show settings print("Settings:") for key, value in asdict(sw.get_setup()).items(): print(f"- {key}: {value}") print() for record in sw.stream(): if isinstance(record, TRRecord): y = record.data y_max = np.max(y) # visualize max amplitude with "level meter" cols = int(80 * y_max / 0.05) # 50 mV input range print(f"{y_max:<8f} V: " + "#" * cols + "-" * (80 - cols), end="\r") elif isinstance(record, AERecord): ...
def main(basename: str, seconds_per_file: float): def get_filename(): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") return f"{basename}_{timestamp}.wav" port = SpotWave.discover()[0] print(port) with SpotWave(port) as sw: sw.set_datetime() sw.set_continuous_mode(True) sw.set_cct(0) sw.set_status_interval(0) sw.set_tr_enabled(True) sw.set_tr_decimation(1) # 2 MHz sw.set_ddt(10_000) # 10 ms sw.set_filter(None, None) # deactivate IIR filter setup = sw.get_setup() samplerate = sw.CLOCK / setup.tr_decimation chunks_per_file = int(seconds_per_file / setup.ddt_seconds) def async_write(): chunks = chunks_per_file # create on first data while trqueue: try: tr = trqueue.get(timeout=0.1) except: continue if chunks >= chunks_per_file: logger.info(f"{chunks_per_file} chunks acquired") writer = WavWriter(get_filename(), samplerate) chunks = 0 writer.write(tr.data) chunks += 1 print("Write finished") last_t = 0 missed = 0 trqueue = queue.SimpleQueue() threading.Thread(target=async_write).start() try: for record in sw.stream( raw=True): # return ADC values with enabled raw flag if isinstance(record, TRRecord): trqueue.put(record) elif isinstance(record, AERecord): if record.trai == 0 or record.flags > 0: missed += 1 if missed > 0 and time.monotonic() - last_t > 1: logger.warning(f"Missed {missed} record(s)") missed = 0 last_t = time.monotonic() finally: trqueue = None # flag to stop
def sw(): devices = SpotWave.discover() if not devices: raise RuntimeError( "No spotWave devices found. Please connect a device to run the system tests" ) with SpotWave(devices[0]) as sw: sw.set_datetime() # set current date/time sw.clear_buffer() yield sw
def test_get_data(serial_mock, samples, raw): sw = SpotWave(serial_mock) mock_data = (2**15 * np.random.randn(samples)).astype(np.int16) serial_mock.read.return_value = mock_data.tobytes() data = sw.get_data(samples, raw=raw) serial_mock.write.assert_called_with(f"get_data b {samples}\n".encode()) serial_mock.read.assert_called_with(samples * 2) if raw: assert_allclose(data, mock_data) else: assert_allclose(data, mock_data * ADC_TO_VOLTS)
def main(): port = SpotWave.discover()[0] with SpotWave(port) as sw: sw.set_continuous_mode(False) # -> hit-based sw.set_cct(0) # disable pulser sw.set_ddt(10_000) # 10.000 µs sw.set_status_interval(2) # generate status data every 2 seconds sw.set_threshold(1000) # 1000 µV = 60 dB(AE) sw.set_tr_enabled(True) # enable transient data recording sw.set_tr_pretrigger(200) # 200 pre-trigger samples sw.set_tr_postduration(0) # 0 post-duration samples sw.set_filter(100e3, 450e3, 4) # 100-450 kHz bandpass for record in merge_ae_tr_records(sw.stream()): print(record)
def main(): ports = SpotWave.discover() print(f"Discovered spotWave devices: {ports}") port = ports[0] with SpotWave(port) as sw: sw.set_datetime() sw.set_cct(0) # disable cct/pulser sw.set_continuous_mode(True) # enable continous mode sw.set_ddt(100_000) # 100 ms block size sw.set_filter(highpass=50e3, lowpass=300e3, order=4) # 50-300 kHz bandpass sw.set_status_interval(0) # disable status data sw.set_tr_enabled(False) # disable transient data for record in sw.stream(): # compute RMS from energy (in eu = 1e-14 V²s) and duration (in seconds) rms_volts = math.sqrt(record.energy / 1e14 / record.duration) print(f"RMS: {1e6 * rms_volts:0.2f} µV")
def test_get_info(serial_mock): sw = SpotWave(serial_mock) response = [ b"hw_id = 0019003A3438511539373231\n", b"fw_version=00.21\n", b"input_range=94 dBAE\n", ] serial_mock.readlines.return_value = response info = sw.get_info() serial_mock.write.assert_called_with(b"get_info\n") assert info.hardware_id == "0019003A3438511539373231" assert info.firmware_version == "00.21" assert info.input_range_decibel == 94 # empty response serial_mock.readlines.return_value = [] with pytest.raises(RuntimeError): sw.get_info()
def main(): port = SpotWave.discover()[0] # prepare plot plt.ion() _, ax = plt.subplots(figsize=(10, 3), tight_layout=True) with SpotWave(port) as sw: sw.set_cct(1, sync=True) sw.set_filter(90e3, 150e3, 4) # 90-150 kHz bandpass while True: data = sw.get_data(2048) # read snapshot -> trigger pulser t = np.arange(len(data)) / sw.CLOCK # create time axis ax.clear() ax.plot(t * 1e6, data * 1e6) ax.set_xlabel("Time [µs]") ax.set_ylabel("Amplitude [µV]") plt.pause(1)
def test_get_ae_data(serial_mock): sw = SpotWave(serial_mock) response = [ b"2\n", b"S temp=27 T = 2010240 A=21 R=502689 D=2000000 C=0 E=38849818 TRAI=0 flags=0\n", b"H temp=27 T=3044759 A=3557 R=24 D=819 C=31 E=518280026 TRAI=1 flags=0\n", ] serial_mock.readline.side_effect = response ae_data = sw.get_ae_data() ADC_TO_EU = ADC_TO_VOLTS**2 * 1e14 / 2e6 # status record s = ae_data[0] assert s.type_ == "S" assert s.time == pytest.approx(2010240 / 2e6) assert s.amplitude == pytest.approx(21 * ADC_TO_VOLTS) assert s.rise_time == pytest.approx(502689 / 2e6) assert s.duration == pytest.approx(2000000 / 2e6) assert s.counts == 0 assert s.energy == pytest.approx(38849818 * ADC_TO_EU) assert s.trai == 0 assert s.flags == 0 # hit record h = ae_data[1] assert h.type_ == "H" assert h.time == pytest.approx(3044759 / 2e6) assert h.amplitude == pytest.approx(3557 * ADC_TO_VOLTS) assert h.rise_time == pytest.approx(24 / 2e6) assert h.duration == pytest.approx(819 / 2e6) assert h.counts == 31 assert h.energy == pytest.approx(518280026 * ADC_TO_EU) assert h.trai == 1 assert h.flags == 0
def test_get_status(serial_mock): sw = SpotWave(serial_mock) response = [ b"temp=24 \xc2\xb0C\n", b"acq_enabled=0\n", b"log_enabled=0\n", b"log_data_usage=13 %\n", b"date=2020-12-17 15:11:42.17\n", ] serial_mock.readlines.return_value = response status = sw.get_status() serial_mock.write.assert_called_with(b"get_status\n") assert status.temperature == 24 assert status.acq_enabled == False assert status.log_enabled == False assert status.log_data_usage == 13 assert status.datetime == datetime(2020, 12, 17, 15, 11, 42, 170_000) # empty response serial_mock.readlines.return_value = [] with pytest.raises(RuntimeError): sw.get_status()
def test_get_setup(serial_mock): sw = SpotWave(serial_mock) response = [ b"acq_enabled=1\n", b"log_enabled=0\n", b"adc2uv=1.74\n", b"cct=-0.5 s\n", b"filter=10.5-350 kHz, order 4\n", b"cont=0\n", b"thr=3162.5 uV\n", b"ddt=250 us\n", b"dummy line without value", b" status_interval = 1000 ms ", b"tr_enabled=1\n", b"tr_decimation=2\n", b"tr_pre_trig=100\n", b"tr_post_dur=100\n", b"tr_max_samples=2097152\n", ] serial_mock.readlines.return_value = response setup = sw.get_setup() serial_mock.write.assert_called_with(b"get_setup\n") assert setup == Setup( acq_enabled=True, cont_enabled=False, log_enabled=False, adc_to_volts=1.74e-6, threshold_volts=3162.5e-6, ddt_seconds=250e-6, status_interval_seconds=1, filter_highpass_hz=10.5e3, filter_lowpass_hz=350e3, filter_order=4, tr_enabled=1, tr_decimation=2, tr_pretrigger_samples=100, tr_postduration_samples=100, cct_seconds=-0.5, ) # test special filter outputs response[4] = b"filter=none-350 kHz, order 4\n" serial_mock.readlines.return_value = response setup = sw.get_setup() assert setup.filter_highpass_hz == None assert setup.filter_lowpass_hz == 350_000 assert setup.filter_order == 4 response[4] = b"filter=10.5-none kHz, order 4\n" serial_mock.readlines.return_value = response setup = sw.get_setup() assert setup.filter_highpass_hz == 10_500 assert setup.filter_lowpass_hz == None assert setup.filter_order == 4 response[4] = b"filter=none-none kHz, order 0\n" serial_mock.readlines.return_value = response setup = sw.get_setup() assert setup.filter_highpass_hz == None assert setup.filter_lowpass_hz == None assert setup.filter_order == 0 # empty response serial_mock.readlines.return_value = [] with pytest.raises(RuntimeError): sw.get_setup()
def test_init_invalid_type(): with pytest.raises(ValueError): SpotWave(123)
def test_init_port(): with pytest.raises(SerialException): SpotWave("invalid_port_id")
def test_init_serial(serial_mock): sw = SpotWave(serial_mock) assert sw._ser == serial_mock # pylint: disable=protected-access serial_mock.open.assert_called()
def test_commands_without_response(serial_mock): sw = SpotWave(serial_mock) def assert_write(expected): serial_mock.write.assert_called_with(expected) sw.set_continuous_mode(True) assert_write(b"set_acq cont 1\n") sw.set_ddt(400) assert_write(b"set_acq ddt 400\n") sw.set_status_interval(2.2) assert_write(b"set_acq status_interval 2200\n") sw.set_tr_enabled(True) assert_write(b"set_acq tr_enabled 1\n") sw.set_tr_decimation(10) assert_write(b"set_acq tr_decimation 10\n") sw.set_tr_pretrigger(200) assert_write(b"set_acq tr_pre_trig 200\n") sw.set_tr_postduration(0) assert_write(b"set_acq tr_post_dur 0\n") sw.set_cct(0.1, sync=False) assert_write(b"set_cct 0.1\n") sw.set_cct(-0.1, sync=False) assert_write(b"set_cct -0.1\n") sw.set_cct(0.1, sync=True) assert_write(b"set_cct -0.1\n") sw.set_filter(highpass=100_000, lowpass=300_000, order=6) assert_write(b"set_filter 100.0 300.0 6\n") sw.set_datetime(datetime(2020, 12, 16, 17, 55, 13)) assert_write(b"set_datetime 2020-12-16 17:55:13\n") sw.set_datetime() # datetime.now() -> frozen time assert_write(b"set_datetime 2022-11-11 00:00:00\n") sw.set_threshold(100) assert_write(b"set_acq thr 100\n") sw.start_acquisition() assert_write(b"set_acq enabled 1\n") sw.stop_acquisition() assert_write(b"set_acq enabled 0\n")