Theory stuff from sials work pc; minor stuff here and there
This commit is contained in:
@@ -22,7 +22,7 @@ classdef Photodiode
|
|||||||
options.responsivity = 1;
|
options.responsivity = 1;
|
||||||
options.dark_current = 0;
|
options.dark_current = 0;
|
||||||
options.temperature = 20;
|
options.temperature = 20;
|
||||||
options.nep = 0; %(Moveit IMDD Standard: 1.8e-11) noise effective power in pA/sqrt(Hz); usually between 10-20 pA; see J.Leibrich Diss/ S. Pachnicke Slides
|
options.nep = 0; %(Moveit IMDD Standard: 1.8e-11 == current noise density in A/sqrt(Hz)! ); usually between 10-20 pA/sqrt(Hz); see J.Leibrich Diss/ S. Pachnicke Slides
|
||||||
options.randomkey = 1;
|
options.randomkey = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -72,9 +72,16 @@ classdef Photodiode
|
|||||||
yout = yout + shot_noise;
|
yout = yout + shot_noise;
|
||||||
|
|
||||||
% Thermal Noise
|
% Thermal Noise
|
||||||
|
% 2026 comment: obj.nep is not the correct naming, but math-wise everything is fine!
|
||||||
|
% (2 * k * T / R ) -> A^2/Hz -> is the psd of thermal noise
|
||||||
|
% earlier: move it's 1.8e-11 is current noise density -> A/sqrt(Hz)
|
||||||
|
|
||||||
|
% power (of white process) is simple multiplication of PSD(f) and B
|
||||||
|
|
||||||
|
|
||||||
% NEP is noise equivalent power, see Dissertation j. Leibrich
|
% NEP is noise equivalent power, see Dissertation j. Leibrich
|
||||||
% P. 121 or Stephan Pachnicke Optical Comm. Lecture Slides
|
% P. 121 or Stephan Pachnicke Optical Comm. Lecture Slides
|
||||||
if obj.nep == 0
|
if obj.nep == 0 %
|
||||||
nep_squared = (2 * k * T / R ) ; %squared
|
nep_squared = (2 * k * T / R ) ; %squared
|
||||||
else
|
else
|
||||||
nep_squared = obj.nep^2;
|
nep_squared = obj.nep^2;
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ classdef DBHandler < handle
|
|||||||
options.port = 3306;
|
options.port = 3306;
|
||||||
options.user = "silas";
|
options.user = "silas";
|
||||||
options.password = "silas";
|
options.password = "silas";
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
% Assign values to class properties based on input arguments
|
% Assign values to class properties based on input arguments
|
||||||
|
|||||||
@@ -23,12 +23,16 @@ D_lin = S0 .* (lambda_nm - lambda0_nm);
|
|||||||
|
|
||||||
% plot
|
% plot
|
||||||
figure('Color','w'); hold on;
|
figure('Color','w'); hold on;
|
||||||
cols = cbrewer2('paired',4);
|
cols = [0.6510 0.8078 0.8902;...
|
||||||
plot(lambda_nm, D_lin(1,:), '-', 'LineWidth',2, 'DisplayName','Linearized model','Color',[cols(1,:)]);
|
0.1216 0.4706 0.7059;...
|
||||||
plot(lambda_nm, D_exact(1,:), 'LineWidth',2, 'DisplayName',sprintf('Exact model'),'Color',[cols(2,:)]);
|
0.6980 0.8745 0.5412;...
|
||||||
|
0.2000 0.6275 0.1725];
|
||||||
|
|
||||||
plot(lambda_nm, D_lin(2,:), '-', 'LineWidth',2, 'HandleVisibility','off','Color',[cols(3,:)]);
|
% plot(lambda_nm, D_lin(1,:), '-', 'LineWidth',2, 'DisplayName','Linearized model','Color',[cols(1,:)]);
|
||||||
plot(lambda_nm, D_exact(2,:), 'LineWidth',2, 'HandleVisibility','off','Color',[cols(4,:)]);
|
plot(lambda_nm, D_exact(1,:), 'LineWidth',2, 'DisplayName',sprintf('S_0 = 0.07'),'Color',[cols(2,:)]);
|
||||||
|
|
||||||
|
% plot(lambda_nm, D_lin(2,:), '-', 'LineWidth',2, 'HandleVisibility','off','Color',[cols(3,:)]);
|
||||||
|
plot(lambda_nm, D_exact(2,:), 'LineWidth',2, 'HandleVisibility','on', 'DisplayName',sprintf('S_0 = 0.09'),'Color',[cols(4,:)]);
|
||||||
|
|
||||||
|
|
||||||
xlabel('Wavelength $\lambda$ [nm]','Interpreter','latex');
|
xlabel('Wavelength $\lambda$ [nm]','Interpreter','latex');
|
||||||
@@ -36,4 +40,7 @@ ylabel('D($\lambda$) [ps/(nm km)]','Interpreter','latex');
|
|||||||
title('Chromatic Dispersion Around the ZDW');
|
title('Chromatic Dispersion Around the ZDW');
|
||||||
legend('Location','best');
|
legend('Location','best');
|
||||||
grid on; box on;
|
grid on; box on;
|
||||||
|
xlim([min(lambda_nm) max(lambda_nm)])
|
||||||
|
ylim([-5 5]);
|
||||||
|
|
||||||
|
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\dispersion\dispersion')
|
||||||
|
|||||||
124
Functions/Theory/Dissertation/photo_diode.m
Normal file
124
Functions/Theory/Dissertation/photo_diode.m
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
%% ============================================================
|
||||||
|
% SNR vs Optical Input Power (dBm) — Shot vs Thermal vs Combined
|
||||||
|
% - Generate optical field as sine with target RMS power (verified)
|
||||||
|
% - Magnitude-square detection -> optical power
|
||||||
|
% - Photocurrent = Rd * P
|
||||||
|
% - Add shot noise + thermal noise (white, PSD-based)
|
||||||
|
% - Compute SNR for: shot-only, thermal-only, combined
|
||||||
|
% ============================================================
|
||||||
|
|
||||||
|
|
||||||
|
% Constants
|
||||||
|
k = Constant.Boltzmann;
|
||||||
|
q = Constant.ElementaryCharge;
|
||||||
|
|
||||||
|
% Receiver / PD parameters
|
||||||
|
T = 20 + 273.15; % K
|
||||||
|
R = 50; % Ohm (front-end/load)
|
||||||
|
Rd = 0.7; % A/W (responsivity)
|
||||||
|
Be = 100e9; % Hz (electrical noise bandwidth)
|
||||||
|
Id = 0; % A (dark current, optional)
|
||||||
|
|
||||||
|
% Sampling for time-domain demo (needs to be >> Be)
|
||||||
|
fs = 1e12; % Hz
|
||||||
|
N = 2^14; % samples
|
||||||
|
t = (0:N-1).'/fs;
|
||||||
|
|
||||||
|
% Choose an electrical tone within bandwidth (arbitrary for demo)
|
||||||
|
f0 = 10e9; % Hz
|
||||||
|
|
||||||
|
% Thermal current PSD (two-sided) and variance in Be
|
||||||
|
Si_th = 4*k*T/R; % A^2/Hz (two-sided)
|
||||||
|
sigma2_th = Si_th * Be; % A^2
|
||||||
|
sigma_th = sqrt(sigma2_th); % A_rms
|
||||||
|
|
||||||
|
% Optical input power sweep (in dBm)
|
||||||
|
P_dBm = linspace(-40, 10, 300);
|
||||||
|
P_W = 10.^((P_dBm - 30)/10); % W
|
||||||
|
|
||||||
|
% Pre-allocate results
|
||||||
|
SNR_shot_dB = zeros(size(P_dBm));
|
||||||
|
SNR_th_dB = zeros(size(P_dBm));
|
||||||
|
SNR_tot_dB = zeros(size(P_dBm));
|
||||||
|
|
||||||
|
% --- Main loop over optical input power
|
||||||
|
for ii = 1:numel(P_W)
|
||||||
|
Pavg = P_W(ii);
|
||||||
|
|
||||||
|
% Optical field with RMS power = Pavg:
|
||||||
|
% Let x(t) be the optical field amplitude such that |x|^2 has mean Pavg.
|
||||||
|
% Use a sinusoid: x(t) = A*sin(2*pi*f0*t), then mean(|x|^2)=A^2/2.
|
||||||
|
A = sqrt(2*Pavg); % -> mean(|x|^2) = Pavg
|
||||||
|
|
||||||
|
x = A * sin(2*pi*f0*t); % "optical field" (real for simplicity)
|
||||||
|
|
||||||
|
% Verify RMS/mean power numerically (optional)
|
||||||
|
P_meas = mean(abs(x).^2); % should be ~ Pavg
|
||||||
|
|
||||||
|
a = P_meas - Pavg;
|
||||||
|
assert(a<1);
|
||||||
|
|
||||||
|
% Magnitude-square detection -> optical power waveform
|
||||||
|
Popt = abs(x).^2; % W (instantaneous)
|
||||||
|
|
||||||
|
% Photocurrent waveform (includes DC + 2f0 component for this demo)
|
||||||
|
I_sig = Rd * Popt; % A
|
||||||
|
|
||||||
|
% Define "signal power" as the mean-squared photocurrent due to signal
|
||||||
|
% (for this sine-squared waveform, it's OK for a demo SNR definition)
|
||||||
|
P_sig = mean(I_sig.^2);
|
||||||
|
|
||||||
|
% -------- Shot noise (white) --------
|
||||||
|
% Two-sided PSD: Si_shot = 2*q*(I_photo + I_dark)
|
||||||
|
% For this demo, use average current to set the white-noise level:
|
||||||
|
Ibar = mean(I_sig) + Id;
|
||||||
|
Si_shot = 2*q*Ibar; % A^2/Hz
|
||||||
|
sigma2_sh = Si_shot * Be; % A^2
|
||||||
|
sigma_sh = sqrt(sigma2_sh); % A_rms
|
||||||
|
|
||||||
|
n_sh = sigma_sh * randn(N,1); % time-domain shot noise
|
||||||
|
|
||||||
|
% -------- Thermal noise (white Gaussian) --------
|
||||||
|
n_th = sigma_th * randn(N,1); % time-domain thermal noise
|
||||||
|
|
||||||
|
% Noise powers (mean-square) in time domain
|
||||||
|
Pn_sh = mean(n_sh.^2);
|
||||||
|
Pn_th = mean(n_th.^2);
|
||||||
|
Pn_tot = mean((n_sh + n_th).^2); % ~ Pn_sh + Pn_th (independent)
|
||||||
|
|
||||||
|
% SNRs
|
||||||
|
SNR_shot = P_sig / Pn_sh;
|
||||||
|
SNR_th = P_sig / Pn_th;
|
||||||
|
SNR_tot = P_sig / Pn_tot;
|
||||||
|
|
||||||
|
SNR_shot_dB(ii) = 10*log10(SNR_shot);
|
||||||
|
SNR_th_dB(ii) = 10*log10(SNR_th);
|
||||||
|
SNR_tot_dB(ii) = 10*log10(SNR_tot);
|
||||||
|
|
||||||
|
% Optional sanity check (can comment out)
|
||||||
|
% if ii == 1
|
||||||
|
% fprintf('Check Pavg target/meas: %.3g W / %.3g W\n', Pavg, P_meas);
|
||||||
|
% end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Plot comparison
|
||||||
|
figure(1); clf; hold on;
|
||||||
|
plot(P_dBm, SNR_shot_dB, 'LineWidth', 1.5);
|
||||||
|
plot(P_dBm, SNR_th_dB, 'LineWidth', 1.5);
|
||||||
|
plot(P_dBm, SNR_tot_dB, 'LineWidth', 1.5);
|
||||||
|
grid on;
|
||||||
|
xlabel('Optical input power [dBm]');
|
||||||
|
ylabel('SNR [dB]');
|
||||||
|
title('SNR vs Optical Input Power: Shot vs Thermal vs Combined');
|
||||||
|
legend('Shot-noise only','Thermal-noise only','Shot + Thermal','Location','best');
|
||||||
|
|
||||||
|
% Print example at 0 dBm
|
||||||
|
[~,idx0] = min(abs(P_dBm - 0));
|
||||||
|
fprintf('At 0 dBm:\n');
|
||||||
|
fprintf(' SNR (shot only) = %.2f dB\n', SNR_shot_dB(idx0));
|
||||||
|
fprintf(' SNR (thermal only) = %.2f dB\n', SNR_th_dB(idx0));
|
||||||
|
fprintf(' SNR (combined) = %.2f dB\n', SNR_tot_dB(idx0));
|
||||||
|
|
||||||
|
% Also print NEP based on thermal PSD (constant NEP_th)
|
||||||
|
NEP_th = sqrt(Si_th)/Rd; % W/sqrt(Hz)
|
||||||
|
fprintf('Thermal NEP = %.3g W/sqrt(Hz)\n', NEP_th);
|
||||||
68
Functions/Theory/Dissertation/power_fading_gif.m
Normal file
68
Functions/Theory/Dissertation/power_fading_gif.m
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
%% ============================================================
|
||||||
|
% IM/DD Power Fading Evolution GIF (1 km -> 20 km)
|
||||||
|
% Uses the provided GifWriter (serial mode)
|
||||||
|
% ============================================================
|
||||||
|
|
||||||
|
clear; close all; clc;
|
||||||
|
|
||||||
|
%% Fiber and system parameters
|
||||||
|
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||||
|
lambda = 1275e-9; % operating wavelength [m]
|
||||||
|
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
|
||||||
|
c = physconst('lightspeed');
|
||||||
|
|
||||||
|
%% Derived quantities (length-independent)
|
||||||
|
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
|
||||||
|
D_si = D_lambda * 1e-6; % s/m^2
|
||||||
|
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
|
||||||
|
|
||||||
|
%% Frequency grid
|
||||||
|
f_max = 150e9;
|
||||||
|
f = linspace(0, f_max, 4000); % [Hz]
|
||||||
|
|
||||||
|
%% Figure setup (keep it stable for nicer GIFs)
|
||||||
|
fig = figure('Color','w');
|
||||||
|
ax = axes(fig); %#ok<LAXES>
|
||||||
|
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
|
||||||
|
xlabel(ax,'Frequency [GHz]');
|
||||||
|
ylabel(ax,'Magnitude [dB]');
|
||||||
|
ylim(ax,[-30 0]);
|
||||||
|
xlim(ax,[0 f_max/1e9]);
|
||||||
|
|
||||||
|
%% GIF writer (serial mode; simplest)
|
||||||
|
g = GifWriter('Name','power_fading_evolution', 'DelayTime',0.12, 'Parallel',false);
|
||||||
|
|
||||||
|
%% Loop: 1 km to 20 km
|
||||||
|
L = [1:20,19:-1:1];
|
||||||
|
for L_km = L
|
||||||
|
L_meter = L_km * 1e3; % [m]
|
||||||
|
|
||||||
|
% IM/DD transfer function (power fading)
|
||||||
|
phi = 2*pi^2 * b2 * f.^2 * L_meter;
|
||||||
|
H = abs(cos(phi));
|
||||||
|
HdB = 10*log10(max(H, 1e-12)); % avoid -Inf for deep notches
|
||||||
|
|
||||||
|
% Clear and redraw (stable axes)
|
||||||
|
cla(ax);
|
||||||
|
|
||||||
|
plot(ax, f/1e9, HdB, 'LineWidth', 1.8, 'Color','black');
|
||||||
|
|
||||||
|
% Analytic first-null frequency marker
|
||||||
|
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L_meter));
|
||||||
|
xline(ax, f_null/1e9, 'r--', 'LineWidth', 1.2, ...
|
||||||
|
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||||
|
'LabelOrientation','horizontal', ...
|
||||||
|
'LabelVerticalAlignment','bottom');
|
||||||
|
|
||||||
|
title(ax, sprintf('Power Fading for: %.0f km @ 1275 nm', L_km));
|
||||||
|
|
||||||
|
drawnow;
|
||||||
|
|
||||||
|
% Add frame to GIF
|
||||||
|
g.addFrame(fig);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Done
|
||||||
|
g.compile(fig.Number);
|
||||||
|
|
||||||
|
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
%% ============================================================
|
||||||
|
% IM/DD Power Fading Evolution vs Wavelength (L = 10 km)
|
||||||
|
% ============================================================
|
||||||
|
|
||||||
|
clear; close all; clc;
|
||||||
|
|
||||||
|
%% Fixed fiber parameters
|
||||||
|
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||||
|
S0 = 0.09; % dispersion slope [ps/(nm^2·km)]
|
||||||
|
L = 10e3; % fiber length FIXED [m]
|
||||||
|
c = physconst('lightspeed');
|
||||||
|
|
||||||
|
%% Frequency grid
|
||||||
|
f_max = 150e9;
|
||||||
|
f = linspace(0, f_max, 4000); % [Hz]
|
||||||
|
|
||||||
|
%% Figure setup (stable axes for clean GIF)
|
||||||
|
fig = figure('Color','w');
|
||||||
|
ax = axes(fig);
|
||||||
|
hold(ax,'on'); grid(ax,'on'); box(ax,'on');
|
||||||
|
xlabel(ax,'Frequency [GHz]');
|
||||||
|
ylabel(ax,'Magnitude [dB]');
|
||||||
|
ylim(ax,[-30 0]);
|
||||||
|
xlim(ax,[0 f_max/1e9]);
|
||||||
|
|
||||||
|
%% GIF writer
|
||||||
|
g = GifWriter('Name','power_fading_vs_wavelength', ...
|
||||||
|
'DelayTime',0.12, ...
|
||||||
|
'Parallel',false);
|
||||||
|
|
||||||
|
%% Wavelength sweep (around ZDW)
|
||||||
|
lambda_vec = linspace(1260e-9, 1360e-9, 25); % 1260–1360 nm
|
||||||
|
|
||||||
|
for k = 1:length(lambda_vec)
|
||||||
|
|
||||||
|
lambda = lambda_vec(k);
|
||||||
|
|
||||||
|
%% Dispersion for current wavelength
|
||||||
|
D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
|
||||||
|
D_si = D_lambda * 1e-6; % s/m^2
|
||||||
|
b2 = -D_si * lambda^2 / (2*pi*c); % s^2/m
|
||||||
|
|
||||||
|
%% Power fading transfer function
|
||||||
|
phi = 2*pi^2 * b2 * f.^2 * L;
|
||||||
|
H = abs(cos(phi));
|
||||||
|
HdB = 10*log10(max(H, 1e-12));
|
||||||
|
|
||||||
|
cla(ax)
|
||||||
|
plot(ax, f/1e9, HdB, 'LineWidth',1.8,'Color','black');
|
||||||
|
|
||||||
|
%% First-null frequency
|
||||||
|
if abs(D_si) > 0
|
||||||
|
f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L));
|
||||||
|
xline(ax, f_null/1e9, 'r--', 'LineWidth',1.2, ...
|
||||||
|
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||||
|
'LabelOrientation','horizontal', ...
|
||||||
|
'LabelVerticalAlignment','bottom');
|
||||||
|
end
|
||||||
|
|
||||||
|
title(ax, sprintf('Power Fading for: 10 km @ %.0f nm', lambda*1e9));
|
||||||
|
|
||||||
|
drawnow;
|
||||||
|
g.addFrame(fig);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Compile GIF
|
||||||
|
g.compile(fig.Number);
|
||||||
|
|
||||||
|
disp(fullfile(g.OutputDir, sprintf('%s_fig_%d.gif', g.Name, fig.Number)));
|
||||||
@@ -8,17 +8,16 @@ c = physconst('lightspeed');
|
|||||||
S0_si = S0 * 1e3; % s/m³
|
S0_si = S0 * 1e3; % s/m³
|
||||||
|
|
||||||
Delta_lambda = linspace(5e-9, 80e-9, 300); % [m] detuning
|
Delta_lambda = linspace(5e-9, 80e-9, 300); % [m] detuning
|
||||||
f_null_2 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L) );
|
|
||||||
L = 2e3; % m
|
|
||||||
f_null_10 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L) );
|
|
||||||
|
|
||||||
cols = cbrewer2('Paired',10);
|
cols = [0.3467 0.5360 0.6907;...
|
||||||
|
0.9153 0.2816 0.2878;...
|
||||||
|
0.4416 0.7490 0.4322];
|
||||||
figure('Color','w');hold on
|
figure('Color','w');hold on
|
||||||
cnt = 2;
|
cnt = 1;
|
||||||
for L = 10%[2,5,10]
|
for L = [2,10,40]
|
||||||
f_null_10 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L*1e3) );
|
f_null_10 = sqrt( c * 0.5 ./ (S0_si .* abs(Delta_lambda) .* lambda0.^2 .* L*1e3) );
|
||||||
plot(1310-Delta_lambda*1e9, f_null_10/1e9, 'LineWidth',2,'DisplayName',sprintf('%d km',L),'Color',cols(cnt,:));
|
plot(1310-Delta_lambda*1e9, f_null_10/1e9, 'LineWidth',2,'DisplayName',sprintf('%d km',L),'Color',cols(cnt,:));
|
||||||
cnt = cnt+2;
|
cnt = cnt+1;
|
||||||
end
|
end
|
||||||
% yticks([56,75,90,112])
|
% yticks([56,75,90,112])
|
||||||
% tickse = 1310-[7.5, 12, 17, 31.5];
|
% tickse = 1310-[7.5, 12, 17, 31.5];
|
||||||
@@ -29,4 +28,5 @@ ylabel('$F_{null}$ [GHz]');
|
|||||||
grid on; box on;
|
grid on; box on;
|
||||||
lim=1310-[5,60];
|
lim=1310-[5,60];
|
||||||
xlim([lim(2) lim(1)]);
|
xlim([lim(2) lim(1)]);
|
||||||
ylim([40,130])
|
ylim([10,130])
|
||||||
|
legend
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
%% Fiber and system parameters
|
%% Fiber and system parameters
|
||||||
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
lambda0 = 1310e-9; % zero-dispersion wavelength [m]
|
||||||
lambda = 1275e-9; % operating wavelength [m]
|
lambda = 1290e-9; % operating wavelength [m]
|
||||||
S0 = 0.09; % dispersion slope [ps/(nm²·km)]
|
S0 = 0.09; % dispersion slope [ps/(nm²·km)]
|
||||||
L = 10e3; % fiber length [m]
|
L = 10e3; % fiber length [m]
|
||||||
c = physconst('lightspeed');
|
c = physconst('lightspeed');
|
||||||
@@ -30,7 +30,7 @@ plot(f/1e9, 10*log10(H), 'LineWidth', 1.8,'Color','black');
|
|||||||
grid on; box on;
|
grid on; box on;
|
||||||
xlabel('Frequency [GHz]');
|
xlabel('Frequency [GHz]');
|
||||||
ylabel('Magnitude [dB]');
|
ylabel('Magnitude [dB]');
|
||||||
title(sprintf('IM/DD Power Fading: 10 km; 1275nm', lambda*1e9, L/1000),"Interpreter","latex");
|
% title(sprintf('IM/DD Power Fading: 10 km; 1275nm', lambda*1e9, L/1000),"Interpreter","latex");
|
||||||
ylim([-30 0]);
|
ylim([-30 0]);
|
||||||
|
|
||||||
%% Mark analytic first-null frequency
|
%% Mark analytic first-null frequency
|
||||||
@@ -38,3 +38,5 @@ f_null = sqrt(c*(0.5)/(abs(D_si)*lambda^2*L));
|
|||||||
xline(f_null/1e9, 'r--', 'LineWidth', 1.2, ...
|
xline(f_null/1e9, 'r--', 'LineWidth', 1.2, ...
|
||||||
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
'Label', sprintf('f_{null}=%.1f GHz', f_null/1e9), ...
|
||||||
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
|
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
|
||||||
|
|
||||||
|
mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\dispersion\power_fading.tikz')
|
||||||
317
Functions/plot_s_parameter.m
Normal file
317
Functions/plot_s_parameter.m
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
%% Plot S-parameters from Touchstone S2P or S4P (schema-aware, no RF Toolbox)
|
||||||
|
clear; clc;
|
||||||
|
|
||||||
|
[file,path] = uigetfile({"*.s2p;*.S2P;*.s4p;*.S4P","Touchstone (*.s2p, *.s4p)"});
|
||||||
|
if isequal(file,0); return; end
|
||||||
|
filename = fullfile(path,file);
|
||||||
|
%%
|
||||||
|
% Decide port count by extension (minimal-invasive, robust)
|
||||||
|
[~,~,ext] = fileparts(file);
|
||||||
|
ext = upper(ext);
|
||||||
|
|
||||||
|
if strcmp(ext,'.S4P')
|
||||||
|
[matrix, meta] = loads4p_schema(filename);
|
||||||
|
N = 4;
|
||||||
|
elseif strcmp(ext,'.S2P')
|
||||||
|
[matrix, meta] = loads2p(filename); % your original loader kept (below)
|
||||||
|
N = 2;
|
||||||
|
else
|
||||||
|
error("Unsupported extension: %s", ext);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Frequency in GHz
|
||||||
|
frex = matrix(:,1);
|
||||||
|
if isfield(meta,'freqScaleHz') && ~isempty(meta.freqScaleHz)
|
||||||
|
frex = frex * meta.freqScaleHz / 1e9; % convert to GHz
|
||||||
|
else
|
||||||
|
% fallback heuristic (your original)
|
||||||
|
for i = 1:numel(frex)
|
||||||
|
if frex(i) > 1e4
|
||||||
|
frex(i) = frex(i).*1e-9;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
figure(101);
|
||||||
|
hold on;
|
||||||
|
% overlay indexing: count lines already there
|
||||||
|
if N == 2
|
||||||
|
lines = numel(findall(gcf, 'type','line'))/4 + 1;
|
||||||
|
else
|
||||||
|
lines = numel(findall(gcf, 'type','line'))/16 + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
% styles (kept)
|
||||||
|
[CC, LL, MM] = ndgrid({1,2,3,4}, {'-', ':', '-.', '--'}, {'none','+', 'o', '*', 'square', 'diamond'});
|
||||||
|
combinations = [CC(:), LL(:), MM(:)];
|
||||||
|
cols = [0.3467 0.5360 0.6907
|
||||||
|
0.9153 0.2816 0.2878
|
||||||
|
0.4416 0.7490 0.4322
|
||||||
|
1.0000 0.5984 0.2000];
|
||||||
|
|
||||||
|
% -------------------- Plotting --------------------
|
||||||
|
if N == 2
|
||||||
|
heads = ["S11","S12","S22","S21"];
|
||||||
|
% matrix layout from loads2p:
|
||||||
|
% col pairs:
|
||||||
|
% 2-3 S11, 4-5 S21, 6-7 S12, 8-9 S22
|
||||||
|
colPairs = [2 3; 6 7; 8 9; 4 5]; % order matches heads above
|
||||||
|
subplots = 1;
|
||||||
|
|
||||||
|
for k = 1:4
|
||||||
|
if subplots, subplot(2,2,k); else, figure('Color','w'); end
|
||||||
|
hold on; grid on;
|
||||||
|
|
||||||
|
reCol = colPairs(k,1);
|
||||||
|
imCol = colPairs(k,2);
|
||||||
|
|
||||||
|
% S-parameter magnitude in dB: 20*log10(|S|)
|
||||||
|
response = 20*log10(abs(matrix(:,reCol) + 1i.*matrix(:,imCol)));
|
||||||
|
response = movmean(response,1);
|
||||||
|
|
||||||
|
plot(frex, response, ...
|
||||||
|
"Color", cols(combinations{lines,1},:), ...
|
||||||
|
"DisplayName", file, ...
|
||||||
|
"LineStyle", combinations{lines,2}, ...
|
||||||
|
"Marker", combinations{lines,3}, ...
|
||||||
|
"MarkerSize", 3);
|
||||||
|
|
||||||
|
if k == 2 || k == 3
|
||||||
|
ylim([-6 2]);
|
||||||
|
else
|
||||||
|
ylim([-30 2]);
|
||||||
|
end
|
||||||
|
xlim([0 100]);
|
||||||
|
title(heads(k));
|
||||||
|
xlabel('Frequency in GHz');
|
||||||
|
ylabel('|S| (dB)');
|
||||||
|
legend('Location','best');
|
||||||
|
end
|
||||||
|
sgtitle(sprintf('S-Parameters (2-port) [%s]', meta.headerLine));
|
||||||
|
|
||||||
|
elseif N == 4
|
||||||
|
% For s4p schema we plot all Sij in a 4x4 grid
|
||||||
|
% matrix layout from loads4p_schema:
|
||||||
|
% columns: 1=f, then pairs in order:
|
||||||
|
% S11,S12,S13,S14, S21..S24, S31..S34, S41..S44
|
||||||
|
subplots = 1;
|
||||||
|
|
||||||
|
for i = 1:4
|
||||||
|
for j = 1:4
|
||||||
|
sp = (i-1)*4 + j;
|
||||||
|
if subplots, subplot(4,4,sp); else, figure('Color','w'); end
|
||||||
|
hold on; grid on;
|
||||||
|
|
||||||
|
idx = (i-1)*4 + j; % 1..16 for Sij in row-major
|
||||||
|
reCol = 1 + 2*(idx-1) + 1; % after freq col
|
||||||
|
imCol = 1 + 2*(idx-1) + 2;
|
||||||
|
|
||||||
|
response = 20*log10(abs(matrix(:,reCol) + 1i.*matrix(:,imCol)));
|
||||||
|
plot(frex, response, ...
|
||||||
|
"Color", cols(combinations{lines,1},:), ...
|
||||||
|
"DisplayName", file, ...
|
||||||
|
"LineStyle", combinations{lines,2}, ...
|
||||||
|
"Marker", combinations{lines,3}, ...
|
||||||
|
"MarkerSize", 2);
|
||||||
|
|
||||||
|
xlim([0 100]);
|
||||||
|
title(sprintf("S%d%d", i, j));
|
||||||
|
set(gca,'FontSize',8);
|
||||||
|
|
||||||
|
% reduce clutter
|
||||||
|
if j ~= 1, yticklabels([]); end
|
||||||
|
if i ~= 4, xticklabels([]); end
|
||||||
|
if j == 1, ylabel('|S| (dB)'); end
|
||||||
|
if i == 4, xlabel('GHz'); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sgtitle(sprintf('S-Parameters (4-port) [%s]', meta.headerLine));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
%% ========================================================================
|
||||||
|
% Loader for S4P with the EXACT provided schema (4 lines per frequency)
|
||||||
|
% ========================================================================
|
||||||
|
function [matrix, meta] = loads4p_schema(filepath)
|
||||||
|
meta = struct();
|
||||||
|
meta.headerLine = "";
|
||||||
|
meta.freqScaleHz = []; % Hz per file unit (e.g., GHz -> 1e9)
|
||||||
|
|
||||||
|
fid = fopen(filepath,'r');
|
||||||
|
if fid < 0, error("Cannot open file: %s", filepath); end
|
||||||
|
cleaner = onCleanup(@() fclose(fid));
|
||||||
|
|
||||||
|
% Parse header: find "#"
|
||||||
|
freUnit = "";
|
||||||
|
while true
|
||||||
|
t = fgetl(fid);
|
||||||
|
if ~ischar(t), break; end
|
||||||
|
ts = strtrim(t);
|
||||||
|
if startsWith(ts,'#')
|
||||||
|
meta.headerLine = ts;
|
||||||
|
parts = split(upper(string(ts)));
|
||||||
|
if numel(parts) >= 2, freUnit = parts(2); end
|
||||||
|
|
||||||
|
switch freUnit
|
||||||
|
case "HZ", meta.freqScaleHz = 1;
|
||||||
|
case "KHZ", meta.freqScaleHz = 1e3;
|
||||||
|
case "MHZ", meta.freqScaleHz = 1e6;
|
||||||
|
case "GHZ", meta.freqScaleHz = 1e9;
|
||||||
|
otherwise, meta.freqScaleHz = [];
|
||||||
|
end
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
data = [];
|
||||||
|
|
||||||
|
while true
|
||||||
|
l1 = nextNumericLine(fid);
|
||||||
|
if strlength(l1) == 0
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
|
||||||
|
% IMPORTANT: sscanf wants char for robust behavior
|
||||||
|
v1 = sscanf(char(l1), '%f').';
|
||||||
|
if numel(v1) < 9
|
||||||
|
error("S4P schema mismatch: expected 9 numbers on first line of a block, got %d.\nLine: %s", numel(v1), char(l1));
|
||||||
|
end
|
||||||
|
|
||||||
|
l2 = nextNumericLine(fid); if strlength(l2)==0, error("Unexpected EOF after first S4P line."); end
|
||||||
|
l3 = nextNumericLine(fid); if strlength(l3)==0, error("Unexpected EOF after second S4P line."); end
|
||||||
|
l4 = nextNumericLine(fid); if strlength(l4)==0, error("Unexpected EOF after third S4P line."); end
|
||||||
|
|
||||||
|
v2 = sscanf(char(l2), '%f').';
|
||||||
|
v3 = sscanf(char(l3), '%f').';
|
||||||
|
v4 = sscanf(char(l4), '%f').';
|
||||||
|
|
||||||
|
if numel(v2) < 8 || numel(v3) < 8 || numel(v4) < 8
|
||||||
|
error("S4P schema mismatch: expected 8 numbers on continuation lines.\nL2: %s\nL3: %s\nL4: %s", char(l2), char(l3), char(l4));
|
||||||
|
end
|
||||||
|
|
||||||
|
f = v1(1);
|
||||||
|
s1 = v1(2:9); % S11..S14 (re/im pairs)
|
||||||
|
s2 = v2(1:8); % S21..S24
|
||||||
|
s3 = v3(1:8); % S31..S34
|
||||||
|
s4 = v4(1:8); % S41..S44
|
||||||
|
|
||||||
|
row = [f, s1, s2, s3, s4]; % 1 + 32 = 33 columns
|
||||||
|
data = [data; row]; %#ok<AGROW>
|
||||||
|
end
|
||||||
|
|
||||||
|
matrix = data;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function ln = nextNumericLine(fid)
|
||||||
|
ln = "";
|
||||||
|
|
||||||
|
while true
|
||||||
|
t = fgetl(fid);
|
||||||
|
if ~ischar(t)
|
||||||
|
ln = "";
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
ts = strtrim(t);
|
||||||
|
|
||||||
|
% Skip blanks and comments and header lines
|
||||||
|
if ts=="" || startsWith(ts,'!') || startsWith(ts,'#')
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Remove inline comment after '!' if present
|
||||||
|
excl = strfind(ts,'!');
|
||||||
|
if ~isempty(excl)
|
||||||
|
ts = strtrim(extractBefore(ts, excl(1)));
|
||||||
|
if ts==""; continue; end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Keep only if there's at least one numeric token
|
||||||
|
if ~isempty(regexp(ts,'[-+]?\d*\.?\d+(?:[eEdD][-+]?\d+)?','once'))
|
||||||
|
ln = string(ts);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% ========================================================================
|
||||||
|
% Your original loads2p (kept as-is, but returns meta too)
|
||||||
|
% ========================================================================
|
||||||
|
function [matrix, meta] = loads2p(filepath)
|
||||||
|
meta = struct();
|
||||||
|
meta.headerLine = "";
|
||||||
|
meta.freqScaleHz = [];
|
||||||
|
|
||||||
|
% Try to read # line for unit scaling (minimal invasive)
|
||||||
|
fid = fopen(filepath,'r');
|
||||||
|
if fid >= 0
|
||||||
|
cleaner = onCleanup(@() fclose(fid));
|
||||||
|
while true
|
||||||
|
t = fgetl(fid);
|
||||||
|
if ~ischar(t), break; end
|
||||||
|
ts = strtrim(t);
|
||||||
|
if startsWith(ts,'#')
|
||||||
|
meta.headerLine = ts;
|
||||||
|
parts = split(upper(string(ts)));
|
||||||
|
if numel(parts) >= 2
|
||||||
|
switch parts(2)
|
||||||
|
case "HZ", meta.freqScaleHz = 1;
|
||||||
|
case "KHZ", meta.freqScaleHz = 1e3;
|
||||||
|
case "MHZ", meta.freqScaleHz = 1e6;
|
||||||
|
case "GHZ", meta.freqScaleHz = 1e9;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
startRow = 2;
|
||||||
|
formatSpec = '%20s%25s%23s%23s%23s%23s%23s%23s%23s%s%[^\n\r]';
|
||||||
|
|
||||||
|
fileID = fopen(filepath,'r');
|
||||||
|
dataArray = textscan(fileID, formatSpec, 'Delimiter', '', 'WhiteSpace', '', ...
|
||||||
|
'TextType', 'string', 'HeaderLines' ,startRow-1, 'ReturnOnError', false, 'EndOfLine', '\r\n');
|
||||||
|
fclose(fileID);
|
||||||
|
|
||||||
|
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
|
||||||
|
for col=1:length(dataArray)-1
|
||||||
|
raw(1:length(dataArray{col}),col) = mat2cell(dataArray{col}, ones(length(dataArray{col}), 1));
|
||||||
|
end
|
||||||
|
numericData = NaN(size(dataArray{1},1),size(dataArray,2));
|
||||||
|
|
||||||
|
for col=[1,2,3,4,5,6,7,8,9,10]
|
||||||
|
rawData = dataArray{col};
|
||||||
|
for row=1:size(rawData, 1)
|
||||||
|
regexstr = '(?<prefix>.*?)(?<numbers>([-]*(\d+[\,]*)+[\.]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\,]*)*[\.]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?<suffix>.*)';
|
||||||
|
try
|
||||||
|
result = regexp(rawData(row), regexstr, 'names');
|
||||||
|
numbers = result.numbers;
|
||||||
|
|
||||||
|
invalidThousandsSeparator = false;
|
||||||
|
if numbers.contains(',')
|
||||||
|
thousandsRegExp = '^[-/+]*\d+?(\,\d{3})*\.{0,1}\d*$';
|
||||||
|
if isempty(regexp(numbers, thousandsRegExp, 'once'))
|
||||||
|
numbers = NaN;
|
||||||
|
invalidThousandsSeparator = true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ~invalidThousandsSeparator
|
||||||
|
numbers = textscan(char(strrep(numbers, ',', '')), '%f');
|
||||||
|
numericData(row, col) = numbers{1};
|
||||||
|
raw{row, col} = numbers{1};
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
raw{row, col} = rawData{row};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),raw);
|
||||||
|
raw(R) = {NaN};
|
||||||
|
|
||||||
|
matrix = cell2mat(raw);
|
||||||
|
end
|
||||||
@@ -78,7 +78,7 @@ for i = 1:length(fsym)
|
|||||||
|
|
||||||
%%%%% Pulseforming %%%%%%
|
%%%%% Pulseforming %%%%%%
|
||||||
rrca=0.3;
|
rrca=0.3;
|
||||||
X = Pulseformer("fsym",fsym(i),"fdac",256e9,"pulse","rrc","pulselength",16,"rrcalpha",rrca).process(digimod_out);
|
X = Pulseformer("fsym",fsym(i),"fdac",256e9,"pulse","rc","pulselength",16,"alpha",rrca).process(digimod_out);
|
||||||
|
|
||||||
% % %%%%% Clip to PAM range %%%%%%
|
% % %%%%% Clip to PAM range %%%%%%
|
||||||
min_ = min(digimod_out.signal).*1.3;
|
min_ = min(digimod_out.signal).*1.3;
|
||||||
@@ -89,7 +89,7 @@ for i = 1:length(fsym)
|
|||||||
|
|
||||||
X2 = M8199A("kover",kover).process(X);
|
X2 = M8199A("kover",kover).process(X);
|
||||||
|
|
||||||
X = Pulseformer("fsym",fsym(i),"fdac",92e9,"pulse","rrc","pulselength",16,"rrcalpha",rrca).process(digimod_out);
|
X = Pulseformer("fsym",fsym(i),"fdac",92e9,"pulse","rc","pulselength",16,"alpha",rrca).process(digimod_out);
|
||||||
|
|
||||||
% % %%%%% Clip to PAM range %%%%%%
|
% % %%%%% Clip to PAM range %%%%%%
|
||||||
min_ = min(digimod_out.signal).*1.3;
|
min_ = min(digimod_out.signal).*1.3;
|
||||||
@@ -117,7 +117,7 @@ for i = 1:length(fsym)
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
%%
|
||||||
cols = linspecer(3);
|
cols = linspecer(3);
|
||||||
|
|
||||||
figure(6)
|
figure(6)
|
||||||
@@ -130,7 +130,7 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("Vpp in V")
|
ylabel("Vpp in V")
|
||||||
legend
|
legend
|
||||||
ylim([0.3 1.4])
|
ylim([0.3 1.4])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
figure(7)
|
figure(7)
|
||||||
hold on
|
hold on
|
||||||
@@ -142,7 +142,7 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("Output Power in dBm")
|
ylabel("Output Power in dBm")
|
||||||
legend
|
legend
|
||||||
ylim([-12 4])
|
ylim([-12 4])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
figure(8)
|
figure(8)
|
||||||
hold on
|
hold on
|
||||||
@@ -154,7 +154,7 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("PAPR linear")
|
ylabel("PAPR linear")
|
||||||
legend
|
legend
|
||||||
ylim([3 10])
|
ylim([3 10])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
|
|
||||||
figure(9)
|
figure(9)
|
||||||
@@ -167,7 +167,7 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("Vpp in V")
|
ylabel("Vpp in V")
|
||||||
legend
|
legend
|
||||||
ylim([0.3 1.4])
|
ylim([0.3 1.4])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
figure(10)
|
figure(10)
|
||||||
hold on
|
hold on
|
||||||
@@ -179,7 +179,7 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("Output Power in dBm")
|
ylabel("Output Power in dBm")
|
||||||
legend
|
legend
|
||||||
ylim([-12 4])
|
ylim([-12 4])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
figure(11)
|
figure(11)
|
||||||
hold on
|
hold on
|
||||||
@@ -191,6 +191,6 @@ xlabel("Baudrate in GBaud");
|
|||||||
ylabel("PAPR linear")
|
ylabel("PAPR linear")
|
||||||
legend
|
legend
|
||||||
ylim([3 10])
|
ylim([3 10])
|
||||||
thickenfigure;
|
|
||||||
|
|
||||||
autoArrangeFigures
|
autoArrangeFigures
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ dsp_options.storage_path = 'Z:\2024\sioe_labor\';
|
|||||||
dsp_options.max_occurences = 1;
|
dsp_options.max_occurences = 1;
|
||||||
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
|
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
|
||||||
|
|
||||||
rates = [300e9];
|
rates = [420e9];
|
||||||
cols = cbrewer2('BuPu',25);
|
cols = cbrewer2('BuPu',25);
|
||||||
cols = [cols(end-10:2:end,:)];
|
cols = [cols(end-10:2:end,:)];
|
||||||
cols = cbrewer2('Set1',6);
|
cols = cbrewer2('Set1',6);
|
||||||
@@ -10,7 +10,7 @@ cols = cbrewer2('Set1',6);
|
|||||||
fignum = 200;
|
fignum = 200;
|
||||||
fig=figure(fignum);clf;
|
fig=figure(fignum);clf;
|
||||||
|
|
||||||
for dbmode = 0:1%length(rates)
|
for dbmode = 1%length(rates)
|
||||||
|
|
||||||
|
|
||||||
if 0
|
if 0
|
||||||
@@ -59,8 +59,8 @@ for dbmode = 0:1%length(rates)
|
|||||||
M = 4;
|
M = 4;
|
||||||
fp.where('Runs', 'pam_level','EQUALS', M);
|
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||||
fp.where('Runs', 'bitrate','EQUALS', rates);%360,390
|
fp.where('Runs', 'bitrate','EQUALS', rates);%360,390
|
||||||
fp.where('Runs', 'fiber_length','EQUALS', 10);
|
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
fp.where('Runs', 'wavelength','EQUALS', 1322.7); %1327.4
|
fp.where('Runs', 'wavelength','EQUALS', 1310); %1327.4
|
||||||
fp.where('Runs', 'db_mode','EQUALS', dbmode);
|
fp.where('Runs', 'db_mode','EQUALS', dbmode);
|
||||||
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
|
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
|
||||||
|
|
||||||
@@ -98,7 +98,10 @@ Scpe_sig.eye(fsym,M,"fignum",47,"displayname",' Eye of AVG Signal');
|
|||||||
scope_mean = scope_mean ./ n;
|
scope_mean = scope_mean ./ n;
|
||||||
Scpe_sig_avg.signal = scope_mean;
|
Scpe_sig_avg.signal = scope_mean;
|
||||||
|
|
||||||
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
|
figure(20);hold on
|
||||||
|
Symbols.spectrum("fignum",20,"normalizeTo0dB",1,"displayname",'Full Response','addDCoffset',0,'color',clr.Set1.red,'normalizeToNyquist',0,'linestyle','--');
|
||||||
|
DB_Symbols.spectrum("fignum",20,"normalizeTo0dB",1,"displayname",'DB-Response','addDCoffset',0,'color',clr.Set1.blue,'normalizeToNyquist',0,'linestyle','--');
|
||||||
|
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1,"addDCoffset",5);
|
||||||
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
|
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
|
||||||
Scpe_sig_avg.eye(fsym,M,"fignum",48,"displayname",' Eye of AVG Signal');
|
Scpe_sig_avg.eye(fsym,M,"fignum",48,"displayname",' Eye of AVG Signal');
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
%% Main Script: Compare Bibliographies
|
||||||
|
% This script loads two .bbl files, parses them into tables, and compares
|
||||||
|
% them to find missing citations and duplicates.
|
||||||
|
|
||||||
|
clc; clear; close all;
|
||||||
|
|
||||||
|
% --- STEP 0: Create Dummy Files for Demonstration ---
|
||||||
|
% (You can remove this step if you have actual files on disk)
|
||||||
|
|
||||||
|
file1 = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\Advanced_DSP_for_400G_IMDD.bbl'; % The file based on your input
|
||||||
|
file2 = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\Advanced_DSP_for_400G_IMDD_v1.bbl'; % A modified version to show differences
|
||||||
|
|
||||||
|
% --- STEP 1: Load and Parse Files ---
|
||||||
|
fprintf('Loading files...\n');
|
||||||
|
try
|
||||||
|
tab1 = parse_bbl_file(file1);
|
||||||
|
tab2 = parse_bbl_file(file2);
|
||||||
|
catch ME
|
||||||
|
error('Error loading files: %s', ME.message);
|
||||||
|
end
|
||||||
|
|
||||||
|
fprintf('File 1 (%s): %d citations found.\n', file1, height(tab1));
|
||||||
|
fprintf('File 2 (%s): %d citations found.\n', file2, height(tab2));
|
||||||
|
disp('------------------------------------------------------------');
|
||||||
|
|
||||||
|
% --- STEP 2: Check for Duplicates within files ---
|
||||||
|
check_duplicates(tab1, file1);
|
||||||
|
check_duplicates(tab2, file2);
|
||||||
|
disp('------------------------------------------------------------');
|
||||||
|
|
||||||
|
% --- STEP 3: Compare Files (Set Differences) ---
|
||||||
|
% Find keys in A that are NOT in B
|
||||||
|
[~, idx1] = setdiff(tab1.Key, tab2.Key);
|
||||||
|
missing_in_B = tab1(idx1, :);
|
||||||
|
|
||||||
|
% Find keys in B that are NOT in A
|
||||||
|
[~, idx2] = setdiff(tab2.Key, tab1.Key);
|
||||||
|
missing_in_A = tab2(idx2, :);
|
||||||
|
|
||||||
|
% --- STEP 4: Display Comparison Results ---
|
||||||
|
|
||||||
|
if isempty(missing_in_B)
|
||||||
|
fprintf('All citations from %s are present in %s.\n', file1, file2);
|
||||||
|
else
|
||||||
|
fprintf('Citations in %s but MISSING in %s (%d):\n', file1, file2, height(missing_in_B));
|
||||||
|
disp(missing_in_B.Key);
|
||||||
|
end
|
||||||
|
fprintf('\n');
|
||||||
|
|
||||||
|
if isempty(missing_in_A)
|
||||||
|
fprintf('All citations from %s are present in %s.\n', file2, file1);
|
||||||
|
else
|
||||||
|
fprintf('Citations in %s but MISSING in %s (%d):\n', file2, file1, height(missing_in_A));
|
||||||
|
disp(missing_in_A.Key);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% ---------------------------------------------------------
|
||||||
|
% HELPER FUNCTIONS
|
||||||
|
% ---------------------------------------------------------
|
||||||
|
|
||||||
|
function check_duplicates(T, filename)
|
||||||
|
% Checks if the 'Key' column has non-unique entries
|
||||||
|
[uKeys, ~, idx] = unique(T.Key);
|
||||||
|
counts = accumarray(idx, 1);
|
||||||
|
|
||||||
|
dup_indices = find(counts > 1);
|
||||||
|
|
||||||
|
if isempty(dup_indices)
|
||||||
|
fprintf('No duplicates found in %s.\n', filename);
|
||||||
|
else
|
||||||
|
fprintf('** WARNING: Duplicates found in %s! **\n', filename);
|
||||||
|
for i = 1:length(dup_indices)
|
||||||
|
key_idx = dup_indices(i);
|
||||||
|
fprintf(' Key "%s" appears %d times.\n', uKeys{key_idx}, counts(key_idx));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function bibTable = parse_bbl_file(filename)
|
||||||
|
% PARSE_BBL_FILE Loads a .bbl file and extracts citations using Regex.
|
||||||
|
%
|
||||||
|
% bibTable = PARSE_BBL_FILE(filename) returns a table with columns:
|
||||||
|
% - Key: The citation key (e.g., 'dambrosiaAug2025Progress')
|
||||||
|
% - RawContent: The full text of the citation entry
|
||||||
|
% - Line: Approximate line number where it starts
|
||||||
|
|
||||||
|
% 1. Read the file content
|
||||||
|
if ~isfile(filename)
|
||||||
|
error('File "%s" not found.', filename);
|
||||||
|
end
|
||||||
|
str = fileread(filename);
|
||||||
|
|
||||||
|
% 2. Define Regex Structure
|
||||||
|
% Explanation:
|
||||||
|
% \\bibitem\{ -> Match literal "\bibitem{"
|
||||||
|
% (?<Key>[^}]+) -> Capture Group 'Key': match anything except '}'
|
||||||
|
% \} -> Match literal "}"
|
||||||
|
% \s* -> Match optional whitespace
|
||||||
|
% (?<Content>.*?) -> Capture Group 'Content': match any character lazily...
|
||||||
|
% (?=(\\bibitem|\\end\{thebibliography\})) -> ...until looking ahead sees "\bibitem" or end of env.
|
||||||
|
|
||||||
|
% Note: 'dotexceptnewline' is usually default, but we need dot to match newlines
|
||||||
|
% for multi-line citations. We handle this using the '(?s)' flag or explicit loop.
|
||||||
|
% Here we use standard pattern matching.
|
||||||
|
|
||||||
|
pattern = '\\bibitem\{(?<Key>[^}]+)\}\s*(?<Content>.*?)(?=(\\bibitem|\\end\{thebibliography\}))';
|
||||||
|
|
||||||
|
% 3. Execute Regex
|
||||||
|
% 'warnings' turned off for empty matches if file is malformed
|
||||||
|
[matches] = regexp(str, pattern, 'names');
|
||||||
|
|
||||||
|
% 4. Convert to Table
|
||||||
|
if isempty(matches)
|
||||||
|
warning('No citations found in %s using standard regex.', filename);
|
||||||
|
bibTable = table({}, {}, 'VariableNames', {'Key', 'RawContent'});
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Clean up content (remove leading/trailing spaces/newlines)
|
||||||
|
keys = {matches.Key}';
|
||||||
|
content = {matches.Content}';
|
||||||
|
content = strtrim(content);
|
||||||
|
|
||||||
|
bibTable = table(keys, content, 'VariableNames', {'Key', 'RawContent'});
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
% minimal example IM/DD
|
% minimal example IM/DD
|
||||||
|
|
||||||
M = 4;
|
M = 4;
|
||||||
fsym = 180e9;
|
fsym = 112e9;
|
||||||
|
|
||||||
apply_pulsef = 1;
|
apply_pulsef = 1;
|
||||||
fdac = 256e9;
|
fdac = 256e9;
|
||||||
fadc = 256e9;
|
fadc = 256e9;
|
||||||
random_key = 1;
|
random_key = 1;
|
||||||
|
|
||||||
rcalpha = 0.6;
|
rcalpha = 0.05;
|
||||||
kover = 16;
|
kover = 16;
|
||||||
|
|
||||||
duob_mode = db_mode.no_db;
|
duob_mode = db_mode.no_db;
|
||||||
@@ -63,9 +63,11 @@ Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"al
|
|||||||
"mrds_code",0,"mrds_blocklength",512).process();
|
"mrds_code",0,"mrds_blocklength",512).process();
|
||||||
|
|
||||||
%%%%% AWG
|
%%%%% AWG
|
||||||
El_sig = M8199A("kover",kover).process(Digi_sig);
|
% El_sig = M8199A("kover",kover).process(Digi_sig);
|
||||||
% El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
||||||
El_sig.spectrum("displayname",'Digi Spectrum','fignum',1,'normalizeTo0dB',1);
|
El_sig.spectrum("displayname",'Digi Spectrum','fignum',1,'normalizeTo0dB',1);
|
||||||
|
xlim([0,130]);
|
||||||
|
ylim([-30,5]);
|
||||||
% El_sig = El_sig.setPower(0,"dBm");
|
% El_sig = El_sig.setPower(0,"dBm");
|
||||||
|
|
||||||
%%%%% Electrical Driver Amplifier %%%%%%
|
%%%%% Electrical Driver Amplifier %%%%%%
|
||||||
|
|||||||
47
test/m2tikz_examples.m
Normal file
47
test/m2tikz_examples.m
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
x = -10:2:25; % Input power [dBm]
|
||||||
|
|
||||||
|
y1 = 1e-5 * 10.^(0.12*x); % Dispersion-only
|
||||||
|
y2 = 1e0 ./ (1 + exp(-0.4*(x-12))); % NLPN
|
||||||
|
y3 = 1e-6 * 10.^(0.45*x); % RP on gamma
|
||||||
|
y4 = 1e-2 * 10.^(0.18*(x-8)); % RP on beta2
|
||||||
|
|
||||||
|
cmap = WesPalette.AsteroidCity1.rgb(4);
|
||||||
|
cmap = linspecer(4);
|
||||||
|
figure1=figure(202998);clf;hold on
|
||||||
|
lw = 0.8; ms = 3;
|
||||||
|
plot(x,y1,'LineWidth',lw,'Color',cmap(1,:),'Marker','o','MarkerEdgeColor',cmap(1,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||||
|
plot(x,y2,'LineWidth',lw,'Color',cmap(2,:),'Marker','square','MarkerEdgeColor',cmap(2,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||||
|
plot(x,y3,'LineWidth',lw,'Color',cmap(3,:),'Marker','o','MarkerEdgeColor',cmap(3,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||||
|
plot(x,y4,'LineWidth',lw,'Color',cmap(4,:),'Marker','o','MarkerEdgeColor',cmap(4,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);
|
||||||
|
yline(3.8e-3,'HandleVisibility','off')
|
||||||
|
|
||||||
|
grid on
|
||||||
|
xlabel('Input power [dBm]')
|
||||||
|
ylabel('NSD ($\%$)')
|
||||||
|
legend({'Dispersion','NLPN','RP','RP on $\beta_2$'}, ...
|
||||||
|
'Location','best')
|
||||||
|
|
||||||
|
grid off
|
||||||
|
set(gca,'MinorGridLineWidth',0.5);
|
||||||
|
set(gca,'GridLineWidth',0.5,'GridLineStyle','--','GridColor',[0.9,0.9,0.9]);
|
||||||
|
|
||||||
|
set(gca,'FontSize',12,'YScale','log');
|
||||||
|
ylim([1e-6 1e3])
|
||||||
|
xlim([-10 23])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fig_path = 'C:\Users\Silas\Documents\Dissertation\00_Examples\tikz\textfig.tikz';
|
||||||
|
matlab2tikz(fig_path, ...
|
||||||
|
'width','\fwidth', ...
|
||||||
|
'height','\fheight', ...
|
||||||
|
'showInfo',false, ...
|
||||||
|
'extraAxisOptions',{ ...
|
||||||
|
'legend style={font=\footnotesize}', ...
|
||||||
|
'xlabel style={font=\color{white!15!black},font=\small},',...
|
||||||
|
'ylabel style={font=\color{white!15!black},font=\small},',...
|
||||||
|
'legend columns=1', ...
|
||||||
|
'every axis/.append style={font=\scriptsize}',...
|
||||||
|
'legend columns=2',...
|
||||||
|
'legend style={at={(0.02,0.98)},font=\footnotesize,draw=black!60,rounded corners=2pt,inner sep=1pt,fill=white,column sep=6pt,anchor= north west}',...
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user