def analyze(P: dict): tx = loadbin(P['txfn'], P['txfs'], tlim=(0, P['tm'])) if P['verbose']: plotraw(tx, None, P['txfs']) print( f'Using {P["pri"]*1000} ms PRI for {P["tm"]*1e6} us chirp, with {P["Nchirp"]} pulses incoherently integrated' ) # %% NrxPRI = int(P['pri'] * rxfs) # samples in a PRI Lrx = NrxPRI * P['Nchirp'] if P['rxfn'] is not None: Nsampfile = P['rxfn'].stat().st_size // LSAMP Tfile = Nsampfile / P['rxfs'] print(P['rxfn'], f'is {Tfile:0.1f} seconds long') isamp = range(0, Nsampfile, Lrx) else: print('simulation') isamp = range(0, Nsim * Lrx, Lrx) t = np.array(isamp) / P['txfs'] # elapsed time seconds if P['t0'] is not None: t += P['t0'] # %% if P['outfn']: print('writing', outfn) with h5py.File(outfn, 'w') as f: f.create_dataset('Rxy', shape=(t.size, int(NrxPRI * P['resample'])), dtype=np.complex128, chunks=True, compression='gzip') f['t'] = t f['lags'] = np.arange(-NrxPRI // 2, NrxPRI // 2) f['t0'] = P['t0'] f['cmd'] = ' '.join(sys.argv) f['fs'] = P['txfs'] for k, (i, j) in enumerate(zip(isamp, isamp[1:])): if P['rxfn'] is None: rx = 0.05 * tx + 0.1 * tx.max() * ( np.random.randn(P['Nchirp'], tx.size) + 1j * np.random.randn(P['Nchirp'], tx.size)) rx = rx.ravel() else: rx = loadbin(P['rxfn'], P['rxfs'], tlim=P['t0'], isamp=(i, j)) lags = procchunk(rx, tx, P) if outfn: with h5py.File(outfn, 'a') as f: f['Rxy'][k, :] = lags print( f'processing t={t[k]:.2f} sec., {t[k]/Tfile*100:.3f} % complete.\r', end="")
def analyze(P: dict): tx = loadbin(P["txfn"], P["txfs"], tlim=(0, P["tm"])) if P["verbose"]: plotraw(tx, None, P["txfs"]) print( f'Using {P["pri"]*1000} ms PRI for {P["tm"]*1e6} us chirp, with {P["Nchirp"]} pulses incoherently integrated' ) # %% NrxPRI = int(P["pri"] * rxfs) # samples in a PRI Lrx = NrxPRI * P["Nchirp"] if P["rxfn"] is not None: Nsampfile = P["rxfn"].stat().st_size // LSAMP Tfile = Nsampfile / P["rxfs"] print(P["rxfn"], f"is {Tfile:0.1f} seconds long") isamp = range(0, Nsampfile, Lrx) else: print("simulation") isamp = range(0, Nsim * Lrx, Lrx) t = np.array(isamp) / P["txfs"] # elapsed time seconds if P["t0"] is not None: t += P["t0"] # %% if P["outfn"]: print("writing", outfn) with h5py.File(outfn, "w") as f: f.create_dataset( "Rxy", shape=(t.size, int(NrxPRI * P["resample"])), dtype=np.complex128, chunks=True, compression="gzip", ) f["t"] = t f["lags"] = np.arange(-NrxPRI // 2, NrxPRI // 2) f["t0"] = P["t0"] f["cmd"] = " ".join(sys.argv) f["fs"] = P["txfs"] for k, (i, j) in enumerate(zip(isamp, isamp[1:])): if P["rxfn"] is None: rx = 0.05 * tx + 0.1 * tx.max() * ( np.random.randn(P["Nchirp"], tx.size) + 1j * np.random.randn(P["Nchirp"], tx.size)) rx = rx.ravel() else: rx = loadbin(P["rxfn"], P["rxfs"], tlim=P["t0"], isamp=(i, j)) lags = procchunk(rx, tx, P) if outfn: with h5py.File(outfn, "a") as f: f["Rxy"][k, :] = lags print( f"processing t={t[k]:.2f} sec., {t[k]/Tfile*100:.3f} % complete.\r", end="")
def analyze(P:dict): tx = loadbin(P['txfn'], P['txfs'], tlim=(0,P['tm'])) if P['verbose']: plotraw(tx, None, P['txfs']) print(f'Using {P["pri"]*1000} ms PRI for {P["tm"]*1e6} us chirp, with {P["Nchirp"]} pulses incoherently integrated') # %% NrxPRI = int(P['pri']*rxfs) # samples in a PRI Lrx = NrxPRI*P['Nchirp'] if P['rxfn'] is not None: Nsampfile = P['rxfn'].stat().st_size//LSAMP Tfile = Nsampfile / P['rxfs'] print(P['rxfn'], f'is {Tfile:0.1f} seconds long') isamp = range(0, Nsampfile, Lrx) else: print('simulation') isamp = range(0, Nsim*Lrx, Lrx) t = np.array(isamp) / P['txfs'] # elapsed time seconds if P['t0'] is not None: t += P['t0'] # %% if P['outfn']: print('writing',outfn) with h5py.File(outfn,'w') as f: f.create_dataset('Rxy',shape=(t.size, int(NrxPRI*P['resample'])), dtype=np.complex128,chunks=True,compression='gzip') f['t'] = t f['lags'] = np.arange(-NrxPRI//2,NrxPRI//2) f['t0'] = P['t0'] f['cmd'] = ' '.join(sys.argv) f['fs'] = P['txfs'] for k,(i,j) in enumerate(zip(isamp,isamp[1:])): if P['rxfn'] is None: rx = 0.05*tx + 0.1*tx.max()*(np.random.randn(P['Nchirp'],tx.size) + 1j*np.random.randn(P['Nchirp'],tx.size)) rx = rx.ravel() else: rx = loadbin(P['rxfn'], P['rxfs'], tlim=P['t0'], isamp=(i, j)) lags = procchunk(rx, tx, P) if outfn: with h5py.File(outfn,'a') as f: f['Rxy'][k,:] = lags print(f'processing t={t[k]:.2f} sec., {t[k]/Tfile*100:.3f} % complete.\r',end="")
def cwproc(fn, fsaudio, tlim, fc, ax=None): fn = Path(p.fn).expanduser() fs = int(p.fs) # to allow 100e3 on command line fsaudio = int(fsaudio) dat, t = loadbin(fn, fs, tlim) dat = freq_translate(dat, fc, fs) dat = downsample(dat, fs, fsaudio) # %% play sound if 0: # not for when looping, it will try to play dozens of files at once. playaudio(dat, fsaudio, p.outwav) #%% plots if 0 and dat.size < 500e3: # plots will crash if too many points if ax is None: ax = figure().gca() ax.plot(t + tlim[0], dat.real[:]) ax.set_title(f"{fn.name} Fs: {fs} Hz t={tlim[0]}..{tlim[1]}") ax.set_xlabel("time [sec]") ax.set_ylabel("amplitude") f, tt, Sxx, Sp = spec(dat, fsaudio, p.flim, tlim, be, vlim=p.vlim, zpad=p.zeropad) # %% analysis Abin = np.empty(be.size - 1) for i in range(len(be) - 1): ibin = (f < be[i + 1]) & (f > be[i]) Abin[i] = Sp[ibin].sum() return Abin
def cwproc(fn, fsaudio, tlim, fc, ax=None): fn=Path(p.fn).expanduser() fs = int(p.fs) # to allow 100e3 on command line fsaudio = int(fsaudio) dat,t = loadbin(fn, fs, tlim) dat = freq_translate(dat,fc,fs) dat = downsample(dat,fs,fsaudio) # %% play sound if 0: # not for when looping, it will try to play dozens of files at once. playaudio(dat, fsaudio, p.outwav) #%% plots if 0 and dat.size < 500e3: # plots will crash if too many points if ax is None: ax = figure().gca() ax.plot(t + tlim[0], dat.real[:]) ax.set_title(f'{fn.name} Fs: {fs} Hz t={tlim[0]}..{tlim[1]}') ax.set_xlabel('time [sec]') ax.set_ylabel('amplitude') f,tt,Sxx,Sp = spec(dat, fsaudio, p.flim, tlim, be, vlim=p.vlim, zpad=p.zeropad) # %% analysis Abin = np.empty(be.size-1) for i in range(len(be)-1): ibin = (f < be[i+1]) & (f > be[i]) Abin[i] = Sp[ibin].sum() return Abin
def dodemod(rx, P: dict): aud = None fs = P["rxfs"] if P["demod"] == "chirp": tx = loadbin(P["txfn"], P["txfs"]) if tx is None: warnings.warn("simulated chirp reception") tx = rx rx = 0.05 * rx + 0.1 * rx.max() * (np.random.randn(rx.size) + 1j * np.random.randn(rx.size)) txfs = fs else: rx = scipy.signal.resample_poly(rx, UP, DOWN) fs = txfs = P["txfs"] txsec = tx.size / txfs # length of TX in seconds if P["pri"] is None: pri = txsec print( f'Using {pri*1000} ms PRI and {P["Npulse"]} pulses incoherently integrated' ) # %% integration NrxPRI = int(fs * pri) # Number of RX samples per PRI NrxStack = rx.size // NrxPRI # number of complete PRIs received in this data Nint = NrxStack // P["Npulse"] # Number of steps we'll take iterating Nextract = ( P["Npulse"] * NrxPRI ) # total number of samples to extract (in general part of one PRI is discarded after numerous PRIs) ax = None for i in range(Nint): ci = slice(i * Nextract, (i + 1) * Nextract) rxint = rx[ci].reshape((NrxPRI, P["Npulse"])).mean(axis=1) Rxy = np.correlate(tx, rxint, "full") ax = plotxcor(Rxy, txfs, ax) draw() pause(0.5) elif P["demod"] == "am": aud = am_demod(P["again"] * rx, fs, fsaudio, P["fc"], p.audiobw, frumble=p.frumble, verbose=True) elif P["demod"] == "ssb": aud = ssb_demod(P["again"] * rx, fs, fsaudio, P["fc"], p.audiobw, verbose=True) return aud, fs
def main(): p = ArgumentParser() p.add_argument('fn', help='binary raw IQ capture SDR file to analyze') p.add_argument('fs', help='sampling frequency [Hz]', type=int) p.add_argument('-fc', help='baseband tunding freq [Hz]', type=float) p.add_argument('-t', '--tlim', help='start stop increment [seconds] to load', type=float, nargs=2, default=(0., None)) p.add_argument('-v', '--verbose', action='store_true') P = p.parse_args() fn = Path(P.fn).expanduser() assert isinstance(P.fs, (float, int)) fs = int(P.fs) # %% sig = loadbin(fn, fs, P.tlim) # %% m = fm_demod(sig, fs, fsaudio, P.fc, 75e3, P.verbose) playaudio(m, fsaudio) show()
def getrx(P: dict): rx = loadbin(P["rxfn"], P["rxfs"], P["tlim"]) plotraw(rx, None, P["rxfs"]) return rx
help='subspace method (esprit,rootmusic)', default='esprit') p.add_argument('--noest', help='skip estimation (just plot) for debugging', action='store_true') p.add_argument( '--python', help='force Python subspace (disable Fortran) for debugging', action='store_true') p.add_argument('--all', help='show all tone freq, including feedthrough', action='store_true') p = p.parse_args() fs = int(p.fs) if p.fn is None: #simulation rx, t = cwsim(fs, p.Np, p.T) else: # load data file rx = loadbin(p.fn, fs, p.tlim) rx = freq_translate(rx, p.fx0, fs) rx = downsample(rx, fs, fsaudio) #%% estimate beat frequency if not p.noest: fb_est, conf = cw_est(rx, fsaudio, p.Nt, p.method, p.python, p.all) print('estimated beat frequencies', fb_est) print('sigma', conf) #%% plot cwplot(fb_est, rx.squeeze(), t, fsaudio, p.fn) show()
def getrx(P: dict): rx = loadbin(P['rxfn'], P['rxfs'], P['tlim']) plotraw(rx, None, P['rxfs']) return rx
p = ArgumentParser() p.add_argument('fn',help='data file .bin to analyze',nargs='?',default=None) p.add_argument('-fs',help='baseband sampling frequency [Hz]',type=float,default=16e3) p.add_argument('-Np',help='number of pulses to integrate',type=int,default=1) p.add_argument('-fx0',help='frequency translation center frequency',type=float) p.add_argument('-Nt',help='number of tones to find',type=int,default=2) p.add_argument('-T',help='pulse length (seconds)',type=float,default=0.1) p.add_argument('-t','--tlim',help='time to analyze e.g. -t 3 4 means process from t=3 to t=4 seconds',nargs=2,type=float ) p.add_argument('-m','--method',help='subspace method (esprit,rootmusic)',default='esprit') p.add_argument('--noest',help='skip estimation (just plot) for debugging',action='store_true') p.add_argument('--python',help='force Python subspace (disable Fortran) for debugging',action='store_true') p.add_argument('--all',help='show all tone freq, including feedthrough',action='store_true') p = p.parse_args() fs = int(p.fs) if p.fn is None: #simulation rx,t = cwsim(fs, p.Np, p.T) else: # load data file rx = loadbin(p.fn, fs, p.tlim) rx = freq_translate(rx,p.fx0,fs) rx = downsample(rx, fs, fsaudio) #%% estimate beat frequency if not p.noest: fb_est,conf = cw_est(rx, fsaudio, p.Nt, p.method, p.python, p.all) print('estimated beat frequencies',fb_est) print('sigma',conf) #%% plot cwplot(fb_est,rx.squeeze(),t, fsaudio, p.fn) show()