function eccDegrees = RetinalEccentricityMMToDegrees(eccMm,species,method,eyeLengthMm) % eccMm = DegreesToRetinalEccentricityMM(eccDegrees,[species],[method],[eyeLengthMm]) % % Convert eccentricity in degrees to retinal eccentricity in mm. By % default, this takes into account a simple model eye, rather than just % relying on a linear small angle approximation. % % Input: % eccDegrees -- retinal eccentricity in degrees % species -- what species % 'Human' -- Human eye [default] % 'Rhesus' -- Rhesus monkey % method -- what method % 'DaceyPeterson' -- formulae from Dacey & Peterson (1992) [default] % 'Linear' -- linear, based on small angle approx % eyeLengthMm -- Eye length to assume for linear calculation, should be % the posterior nodal distance. Defaults to the default values returned % by function EyeLength for the chosen species. % % The Dacey and Peterson formulae are based on digitizing and fitting % curves published by % 1) Drasdo and Fowler, 1974 (British J. Opthth, 58,pp. 709 ff., Figure 2, % for human. % 2) Perry and Cowey (1985, Vision Reserch, 25, pp. 1795-1810, Figure 4, % for rhesus monkey. % These curves, I think, were produced by ray tracing or otherwise solving % model eyes. % % The default eye length returned by EyeLength for Human is currently the Rodiek value of % 16.1 mm. Drasdo and Fowler formulae are based on a length of about this, % so the linear and DaceyPeterson methods are roughly consistent for small % angles. Similarly with the Rhesus default. Using other EyeLength's will % make the two methods inconsistent. % % The Dacey and Peterson equations don't go through (0,0), but rather % produce a visual angle of 0.1 degree for an eccentricity of 0. This % seems bad to me. I modified the formulae so that they use the linear % approximation for small angles, producing a result that does go through % (0,0). This may be related to the fact that there is some ambiguity in % the papers between whether the center should be thought of as the fovea % or the center of the optical axis. But I think this difference is small % enough that the same formulae would apply across such a shift in origin. % % I digitized Drasdo and Fowler Figure 2 and compared it to what % DegreesToRetinalEccentricity produces. I'd call agreement so-so, but % considerably better than what the linear approximation produces. One % could probably do better, but my intuition is that the deviations are % small compared to eye to eye differences and differences that would be % produced by different model eyes, so that juice isn't worth the squeeze. % I pasted my digitization at the end of DegreesToRetinalEccentricity if % anyone wants to fuss with this. But probably if you're going to do that, % you should do the whole ray tracing thing with our best current model % eye. % % I have not checked the fit to the Perrry and Cowey curve for Rhesus % against a digitization of that figure. % % See also: EyeLength, DegreesToRetinalEccentricityMM, DegreesToRetinalMM, RetinalMMToDegrees % % 6/30/2015 dhb Wrote it. %% Set defaults if (nargin < 2 || isempty(species)) species = 'Human'; end if (nargin < 3 || isempty(method)) method = 'DaceyPeterson'; end if (nargin < 4 || isempty(eyeLengthMm)) switch (species) case 'Human' eyeLengthMm = EyeLength(species,'Rodieck'); case 'Rhesus' eyeLengthMm = EyeLength(species,'PerryCowey'); otherwise error('Unknown species specified'); end end %% Checks if (any(eccMm < 0)) error('Can only convert non-negative eccentricities'); end %% Do the method dependent thing switch (method) case 'DaceyPeterson' % Out of paranoia, make sure we use the right eye length parameters % for this method, so that the low angle linear approximation that % we tag on comes out right. switch (species) case 'Human' eyeLengthMm = EyeLength(species,'Rodieck'); case 'Rhesus' eyeLengthMm = EyeLength(species,'PerryCowey'); otherwise error('Unknown species specified'); end % Set quadratic parameters switch (species) case 'Human' a = 0.035; b = 3.4; c1 = 0.1; case 'Rhesus' a = 0.038; b = 4.21; c1 = 0.1; otherwise error('Unknown species passed'); end % Evaulate the quadratic eccDegrees = c1 + b*eccMm + a*(eccMm.^2); % Replace small angles by the linear approximation degreeThreshold = 0.2; index = find(eccDegrees < degreeThreshold); if (~isempty(index)) eccDegrees(index) = RetinalMMToDegrees(eccMm(index),eyeLengthMm,false); end case 'Linear' eccDegrees = RetinalMMToDegrees(eccMm,eyeLengthMm,false); otherwise error('Unknown method passed') end end