This question may seem like it has been answered in the forums but I believe there is a subtlety that has not been directly answered. I want to plot the optical absorption coefficient of a material as a function of both photon wavelength (bottom x-axis) and energy (top x-axis) similar to this figure shown below. There are two problems with this task that I have not found sufficiently addressed. The first is to ensure that all of the points in the bottom axis line up with the points in the top axis (we need to some how link the two x-axes). Second, because of how energy and wavelength are related, one axis will be ascending while the other will be descending (Matlab doesn't like descending x-axes). How can you make the referenced plot? Can someone recreate the reference plot using the following data taken from the reference plot?
clear
close all
data = [0.35737704918032787, 92649850.48039015
0.3819672131147541, 72475211.53588514
0.41147540983606556, 55967196.301264346
0.4229508196721312, 51126728.207795605
0.4557377049180328, 47937263.23846833
0.5016393442622952, 43803474.996365294
0.539344262295082, 40544606.59504045
0.5688524590163934, 34277014.89316264
0.5950819672131147, 25461360.619704828
0.6229508196721312, 16618285.037019765
0.6655737704918033, 10037712.197086804
0.7213114754098361, 6724703.556947659
0.7950819672131147, 4169337.0144349397
0.8836065573770491, 2722604.5977291227
0.9557377049180328, 1997130.2156342946
1.0344262295081967, 1523018.3932672704
1.1049180327868853, 1255113.4937515096
1.1852459016393442, 1034416.372625131
1.2737704918032788, 886319.8712540427
1.359016393442623, 779309.6059234422
1.4540983606557378, 609961.3425615291
1.4918032786885247, 502533.5248888627
1.5098360655737708, 398203.214420678
1.5196721311475412, 299601.3683763488
1.5213114754098362, 195504.2893801002
1.5262295081967214, 119588.7737216253
1.5360655737704918, 65114.84416472715
1.5475409836065577, 38316.26954492593
1.5508196721311474, 25329.082065449114
1.559016393442623, 18331.533361062826
1.5688524590163935, 14713.897024069562
1.5934426229508198, 11361.99263934681
1.6196721311475408, 8773.786275376307
1.6508196721311474, 6433.761487810411
1.6754098360655738, 5032.800618487584
1.7049180327868854, 3787.196421050415
1.7327868852459019, 2886.942647505133
1.7557377049180327, 2287.679320744783
1.777049180327869, 1933.9100405245356];
%planks constant
h = 4.135e-15; %eV s
%speed of light
c = 3e8; %m/s
%Ge absorption coef
alpha = data(:,2); %1/m
%wavelength
lambda = data(:,1); %microns
%energy
E = h*c./(lambda*1e-6); %eV
figure(1)
plot(lambda,alpha,'r')
xlabel('Wavelength (\mum)')
ylabel('\alpha (m^{-1})')
set(gca,'Yscale','log')
figure(2)
plot(E,alpha,'r')
xlabel('Energy (eV)')
ylabel('\alpha (m^{-1})')
set(gca,'Yscale','log')

6 commentaires

Adam
Adam le 9 Mar 2020
What do you mean by 'Matlab doesn't like descending x-axes'?
The following works fine for me to reverse an x-axis, though obviously it is a trivial case.
figure; hAxes = gca;
hAxes.XDir = 'reverse'
I'm also not sure what you mean by the points on top and bottom x-axis 'lining up' (I don't really see in the link you gave an obvious example of what you are asking). Do you mean you want the ticks on the two axes to line up even though they are showing two different properties?
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Modifié(e) : Christopher Saltonstall le 9 Mar 2020
Thank you for the answer for reversing the axis direction. I didn't know that you could do that.
Energy and wavelength are related and so any "tick" on the bottom x-axis (wavelength) must line up with its corresponding energy on the top x-axis. Otherwise the top axis has no meaning when related to the y-axis.
%planks constant
h = 4.135e-15; %eV s
%speed of light
c = 3e8; %m/s
%wavlength
lambda = linspace(200e-9,800e-9,100); %m
%energy
E = h*c./lambda; %eV
However, the science obsures the point. In the first post, I want to make sure the points on x1 and x2 axis line up. Specifically, I want x1(1) to line up--be directly below--x2(2) and so on.
Adam
Adam le 9 Mar 2020
Well, if you set the limits of both axes then they will line up. The exact ticks will likely not line up with ticks on the other axes, but if you want that too then you would need to edit the XTick and maybe XTickLabel properties as appropriate, as well as the XLim properties. Zooming in would be a problem though.
In which case your best bet would, perhaps be to have the exact same ticks for each axes and use only the XTickLabel property of the 2nd axis to give the true value. Then you can use
doc linkaxes
to ensure the ranges stay linked. I don't like using XTickLabels rather than actual XTick values like this myself because data cursor reporting and stuff like that is incorrect as it is based on the actual axis values, not any labels applied to the ticks.
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Adam, I've editted the question a little and added some data taken from the reference plot. Do you think you could recreat the reference plot based on what I have provided?
Adam Danz
Adam Danz le 9 Mar 2020
Note that a similar solution was offered for the same question (and same OP) a while back,
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Modifié(e) : Christopher Saltonstall le 9 Mar 2020
That's my question but the code does not work. Since there was no activity on it in about 2 years I reposted it. Note, the answer was not accepted.

Connectez-vous pour commenter.

 Réponse acceptée

Ameer Hamza
Ameer Hamza le 9 Mar 2020
Modifié(e) : Ameer Hamza le 2 Oct 2020

4 votes

data = [0.35737704918032787, 92649850.48039015
0.3819672131147541, 72475211.53588514
0.41147540983606556, 55967196.301264346
0.4229508196721312, 51126728.207795605
0.4557377049180328, 47937263.23846833
0.5016393442622952, 43803474.996365294
0.539344262295082, 40544606.59504045
0.5688524590163934, 34277014.89316264
0.5950819672131147, 25461360.619704828
0.6229508196721312, 16618285.037019765
0.6655737704918033, 10037712.197086804
0.7213114754098361, 6724703.556947659
0.7950819672131147, 4169337.0144349397
0.8836065573770491, 2722604.5977291227
0.9557377049180328, 1997130.2156342946
1.0344262295081967, 1523018.3932672704
1.1049180327868853, 1255113.4937515096
1.1852459016393442, 1034416.372625131
1.2737704918032788, 886319.8712540427
1.359016393442623, 779309.6059234422
1.4540983606557378, 609961.3425615291
1.4918032786885247, 502533.5248888627
1.5098360655737708, 398203.214420678
1.5196721311475412, 299601.3683763488
1.5213114754098362, 195504.2893801002
1.5262295081967214, 119588.7737216253
1.5360655737704918, 65114.84416472715
1.5475409836065577, 38316.26954492593
1.5508196721311474, 25329.082065449114
1.559016393442623, 18331.533361062826
1.5688524590163935, 14713.897024069562
1.5934426229508198, 11361.99263934681
1.6196721311475408, 8773.786275376307
1.6508196721311474, 6433.761487810411
1.6754098360655738, 5032.800618487584
1.7049180327868854, 3787.196421050415
1.7327868852459019, 2886.942647505133
1.7557377049180327, 2287.679320744783
1.777049180327869, 1933.9100405245356];
fig = figure();
% setup bottom axis
ax = axes();
hold(ax);
ax.YAxis.Scale = 'log';
xlabel(ax, 'Wavelength ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14);
ylabel(ax, '$\alpha$ ($m^{-1}$)', 'Interpreter', 'latex', 'FontSize', 14);
% setup top axis
ax_top = axes(); % axis to appear at top
hold(ax_top);
ax_top.XAxisLocation = 'top';
ax_top.YAxisLocation = "right";
ax_top.YTick = [];
% ax_top.XDir = 'reverse';
ax_top.Color = 'none';
xlabel(ax_top, 'Energy($e$V)', 'Interpreter', 'latex', 'FontSize', 14);
% linking axis
linkprop([ax, ax_top],{'Units','Position','ActivePositionProperty'});
ax.Position(4) = ax.Position(4) * .96;
h = 4.135e-15; %eV s
c = 3e8; %m/s
lambda = linspace(0.2,1.8,9); %m
E = h*c./lambda*10^6; % 10^6 because lambda is in microns
% configure limits of bottom axis
ax.XLim = [lambda(1) lambda(end)];
ax.XTick = lambda;
ax.XAxis.TickLength = [0.015, 0.00];
ax.YAxis.TickLength = [0.02, 0.00];
ax.XAxis.MinorTick = 'on';
ax.XAxis.MinorTickValues = linspace(0.2,1.8,17);
% configure limits and labels of top axis
y_ticks = [0.7 0.8 0.9 1 2 3 4 5];
lambda_y_tick = h*c./y_ticks*10^6;
ax_top.XLim = [lambda(1) lambda(end)];
ax_top.XTick = fliplr(lambda_y_tick);
ax_top.XTickLabel = compose('%1.1f', fliplr(y_ticks));
ax_top.XAxis.TickLength = [0.02, 0.00];
ax_top.XAxis.MinorTick = 'off';
plot(ax, data(:,1), data(:,2), 'r-', 'LineWidth', 3);

18 commentaires

Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
This does not solve the problem of lining up the top and bottom axes.
Ameer Hamza
Ameer Hamza le 9 Mar 2020
Modifié(e) : Ameer Hamza le 9 Mar 2020
You need to specify it yourself. For example, if you are working with the wavelength and energy of a photon, then the relation is: , Then you can do something like this
h = % define value of h
c = % define value of c
% suppose wavelength axis is at top
ax_top.XLim = [400 700]; % limits of the wavelength axis
ax.XLim = fliplr(h*c./ax_top.XLim); % calculate limits of the energy axis
In this way, the limits of both axes are automatically bounded.
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Can you try this the code I just posted above. I'm pretty sure it doesn't work.
Ameer Hamza
Ameer Hamza le 9 Mar 2020
There was an issue with the second limit. Check the updated code. It should run fine now. Note, values of h and c need to be added according to your units.
Ameer Hamza
Ameer Hamza le 9 Mar 2020
Modifié(e) : Ameer Hamza le 9 Mar 2020
Based on your comments, it appears that you also want to preserve the nonlinear relation between the two axes. Although MATLAB does not provide a direct way to do this however there is a bodge to make it look nonlinear. I have updated the code to just changes the axes label on the top axes to show the nonlinear relation. Note that this solution will break down if you try to zoom or move the axis manually.
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Hi Ammer. Thanks for your efforts. I've changed the question code to include the data from the reference plot. Do you think you could recreate the reference plot from what I have provided?
What are the units of lambda? In one of the previous comment, you mentioned the range of lambda to be
lambda = linspace(200e-9,800e-9,100); %m
But the first column seems to contain values in range [0.3 1.8].
Also, which specific figure number you are referring in the link. The link opens all the figures in that book.
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
I've attached the figure above. The units are in comments, microns, micrometers.
Ameer Hamza
Ameer Hamza le 9 Mar 2020
Christopher Saltonstall, check the updated code. Although the code is a bit messy and uses tricks to display labels on the top axis, it creates the same graph.
Christopher Saltonstall
Christopher Saltonstall le 9 Mar 2020
Modifié(e) : Christopher Saltonstall le 9 Mar 2020
This is great. Its only taken 2 years.
One minor question though. Why does the top x-axis seem to be shifted below the top border?
Answer: Its because the axes positions need to be aligned.
ax_top.Position = ax.Position;
Adam Danz
Adam Danz le 9 Mar 2020
Modifié(e) : Adam Danz le 9 Mar 2020
+1, Ameer
I suggest using
linkprop([ax, ax_top],{'Units','Position','ActivePositionProperty'});
to make sure the axis positions are always aligned.
You may also want to decrease the height of the axes so the title, shifted by the upper ticks, doesn't go off the figure border. After the line above,
ax.Position(4) = ax.Position(4) * .92;
Ameer Hamza
Ameer Hamza le 10 Mar 2020
Adam, Thanks for the suggestion. I have updated the code in my answer to link and change the height of both axes.
Christopher Saltonstall
Christopher Saltonstall le 10 Mar 2020
Now the tick marks are off on the top axis.
Remove the line
box(ax);
Zachary Davonski
Zachary Davonski le 2 Oct 2020
How would you add a legend to this kind of plot? I've tried both the legend command and the DisplayName property but neither work in this case.
Specify the axes on which you want to place the legend.
plot(ax, data(:,1), data(:,2), 'r-', 'LineWidth', 3, 'DisplayName', 'Line 1');
legend(ax);
Zachary Davonski
Zachary Davonski le 2 Oct 2020
Thanks!
Hi Ameer Hamza,
May I know is it possible to use your code to plot like a picture below? Because I would like to plot 2 x-axis as per depicts in figure below.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Data Exploration dans Centre d'aide et File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by