2021-02-22 17:43:48 +08:00
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plot
|
|
|
|
from scipy import signal, constants
|
2021-03-09 12:40:51 +08:00
|
|
|
import argparse
|
|
|
|
import os
|
2021-10-06 14:58:52 +08:00
|
|
|
import datetime
|
2021-03-09 12:40:51 +08:00
|
|
|
|
2021-02-22 17:43:48 +08:00
|
|
|
|
|
|
|
def rp_raw_to_numpy(rp_raw):
|
|
|
|
# Convert raw buffer strings to numpy arrays
|
|
|
|
buff_string = rp_raw.split(',')
|
|
|
|
return np.array(list(map(float, buff_string)))
|
|
|
|
|
2021-03-09 12:40:51 +08:00
|
|
|
|
|
|
|
RP_IP_ADDRS = {
|
|
|
|
"creotech-1": "192.168.1.104",
|
|
|
|
"creotech-2": "192.168.1.105",
|
2021-05-13 10:27:16 +08:00
|
|
|
"mlabs-1": "rp-f05cc9",
|
|
|
|
"mlabs-2": "rp-f0612e",
|
2021-03-09 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-02-22 17:43:48 +08:00
|
|
|
def main():
|
2021-03-09 12:40:51 +08:00
|
|
|
parser = argparse.ArgumentParser(description="Data plotting tool for Sayma DAC/TTL")
|
|
|
|
parser.add_argument("dir", help="output directory", type=str)
|
|
|
|
parser.add_argument("rps", metavar="NAME:CHANNEL",
|
|
|
|
help="input <CHANNEL> of the RedPitaya at <NAME> where data is collected; "
|
|
|
|
"CHANNEL must be 1 or 2; "
|
|
|
|
"NAME must be any of: " + " ".join(list(RP_IP_ADDRS.keys())),
|
|
|
|
type=str, nargs=2)
|
2021-10-06 14:49:52 +08:00
|
|
|
parser.add_argument("--log",
|
|
|
|
help="path of the log file where the measurement record will be appended",
|
|
|
|
type=str)
|
2021-10-06 12:26:20 +08:00
|
|
|
parser.add_argument("--noplot",
|
|
|
|
help="do not show data plot, which is blocking until the GUI is closed",
|
|
|
|
action="store_true")
|
2021-03-09 12:40:51 +08:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
# Must only compare 2 data
|
|
|
|
name, channel = args.rps[0].split(':')
|
|
|
|
y1_filename = 'rp_{}_y{}_raw.bin'.format(name, channel)
|
|
|
|
name, channel = args.rps[1].split(':')
|
|
|
|
y2_filename = 'rp_{}_y{}_raw.bin'.format(name, channel)
|
|
|
|
if y1_filename == y2_filename:
|
|
|
|
raise ValueError("Both files are the same.")
|
2021-02-22 17:43:48 +08:00
|
|
|
|
2021-03-09 12:40:51 +08:00
|
|
|
with open(os.path.join(args.dir, y1_filename), 'rb') as f:
|
2021-10-06 14:58:52 +08:00
|
|
|
y1_now_iso, y1_raw = [l.decode('utf-8') for l in f.readlines()]
|
2021-03-09 12:40:51 +08:00
|
|
|
with open(os.path.join(args.dir, y2_filename), 'rb') as f:
|
2021-10-06 14:58:52 +08:00
|
|
|
y2_now_iso, y2_raw = [l.decode('utf-8') for l in f.readlines()]
|
2021-02-22 17:43:48 +08:00
|
|
|
if None in [y1_raw, y2_raw]:
|
|
|
|
raise IOError("Raw RP string files cannot be opened.")
|
2021-10-06 14:58:52 +08:00
|
|
|
if y1_now_iso != y2_now_iso:
|
|
|
|
raise ValueError("Timestamps of raw RP files are not identical.")
|
|
|
|
now_iso = y1_now_iso.rstrip()
|
|
|
|
print("Reading raw RP data collected at {}.".format(now_iso))
|
2021-02-22 17:43:48 +08:00
|
|
|
|
|
|
|
y1 = rp_raw_to_numpy(y1_raw)
|
|
|
|
y2 = rp_raw_to_numpy(y2_raw)
|
|
|
|
|
2021-03-15 15:26:36 +08:00
|
|
|
# Define t as an array of timestamps (in seconds) for each sample
|
|
|
|
# (Note that RedPitaya's oscilloscope has a sampling rate @ 125MHz)
|
2021-02-22 17:43:48 +08:00
|
|
|
t = np.arange(y1.shape[0])/125e6
|
2021-03-09 12:40:51 +08:00
|
|
|
# Generate matrix Y by having arrays y1 and y2 as 2 rows
|
2021-02-22 17:43:48 +08:00
|
|
|
y = np.c_[y1, y2].T
|
2021-03-15 15:26:36 +08:00
|
|
|
# Element-wise multiply an array of cos(2pi*9e6*t) with each row in Y;
|
|
|
|
# Then, downsample the array by 10 as Z
|
2021-02-22 17:43:48 +08:00
|
|
|
z = signal.decimate(y*np.exp(1j*2*np.pi*9e6*t), q=10, ftype="fir", zero_phase=True)[:, 10:]
|
2021-03-09 12:40:51 +08:00
|
|
|
# Downsample Z by 10 again.
|
2021-02-22 17:43:48 +08:00
|
|
|
z = signal.decimate(z, q=10, ftype="fir", zero_phase=True)[:, 10:]
|
2021-03-15 15:26:36 +08:00
|
|
|
# Element-wise multiply Z[0] with the conjugate of Z[1] to get the phase difference (i.e. angle(z0) - angle(z1)), and use the mean value.
|
2021-02-22 17:43:48 +08:00
|
|
|
angle = np.angle(np.mean(z[0]*z[1].conj()))
|
|
|
|
|
2021-10-06 14:49:52 +08:00
|
|
|
# Append the phase difference to the log file
|
|
|
|
log = args.log
|
|
|
|
if log is not None:
|
|
|
|
with open(log, 'a') as f:
|
|
|
|
f.write("{}\t{}\n".format(now_iso, angle))
|
|
|
|
print("Phase measurement record appended to log: {}".format(log))
|
|
|
|
# Print the phase difference
|
2021-02-22 17:43:48 +08:00
|
|
|
print(angle)
|
|
|
|
|
2021-10-06 12:26:20 +08:00
|
|
|
if not args.noplot:
|
|
|
|
# Normalize y1 and y2 for plotting
|
|
|
|
y1 /= abs(y1).max()
|
|
|
|
y2 /= abs(y2).max()
|
|
|
|
plot.plot(y1)
|
|
|
|
plot.plot(y2)
|
|
|
|
plot.show()
|
2021-02-22 17:43:48 +08:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|