def get_lock_position_from_autolock_instructions( spectrum, description, time_scale, initial_spectrum, final_wait_time ): summed = sum_up_spectrum(spectrum) summed_xscaled = get_diff_at_time_scale(summed, time_scale) description_idx = 0 last_detected_peak = 0 for idx, value in enumerate(summed_xscaled): wait_for, current_threshold = description[description_idx] if ( sign(value) == sign(current_threshold) and abs(value) >= abs(current_threshold) and idx - last_detected_peak > wait_for ): description_idx += 1 last_detected_peak = idx if description_idx == len(description): # this was the last peak! return idx + final_wait_time raise LockPositionNotFound()
def test_sum_diff_calculator2(): spectrum = pfd_spectrum(0)[0] delay = 60 out_fpga = [] def tb(dut): yield dut.restart.eq(0) yield dut.delay_value.eq(delay) yield dut.writing_data_now.eq(1) for point in spectrum: yield dut.input.eq(int(point)) yield out = yield dut.output out_fpga.append(out) dut = SumDiffCalculator(14, 8192) run_simulation(dut, tb(dut), vcd_name="experimental_autolock_sum_diff_calculator.vcd") summed = sum_up_spectrum(spectrum) summed_xscaled = get_diff_at_time_scale(summed, delay) # plt.plot(out_fpga[1:]) # plt.plot(summed_xscaled) # plt.show() assert out_fpga[1:] == summed_xscaled[:-1]
def test_compare_sum_diff_calculator_implementations(debug=False): for iteration in (0, 1): if iteration == 1: spectrum, target_idxs = atomic_spectrum(0) time_scale = get_time_scale(spectrum, target_idxs) else: spectrum = [1 * i for i in range(1000)] time_scale = 5 summed = sum_up_spectrum(spectrum) summed_xscaled = get_diff_at_time_scale(summed, time_scale) summed_fpga = {"summed_xscaled": [], "summed": []} def tb(dut): yield dut.request_lock.eq(1) yield dut.at_start.eq(1) yield dut.writing_data_now.eq(1) yield dut.at_start.eq(0) yield dut.time_scale.storage.eq(int(time_scale)) for i in range(len(spectrum)): yield dut.input.eq(int(spectrum[i])) sum_diff = yield dut.sum_diff_calculator.output sum = yield dut.sum_diff_calculator.sum_value summed_fpga["summed_xscaled"].append(sum_diff) summed_fpga["summed"].append(sum) yield dut = RobustAutolock() run_simulation( dut, tb(dut), vcd_name="experimental_autolock_fpga_lock_position_finder.vcd") if debug: plt.plot(summed[:-FPGA_DELAY_SUMDIFF_CALCULATOR], label="normal calculation") plt.plot( summed_fpga["summed"][FPGA_DELAY_SUMDIFF_CALCULATOR:], label="FPGA calculation", ) plt.legend() plt.show() plt.plot( summed_xscaled[:-FPGA_DELAY_SUMDIFF_CALCULATOR], label="normal calculation", ) plt.plot( summed_fpga["summed_xscaled"][FPGA_DELAY_SUMDIFF_CALCULATOR:], label="FPGA calculation", ) plt.legend() plt.show() assert (summed[:-FPGA_DELAY_SUMDIFF_CALCULATOR] == summed_fpga["summed"][FPGA_DELAY_SUMDIFF_CALCULATOR:]) assert (summed_xscaled[:-FPGA_DELAY_SUMDIFF_CALCULATOR] == summed_fpga["summed_xscaled"][FPGA_DELAY_SUMDIFF_CALCULATOR:])
def calculate_autolock_instructions(spectra_with_jitter, target_idxs): spectra, crop_left = crop_spectra_to_same_view(spectra_with_jitter) target_idxs = [idx - crop_left for idx in target_idxs] time_scale = int( round(np.mean([get_time_scale(spectrum, target_idxs) for spectrum in spectra])) ) print("x scale is %d" % time_scale) prepared_spectrum = get_diff_at_time_scale(sum_up_spectrum(spectra[0]), time_scale) peaks = get_all_peaks(prepared_spectrum, target_idxs) y_scale = peaks[0][1] lock_regions = [get_lock_region(spectrum, target_idxs) for spectrum in spectra] for tolerance_factor in [0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5]: print("try out tolerance", tolerance_factor) peaks_filtered = [ (peak_position, peak_height * tolerance_factor) for peak_position, peak_height in peaks ] # it is important to do the filtering that happens here after the previous # line as the previous line shrinks the values peaks_filtered = [ (peak_position, peak_height) for peak_position, peak_height in peaks_filtered if abs(peak_height) > abs(y_scale * (1 - tolerance_factor)) ] # now find out how much we have to wait in the end (because we detect the peak # too early because our threshold is too low) target_peak_described_height = peaks_filtered[0][1] target_peak_idx = get_target_peak(prepared_spectrum, target_idxs) current_idx = target_peak_idx while True: current_idx -= 1 if np.abs(prepared_spectrum[current_idx]) < np.abs( target_peak_described_height ): break final_wait_time = target_peak_idx - current_idx print("final wait time is %d samples" % final_wait_time) description = [] last_peak_position = 0 for peak_position, peak_height in list(reversed(peaks_filtered)): # TODO: this .9 factor is very arbitrary. description.append( (int(0.9 * (peak_position - last_peak_position)), int(peak_height)) ) last_peak_position = peak_position # test whether description works fine for every recorded spectrum does_work = True for spectrum, lock_region in zip(spectra, lock_regions): try: lock_position = get_lock_position_from_autolock_instructions( spectrum, description, time_scale, spectra[0], final_wait_time ) if not lock_region[0] <= lock_position <= lock_region[1]: raise LockPositionNotFound() except LockPositionNotFound: does_work = False if does_work: break else: raise UnableToFindDescription() if len(description) > AUTOLOCK_MAX_N_INSTRUCTIONS: print("warning: autolock description too long. Cropping!", len(description)) description = description[-AUTOLOCK_MAX_N_INSTRUCTIONS:] print("description is", description) return description, final_wait_time, time_scale