1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
function absorbance = ShiftPhotopigmentAbsorbance(S,absorbance,lambdaMaxShift,shiftMode)
% absorbance = ShiftPhotopigmentAbsorbance(S,absorbance,lambdaMaxShift,shiftMode)
%
% Function to shift photopigment absorbances. Probably a reasonable
% approximation to biological reality for small shifts of lambda max.
%
% There are two ways of shifting photopigment absorbances:
% 'linear' - default
% Shifts the photopigment absorbance on a linear wavelength axis. This
% is what Asano, Fairchild, & Bonde (2016), PLOS One, doi:
% 10.1371/journal.pone.0145671 do.
%
% 'log'
% Shift the photopigment absorbance along a log wavelength axis to give it
% a new lambda max. This is the way Lamb (1995) suggested would lead to a
% close approximation of biological shifts in photopigment lambda-max.
%
% Linearly extrapolates as necessary to preserve wavelength sampling of
% input.
%
% 2/8/16 dhb, ms Wrote it.
% 2/10/16 dhb, ms Do shifting on a fine (0.25 nm) wavelength spacing.
% 2/12/16 ms Implement linear and log shifting.
% Assume linear shifting as default
if (nargin < 4 | isempty(shiftMode))
shiftMode = 'linear';
end
% Check
if (length(lambdaMaxShift) ~= size(absorbance,1))
error('Number of absorbances and length of shift vector do not match');
end
% Do the shifting on a fine wavelength spacing scale, so as to avoid
% unexpected wavelength quantization artifacts as a result of the shift.
wls = MakeItWls(S);
fineSpacing = 0.25;
if (S(2) < fineSpacing)
error('Not a good idea to run this function with an input wavelength spacing less than 0.25 nm');
end
wlsFine = (wls(1):fineSpacing:wls(end))';
SFine = WlsToS(wlsFine);
absorbanceFine = SplineCmf(S,absorbance,SFine);
switch shiftMode
case 'linear'
for ii = 1:size(absorbanceFine,1);
absorbanceFine(ii, :) = interp1(wlsFine+lambdaMaxShift(ii), absorbanceFine(ii, :), wlsFine, 'linear', 'extrap');
end
case 'log'
% Normalize the wave number and log wavelength
[~, maxIdx] = max(absorbanceFine, [], 2);
for ii = 1:size(absorbanceFine,1);
logWavelengthsNorm = log10(wlsFine) - log10(wlsFine(maxIdx(ii)));
logWavelengthsNew = logWavelengthsNorm + log10(wlsFine(maxIdx(ii))+lambdaMaxShift(ii));
wlsFineNew = 10.^logWavelengthsNew;
absorbanceFine(ii, :) = interp1(wlsFineNew, absorbanceFine(ii, :), wlsFine, 'linear','extrap');
end
end
% Spline the shifted function back to the original wavelength spacing
absorbance = SplineCmf(SFine,absorbanceFine,S);
|