Aligning a linear and non-linear x-axis
8 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Theo McCarthy
il 19 Feb 2024
Commentato: Cris LaPierre
il 7 Nov 2024
I have a spectroscopy plot of two curves, one relating to wavelength and one to wave number.
Wavenumber = 1/wavelegnth, so the relation is non linear. I want to align the top x-axis with bottom x-axis so that the peaks of the two curves are displayed in line with each other. Is this possible?
This is my current code:
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1,wl1,sol1,'-r','LineWidth',3)
ax1.XAxisLocation = 'bottom';
ax1.YAxisLocation = 'left';
ax1.XColor = 'r';
ax1.YColor = 'r';
set(ax1, 'xlim',[300 400])
xlabel('wavelength (nm)',FontSize=18)
ylabel('Absorption',FontSize=18)
hold on
ax2 = axes(t);
plot(ax2,wn1,sol1_adj,'-k','LineWidth',3)
set(ax2, 'xlim',[250000 333333])
ax2.XAxisLocation = 'top';
ax2.YAxisLocation = 'right';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlabel('wavenumber(m^-^1)',FontSize=18)
ylabel('Absorption',FontSize=18)
set(gca, 'XDir','reverse')
ax1.FontSize = 16;
ax2.FontSize = 16;
2 Commenti
William Rose
il 19 Feb 2024
Is there a factor-of-ten error in one of the x-axis scales? Consider the wavenumber and wavelength for the right-most peak in the figure you provided. The black (wavenumber) peak is at about 2.65e5 m^-1. This corresponds to 3.77e-6 m = 3770 nm. But the red (wavelength) peak is at about 377 nm.
Risposta accettata
Cris LaPierre
il 19 Feb 2024
Modificato: Cris LaPierre
il 19 Feb 2024
The axes you are plotting into are linear, so I think the best solution would be to plot both plots using wavelength, and then convert the labels of to top x axis to wavenumber using xticklabels. Note that xticklabels displays the label as a string, not a numeric, so you need to format your number so that it appears as you want. I use sprintf below for that purpose.
If you are particular about which wavenumbers are shown, you can set the tick locations using xticks. Just remember to set the tick location using wavelength, not wavenumber.
The code might look like this. The first part just reproduces the issue.
BTW, one of your axes is off by a factor of 10 based on the equation you have shared.
x1 = (300:10:400)*1e-9;
x2 = 1./x1;
y=rand(1,length(x1));
% current aproach to show the issue
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1,x1,y,'-r')
xlabel('Wavelength (m)')
ax1.XColor = 'r';
ax1.YColor = 'r';
ax2 = axes(t);
plot(ax2,x2,y,'k')
ax2.XAxisLocation = 'top';
ax2.YAxisLocation = 'right';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlabel('Wavenumber (m^{-1})')
ax1.XAxis.Exponent = -9;
ax2.XAxis.Exponent = 4;
Now here is the same plot but with the proposed solution
figure
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1,x1,y,'-r')
xlabel('Wavelength (m)')
ax1.XColor = 'r';
ax1.YColor = 'r';
ax2 = axes(t);
plot(ax2,x1,y,'--k')
ax2.XAxisLocation = 'top';
ax2.YAxisLocation = 'right';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlabel('Wavenumber (m^{-1})')
% desired wavenumber tick locations
wvnum = (3.3:-0.1:2.5)*1e6 % 1/m
% corresponding wavelength
wvlg_nmTk = 1./wvnum % nm
ax1.XAxis.Exponent = -9;
xticks(ax2,wvlg_nmTk);
xticklabels(ax2,sprintf('%3.0f\n',wvnum/1e4)); % display in meters
2 Commenti
Anna
il 7 Nov 2024
Modificato: Cris LaPierre
il 7 Nov 2024
Hi Cris, Can I please seek some help with the code to plot spectrum data? The top x-axis is a wavelength in nm and the bottom one is a wavenumber in cm^{-1}. The top axis should align with the bottom one so that the top one has smaller tick spacing in the infra-red region and bigger tick spacing in the UV range. Appreciate your guidance with this matter.
clear all; clc;
wavelength = 300:1600; % in nm
wavenumber = 1e7./wavelength; % in cm-1
data = rand(1, length(wavenumber));
figure;
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1, wavenumber/1e3, data, '-r')
set(gca, 'XDir','reverse')
xlabel('Wavenumber (10^3 cm^{-1})')
ylabel('Absorption (a.u.)')
ax2 = axes(t);
plot(ax2, wavelength, data, '-g')
ax2.XAxisLocation = 'top';
xlabel('Wavelength (nm)')
Cris LaPierre
il 7 Nov 2024
First, your second axes is covering the first one. You need to turn the background off.
Otherwise, this is the same issue as OP. The difference between each wavelength is the same: 1. The difference between each wavenumber is not the same.
wavelength = 300:1600; % in nm
wavenumber = 1e7./wavelength; % in cm-1
data = rand(1, length(wavenumber));
figure
plot(diff(wavelength))
hold on
plot(diff(wavenumber))
hold off
Therefore, when you plot the two on the same axis, the two signals will not align.
figure
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1, wavenumber(1:20), data(1:20), '-b')
set(gca, 'XDir','reverse')
xlim(wavenumber([20 1]))
ax2 = axes(t);
plot(ax2, wavelength(1:20), data(1:20), '--r')
ax2.XAxisLocation = 'top';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlim(wavelength([1 20]))
As with the OP, you need to plot both signals using the same X values, and then convert the ticks of one to the other scale.
You can do that using wavenumber:
figure
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1, wavenumber/1e3, data, '-r')
set(ax1, 'XDir','reverse')
xlabel('Wavenumber (10^3 cm^{-1})')
ylabel('Absorption (a.u.)')
ax2 = axes(t);
plot(ax2, wavenumber/1e3, data, '--g')
set(ax2, 'XDir','reverse')
ax2.XAxisLocation = 'top';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlabel('Wavelength (nm)')
% desired wavelength tick locations
wvlgth = [1600 1000 800 600 500 400 300];
% corresponding wavenumber in cm^-1
wvlg_nmTk = 1e7./wvlgth/1e3
xticks(ax2,wvlg_nmTk);
xticklabels(ax2,sprintf('%3.0f\n',wvlgth)); % display in meters
or wavelength:
Note how the plot looks different depending which one you use because of the difference in step (constant vs changing).
figure
t = tiledlayout(1,1);
ax1 = axes(t);
plot(ax1, wavelength, data, '-r')
xlabel('Wavenumber (10^3 cm^{-1})')
ylabel('Absorption (a.u.)')
ax2 = axes(t);
plot(ax2, wavelength, data, '--g')
ax2.XAxisLocation = 'top';
ax2.Color = 'none';
ax1.Box = 'off';
ax2.Box = 'off';
xlabel('Wavelength (nm)')
% desired wavelength tick locations
wvnum = [35 25 20 15 12 10 8 7]; % 1e3 cm^-1
wvnum = wvnum*1e3; % cm^-1
% corresponding wavelength in nm
wvlg_nmTk = 1e7./wvnum
xticks(ax1,wvlg_nmTk);
xticklabels(ax1,sprintf('%3.0f\n',wvnum/1e3)); % display in 1e3 cm^-1
Più risposte (0)
Vedere anche
Categorie
Scopri di più su 2-D and 3-D Plots in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!