File: CalibrateMonitorPhotometer.m

package info (click to toggle)
psychtoolbox-3 3.0.9%2Bsvn2579.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 63,408 kB
  • sloc: ansic: 73,310; cpp: 11,139; objc: 3,129; sh: 1,669; python: 382; php: 272; makefile: 172; java: 113
file content (114 lines) | stat: -rw-r--r-- 4,494 bytes parent folder | download
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
function [ gammaTable1, gammaTable2, displayBaseline, displayRange, displayGamma ] = CalibrateMonitorPhotometer( numMeasures )
% [gammaTable1, gammaTable2, displayRange. displayGamma] =
%       CalibrateMonitorPhotometer(numMeasures)
% A simple calibration script for analog photometers. numMeasures (default: 9) 
% readings are taken manually, and the readings are fit with a gamma function 
% and piecewise cubic splines. numMeasures - 1 should be a power of 2, ideally (9, 17, 33, etc.).
% The corresponding linearized gamma tables (1 -> gamma,
% 2 -> splines) are returned, as well as the display baseline, display range in cd/m^2 and
% display gamma. Plots of the two fits are created as well. Requires fit
% tools.
%
% If the normalized gamma table is not loaded, then the cd/m^2 value of a
% screen value can be figured out by the formula: cdm2 =
% displayRange*(screenval/255).^(1/displayGamma) + displayBaseline.
%
% Generally, you will want to load the normalized gamma tables and use them
% in Screen('LoadNormalizedGammaTable'). For example:
%
% [gammaTable1, gammaTable2] = CalibrateMonitorPhotometer;
% %Look at the outputted graphs to see which one gives a better fit
% %Then save the corresponding gamma table for later use
% gammaTable = gammaTable1;
% save MyGammaTable gammaTable
% 
% %Then when you're ready to use the gamma table:
% load MyGammaTable
% Screen('LoadNormalizedGammaTable', win, gammaTable*[1 1 1]);
%
%
% History:
% Version 1.0: Patrick Mineault (patrick.mineault@gmail.com)
% 22.10.2010 mk Switch numeric input from use of input() to use of
%               GetNumber(). Restore gamma table after measurement. Make
%               more robust.

global vals;
global inputV;

    if(nargin < 1)
        numMeasures = 9;
    end

    input(sprintf(['When black screen appears, point photometer, \n' ...
           'get reading in cd/m^2, input reading using numpad and press enter. \n' ...
           'A screen of higher luminance will be shown. Repeat %d times. ' ...
           'Press enter to start'], numMeasures));
       
    origclut = repmat([0:255]'/255,1,3); %#ok<NBRAK>
    psychlasterror('reset');
    
    try
        win = Screen('OpenWindow', 0, 0);

        BackupCluts;        
        Screen('LoadNormalizedGammaTable', win, origclut );

        vals = [];
        inputV = [0:256/(numMeasures - 1):256]; %#ok<NBRAK>
        inputV(end) = 255;
        for i = inputV
            Screen('FillRect',win,i);
            Screen('Flip',win);

            % MK: Deprecated as not reliable: resp = input('Value?');
            fprintf('Value? ');
            resp = GetNumber;
            fprintf('\n');
            vals = [vals resp]; %#ok<AGROW>
        end
        
        RestoreCluts;
        Screen('CloseAll');
    catch
        RestoreCluts;
        Screen('CloseAll');
        psychrethrow(psychlasterror);
    end

    displayRange = (max(vals) - min(vals));
    displayBaseline = min(vals);
    
    %Normalize values
    vals = (vals - displayBaseline)/(max(vals) - min(vals));
    inputV = inputV/255;
    
    if ~exist('fittype'); %#ok<EXIST>
        fprintf('This function needs fittype() for automatic fitting. This function is missing on your setup.\n');
        fprintf('Therefore i can''t proceed, but the input values for a curve fit are available to you by\n');
        fprintf('defining "global vals;" and "global inputV" on the command prompt, with "vals" being the displayed\n');
        fprintf('values and "inputV" being user input from the measurement. Both are normalized to 0-1 range.\n\n');
        error('Required function fittype() unsupported. You need the curve-fitting toolbox for this to work.\n');
    end
    
    %Gamma function fitting
    g = fittype('x^g');
    fittedmodel = fit(inputV',vals',g);
    displayGamma = fittedmodel.g;
    gammaTable1 = ((([0:255]'/255))).^(1/fittedmodel.g); %#ok<NBRAK>
    
    firstFit = fittedmodel([0:255]/255); %#ok<NBRAK>
    
    %Spline interp fitting
    fittedmodel = fit(inputV',vals','splineinterp');
    secondFit = fittedmodel([0:255]/255); %#ok<NBRAK>
    
    figure;
    plot(inputV, vals, '.', [0:255]/255, firstFit, '--', [0:255]/255, secondFit, '-.'); %#ok<NBRAK>
    legend('Measures', 'Gamma model', 'Spline interpolation');
    title(sprintf('Gamma model x^{%.2f} vs. Spline interpolation', displayGamma));
    
    %Invert interpolation
    fittedmodel = fit(vals',inputV','splineinterp');
    
    gammaTable2 = fittedmodel([0:255]/255); %#ok<NBRAK>