This file is indexed.

/usr/share/psychtoolbox-3/PsychGLImageProcessing/DisplayUndistortionBVL.m is in psychtoolbox-3-common 3.0.11.20140816.dfsg1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
function [scal] = DisplayUndistortionBVL(caliboutfilename, screenid, xnum, ynum, referenceImage, stereomode)
% [scal] = DisplayUndistortionBVL([caliboutfilename][, screenid][, xnum=37][, ynum=27][, referenceImage=None][, stereomode=0])
% [scal] = DisplayUndistortionBVL([caliboutfilename][, calibinfilename])
%
% Geometric display calibration procedure for undistortion of distorted
% displays. Needs graphics hardware with basic support for the PTB imaging
% pipeline (see below).
%
% This code was contributed by the members of the Banks Vision Lab at
% University of California, Berkeley. It is a subset of their internal
% "BVL" library and used since many years for their display devices,
% haploscopes etc., so it should be reasonably bug-free and mature.
%
% Many display devices, e.g., video beamers and most CRT displays cause
% some amount of spatial distortion to your visual stimuli during display.
% Psychtoolbox can "undistort" your visual stimuli for you: At stimulus
% onset time, PTB applies a geometric warping transformation to your
% stimulus which is meant to counteract or cancel out the geometric
% distortion caused by your display device. If both, PTB's warp transform
% and the implicit distortion transform of the display match, your stimulus
% will show up undistorted on the display device.
%
% For this to work, PTB needs two things:
%
% 1. Recent graphics hardware with support for the PTB imaging pipeline:
% See our Wiki for recommendations. However, all ATI cards starting with
% Radeon 9500 and all NVidia cards of type GeForce-FX5200 and later, as
% well as the Intel-GMA 950 and later should be able to do it, although
% more recent cards will have a higher performance.
%
% 2. A calibration file that defines the warp transformation to apply. Your
% experiment script will load that file into Screen's "warp engine" at the
% beginning of your experiment.
%
% This routine allows you to create such a calibration file in an
% interactive procedure: You can change and tweak the transformation until
% it fits your needs, ie. until it nicely undistorts your display. Then the
% corresponding calibration file is saved for later use with that display.
%
% DisplayUndistortionBVL defines a continous mapping (x', y') = f(x, y)
% from uncorrected input pixel locations (x,y) in your stimulus image to
% output locations (x', y') on your display. This mapping is defined by a
% 3rd order, 2-dimensional polynomial that is fitted to the calibration data.
%
%
% How to use:
% 
% 1. Start the script, providing all parameters that you don't want to have
% at default settings (all parameters have reasonable defaults):
%
% 'caliboutfilename' Name of the file to which calibration results should
% be stored. If no name is provided, the file will be stored inside the
% 'GeometryCalibration' subfolder of your psychtoolbox configuration
% directory (path is PsychToolboxConfigDir('GeometryCalibration'). The
% filename will contain the screenid and resolution of the display that was
% calibrated.
%
% 'calibinfilename' is the optional path and filename of an existing
% calibration file that you want to use as a template or starting point for
% your calibration, e.g., from previous calibrations in order to save you
% some setup work. If no 'calibinfilename' is provided or if 'screenid' and
% other parameters are provided instead, the script will start with a
% default rectilinear calibration grid of equally spaced points.
%
% These parameters only have meaning if no 'calibinfilename' was provided:
%
% 'screenid' screen id of the target display for calibration. If
% 'calibinfilename' was provided, the screenid encoded in that file will be
% used. Otherwise, the provided screenid will be used. If this parameter is
% omitted, PTB will use the single screen on a single display setup. On a
% multi-display setup, PTB will ask for the screenid.
%
% 'xnum' and 'ynum' Optional number of horizontal and vertical calibration
% points to use. Their number doesn't affect runtime behaviour of your
% stimulus script, only the quality of your calibration and the amount of
% time you'll need to calibrate. The default settings are xnum = 37 and
% ynum = 27. 'xnum' and 'ynum' should be odd numbers. If you provide an
% even number it will be rounded up to the next odd number.
%
% 'referenceImage' Optional name of an image file in a format supported by
% Matlab/Octaves imread() command: If provided, the image will be loaded
% from filesystem and drawn as a backdrop to the calibration grid. You can
% use this if you want to use this routine not to undistort a physical
% display, but want to undistort an existing image, e.g., create a proper
% calibration file for the ImageUndistortionDemo routine.
%
% 'stereomode' Optional stereo mode for display of calibration. Defaults to
% zero, i.e., monoscopic display.
%
% 2. After startup, the script will display a grid of mostly evenly spaced
% points onscreen. The points will not be perfectly aligned to a grid due
% to the distortion caused by your display. Your job is to tweak and shift
% those points so that they line up to a rectilinear grid as good as
% possible on your display from the viewpoint of your subject.
%
% The best way to do this is to build a real mechanical rectilinear grid of
% fine wires and mount it to your display as a "real world" reference for a
% perfect grid. Then you move the displayed calibration dots so that they
% perfectly align with the crossings of the horizontal- and vertical wires
% of your mechanical reference grid.
%
% Mouse operation:
%
% In 'global mode' (when you see the hair-cross in the center of the
% screen), the mouse buttons do the following:
%
% 'Left mouse' or 'l' key:   Switch to local mode.
% 'Middle mouse' or 'm' key: Change stepsize for parameter adjustments.
% 'Right mouse' or 'r' key:  Change type of parameter to adjust.
%
% Following global parameters can be adjusted in global mode:
% 'Translation' of whole dot field.
% 'Scale' of dot field.
% 'Shear' of dot field.
% 'Trapezoid' correction.
% 'Barrel and pincusion' distortion.
%
% In 'local mode': The location of a selected dot or a selection of dots
% can be changed:
%
% 'Left mouse' + mouse drag: Select a single dot close to mouse cursor, or
%                            draw a bounding rectangle around a region of
%                            dots to select.
%
% 'Middle mouse' or 'm' key: Change stepsize for translation of dot(s).
% 'Right mouse' or 'r' key:  Unselect dot(s) if dot(s) is/are selected.
%                            Switch to 'global mode' if no dot(s) selected.
%
%
% 
% Keys and their meaning:
%
% 'l' 'm' and 'r' buttons are synonyms for left- middle- and right mouse
% buttons. However, its much more convenient to use a three button mouse.
%
% Cursor arrow keys move selected dot(s) or change selected global
% parameters.
%
% 'space' key toggles the display of the online help text.
%
% You finish the calibration and write it into a calibration file by
% pressing the ESCape key. This will end the calibration script. The
% structure 'scal' which contains all calibration results will also be
% returned by this function as optional return argument.
%
% This script will print out a little snippet of code that you can paste
% and include into your experiment script - That will automatically load
% the calibration result file and apply the proper undistortion operation.
%
%

% History:
%
% 02/17/08  Initial (incomplete) proposal, derived from David Hoffmanns
%           example script script4David.m. (MK)
%           This is just an initial working draft: Its basic naming
%           conventions and syntax are similar to the
%           DisplayUndistortionBezier.m calibration script.
%
% 05/01/08  Refinement: Integrated all BVL helper routines into distro, as
%           hidden (private) subfolder of PsychGLImageProcessing, so
%           they're only accessible from this master function.
%
%           Fixed and modified a few of the helpers, moved some init and
%           error checking code etc. to this master function for a
%           "smoother" user experience. Now user can either pass in the
%           name of a previous calibration file (as starting point for a
%           calibration), or create a calibration from scratch. If creating
%           from scratch, the 'screenid' can be specified on multi-display
%           systems. On single display setups, the single screen is used
%           and on multi-display setups without 'screenid', the user is
%           asked.
%
%           The default number of calibration dots is 37 by 27, but user
%           can override via the 'xnum' and 'ynum' arguments.
%
%           Output files are now stored in a subfolder of
%           PsychtoolboxConfigDir, with a name that encodes screenid and
%           resolution by default.
%
% 05/03/13  Add optional stereomode parameter to select other display modes
%           than monoscopic display for calibration. (MK)

% Running on PTB-3? Abort otherwise:
PsychDefaultSetup(1);

% Need to temporarily add the '/private' subfolder to Octave's path, as
% Octave as of V3.0.5 doesn't know about private subfolders yet:
if IsOctave
    warning('As of Octave version 3.2.0, this function does not always produce correct results, due to insufficient support for the griddata() v3 interpolation method!');
    addpath([ fileparts(mfilename('fullpath')) '/private' ]);
end

% Enable unified key mapping for all operating systems:
KbName('UnifyKeyNames');

if ~exist('screenid', 'var')
    screenid = [];
end

if ~isempty(screenid)
    % 2nd argument exists: Numeric screenid or name of input calibfile?
    if isnumeric(screenid)
        % Screen id: Assign it.
        if length(screenid)~=1
            error('The "screenid" parameter must be a single integral screen number.');
        end
        
        if ~any(ismember(screenid, Screen('Screens')))
            error('Invalid "screenid" provided - no such screen.');
        end
        
        % Ok, seems to be a valid screenid. Null-Out the calibinfilename.
        calibinfilename = [];
        scal = [];
    else
        % Not a number, so it must be the filename of a calibration input
        % file:
        if ~ischar(screenid)
            error('You must provide the namestring of a valid calibration input file for parameter "calibinfilename"!');
        end
        
        % Namestring provided: Assign it, and Null-Out screenid.
        calibinfilename = screenid;
        screenid = [];
        
        % Check for such a file:
        if ~exist(calibinfilename, 'file')
            error(sprintf('No such calibration input file %s exists!', calibinfilename));
        end
        
        % Ok, valid file provided. Read it in:
        try
            load(calibinfilename);
        catch
            error(sprintf('Failed to load input calibration file %s for some reason.', calibinfilename));
        end
        
        fprintf('\nLoaded initial calibration data from file %s.\n', calibinfilename);
        
        if ~exist('warptype', 'var')
            fprintf('This file is not yet in PTB-3 format. It will be upgraded during save operation.\n');
        else
            if ~strcmp(warptype, 'BVLDisplayList')
                error('The calibration file is not a BVL calibration file, but some other incompatible format! Check your filenames - Aborted.');
            end
        end
        
        if ~exist('scal', 'var')
            error('The calibration file is not a BVL calibration file, but some other incompatible format! Check your filenames - Aborted.');
        end
        
        % Ok, warptype may or may not be initialized, but that doesn't matter.
        % 'scal' should contain initial calibration data...
        
        % Assign screenid from scal:
        screenid = scal.screenNumber;
        
        if isfield(scal, 'stereoMode')
            % Assign stereo mode from scal:
            stereomode = scal.stereoMode;
        end
    end
else
    % No 'screenid' provided: No calibration input file and no screenid:
    calibinfilename = [];
    scal = [];
    screenid = [];
end

% Target screen selection, if not yet defined by cmd-line input or calib
% input file:
if isempty(screenid)
    % Determine the arrangement of monitors, if more than one monitor is
    % used:
    scrns = Screen('Screens');

    % Decide what monitor to calibrate. This won't be asked if there is only
    % one monitor
    if length(scrns)>1,
        screenid = str2double(input(['Screen number of display to calibrate? [' num2str(scrns) '] '],'s'));
        if ~ismember(screenid, scrns)
            error('No such screen - Provide a valid id please! Aborted.');
        end
    else
        screenid = scrns;
    end    
end

if ~exist('stereomode', 'var')
    stereomode = [];
end

if isempty(stereomode)
    stereomode = 0;
end

% At this point, screenid contains the final screenid for the screen to
% calibrate.
% Assign it to scal struct. This will create 'scal' if it doesn't exist
% yet, or override its screenid in some cases:
scal.screenNumber = screenid;

% Ditto for stereoMode:
scal.stereoMode = stereomode;

% Fetch screen resolution: This is just used to build default output file
% name if none provided:
[w, h] = Screen('WindowSize', screenid);

% Check if name for calibration result file is provided:
if ~exist('caliboutfilename', 'var')
    caliboutfilename = [];
end

if isempty(caliboutfilename)
    % Nope: Assign default name - Store in dedicated subfolder of users PTB
    % config dir, with a well defined name that also encodes the screenid
    % and resolution for which to calibrate:
    caliboutfilename = [ PsychtoolboxConfigDir('GeometryCalibration') 'BVLCalibdata' sprintf('_%i_%i_%i', screenid, w, h) '.mat'];
    fprintf('\nNo name for calibration file provided. Using default name and location...\n');
end

% Print name of calibfile and check for existence of file:
fprintf('Name of calibration result file: %s\n\n', caliboutfilename);
if exist(caliboutfilename, 'file')
    answer = input('This file already exists. Overwrite it [y/n]? ','s');
    if ~strcmp(lower(answer), 'y') %#ok<STCI>
        fprintf('\n\nCalibration aborted. Please choose a different name for calibration result file.\n\n');
        return;
    end
end

% No need for synctests here...
oldsynclevel = Screen('Preference', 'SkipSyncTests', 2);
% Reduce PTB output to errors only:
oldverbosity = Screen('Preference', 'Verbosity', 1);

% Open the onscreen window for calibration on screen screenid:
[scal.windowPtr, screenrect] = Screen('OpenWindow', scal.screenNumber, 0, [], [], [], scal.stereoMode);

if isfield(scal, 'rect')
    % rect defined. Check for match with current screens rect:
    if sum(screenrect - scal.rect)~=0,
        Screen('CloseAll');
        error('The resolution of the monitor does not match the resolution stored in spatial calibration input file! Aborted.')
    end
else
    % rect not yet defined. Assign it:
    scal.rect = screenrect;
end

% Select a cross hair cursor:
ShowCursor('CrossHair');

% 'scal' has at least fields screenNumber, windowPtr and screen rect...

success = 0;

if ~exist('referenceImage', 'var')
    referenceImage = [];
end

if ~isempty(referenceImage)
    try
        refImg = imread(referenceImage);
    catch
        Screen('CloseAll');
        error(sprintf('Reference image file %s failed to load - No such file or permission problems?! Aborted.', referenceImage));
    end
    
    % Build reference texture and assign it to scal:
    scal.refTex = Screen('MakeTexture', scal.windowPtr, refImg);
end

% Define type of mapping for this calibration method:
% This is used in the CreateDisplayWarp() routine when parsing the
% calibration file to detect the type of undistortion method to use, ie.
% how to interpret the data in the calibration file to setup the
% calibration.
warptype = 'BVLDisplayList'; %#ok<NASGU>

% All following calibration code is try-catch protected...
try
    % Input file with starting point for calibration provided?
    if isempty(calibinfilename)
        % No. Create default calibration grid from scratch:
        
        % These are the initial settings for horizontal and vertical number
        % of evenly spaced calibration dots as used for the Banks Labs
        % haploscope:
        scal.NxdotsG = 37;
        scal.NydotsG = 27;

        if ~exist('xnum', 'var')
            xnum = [];
        end
        
        if ~exist('ynum', 'var')
            ynum = [];
        end
        
        % Any override values provided?
        if ~isempty(xnum)
            scal.NxdotsG = max(xnum, 1);
        end
        
        if ~isempty(ynum)
            scal.NydotsG = max(ynum, 1);
        end

        % Enforce odd number of points in new calibration interface
        if ~mod(scal.NxdotsG, 2)
            scal.NxdotsG = scal.NxdotsG + 1;
        end
        if ~mod(scal.NydotsG, 2)
            scal.NydotsG = scal.NydotsG + 1;
        end

        % Create default grid from scratch with full grid of calibration
        % dots:
        [scal] = createnewcalibrationgrid(scal);

        % Interactive selection of the dots that will be fitted. The dots x and y coordinates
        % will be stored in scal.FITDOTLIST
        [scal] = bvlSelectFitPts(scal);
        
        % Save intermediate calibration variables to file 'caliboutfilename'. This
        % method should work on both, Matlab 6.x, 7.x, ... and GNU/Octave - create
        % files that are readable by all runtime environments:
        save(caliboutfilename, 'warptype', 'scal', '-mat', '-V6');
        
        % MK: Superseded by direct call to bvlSelectFitPts above: [scal] = selectcalibrationpoints(scal);
    else
        % Yes. 'scal' should contain a good starting point. Take 'scal' as
        % starting point for interactive (re-)calibration procedure:

        % MK: Nothing to do yet as codepath shared with if-then branch...
    end

    % At this point, the initial 'scal' calibration grid is ready for
    % actual interactive calibration...
    
    % 'scal' contains initial calib params and grid setup. Perform interactive
    % GUI based calibration, adjustment and fitting:    
    scal.isDONTSTOP = 0;

    % Try to disable keystroke input to Matlab, but just continue if it fails:
    try
        ListenChar(2);
    catch
    end

    scal = manual_calibrate(scal);

    % Try to reenable keystroke input to Matlab, but just continue if it fails:
    try
        ListenChar(0);
    catch
    end

    % MK: Superseded by call to manual_calibrate above: scal = fineadjust(scal);

    % Save intermediate calibration variables to file 'caliboutfilename'. This
    % method should work on both, Matlab 6.x, 7.x, ... and GNU/Octave - create
    % files that are readable by all runtime environments:
    save(caliboutfilename, 'warptype', 'scal', '-mat', '-V6');

    % Interactive calibration finished, 'scal' is ready for numeric
    % polynomial fit to create the final useable calibration:
    
    % Perform fit operation:
    [scal] = fit(scal);
    
    % Successfully finished!
    success = 1;
catch
    % Close screen, restore everything...
    
    % Select standard arrow cursor:
    ShowCursor('Arrow');

    sca;
    Screen('Preference', 'SkipSyncTests', oldsynclevel);
    Screen('Preference', 'Verbosity', oldverbosity);
    
    % Rethrow the error for debugging...
    psychrethrow(psychlasterror);

    % Try to reenable keystroke input to Matlab, but just continue if it fails:
    try
        ListenChar(0);
    catch
    end
    
    % We try to continue, so the intermediate state gets saved to file as a
    % "restore point".
end

% Select standard arrow cursor:
ShowCursor('Arrow');

% Close display:
Screen('CloseAll');

% Restore sync test settings:
Screen('Preference', 'SkipSyncTests', oldsynclevel);
Screen('Preference', 'Verbosity', oldverbosity);

% 'scal' contains the final results of calibration. Write it out to
% calibfile for later use by the runtime routines:

% Save all relevant calibration variables to file 'caliboutfilename'. This
% method should work on both, Matlab 6.x, 7.x, ... and GNU/Octave - create
% files that are readable by all runtime environments:
save(caliboutfilename, 'warptype', 'scal', '-mat', '-V6');

if success
    fprintf('Calibration finished :-)\n\n');
    fprintf('You can apply the calibration in your experiment script by replacing your \n')
    fprintf('win = Screen(''OpenWindow'', ...); command by the following sequence of \n');
    fprintf('commands:\n\n');
    fprintf('PsychImaging(''PrepareConfiguration'');\n');
    fprintf('PsychImaging(''AddTask'', ''LeftView'', ''GeometryCorrection'', ''%s'');\n', caliboutfilename);
    fprintf('win = PsychImaging(''OpenWindow'', ...);\n\n');
    fprintf('This would apply the calibration to the left-eye display of a stereo setup.\n');
    fprintf('Additional options would be ''RightView'' for the right-eye display of a stereo setup,\n');
    fprintf('or ''AllViews'' for both views of a stereo setup or the single display of a mono\n');
    fprintf('setup.\n\n');
    fprintf('The ''GeometryCorrection'' call has three additional optional parameters:\n');
    fprintf('The first one is a ''debug'' flag: Set it to a non-zero value for diagnostic output at runtime.\n');
    fprintf('The 2nd and 3rd one are override values for the xLoomSize and yLoomSize of the "warp mesh".\n');
    fprintf('Higher values mean a finer calibration but more computation time. Defaults are 73 and 53.\n');
    fprintf('Example:\n');
    fprintf('PsychImaging(''AddTask'', ''LeftView'', ''GeometryCorrection'', ''%s'', 0, 150, 100);\n', caliboutfilename);
    fprintf('would choose no debug output (=0), but a xLoomSize of 150 instead of 73 and a yLoomSize of 100\n');
    fprintf('instead of the default 53.\n');
    fprintf('For most purpose, the default settings will be fine though.\n\n');
    
else
    fprintf('CALIBRATION ABORTED DUE TO ERROR!\n\n');
    fprintf('The current state of calibration has been saved to %s.\n', caliboutfilename);
    fprintf('After fixing the issue, you can restart, using that file as "calibinfilename",\n');
    fprintf('so you don''t lose all of your work.\n\n');
end

% Done.
return;