Is there a way I can convert image (pixel) values ​​to Raman shift using MATLAB?

13 views (last 30 days)
ortizgc
ortizgc on 13 Dec 2021
Edited: David Goodmanson on 25 Dec 2021
Hi, I have a little newbie problem using Raman Spectroscopy information. I have a .spc file which by mistake of mine was saved with pixel values for x axis and needed the values to be in Raman shift. Is there a way to convert these image values to Raman Shift for x axis with MATLAB? For the y axis it is the same parameter for both.
  2 Comments
ortizgc
ortizgc on 19 Dec 2021
Hi. The .txt files that I uploaded are two graphs with different parameters on the x axis, what I want to do is that the graph of Calcite, in Pixel values on the x axis, will be the same as the graph of Calcite with values of Raman Shift on the x axis, that is, I want to perform a conversion of units of values from Pixel to Raman Shift, by means of MATLAB. There are scientific articles that mention this conversion through MATLAB but do not say how, only that they used the software...

Sign in to comment.

Answers (3)

Star Strider
Star Strider on 19 Dec 2021
They appear to me to be different data.
However, filtering out the high-frequency noise is likely as close as it is possible to get to correcting the ‘Pixel’ data —
T1 = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/833340/Calcite%20Pixel.txt', 'VariableNamingRule','preserve')
T1 = 1920×2 table
Pixel Dark Subtracted _____ _______________ 86 2322 87 2418.7 88 2495.7 89 2612.7 90 2595.7 91 2477.3 92 2252.3 93 2153.7 94 2163.7 95 2126.7 96 2140.7 97 2086 98 2080.3 99 2049.3 100 2049.3 101 2046.7
T2 = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/833345/Calcite%20Raman%20Shift.txt', 'VariableNamingRule','preserve')
T2 = 2629×2 table
Raman Shift Dark Subtracted ___________ _______________ 162 1512.2 163 1431.5 164 1366.8 165 1319.7 166 1271.8 167 1228.4 168 1172.3 169 1126.9 170 1116.9 171 1139.4 172 1139.1 173 1124 174 1106.7 175 1090.3 176 1078.9 177 1070.1
Pixx = T1.Pixel;
PixDS = T1.('Dark Subtracted');
RSx = T2.('Raman Shift');
RSDS = T2.('Dark Subtracted');
figure
plot(Pixx, PixDS)
grid
title('Pixel')
figure
plot(RSx, RSDS)
grid
title('Raman Shift')
PixDScb = correctBaseline(Pixx, PixDS, 5, 50, 3);
figure
plot(Pixx, PixDScb)
grid
title('Pixel — Corrected Baseline')
RSDScb = correctBaseline(RSx, RSDS, .01, 5);
Warning: Polynomial is badly conditioned. Add points with distinct X values, reduce the degree of the polynomial, or try centering and scaling as described in HELP POLYFIT.
figure
plot(RSx, RSDScb)
grid
title('Raman Shift — Corrected Baseline')
Pixx_stats = [mean(diff(Pixx)); std(diff(Pixx))];
Fs = 1;
Fn = Fs/2;
L = numel(Pixx);
NFFT = 2^nextpow2(L);
FTPixDS = fft(PixDScb,NFFT)/L;
Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTPixDS(Iv))*2)
grid
xlim([0 0.1])
Passband = 0.03; % Hz (Or Cycles/(Whatever The x-Axis Units Are))
PixDScb_f = lowpass(PixDScb, 0.03, Fs);
figure
subplot(2,1,1)
plot(Pixx, PixDScb)
grid
title('Pixel — Corrected Baseline')
subplot(2,1,2)
plot(Pixx, PixDScb_f)
grid
title('Pixel — Corrected Baseline — Filtered')
function correctedSignal = correctBaseline(varargin)
% % % ARGUMENT LIST (IN ORDER) —
% % % x: X-Vector
% % % y: Y=Vector
% % % prom: Peak Minimum Prominence
% % % sep: Miinimum Peak Separation
% % % pd: Polynomial Degree
% % %
% % % CALLING CONVENTION —
% % % correctedSignal = correctedBaseline(x, y, prom, sep, pd_
% vn = numel(varargin)
x = varargin{1};
y = varargin{2};
prom = varargin{3};
sep = varargin{4};
pd = 4;
if numel(varargin) > 4
pd = varargin{5};
end
TF = islocalmin(y, 'MinProminence',prom, 'MinSeparation',sep);
p = polyfit(x(TF), y(TF),4);
BL = polyval(p, x);
correctedSignal = y-BL;
end
.
  12 Comments
Image Analyst
Image Analyst on 25 Dec 2021
OK, so for one signal (which one), it starts at 280 cm-1, and ends at 1085 cm-1, and I ignore the 711.
And for the other signal, it starts at what and ends at what?
I don't need the pixel values because you said those are in the first column of the text file, so we know those. Calcite's x (pixel value) goes from 86 to 2005, and Calcite Raman Shift's x (pixel value) goes from 162 to 2790 -- these are just values from the first column of the text files and I presume these are the pixel coordinates.
OK, let's try a different approach. Are you saying that one signal is a scaled and shifted version of the other and that we need to rescale and shift one signal such that certain spikes align with the corresponding peaks on the other signal? Like maybe you want to do normalized cross correlation? Or just find the two tallest peaks in each signal and align those?

Sign in to comment.


Image Analyst
Image Analyst on 20 Dec 2021
Assuming that both signals were acquired with the same wavenumber range, you can simply rescale the x axis for each to go linearly from the starting wavenumber to the ending wavenumber. However since each signal for some reason has a different number of samples, you'll have to interpolat. See my code below. I'm assuming that the first element of each signal should be relocated to wavenumber1 and the last element of each signal should be relocated to wavenumber2. If we assume that they look reasonably well aligned now, and we have a new x axis that is the wavenumbers. Adapt my code below to use the actual wavenumbers for the signals.
% Read in first signal.
data1 = readmatrix('Calcite Pixel.txt');
x1 = data1(:, 1); % Get pixels.
signal1 = data1(:, 2); % Get intensity.
% Read in other signal
data2 = readmatrix('Calcite Raman Shift.txt');
x2 = data2(:, 1); % Get pixels.
signal2 = data2(:, 2);
subplot(2, 1, 1);
plot(x1, signal1, 'r-', 'LineWidth', 2);
hold on;
plot(x2, signal2, 'b-', 'LineWidth', 2);
grid on;
ylabel('Signal')
xlabel('Pixels')
wavenumber1 = 1700; % Whatever
wavenumber2 = 4000; % Whatever
% Find the max number of wavenumber samples
numSamples = max([length(signal1), length(signal2)])
% Get wavenumbers going from wavenumber1 to wavenumber2 with numSamples
wavenumbers = linspace(wavenumber1, wavenumber2, 2*numSamples);
% Interpolate both signals to be on a common x axis.
xi1 = linspace(wavenumber1, wavenumber2, length(signal1));
signal1 = interp1(xi1, signal1, wavenumbers);
xi2 = linspace(wavenumber1, wavenumber2, length(signal2));
signal2 = interp1(xi2, signal2, wavenumbers);
subplot(2, 1, 2);
plot(wavenumbers, signal1, 'r-', 'LineWidth', 2);
hold on;
plot(wavenumbers, signal2, 'b-', 'LineWidth', 2);
grid on;
ylabel('Signal')
xlabel('Wavenumber')
The top is the original, pixel-based signals, and the bottom is the new signals shfted, interpolated, and rescaled so that the x axis now represents wavenumbers.
  4 Comments
Image Analyst
Image Analyst on 24 Dec 2021
Now I'm confused even more. You talk like "Pixel" is some specific program. Why are you capitalizing Pixel? Is it a software package? Because just a "pixel" from an image would not be capitalized. I assumed that somehow you'd gotten coordinates by scanning some image of a plot/graph and the coordinates were in pixels.
I still don't know what you mean by that third number.
Can you attach the original .spc files (zipped up). Why don't we just use those instead of messing with some text file with other, incorrect coordinates?

Sign in to comment.


David Goodmanson
David Goodmanson on 24 Dec 2021
Edited: David Goodmanson on 24 Dec 2021
Now that the peaks in both pixels and cm^(-1) are provided, you can do a linear fit, which is very close.
p = [155.56834, 396.54987 624.69582,]
r = [280.05051 711.46459 1085.32579]
a = polyfit(p,r,1)
figure(1)
plot(p,r,'o-',p,polyval(a,p),'o-')
grid on
xlabel('pixels')
ylabel('inverse cm')
a = 1.7172 18.6607
i.e.
cm^(-1) = 1.7172*pixel + 18.66
so one cm^(-1) is worth 1.717 pixels.
It seems unikely in this case but suppose you knew for a fact that, because of the way the instrumentation is built and data is taken, cm^(-1) has to be strictly proportional to pixels, i.e. no offset like the 18.66 above. Then you could find the proportionality constant
c = r/p
p = [0 p];
r = [0 r];
figure(2)
plot(p,r,'o-',p,c*p,'o-')
grid on
xlabel('pixels')
ylabel('inverse cm')
c = 1.7556
  2 Comments
David Goodmanson
David Goodmanson on 25 Dec 2021
Hi ortizgd,
I guess I could, but your access to the files is much more convenient than mine. Defining
pixel file
p = pixels (col 1)
Ip = intensity (col 2)
inverse cm file
icm = inv cm (col 1)
Iicm = intensity (col 2)
then with
figure(1)
plot(1.7172*p+18.66,Ip,icm,Iicm)
grid on
either the peaks willl match up or they won't.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by