Scattered stuff from Silas during Dissertation
This commit is contained in:
@@ -198,44 +198,65 @@ classdef Signal
|
||||
end
|
||||
|
||||
%% Add signals from one signal to another, the first object will sustain
|
||||
function Sum = plus(X,y)
|
||||
|
||||
if isa(y,'Signal')
|
||||
Sum = X;
|
||||
Sum.signal = X.signal + y.signal;
|
||||
elseif isnumeric(y)
|
||||
Sum = X;
|
||||
Sum.signal = X.signal + y;
|
||||
end
|
||||
|
||||
end
|
||||
function Sum = plus(X,y)
|
||||
|
||||
if isa(X,'Signal') && isa(y,'Signal')
|
||||
Sum = X;
|
||||
Sum.signal = X.signal + y.signal;
|
||||
elseif isa(X,'Signal') && isnumeric(y)
|
||||
Sum = X;
|
||||
Sum.signal = X.signal + y;
|
||||
elseif isnumeric(X) && isa(y,'Signal')
|
||||
Sum = y;
|
||||
Sum.signal = X + y.signal;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Add signals from one signal to another, the first object will sustain
|
||||
function Diff = minus(X,y)
|
||||
|
||||
if isa(y,'Signal')
|
||||
Diff = X;
|
||||
Diff.signal = X.signal - y.signal;
|
||||
elseif isnumeric(y)
|
||||
Diff = X;
|
||||
Diff.signal = X.signal - y;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Product = times(X,y)
|
||||
|
||||
if isa(y,'Signal')
|
||||
Product = X;
|
||||
Product.signal = X.signal .* y.signal;
|
||||
elseif isnumeric(y)
|
||||
Product = X;
|
||||
Product.signal = X.signal .* y;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Display length
|
||||
function Diff = minus(X,y)
|
||||
|
||||
if isa(X,'Signal') && isa(y,'Signal')
|
||||
Diff = X;
|
||||
Diff.signal = X.signal - y.signal;
|
||||
elseif isa(X,'Signal') && isnumeric(y)
|
||||
Diff = X;
|
||||
Diff.signal = X.signal - y;
|
||||
elseif isnumeric(X) && isa(y,'Signal')
|
||||
Diff = y;
|
||||
Diff.signal = X - y.signal;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Product = times(X,y)
|
||||
|
||||
if isa(X,'Signal') && isa(y,'Signal')
|
||||
Product = X;
|
||||
Product.signal = X.signal .* y.signal;
|
||||
elseif isa(X,'Signal') && isnumeric(y)
|
||||
Product = X;
|
||||
Product.signal = X.signal .* y;
|
||||
elseif isnumeric(X) && isa(y,'Signal')
|
||||
Product = y;
|
||||
Product.signal = X .* y.signal;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Product = mtimes(X,y)
|
||||
|
||||
if (isa(X,'Signal') && isnumeric(y) && isscalar(y)) || ...
|
||||
(isnumeric(X) && isscalar(X) && isa(y,'Signal'))
|
||||
Product = times(X,y);
|
||||
else
|
||||
error('Signal:mtimes:UnsupportedOperands', ...
|
||||
'Use element-wise .* for Signal multiplication, or scalar * Signal for scaling.');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Display length
|
||||
function return_length = length(obj)
|
||||
%METHOD1 Summary of this method goes here
|
||||
% Detailed explanation goes here
|
||||
@@ -325,7 +346,8 @@ classdef Signal
|
||||
|
||||
else
|
||||
|
||||
obj.signal = resample(obj.signal,options.fs_out,options.fs_in,options.n,options.beta);
|
||||
[p, q] = rat(options.fs_out / options.fs_in);
|
||||
obj.signal = resample(obj.signal,p,q,options.n,options.beta);
|
||||
|
||||
desc = ['resample signal from ', num2str(options.fs_in*1e-9), ' GHz to ', num2str(options.fs_out*1e-9), ' GHz' ];
|
||||
|
||||
@@ -344,16 +366,17 @@ classdef Signal
|
||||
obj
|
||||
options.fignum = 2025
|
||||
options.displayname = "";
|
||||
options.color = [];
|
||||
options.linestyle = '-';
|
||||
options.normalizeToNyquist = 0;
|
||||
options.normalizeToSamplingRate = 0;
|
||||
options.addDCoffset = 0;
|
||||
options.normalizeToDC = 0;
|
||||
options.normalizeTo0dB = 0;
|
||||
options.show_onesided = false;
|
||||
options.max_num_lines = []; % Leave empty or omit to disable line rotation
|
||||
options.fft_length = [];
|
||||
options.color = [];
|
||||
options.linestyle = '-';
|
||||
options.HandleVisibility (1,1) string {mustBeMember(options.HandleVisibility, ["on","off"])} = "on";
|
||||
options.normalizeToNyquist = 0;
|
||||
options.normalizeToSamplingRate = 0;
|
||||
options.addDCoffset = 0;
|
||||
options.normalizeToDC = 0;
|
||||
options.normalizeTo0dB = 0;
|
||||
options.show_onesided = false;
|
||||
options.max_num_lines = []; % Leave empty or omit to disable line rotation
|
||||
options.fft_length = [];
|
||||
% --- NEW options ---
|
||||
options.useWavelengthAxis (1,1) logical = false % plot x-axis in wavelength
|
||||
options.lambda0_nm (1,1) double = 1310 % center wavelength [nm]
|
||||
@@ -364,23 +387,23 @@ classdef Signal
|
||||
end
|
||||
|
||||
|
||||
useSamplingRateAxis = options.normalizeToSamplingRate ~= 0;
|
||||
useRadPerSampleAxis = options.normalizeToNyquist ~= 0 && ~useSamplingRateAxis;
|
||||
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
[p_lin,f_Hz] = pwelch(obj.signal, hanning(options.fft_length), ...
|
||||
options.fft_length/2, options.fft_length, ...
|
||||
obj.fs, "centered", "power", "mean");
|
||||
f_GHz = f_Hz*1e-9; % keep frequency vector for frequency axis
|
||||
else
|
||||
[p_lin,f_rad] = pwelch(obj.signal, hanning(options.fft_length), ...
|
||||
options.fft_length/2, options.fft_length, ...
|
||||
"centered", "power", "mean");
|
||||
% In normalized modes, pwelch returns rad/sample centered on 0.
|
||||
% Divide by 2*pi for the f/fs axis where Nyquist is 0.5.
|
||||
end
|
||||
useSamplingRateAxis = options.normalizeToSamplingRate ~= 0;
|
||||
useRadPerSampleAxis = options.normalizeToNyquist ~= 0 && ~useSamplingRateAxis;
|
||||
|
||||
% p_lin = movmean(p_lin,4);
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
[p_lin,f_Hz] = pwelch(obj.signal, hanning(options.fft_length), ...
|
||||
options.fft_length/2, options.fft_length, ...
|
||||
obj.fs, "centered", "power", "mean");
|
||||
f_GHz = f_Hz*1e-9; % keep frequency vector for frequency axis
|
||||
else
|
||||
[p_lin,f_rad] = pwelch(obj.signal, hanning(options.fft_length), ...
|
||||
options.fft_length/2, options.fft_length, ...
|
||||
"centered", "power", "mean");
|
||||
% In normalized modes, pwelch returns rad/sample centered on 0.
|
||||
% Divide by 2*pi for the f/fs axis where Nyquist is 0.5.
|
||||
end
|
||||
|
||||
p_lin = movmean(p_lin,10);
|
||||
|
||||
if options.normalizeTo0dB
|
||||
p_lin = p_lin ./ max(p_lin);
|
||||
@@ -392,67 +415,67 @@ classdef Signal
|
||||
end
|
||||
|
||||
% --- If requested, build wavelength axis from frequency offset ---
|
||||
if options.useWavelengthAxis && ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
c = physconst('LightSpeed'); % [m/s]
|
||||
lambda0_m = options.lambda0_nm*1e-9; % center wavelength [m]
|
||||
f_c = c / lambda0_m; % carrier frequency [Hz]
|
||||
if options.useWavelengthAxis && ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
c = physconst('LightSpeed'); % [m/s]
|
||||
lambda0_m = options.lambda0_nm*1e-9; % center wavelength [m]
|
||||
f_c = c / lambda0_m; % carrier frequency [Hz]
|
||||
|
||||
% exact mapping
|
||||
f_abs = f_c + f_Hz; % absolute frequency [Hz]
|
||||
lambda_m = c ./ f_abs; % wavelength [m]
|
||||
lambda_nm = lambda_m * 1e9; % wavelength [nm]
|
||||
|
||||
% assign axis
|
||||
x_vec = lambda_nm(:);
|
||||
x_label = "Wavelength [nm]";
|
||||
dc_axis = f_Hz;
|
||||
|
||||
% Sort to ensure axis is ascending
|
||||
[x_vec, sortIdx] = sort(x_vec, 'ascend');
|
||||
p_dbm = p_dbm(sortIdx, :);
|
||||
dc_axis = dc_axis(sortIdx);
|
||||
else
|
||||
% Frequency or normalized axes
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
x_vec = f_GHz;
|
||||
x_label = "Frequency in GHz";
|
||||
dc_axis = f_GHz;
|
||||
elseif useSamplingRateAxis
|
||||
x_vec = f_rad ./ (2*pi);
|
||||
x_label = "Normalized Frequency f/fs";
|
||||
dc_axis = x_vec;
|
||||
else
|
||||
x_vec = f_rad; % normalized frequency in rad/sample
|
||||
x_label = "Normalized Frequency [rad/sample]";
|
||||
dc_axis = x_vec;
|
||||
end
|
||||
end
|
||||
|
||||
if options.show_onesided
|
||||
keep_idx = dc_axis >= 0;
|
||||
x_vec = x_vec(keep_idx);
|
||||
dc_axis = dc_axis(keep_idx);
|
||||
p_dbm = p_dbm(keep_idx, :);
|
||||
end
|
||||
|
||||
figure(options.fignum);
|
||||
ax = gca;
|
||||
% assign axis
|
||||
x_vec = lambda_nm(:);
|
||||
x_label = "Wavelength [nm]";
|
||||
dc_axis = f_Hz;
|
||||
|
||||
% Sort to ensure axis is ascending
|
||||
[x_vec, sortIdx] = sort(x_vec, 'ascend');
|
||||
p_dbm = p_dbm(sortIdx, :);
|
||||
dc_axis = dc_axis(sortIdx);
|
||||
else
|
||||
% Frequency or normalized axes
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
x_vec = f_GHz;
|
||||
x_label = "Frequency in GHz";
|
||||
dc_axis = f_GHz;
|
||||
elseif useSamplingRateAxis
|
||||
x_vec = f_rad ./ (2*pi);
|
||||
x_label = "Normalized Frequency f/fs";
|
||||
dc_axis = x_vec;
|
||||
else
|
||||
x_vec = f_rad; % normalized frequency in rad/sample
|
||||
x_label = "Normalized Frequency [rad/sample]";
|
||||
dc_axis = x_vec;
|
||||
end
|
||||
end
|
||||
|
||||
if options.show_onesided
|
||||
keep_idx = dc_axis >= 0;
|
||||
x_vec = x_vec(keep_idx);
|
||||
dc_axis = dc_axis(keep_idx);
|
||||
p_dbm = p_dbm(keep_idx, :);
|
||||
end
|
||||
|
||||
figure(options.fignum);
|
||||
ax = gca;
|
||||
hold on
|
||||
|
||||
p_dbm = p_dbm+options.addDCoffset;
|
||||
|
||||
if options.normalizeToDC
|
||||
[~,min_idx]=min(abs(dc_axis));
|
||||
pow_at_dc = p_dbm(min_idx);
|
||||
p_dbm = p_dbm-pow_at_dc;
|
||||
end
|
||||
p_dbm = p_dbm+options.addDCoffset;
|
||||
|
||||
if options.normalizeToDC
|
||||
[~,min_idx]=min(abs(dc_axis));
|
||||
pow_at_dc = p_dbm(min_idx);
|
||||
p_dbm = p_dbm-pow_at_dc;
|
||||
end
|
||||
% p_dbm = movmean(p_dbm,10);
|
||||
|
||||
for s = 1:min(size(p_dbm))
|
||||
if isempty(options.color)
|
||||
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1);
|
||||
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1, 'LineStyle', options.linestyle, 'HandleVisibility', options.HandleVisibility);
|
||||
else
|
||||
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1, 'Color', options.color,'LineStyle',options.linestyle);
|
||||
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1, 'Color', options.color,'LineStyle',options.linestyle, 'HandleVisibility', options.HandleVisibility);
|
||||
end
|
||||
end
|
||||
|
||||
@@ -468,27 +491,27 @@ classdef Signal
|
||||
% Axis labels and limits
|
||||
xlabel(x_label);
|
||||
|
||||
if options.useWavelengthAxis && ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
xlim([min(x_vec) max(x_vec)]);
|
||||
else
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
% Keep your existing freq handling (you can fine-tune as needed)
|
||||
% xlim([-128 128]); % example for 256 GSa/s if desired
|
||||
xlim([min(x_vec) max(x_vec)]);
|
||||
elseif useSamplingRateAxis
|
||||
if options.show_onesided
|
||||
xlim([0, 0.5]);
|
||||
else
|
||||
xlim([-0.5, 0.5]);
|
||||
end
|
||||
else
|
||||
if options.show_onesided
|
||||
xlim([0, pi]);
|
||||
else
|
||||
xlim([-pi, pi]);
|
||||
end
|
||||
end
|
||||
end
|
||||
if options.useWavelengthAxis && ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
xlim([min(x_vec) max(x_vec)]);
|
||||
else
|
||||
if ~useRadPerSampleAxis && ~useSamplingRateAxis
|
||||
% Keep your existing freq handling (you can fine-tune as needed)
|
||||
% xlim([-128 128]); % example for 256 GSa/s if desired
|
||||
xlim([min(x_vec) max(x_vec)]);
|
||||
elseif useSamplingRateAxis
|
||||
if options.show_onesided
|
||||
xlim([0, 0.5]);
|
||||
else
|
||||
xlim([-0.5, 0.5]);
|
||||
end
|
||||
else
|
||||
if options.show_onesided
|
||||
xlim([0, pi]);
|
||||
else
|
||||
xlim([-pi, pi]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ylabel(ylab);
|
||||
|
||||
@@ -1007,15 +1030,47 @@ classdef Signal
|
||||
elseif mode == 1
|
||||
% generate eye diagram using histogram
|
||||
|
||||
maxA = max(sig(100:end-100))*1.3;
|
||||
minA = min(sig(100:end-100))*1.3;
|
||||
finite_eye = eye_mat(isfinite(eye_mat));
|
||||
if isempty(finite_eye)
|
||||
finite_eye = sig(isfinite(sig));
|
||||
end
|
||||
amp_min = min(finite_eye);
|
||||
amp_max = max(finite_eye);
|
||||
amp_center = (amp_max + amp_min) / 2;
|
||||
amp_span = amp_max - amp_min;
|
||||
if amp_span == 0
|
||||
amp_span = max(abs(amp_center),1);
|
||||
end
|
||||
amp_margin = 0.08 * amp_span;
|
||||
maxA = amp_center + amp_span/2 + amp_margin;
|
||||
minA = amp_center - amp_span/2 - amp_margin;
|
||||
if ~isa(obj,'Opticalsignal') && minA < 0 && maxA > 0
|
||||
targetStep = max(abs([minA maxA])) / 2;
|
||||
if targetStep > 0
|
||||
stepMagnitude = 10^floor(log10(targetStep));
|
||||
normalizedStep = targetStep / stepMagnitude;
|
||||
if normalizedStep <= 1
|
||||
tickStep = stepMagnitude;
|
||||
elseif normalizedStep <= 2
|
||||
tickStep = 2 * stepMagnitude;
|
||||
elseif normalizedStep <= 5
|
||||
tickStep = 5 * stepMagnitude;
|
||||
else
|
||||
tickStep = 10 * stepMagnitude;
|
||||
end
|
||||
axisLimit = 2 * tickStep;
|
||||
maxA = axisLimit;
|
||||
minA = -axisLimit;
|
||||
end
|
||||
end
|
||||
|
||||
% maxA = 0.12;
|
||||
% minA = -0.08;
|
||||
|
||||
difference= maxA-minA;
|
||||
|
||||
data_ind_y=round((eye_mat-minA)/difference*(histpoints-1)) +1;
|
||||
data_ind_y=round((eye_mat-minA)/difference*(histpoints-1)) +1;
|
||||
data_ind_y = min(max(data_ind_y,1),histpoints);
|
||||
|
||||
for n=1:size(data_ind_y,1)
|
||||
nn=histcounts(data_ind_y(n,:),1:histpoints+1);
|
||||
@@ -1041,22 +1096,22 @@ classdef Signal
|
||||
if isa(obj,'Opticalsignal')
|
||||
title(['Optical Eye ',options.displayname])
|
||||
ylabel("Power in mW");
|
||||
y_tickstring = string(linspace(maxA.*1e3,minA.*1e3,6));
|
||||
min_ = min(abs(obj.signal(100:end-100)).^2);
|
||||
max_ = abs(max(obj.signal(100:end-100)).^2);
|
||||
elseif isa(obj,'Electricalsignal')
|
||||
title(['Electrical Eye ',options.displayname])
|
||||
ylabel("Voltage in V");
|
||||
y_tickstring = string(linspace(maxA,minA,6));
|
||||
min_ = min(obj.signal(100:end-100));
|
||||
max_ = abs(max(obj.signal(100:end-100)));
|
||||
else
|
||||
title(['Digital Eye ',options.displayname])
|
||||
ylabel("Digital Signal Amplitude");
|
||||
y_tickstring = string(linspace(maxA,minA,6));
|
||||
min_ = min(obj.signal(100:end-100));
|
||||
max_ = abs(max(obj.signal(100:end-100)));
|
||||
end
|
||||
yTickValues = linspace(maxA.*1e3,minA.*1e3,5);
|
||||
min_ = min(abs(obj.signal(100:end-100)).^2);
|
||||
max_ = abs(max(obj.signal(100:end-100)).^2);
|
||||
elseif isa(obj,'Electricalsignal')
|
||||
title(['Electrical Eye ',options.displayname])
|
||||
ylabel("Voltage in V");
|
||||
yTickValues = linspace(maxA,minA,5);
|
||||
min_ = min(obj.signal(100:end-100));
|
||||
max_ = abs(max(obj.signal(100:end-100)));
|
||||
else
|
||||
title(['Digital Eye ',options.displayname])
|
||||
ylabel("Digital Signal Amplitude");
|
||||
yTickValues = linspace(maxA,minA,5);
|
||||
min_ = min(obj.signal(100:end-100));
|
||||
max_ = abs(max(obj.signal(100:end-100)));
|
||||
end
|
||||
xlabel('Time in ps')
|
||||
|
||||
|
||||
@@ -1094,7 +1149,14 @@ classdef Signal
|
||||
hist_interest_smoth = smooth(hist_interest,20);
|
||||
a = scatter(hist_interest_smoth+posxall,1:length(hist_interest_smoth),4,'.','MarkerEdgeColor','red');
|
||||
|
||||
[pk,loc] = findpeaks(hist_interest_smoth,"MinPeakDistance",10,"NPeaks",M,"MinPeakHeight",30,"MinPeakProminence",10);
|
||||
minPeakDistance = max(10, floor(histpoints / (2*M)));
|
||||
minPeakProminence = max(3, 0.05 * max(hist_interest_smoth));
|
||||
[pk,loc] = findpeaks(hist_interest_smoth, ...
|
||||
"MinPeakDistance",minPeakDistance, ...
|
||||
"NPeaks",M, ...
|
||||
"MinPeakProminence",minPeakProminence, ...
|
||||
"SortStr","descend");
|
||||
loc = sort(loc);
|
||||
|
||||
scatter(posxall,loc,'red','Marker','x','LineWidth',2);
|
||||
|
||||
@@ -1177,13 +1239,14 @@ classdef Signal
|
||||
end
|
||||
|
||||
|
||||
yticks(linspace(0,histpoints,6));
|
||||
y_tickstring = sprintfc('%.2f', y_tickstring);
|
||||
yticklabels(y_tickstring);
|
||||
|
||||
xticks(linspace(0,histpoints_horizontal,6))
|
||||
x_tickstring = sprintfc('%.2f', linspace(0, 2/fsym, 8) .* 1e12);
|
||||
xticklabels(x_tickstring);
|
||||
yTickPositions = linspace(1,histpoints,numel(yTickValues));
|
||||
yticks(yTickPositions);
|
||||
yticklabels(sprintfc('%.2f', yTickValues));
|
||||
|
||||
xTickValues = linspace(0, 2/fsym, 6) .* 1e12;
|
||||
xticks(linspace(1,histpoints_horizontal,numel(xTickValues)))
|
||||
x_tickstring = sprintfc('%.2f', xTickValues);
|
||||
xticklabels(x_tickstring);
|
||||
|
||||
%
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user