Skip to content

Commit e50c98e

Browse files
committed
In process on understanding the real contrasts
1 parent 45e972c commit e50c98e

File tree

1 file changed

+131
-53
lines changed

1 file changed

+131
-53
lines changed

code/analysis/monitorGamutInLSPlane/makeMonitorGamutFigure.m

Lines changed: 131 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
% Make a figure showing our monitor gamut in the LS contrast plane
22

33
%% Initialize
4-
clear; %close all;
4+
clear; close all;
55

66
%% Where to write figure
77
figureDir = getpref('ColorTracking','figureSavePath');
88

99
%% Load typical calibration file from the experiment
10-
whichExperiment = 'detection';
10+
whichExperiment = 'tracking';
1111
switch (whichExperiment)
1212
case 'tracking'
1313
whichCalFile = 'ViewSonicG220fb.mat';
@@ -39,6 +39,7 @@
3939
% Make the bit depth correct as far as the calibration file goes.
4040
nDeviceLevels = 2^nDeviceBits;
4141
CalibrateFitGamma(calObjCones, nDeviceLevels);
42+
CalibrateFitGamma(calObjCones1, nDeviceLevels);
4243
nPrimaries = calObjCones.get('nDevices');
4344

4445
% Set gamma mode. A value of 2 was used in the experiment
@@ -77,14 +78,15 @@
7778
T_cones1 = T_cones;
7879
end
7980
SetSensorColorSpace(calObjCones,T_cones,Scolor);
80-
SetSensorColorSpace(calObjCones1,T_cones,Scolor);
81+
SetSensorColorSpace(calObjCones1,T_cones1,Scolor);
8182

8283
%% XYZ cal object
8384
calObjXYZ = ObjectToHandleCalOrCalStruct(cal);
8485
calObjXYZ1 = ObjectToHandleCalOrCalStruct(cal);
8586

8687
% Get gamma correct
8788
CalibrateFitGamma(calObjXYZ, nDeviceLevels);
89+
CalibrateFitGamma(calObjXYZ1, nDeviceLevels);
8890
SetGammaMethod(calObjXYZ,gammaMode);
8991
SetGammaMethod(calObjXYZ1,gammaMode);
9092
if (NOAMBIENT)
@@ -313,66 +315,142 @@
313315
% angular directions
314316
specificVectorLengthContrast;
315317
theSpecificAngles;
316-
clear theSpecficAngles
317318

318319
%% Convert cone contrasts with respect to first calibration to second.
319320
%
320321
% Angles from paper Figure 5 labels, contrasts read off of those graphs
321322
% roughly by eye. If we go to 16 bit depth, the match would have been very
322323
% good, had the detection calibration been used the way it should have
323324
% been.
324-
theDetectionSpecificAngles = [-86.25 -82.5 -78.75 -75 -45 0 45 75 78.75 82.5 86.25 90];
325-
theVectorLengthContrasts = [ 0.05 0.03 0.02 0.017 0.005 0.003 0.004 0.015 0.02 0.03 0.04 0.05];
326-
for aa = 1:length(theDetectionSpecificAngles)
327-
fprintf('Angle %0.1f, vector length contrast %0.1f\n',theDetectionSpecificAngles(aa),100*theVectorLengthContrasts(aa));
328-
329-
% Convert from cone contrast to cone excitation direction.
330-
% Don't care about length here as that is handled by the contrast
331-
% maximization code below.
332-
targetContrastDir = [cosd(theDetectionSpecificAngles(aa)) 0 sind(theDetectionSpecificAngles(aa))]';
333-
targetConeContrast(:,aa) = (theVectorLengthContrasts(aa)*targetContrastDir);
334-
335-
% Convert from cone contrast to cone excitation direction.
336-
% Don't care about length here as that is handled by the contrast
337-
% maximization code below.
338-
targetCones = (targetConeContrast(:,aa).* bgCones) + bgCones;
339-
340-
% Compute settings we would have used using first calibration
341-
[theSettings,badIndex] = SensorToSettings(calObjCones,targetCones);
342-
if (any(badIndex))
343-
fprintf(' Out of gamut\n');
325+
%
326+
% Use this code to correct the detection stimuli for further analysis
327+
subjID = 'MAB';
328+
switch (whichExperiment)
329+
case 'tracking'
330+
contrastLim = 1.0;
331+
contrastDevLim = 0.06;
332+
angleDevLim = 4;
333+
expNameCell = { 'Experiment1-Pos' 'Experiment2-Pos' ['Experiment3-' subjID '-Pos']};
334+
expContrastLMS = [];
335+
for ii = 1:length(expNameCell)
336+
expContrastLMS = [expContrastLMS ; LMSstimulusContrast('experiment',expNameCell{ii})];
337+
end
338+
for ii = 1:size(expContrastLMS,1)
339+
targetAngle(ii) = atand(expContrastLMS(ii,2),expContrastLMS(ii,1));
340+
targetContrast(ii) = norm([expContrastLMS(ii,1) expContrastLMS(ii,2)]);
341+
end
342+
343+
targetAngleRaw = theSpecificAngles;
344+
targetContrast = specificVectorLengthContrast;
345+
case {'detection', 'detectionRaw'};
346+
% Options are 'MAB', 'BMC', 'KAS'
347+
contrastLim = 0.3;
348+
contrastDevLim = 0.015;
349+
angleDevLim = 2;
350+
351+
[targetContrast,targetAngleRaw] = getContrastLSD(subjID,'combined');
352+
targetAngleRaw = targetAngleRaw';
353+
end
354+
for cc = 1:size(targetContrast,1)
355+
targetAngle(cc,:) = targetAngleRaw;
356+
for aa = 1:length(targetAngleRaw)
357+
fprintf('Angle %0.1f, vector length contrast %0.1f\n',targetAngle(cc,aa),100*targetContrast(cc,aa));
358+
359+
% Convert from cone contrast to cone excitation direction.
360+
% Don't care about length here as that is handled by the contrast
361+
% maximization code below.
362+
targetContrastDir = [cosd(targetAngle(cc,aa)) 0 sind(targetAngle(cc,aa))]';
363+
targetConeContrast(:,cc,aa) = (targetContrast(cc,aa)*targetContrastDir);
364+
365+
% Convert from cone contrast to cone excitation direction.
366+
% Don't care about length here as that is handled by the contrast
367+
% maximization code below.
368+
targetCones = (targetConeContrast(:,cc,aa).* bgCones) + bgCones;
369+
370+
% Compute settings we would have used using first calibration
371+
[theSettings,badIndex] = SensorToSettings(calObjCones,targetCones);
372+
if (any(badIndex))
373+
fprintf(' Out of gamut\n');
374+
end
375+
376+
% Go back to contrast with both calibrations
377+
obtainedCones(:,cc,aa) = SettingsToSensor(calObjCones,theSettings);
378+
obtainedCones1(:,cc,aa) = SettingsToSensor(calObjCones1,theSettings);
379+
obtainedConeContrast(:,cc,aa) = ((obtainedCones(:,cc,aa)-bgCones) ./ bgCones);
380+
obtainedConeContrast1(:,cc,aa) = ((obtainedCones1(:,cc,aa)-bgCones1) ./ bgCones1);
381+
382+
% Need to deal with angle flipping which can happen for small
383+
% contrasts.
384+
obtainedAngle(cc,aa) = atand(obtainedConeContrast(3,cc,aa)/obtainedConeContrast(1,cc,aa));
385+
if (targetAngle(cc,aa) > 0 && obtainedAngle(cc,aa) < 0)
386+
obtainedAngle(cc,aa) = obtainedAngle(cc,aa) + 180;
387+
end
388+
if (targetAngle(cc,aa) < 0 && obtainedAngle(cc,aa) > 0)
389+
obtainedAngle(cc,aa) = obtainedAngle(cc,aa) - 180;
390+
end
391+
obtainedAngle1(cc,aa) = atand(obtainedConeContrast1(3,cc,aa)/obtainedConeContrast1(1,cc,aa));
392+
if (targetAngle(cc,aa) > 0 && obtainedAngle1(cc,aa) < 0)
393+
obtainedAngle1(cc,aa) = obtainedAngle1(cc,aa) + 180;
394+
end
395+
if (targetAngle(cc,aa) < 0 && obtainedAngle1(cc,aa) > 0)
396+
obtainedAngle1(cc,aa) = obtainedAngle1(cc,aa) - 180;
397+
end
398+
obtainedContrast(cc,aa) = norm(obtainedConeContrast(:,cc,aa));
399+
obtainedContrast1(cc,aa) = norm(obtainedConeContrast1(:,cc,aa));
400+
angleDeviation(cc,aa) = obtainedAngle(cc,aa)-targetAngle(cc,aa);
401+
angleDeviation1(cc,aa) = obtainedAngle1(cc,aa)-targetAngle(cc,aa);
402+
contrastDeviation(cc,aa) = obtainedContrast(cc,aa) - targetContrast(cc,aa);
403+
contrastDeviation1(cc,aa) = obtainedContrast1(cc,aa) - targetContrast(cc,aa);
404+
405+
% Figure out the cone excitations for the settings we computed, and
406+
% then convert to contrast as our maximum contrast in this direction.
407+
%
408+
% Dividing by imageScaleFactor handles the sine phase of the Gabor
409+
fprintf(' Target contrasts: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
410+
100*targetConeContrast(1,cc,aa),100*targetConeContrast(2,cc,aa),100*targetConeContrast(3,cc,aa), ...
411+
targetAngle(cc,aa),100*targetContrast(cc,aa));
412+
fprintf(' Had ambient/cones used been right: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
413+
100*obtainedConeContrast(1,cc,aa),100*obtainedConeContrast(2,cc,aa),100*obtainedConeContrast(3,cc,aa), ...
414+
obtainedAngle(cc,aa),100*obtainedContrast(cc,aa));
415+
fprintf(' What we actually got: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
416+
100*obtainedConeContrast1(1,cc,aa),100*obtainedConeContrast1(2,cc,aa),100*obtainedConeContrast1(3,cc,aa), ...
417+
obtainedAngle1(cc,aa),100*obtainedContrast1(aa));
344418
end
419+
end
345420

346-
% Go back to contrast with both calibrations
347-
obtainedCones(:,aa) = SettingsToSensor(calObjCones,theSettings);
348-
obtainedCones1(:,aa) = SettingsToSensor(calObjCones1,theSettings);
349-
obtainedConeContrast(:,aa) = ((obtainedCones(:,aa)-bgCones) ./ bgCones);
350-
obtainedConeContrast1(:,aa) = ((obtainedCones1(:,aa)-bgCones1) ./ bgCones1);
351-
obtainedAngle(aa) = atand(obtainedConeContrast(3,aa)/obtainedConeContrast(1,aa));
352-
obtainedAngle1(aa) = atand(obtainedConeContrast1(3,aa)/obtainedConeContrast1(1,aa));
353-
obtainedVectorLength(aa) = norm(obtainedConeContrast(:,aa));
354-
obtainedVectorLength1(aa) = norm(obtainedConeContrast1(:,aa));
355-
angleDeviation(aa) = obtainedAngle(aa)-theDetectionSpecificAngles(aa);
356-
angleDeviation1(aa) = obtainedAngle1(aa)-theDetectionSpecificAngles(aa);
357-
vectorLengthDeviation(aa) = obtainedVectorLength(aa) - theVectorLengthContrasts(aa);
358-
vectorLengthDeviation1(aa) = obtainedVectorLength1(aa) - theVectorLengthContrasts(aa);
421+
% Compute values to use
422+
targetAngleToUse = mean(obtainedAngle1,1);
423+
targetContrastToUse = obtainedContrast1;
424+
figure; clf; hold on;
425+
subplot(2,2,1); hold on;
426+
plot(targetAngleRaw,targetAngleToUse,'ro','MarkerFaceColor','r','MarkerSize',10);
427+
plot([-100 100],[-100 100],'k');
428+
xlim([-100 100]); ylim([-100 100]);
429+
axis('square');
430+
xlabel('Target Angle (deg)'); ylabel('Obtained Angle (deg)');
431+
subplot(2,2,2); hold on;
432+
plot(100*targetContrast(:),100*targetContrastToUse(:),'ro','MarkerFaceColor','r','MarkerSize',10);
433+
plot([0 100*contrastLim],[0 100*contrastLim],'k');
434+
xlim([0 100*contrastLim]); ylim([0 100*contrastLim]);
435+
axis('square');
436+
xlabel('Target Contrast (%)'); ylabel('Obtained Contrast (%)');
437+
subplot(2,2,3); hold on;
438+
plot(targetAngleRaw,targetAngleToUse-targetAngleRaw,'ro','MarkerFaceColor','r','MarkerSize',10);
439+
plot([-100 100],[0 0],'k');
440+
xlim([-100 100]); ylim([-angleDevLim angleDevLim]);
441+
axis('square');
442+
xlabel('Target Angle (deg)'); ylabel('Obtained Angle Deviation (deg)');
443+
subplot(2,2,4); hold on;
444+
plot(100*targetContrast(:),100*targetContrastToUse(:)-100*targetContrast(:),'ro','MarkerFaceColor','r','MarkerSize',10);
445+
plot([0 100*contrastLim],[0 0],'k');
446+
xlim([0 100*contrastLim]); ylim([100*-contrastDevLim 100*contrastDevLim]);
447+
axis('square');
448+
xlabel('Target Contrast (%)'); ylabel('Obtained Contrast Deviation (%)');
359449

360-
% Figure out the cone excitations for the settings we computed, and
361-
% then convert to contrast as our maximum contrast in this direction.
362-
%
363-
% Dividing by imageScaleFactor handles the sine phase of the Gabor
364-
fprintf(' Target contrasts: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
365-
100*targetConeContrast(1,aa),100*targetConeContrast(2,aa),100*targetConeContrast(3,aa), ...
366-
theDetectionSpecificAngles(aa),100*theVectorLengthContrasts(aa));
367-
fprintf(' Had ambient/cones used been right: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
368-
100*obtainedConeContrast(1,aa),100*obtainedConeContrast(2,aa),100*obtainedConeContrast(3,aa), ...
369-
obtainedAngle(aa),100*obtainedVectorLength(aa));
370-
fprintf(' What we actually got: L cone contrast %7.3f%%, M, %7.3f%%, S %7.3f%%, angle %7.1f, vector length %0.1f%%\n', ...
371-
100*obtainedConeContrast1(1,aa),100*obtainedConeContrast1(2,aa),100*obtainedConeContrast1(3,aa), ...
372-
obtainedAngle1(aa),100*obtainedVectorLength1(aa));
373-
end
374-
fprintf('\n Had ambient/cones used been right: Max abs angle deviation %0.4f, max abs vector length deviation %0.4f\n',max(abs(angleDeviation)),max(abs(vectorLengthDeviation)));
375-
fprintf('\n What we actually got: Max abs angle deviation %0.4f, max abs vector length deviation %0.4f\n',max(abs(angleDeviation1)),max(abs(vectorLengthDeviation1)));
450+
% The angular deviations start to lose meaning as the contrast gets very
451+
% small
452+
fprintf('\n Had ambient/cones used been right: Max abs angle deviation %0.4f, max abs vector length deviation %0.4f\n',max(abs(angleDeviation(:))),max(abs(contrastDeviation(:))));
453+
fprintf('\n What we actually got: Max abs angle deviation %0.4f, max abs vector length deviation %0.4f\n',max(abs(angleDeviation1(:))),max(abs(contrastDeviation1(:))));
376454

377455
%% Gamut chromaticity plot for comparisons
378456
%

0 commit comments

Comments
 (0)