In [1]:
# -*- coding: utf-8 -*-
"""
---
Title: Color Calibration with Mavo-Monitor USB  
Date: 04-01-2018
Author: D.Cook
---
"""

# Import analysis modules 
import pandas as pd 
import numpy as np

# plot functions 
import matplotlib as mpl
from matplotlib import mlab
from matplotlib import pyplot as plt
%matplotlib inline 

Photometer Measurements

Creating a CLUT - Dec 2017

  • A PTB script presented 25 red, green or blue square patches of increasing brightness in the center of the monitor on a black background.
  • No CLUT was uploaded to PTB during the presentation of the colored patches.
  • A ColorCAL MKII Colorimeter was used to measure the $cd/m^2$ for the color patches.
  • The ColorCal was placed 20cm away from monitor.
  • Models were fit to the $cd/m^2$ readings from the ColorCAL.
  • 6 Color Look-Up Tables were produced from the model outputs.

Measuring with a CLUT - Jan 2018

  • PTB presented a full screen of increasing brightness in red, green and blue.
  • A Mavo-Monitor USB photometer was used to measure the $cd/m^2$ of the screen WITH and WITHOUT the CLUT for the gamma fit (see above).
  • The Gamma CLUT was loaded with the function, Screen('LoadNormalizedGammaTable').
  • The results of the measurements are given in the python dictionary below:
In [2]:
colorCal = {"gamma":{"b":np.array([1.35, 1.36, 1.40, 1.48, 1.61, 1.79, 1.99, 2.32, 2.71, 3.23, 3.79, 
                                   4.59, 5.44, 6.55, 7.74, 9.47, 11.68, 14.3, 17.32, 19.40, 21.4]),
                     "g":np.array([1.35, 1.84, 2.65, 3.80, 5.40, 7.58, 9.94, 13.26, 17.10, 21.4, 25.9, 
                                   31.8, 38.5, 46.7, 56.0, 66.9, 79.9,92.6, 102.7, 113.9,127.5]),
                     "r":np.array([1.35, 1.38, 1.47, 1.62, 1.86, 2.21, 2.65, 3.30, 4.1, 5.09, 6.27, 7.77, 
                                   9.6, 11.87, 14.56, 18.20, 22.8, 27.9, 31.4, 35.5, 40.7])}, 
            "noGamma": {"gr":np.array([1.35, 1.91, 2.88, 4.28, 6.26, 8.99, 12.0, 16.25, 21.2, 28.1, 36.5,
                                      48.9, 57.8, 67.6, 78.0, 89.0, 103.1, 114.0, 120.3, 125.6, 130.1]),
                        "r":np.array([1.32, 1.35, 1.45, 1.61, 1.86, 2.21, 2.65, 3.3, 4.08, 5.08,6.27, 
                                      7.77, 9.61, 11.86, 14.56, 18.25, 22.9, 28.0, 31.4, 35.5, 40.8]),
                        "g":np.array([1.33, 1.83, 2.65, 3.80, 5.39, 7.57, 9.94, 13.26, 17.09, 21.4, 25.8, 
                                      31.7,38.5, 46.6, 56.0, 66.9, 80.2, 92.9, 103.0,114.1, 127.6]),
                        "b":np.array([1.33, 1.35, 1.40, 1.47, 1.61, 1.80, 2.00, 2.33, 2.72, 3.24, 3.79, 4.60, 5.46,
                                      6.57, 7.74, 9.48, 11.67, 14.32,17.35, 19.44, 21.4])}}

Results

We plot the results of two measurements from a Mavo-Monitor USB photometer. The $cd/m^2$ of the screen was read WITH and WITHOUT a CLUT for a gamma fit to orignal readings from a ColorCal MKII (see above).

In [3]:
# First, we create a color index from 0 for no color, to 256 for full brightness, with 21 even spaces. 
ramp = np.linspace(0, 256, 21, dtype=int)
In [57]:
fig = plt.figure(figsize=(12, 3))
ax = plt.subplot(131);
ax.plot(ramp, colorCal['gamma']['r'], ".", color="r", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['gamma']['r'])]);
ax.set_ylabel(r'$cd/m^2$', size='xx-large');
ax = plt.subplot(132);
ax.plot(ramp, colorCal['gamma']['b'], ".", color="b", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['gamma']['b'])]);
ax.set_title("Screen('LoadNormalizedGammaTable') \n USED", size='x-large');
ax.set_xlabel(r'Color Index', size='x-large');
ax = plt.subplot(133);
ax.plot(ramp, colorCal['gamma']['g'], ".", color="g",  linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['gamma']['g'])]);

Figure 1. The $cd$/$m^2$ of the three guns of the CRT Monitor obtained with the Mavo-Monitor USB photometer. 22 color measurements were taken with the Gamma Table loaded. The photometer was positioned at the center of the screen, and the entire screen was set to one of the indexed color values. Read, blue, green dots show the measurements for the respective colors, etc.

In [58]:
fig = plt.figure(figsize=(12, 3))
ax = plt.subplot(141);
ax.plot(ramp, colorCal['noGamma']['r'], ".", color="r", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['r'])]);
ax.set_ylabel(r'$cd/m^2$', size='xx-large');
ax = plt.subplot(142);
ax.plot(ramp, colorCal['noGamma']['b'], ".", color="b", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['b'])]);
ax.set_title("Screen('LoadNormalizedGammaTable') \n NOT USED", size='x-large');
ax.set_xlabel(r'Color Index', size='x-large');
ax = plt.subplot(143);
ax.plot(ramp, colorCal['noGamma']['g'], ".", color="g",  linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['g'])]);
ax = plt.subplot(144);
ax.plot(ramp, colorCal['noGamma']['gr'], ".", color="black",  linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['gr'])]);

Figure 2. The $cd$/$m^2$ of the three guns of the CRT Monitor obtained with the Mavo-Monitor USB photometer. 22 color measurements were taken WITHOUT the Gamma Table loaded. The photometer was positioned at the center of the screen, and the entire screen was set to one of the indexed color values. Red, blue, green, grey dots show the measurements for the respective colors, etc.

In [21]:
ax = plt.subplot(111);
ax.plot(ramp, colorCal['gamma']['r'] - colorCal['noGamma']['r'], color='r');
ax.set_xlim([0, 256]);
ax.set_ylim([-0.5, 0.5]);
plt.plot(ramp, colorCal['gamma']['g'] - colorCal['noGamma']['g'], color='g');
plt.plot(ramp, colorCal['gamma']['b'] - colorCal['noGamma']['b'], color='b');
ax.set_title("ERROR", size='x-large');
ax.set_ylabel(r'$cd/m^2$', size='xx-large');
ax.set_xlabel(r'Color Index', size='x-large');

Figure 3. The difference between the $cd$/$m^2$ measurements for the the three guns of the CRT Monitor obtained with the Mavo-Monitor USB photometer with and without the Gamma Table loaded.

Interim conclusion

Using the Gamma table from the ColorCal MKII with Screen('LoadNormalizedGammaTable') in PTB did not make a difference to the measurements with the Mavo-Monitor photmeter.

Possible causes:

  • The CLUT table is not correct?
  • The PTB function is not correct?
  • The graphics card is overruling the loading of the table?
  • The os is overruling the loading of the table?
  • the new CLUT is the same as the old CLUT?

Refitting Curves to the colorCal['noGamma'] data

The first CLUT did not make a difference to the luminance values obtained. Therefore, we re-fit curves to the readings from CRT monitor without the Gamma tables uploaded.

The data from colorCal['noGamma'] (see Python dict above) without Gamma tables uploaded was imported into Matlab, and the script below was run:

.m
% mavoRecording contains 21 cd/m^2 readings from a mavo photometer 
% for the three guns of the CRT monitor 
% the script produces pl

clear all

mavoRecording  = {[1.32, 1.35, 1.45, 1.61, 1.86, 2.21, 2.65, 3.3, 4.08, 5.08,6.27,  7.77, 9.61, 11.86, 14.56, 18.25, 22.9, 28.0, 31.4, 35.5, 40.8],
    [1.33, 1.83, 2.65, 3.80, 5.39, 7.57, 9.94, 13.26, 17.09, 21.4, 25.8, 31.7,38.5, 46.6, 56.0, 66.9, 80.2, 92.9, 103.0,114.1, 127.6], 
    [1.33, 1.35, 1.40, 1.47, 1.61, 1.80, 2.00, 2.33, 2.72, 3.24, 3.79, 4.60, 5.46,6.57, 7.74, 9.48, 11.67, 14.32,17.35, 19.44, 21.4]}
mavoColor={'RED', 'GREEN', 'BLUE'};

for Z = 1:3
colorCal.inputValues = mavoRecording{Z}

%colorCal.ramp = [0,  12,  25,  38,  51,  64,  76,  89, 102, 115, 128, 140, 153, 166, 179, 192, 204, 217, 230, 243, 256]
colorCal.rampNorm = [0.  ,  0.05,  0.1 ,  0.15,  0.2 ,  0.25,  0.3 ,  0.35,  0.4 ,  0.45,  0.5 ,  0.55,  0.6 ,  0.65,  0.7 ,  0.75,  0.8 ,  0.85,0.9 ,  0.95,  1.]

colorCal.nMeasures = 21
colorCal.ramp = [0:1/(colorCal.nMeasures - 1):1];
colorCal.ramp(end) = 1;

screenBits = 8; 
lumSteps = 2^screenBits;
colorCal.analysisMethods = {'pchipinterp';'smoothingspline';'cubicinterp';'splineinterp';'cubicspline'}
colorCal.canAnalyze = 1; 
colorCal.displayRange = (max(colorCal.inputValues) - min(colorCal.inputValues));
colorCal.displayBaseline = min(colorCal.inputValues);

%Normalize values
colorCal.inputValuesNorm = (colorCal.inputValues - colorCal.displayBaseline)/(max(colorCal.inputValues) - min(colorCal.inputValues));
colorCal.rampNorm = colorCal.ramp;

%Gamma function fitting
g = fittype('x^g');
fo = fitoptions('Method','NonlinearLeastSquares',...
'Display','iter','MaxIter',1000,...
'Upper',3,'Lower',0,'StartPoint',1.5);
[fittedmodel, gof, output] = fit(colorCal.rampNorm',colorCal.inputValuesNorm',g,fo);
colorCal.displayGamma = fittedmodel.g;
colorCal.gammaTable{1} = ((([0:1/(lumSteps-1):1]'))).^(1/fittedmodel.g);
colorCal.modelFit{1}.method = 'Gamma';
colorCal.modelFit{1}.table = fittedmodel([0:1/(lumSteps-1):1]);
colorCal.modelFit{1}.gof = gof;
colorCal.modelFit{1}.output = output;

for i = 1:length(colorCal.analysisMethods)                    
    method = colorCal.analysisMethods{i};
    [fittedmodel,gof,output] = fit(colorCal.rampNorm',colorCal.inputValuesNorm', method);
    colorCal.modelFit{i+1}.method = method;
    colorCal.modelFit{i+1}.table = fittedmodel([0:1/(lumSteps-1):1]);
    colorCal.modelFit{i+1}.gof = gof;
    colorCal.modelFit{i+1}.output = output;

    %Invert interpolation
    [fittedmodel,gof] = fit(colorCal.inputValuesNorm',colorCal.rampNorm',method);
    colorCal.gammaTable{i+1} = fittedmodel([0:1/(lumSteps-1):1]);
end 

% ===================================================================
%> @brief plot
%>    This plots the calibration results
% ===================================================================
    colorCal.plotHandle = figure;
    %colorCal.p = panel(colorCal.plotHandle,'defer');
    scnsize = get(0,'ScreenSize');
    pos=get(gcf,'Position');
    %colorCal.p.pack(2,2);
    %colorCal.p.margin = [15 20 5 15];
    %colorCal.p.fontsize = 12;
    %colorCal.p(1,1).select();
    subplot(2,2,1)
    plot(colorCal.ramp, colorCal.inputValues, 'k.-');
    axis tight
    xlabel('Indexed Values');
    ylabel('Luminance cd/m^2');
    title( strcat(mavoColor{Z}, ' Input -> Output Raw Data' )   );
    %colorCal.p(1,2).select();
    subplot(2,2,2)
    hold all
        for i=1:length(colorCal.modelFit)
            plot([0:1/(lumSteps-1):1], colorCal.modelFit{i}.table);
            legendtext{i} = colorCal.modelFit{i}.method;
        end
        plot(colorCal.rampNorm, colorCal.inputValuesNorm, 'r.')
        legendtext{end+1} = 'Raw Data';
    hold off
    axis tight
    xlabel('Normalised Luminance Input');
    ylabel('Normalised Luminance Output');
    legend(legendtext,'Location','NorthWest');

    title(sprintf('Gamma model x^{%.2f} vs. Interpolation', colorCal.displayGamma));
    legendtext=[];
    subplot(2,2,3)
    %colorCal.p(2,1).select();
    hold all
    for i=1:length(colorCal.gammaTable)
        plot(1:length(colorCal.gammaTable{i}),colorCal.gammaTable{i});
        legendtext{i} = colorCal.modelFit{i}.method;
    end
    hold off
    axis tight
    xlabel('Indexed Values')
    ylabel('Normalised Luminance Output');
    legend(legendtext,'Location','NorthWest');
    title('Plot of output Gamma curves');
    subplot(2,2,4)
    %colorCal.p(2,2).select();
    hold all
    for i=1:length(colorCal.gammaTable)
        plot(colorCal.modelFit{i}.output.residuals);
        legendtext{i} = colorCal.modelFit{i}.method;
    end
    hold off
    axis tight
    xlabel('Indexed Values')
    ylabel('Residual Values');
    legend(legendtext,'Location','Best');
    title('Model Residuals');
    if scnsize(3) > 2000
        scnsize(3) = scnsize(3)/2;
    end
    newpos = [scnsize(3)/2-scnsize(3)/3 1 scnsize(3)/1.5 scnsize(4)];
    set(gcf,'Position',newpos);

    if Z == 1
        calibrationRed = colorCal.gammaTable 
    end 
    if Z == 2
        calibrationGreen = colorCal.gammaTable 
    end 
    if Z == 3
        calibrationBlue = colorCal.gammaTable 
    end     
end 

gammaCalib = [calibrationRed{1}, calibrationGreen{1}, calibrationBlue{1}]
pchipinterpCalib = [calibrationRed{2}, calibrationGreen{2}, calibrationBlue{2}]
smoothingsplineCalib = [calibrationRed{3}, calibrationGreen{3}, calibrationBlue{3}]
cubicinterpCalib = [calibrationRed{4}, calibrationGreen{4}, calibrationBlue{4}]
splineinterpCalib = [calibrationRed{5}, calibrationGreen{5}, calibrationBlue{5}]
cubicsplineCalib = [calibrationRed{6}, calibrationGreen{6}, calibrationBlue{6}]
csvwrite('gammaCalibration.csv', gammaCalib)
csvwrite('pchipinterpCalibration.csv', pchipinterpCalib)
csvwrite('smoothingsplineCalibration.csv', smoothingsplineCalib)
csvwrite('cubicinterpCalibration.csv', cubicinterpCalib)
csvwrite('splineinterpCalibration.csv', splineinterpCalib)
csvwrite('cubicsplineCalibration.csv', cubicsplineCalib)

Above Script. The Matlab script for analyzing photometric readings. This script produces 6 new CLUT tables, which are saved as .csv files, and the script outputs plots for inspecting.

The plots of the Gamma fit to the photometer measurements versus alternative fits are shown below.

In [61]:
from IPython.display import Image
Image('/Users/cookdj0128/Desktop/eegLab/GRAY OUTPUT.png')
Out[61]:

Figure 4. Fits for the gray colors. 22 measurements were taken. The worst fits appear to be the SmoothingSpline, and the Gamma fit.

In [62]:
Image('/Users/cookdj0128/Desktop/eegLab/RED OUTPUT.png')
Out[62]:
In [63]:
Image('/Users/cookdj0128/Desktop/eegLab/BLUE OUTPUT.png')
Out[63]:

Figure 5. Fits for the blue colors. 22 measurements were taken. The worst fits appear to be the SmoothingSpline, and the Gamma fit.

In [64]:
Image('/Users/cookdj0128/Desktop/eegLab/GREEN OUTPUT.png')
Out[64]:

Figure 6. Fits for the green colors. 22 measurements were taken. The worst fits appear to be the SmoothingSpline, and the Gamma fit.

The MATLAB Cluts are read into Python below, and their output curves are shown:

In [70]:
import os
calibTables  = [i for i in os.listdir(os.getcwd()) if i.endswith(".csv")]
In [71]:
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(14, 6), sharey=True)

df = pd.read_csv(calibTables[0], names=['red','green', 'blue'], index_col=False)
axes[0, 0].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[0, 0].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[0, 0].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[0, 0].set_ylabel('Normalized \n luminance output', size='x-large');
axes[0, 0].set_title(calibTables[0].replace(".csv",""), size='x-large');

df = pd.read_csv(calibTables[1], names=['red','green', 'blue'], index_col=False)
axes[0, 1].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[0, 1].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[0, 1].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[0, 1].set_title("Output Gamma Curves \n \n " +calibTables[1].replace(".csv",""), size='x-large');

df = pd.read_csv(calibTables[2], names=['red','green', 'blue'], index_col=False)
axes[0, 2].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[0, 2].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[0, 2].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[0, 2].set_title(calibTables[2].replace(".csv",""), size='x-large');

df = pd.read_csv(calibTables[3], names=['red','green', 'blue'], index_col=False)
axes[1, 0].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[1, 0].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[1, 0].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[1, 0].set_ylabel('Normalized \n luminance output', size='x-large');
axes[1, 0].set_title(calibTables[3].replace(".csv",""), size='x-large');

df = pd.read_csv(calibTables[4], names=['red','green', 'blue'], index_col=False)
axes[1, 1].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[1, 1].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[1, 1].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[1, 1].set_xlabel(r'Color Index', size='x-large');
axes[1, 1].set_title(calibTables[4].replace(".csv",""), size='x-large');

df = pd.read_csv(calibTables[5], names=['red','green', 'blue'], index_col=False)
axes[1, 2].plot(np.linspace(0,256,256), df['red'].values,linewidth=2)
axes[1, 2].plot(np.linspace(0,256,256), df['green'].values,linewidth=2)
axes[1, 2].plot(np.linspace(0,256,256), df['blue'].values,linewidth=2)
axes[1, 2].set_title(calibTables[5].replace(".csv",""), size='x-large');

Figure 7. The CLUT tables from the MATLAB script (above) ploted against the index of the row in the table.

The CubicSpline Calibration Table looks like it is a good fit. This table is available as a .csv file:

In [73]:
calibTables[5]
Out[73]:
'cubicsplineCalibration.csv'

Uploading new CLUTs and measuring

After fitting new curves to the colorCal['noGamma'] data above, we performed a new measurement on the monitor with the Gamma Clut uploaded to PTB.

A Mavo-Monitor USB photometer was used to re-measure the $cd/m^2$ of the CRT Monitor with the Gamma clut.

21 evenly spaced values of absolute red, green, blue and gray were presented on the screen using PsychToolBox. The RGB color values are given in the table of tuples, colorValues (below).

Indexed colors were presented on the entire screen until a button was pressed. The Mavo-Monitor USB was positioned at the center of the screen, and measurements on the colored screen was taken twice.

We plot the results of the readings to assess linearity below.

In [7]:
mavoUSB = {"gamma":{"gr": np.array([1.37, 19.66, 34.1, 46.8, 55.5, 64.5, 71.6, 79.2, 87.1, 94.8, 101.0, 106.0, 110.1, 114.1, 116.6, 119.4, 122.3, 124.4,
126.9, 129.0, 130.4]),
"r": np.array([1.39, 5.88, 8.3, 10.64, 12.97, 15.43, 17.76, 20.3, 22.6, 25.2, 27.3, 28.8, 30.2, 31.5, 32.9, 34.1, 35.6, 37.1, 38.4, 39.7,
40.8]),
"g": np.array([1.38, 12.42, 19.38, 26.3, 32.7, 39.1, 45.4, 52.6, 59.8, 66.9, 73.6, 80.9, 88.1, 94.1, 98.6, 103.6, 108.9, 
         113.4, 118.7, 124.2, 128.7]),
"b": np.array([1.34, 3.82, 5.07, 6.3, 7.4, 8.58, 9.74, 10.9, 11.98, 13.17, 14.35, 15.6, 16.7, 17.7, 18.3, 18.98, 19.51,
         20.0, 20.4, 21.0, 21.5])}}
In [32]:
# the table of colors that were used with the gamma clut:
colorValues = {"rValues_normed": [], "gValues_normed": [], "bValues_normed": [],
              "rValues": [], "gValues": [], "bValues": []}
for i in list(np.linspace(0, 1, 21)):
    colorValues['rValues_normed'].append((float(str(i)[0:4]), 0, 0))
    colorValues['gValues_normed'].append((0, float(str(i)[0:4]), 0))
    colorValues['bValues_normed'].append((0, 0, float(str(i)[0:4])))
for i in np.linspace(0, 255, 21, dtype=int):
    colorValues['rValues'].append((i,0,0))
    colorValues['gValues'].append((0,i,0))
    colorValues['bValues'].append((0,0,i))
colorValues = pd.DataFrame(colorValues)
colorValues.head()
Out[32]:
bValues bValues_normed gValues gValues_normed rValues rValues_normed
0 (0, 0, 0) (0, 0, 0.0) (0, 0, 0) (0, 0.0, 0) (0, 0, 0) (0.0, 0, 0)
1 (0, 0, 12) (0, 0, 0.05) (0, 12, 0) (0, 0.05, 0) (12, 0, 0) (0.05, 0, 0)
2 (0, 0, 25) (0, 0, 0.1) (0, 25, 0) (0, 0.1, 0) (25, 0, 0) (0.1, 0, 0)
3 (0, 0, 38) (0, 0, 0.15) (0, 38, 0) (0, 0.15, 0) (38, 0, 0) (0.15, 0, 0)
4 (0, 0, 51) (0, 0, 0.2) (0, 51, 0) (0, 0.2, 0) (51, 0, 0) (0.2, 0, 0)
In [9]:
def giveRange(x):
    return np.max(x) - np.min(x)
fig = plt.figure(figsize=(12, 3))
ax = plt.subplot(141);
ax.plot(ramp, mavoUSB['gamma']['r'], ".", color="r", linewidth=2);
ax.plot(range(0,256), np.linspace(0,giveRange(mavoUSB['gamma']['r']),256), 'r')
ax.set_xlim([-10, 260]);
ax.set_ylim([0, np.max(mavoUSB['gamma']['r'])]);
ax.set_ylabel(r'$cd/m^2$', size='xx-large');
ax = plt.subplot(142);
ax.plot(ramp, mavoUSB['gamma']['b'], ".", color="b", linewidth=2);
ax.plot(range(0,256), np.linspace(0,giveRange(mavoUSB['gamma']['b']),256), 'b')
ax.set_xlim([-10, 260]);
ax.set_ylim([0, np.max(mavoUSB['gamma']['b'])]);
ax.set_title("Screen('LoadNormalizedGammaTable') \n USED", size='x-large');
ax.set_xlabel(r'Color Index', size='x-large');
ax = plt.subplot(143);
ax.plot(ramp, mavoUSB['gamma']['g'], ".", color="g",  linewidth=2);
ax.plot(range(0,256), np.linspace(0,giveRange(mavoUSB['gamma']['g']),256), 'g')
ax.set_xlim([-10, 260]);
ax.set_ylim([0, np.max(mavoUSB['gamma']['g'])]);
ax = plt.subplot(144);
ax.plot(ramp, mavoUSB['gamma']['gr'], ".", color="black",  linewidth=2);
ax.plot(range(0,256), np.linspace(0,giveRange(mavoUSB['gamma']['gr']),256), 'black')
ax.set_xlim([-10, 260]);
ax.set_ylim([0, np.max(mavoUSB['gamma']['gr'])]);

Figure 8. Uploading a Gamma Clut fit from the colorCal['noGamma'] data nearly linearizes the guns of the CRT monitor. A linear plot of the range of luminance for the screen is shown in solid line. Dots show the measurements taken for the 21 values.

In [15]:
fig = plt.figure(figsize=(12, 3))
ax = plt.subplot(141);
ax.plot(ramp, colorCal['noGamma']['r'], ".", color="r", linewidth=2);
ax.plot(ramp, mavoUSB['gamma']['r'], "-", color="r", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['r'])]);
ax.set_ylabel(r'$cd/m^2$', size='xx-large');
ax = plt.subplot(142);
ax.plot(ramp, colorCal['noGamma']['b'], ".", color="b", linewidth=2);
ax.plot(ramp, mavoUSB['gamma']['b'], "-", color="b", linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['b'])]);
ax.set_title("Screen('LoadNormalizedGammaTable') \n NOT USED", size='x-large');
ax.set_xlabel(r'Color Index', size='x-large');
ax = plt.subplot(143);
ax.plot(ramp, colorCal['noGamma']['g'], ".", color="g",  linewidth=2);
ax.plot(ramp, mavoUSB['gamma']['g'], "-", color="g",  linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['g'])]);
ax = plt.subplot(144);
ax.plot(ramp, colorCal['noGamma']['gr'], ".", color="black",  linewidth=2);
ax.plot(ramp, mavoUSB['gamma']['gr'], "-", color="black",  linewidth=2);
ax.set_xlim([0, 260]);
ax.set_ylim([0, np.max(colorCal['noGamma']['gr'])]);

Figure 9. Uploading a Gamma Clut fit from the colorCal['noGamma'] data nearly linearizes the guns of the CRT monitor. The linearized readings of the luminance for the screen are shown with a solid line. Dots show the measurements taken for the 21 values without the CLUT uploaded.