├── LICENSE
├── README.md
└── colorpy
├── COPYING.LESSER.txt
├── COPYING.txt
├── ColorPy.html
├── MANIFEST.in
├── PKG-INFO
├── README.txt
├── __init__.py
├── blackbody.py
├── ciexyz.py
├── colormodels.py
├── data
├── CIEXYZ_1931_x2.txt
├── CIEXYZ_1931_y2.txt
├── CIEXYZ_1931_z2.txt
├── Illuminanta.txt
├── Illuminantd65.txt
├── ciexyz31_1.txt
└── massage_CIEXYZ.py
├── dist
├── colorpy-0.1.0.tar.gz
├── colorpy-0.1.0.win32.exe
└── colorpy-0.1.0.zip
├── figures.py
├── illuminants.py
├── index.html
├── license.txt
├── misc.py
├── plots.py
├── rayleigh.py
├── setup.py
├── test.py
├── test_blackbody.py
├── test_ciexyz.py
├── test_colormodels.py
├── test_illuminants.py
├── test_rayleigh.py
├── test_thinfilm.py
└── thinfilm.py
/README.md:
--------------------------------------------------------------------------------
1 | ColorPy
2 | =======
3 |
4 | Physical color calculations in Python.
5 |
6 | More documentation is currently at http://markkness.net/colorpy/ColorPy.html.
7 |
8 |
9 | 
10 | A taste of the plots that ColorPy can create: RGB values for the pure spectral lines.
11 |
12 |
13 | Version 0.1.1.
14 | Changes from 0.1.0:
15 | Various things I did on my local machine.
16 | A better shark fin plot, for example.
17 | Now on GitHub!
18 |
19 | Version 0.1.0.
20 | I had this hosted at http://markkness.net
21 | (and still do) but GitHub is a better place for it now.
22 |
23 |
--------------------------------------------------------------------------------
/colorpy/COPYING.LESSER.txt:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/colorpy/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include *.py
2 | include README.txt
3 | include COPYING.txt
4 | include COPYING.LESSER.txt
5 | include license.txt
6 | include ColorPy.html
7 | prune data/massage_CIEXYZ.py
8 |
--------------------------------------------------------------------------------
/colorpy/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 1.0
2 | Name: colorpy
3 | Version: 0.1.0
4 | Summary: Color calculations with physical descriptions of light spectra
5 | Home-page: http://markkness.net/colorpy/
6 | Author: Mark Kness
7 | Author-email: mkness@alumni.utexas.net
8 | License: GNU Lesser GPL Version 3
9 | Description:
10 | ColorPy is a Python package to convert physical descriptions of light -
11 | spectra of light intensity vs. wavelength - into RGB colors that can
12 | be drawn on a computer screen.
13 | It provides a nice set of attractive plots that you can make of such
14 | spectra, and some other color related functions as well.
15 |
16 | Platform: UNKNOWN
17 |
--------------------------------------------------------------------------------
/colorpy/README.txt:
--------------------------------------------------------------------------------
1 | *** ReadMe for ColorPy 0.1.0. ***
2 |
3 | ColorPy is a Python package that can convert physical descriptions of light -
4 | spectra of light intensity vs. wavelength - into RGB colors that can
5 | be drawn on a computer screen.
6 | It provides a nice set of attractive plots that you can make of such
7 | spectra, and some other color related functions as well.
8 |
9 | Unpacking the Distribution:
10 |
11 | The instruction depend on if you are using Windows or Linux.
12 | If you are using Windows, you can use the binary distribution executable,
13 | and all you need to do is run that. Otherwise...
14 |
15 | Windows -
16 |
17 | Unzip the .zip distribution. Recent versions of Windows (XP or later),
18 | will unpack the directory automatically, you can simply enter the
19 | directory in Windows Explorer. You will probably need to copy the
20 | uncompressed files into another directory.
21 |
22 | Linux -
23 |
24 | The distribution is a compressed tar archive, uncompress it as follows:
25 |
26 | gunzip -c colorpy-0.1.0.tar.gz | tar xf -
27 | cd colorpy-0.1.0
28 |
29 | Installation:
30 |
31 | To install ColorPy from the source distributions (.zip on Windows,
32 | or .tar.gz on Linux) you must first unpack the distribution.
33 |
34 | Then, from the directory in which the files are unpacked, run:
35 |
36 | python setup.py install
37 |
38 | It is possible that you may need to supply a path to the Python executable.
39 | You also probably will need administrator privileges to do this.
40 |
41 | This should complete the installation.
42 |
43 | If you are installing from the Windows binary distribution (.win32.exe),
44 | then all you need to do is run that executable and follow the prompts.
45 |
46 | After installation, I recommend that you run the test cases.
47 | In the Python interpreter, do:
48 |
49 | import colorpy.test
50 | colorpy.test.test()
51 |
52 | This should run several test cases.
53 | As an additional (and more interesting) test, create the sample figures:
54 |
55 | import colorpy.figures
56 | colorpy.figures.figures()
57 |
58 | This should create a number of plot files (typically .png files) in
59 | the current directory. These will include all of the plots in the HTML
60 | documentation, as well as several others.
61 |
62 | License:
63 |
64 | Copyright (C) 2008 Mark Kness
65 |
66 | Author - Mark Kness - mkness@alumni.utexas.net
67 |
68 | This file is part of ColorPy.
69 |
70 | ColorPy is free software: you can redistribute it and/or modify
71 | it under the terms of the GNU Lesser General Public License as
72 | published by the Free Software Foundation, either version 3 of
73 | the License, or (at your option) any later version.
74 |
75 | ColorPy is distributed in the hope that it will be useful,
76 | but WITHOUT ANY WARRANTY; without even the implied warranty of
77 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78 | GNU Lesser General Public License for more details.
79 |
80 | You should have received a copy of the GNU Lesser General Public License
81 | along with ColorPy. If not, see .
82 |
--------------------------------------------------------------------------------
/colorpy/__init__.py:
--------------------------------------------------------------------------------
1 | '''
2 | __init__.py
3 |
4 | ColorPy is a Python package to convert physical descriptions of light:
5 | spectra of light intensity vs. wavelength - into RGB colors that can
6 | be drawn on a computer screen.
7 | It provides a nice set of attractive plots that you can make of such
8 | spectra, and some other color related functions as well.
9 |
10 | License:
11 |
12 | Copyright (C) 2008 Mark Kness
13 |
14 | Author - Mark Kness - mkness@alumni.utexas.net
15 |
16 | This file is part of ColorPy.
17 |
18 | ColorPy is free software: you can redistribute it and/or modify
19 | it under the terms of the GNU Lesser General Public License as
20 | published by the Free Software Foundation, either version 3 of
21 | the License, or (at your option) any later version.
22 |
23 | ColorPy is distributed in the hope that it will be useful,
24 | but WITHOUT ANY WARRANTY; without even the implied warranty of
25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 | GNU Lesser General Public License for more details.
27 |
28 | You should have received a copy of the GNU Lesser General Public License
29 | along with ColorPy. If not, see .
30 | '''
31 |
32 | # This file only needs to exist to indicate that this is a package.
33 |
--------------------------------------------------------------------------------
/colorpy/blackbody.py:
--------------------------------------------------------------------------------
1 | '''
2 | blackbody.py - Color of thermal blackbodies.
3 |
4 | Description:
5 |
6 | Calculate the spectrum of a thermal blackbody at an arbitrary temperature.
7 |
8 | Constants:
9 |
10 | PLANCK_CONSTANT - Planck's constant, in J-sec
11 | SPEED_OF_LIGHT - Speed of light, in m/sec
12 | BOLTZMAN_CONSTANT - Boltzman's constant, in J/K
13 | SUN_TEMPERATURE - Surface temperature of the Sun, in K
14 |
15 | Functions:
16 |
17 | blackbody_specific_intensity (wl_nm, T_K) -
18 | Get the monochromatic specific intensity for a blackbody -
19 | wl_nm = wavelength [nm]
20 | T_K = temperature [K]
21 | This is the energy radiated per second per unit wavelength per unit solid angle.
22 | Reference - Shu, eq. 4.6, p. 78.
23 |
24 | blackbody_spectrum (T_K) -
25 | Get the spectrum of a blackbody, as a numpy array.
26 |
27 | blackbody_color (T_K) -
28 | Given a temperature (K), return the xyz color of a thermal blackbody.
29 |
30 | Plots:
31 |
32 | blackbody_patch_plot (T_list, title, filename) -
33 | Draw a patch plot of blackbody colors for the given temperature range.
34 |
35 | blackbody_color_vs_temperature_plot (T_list, title, filename) -
36 | Draw a color vs temperature plot for the given temperature range.
37 |
38 | blackbody_spectrum_plot (T_K) -
39 | Draw the spectrum of a blackbody at the given temperature.
40 |
41 | References:
42 |
43 | Frank H. Shu, The Physical Universe. An Introduction to Astronomy,
44 | University Science Books, Mill Valley, California. 1982. ISBN 0-935702-05-9.
45 |
46 | Charles Kittel and Herbert Kroemer, Thermal Physics, 2nd edition,
47 | W. H. Freeman, New York, 1980. ISBN 0-7167-1088-9.
48 |
49 | License:
50 |
51 | Copyright (C) 2008 Mark Kness
52 |
53 | Author - Mark Kness - mkness@alumni.utexas.net
54 |
55 | This file is part of ColorPy.
56 |
57 | ColorPy is free software: you can redistribute it and/or modify
58 | it under the terms of the GNU Lesser General Public License as
59 | published by the Free Software Foundation, either version 3 of
60 | the License, or (at your option) any later version.
61 |
62 | ColorPy is distributed in the hope that it will be useful,
63 | but WITHOUT ANY WARRANTY; without even the implied warranty of
64 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65 | GNU Lesser General Public License for more details.
66 |
67 | You should have received a copy of the GNU Lesser General Public License
68 | along with ColorPy. If not, see .
69 | '''
70 | import math
71 | import numpy
72 | import pylab
73 |
74 | import colormodels
75 | import ciexyz
76 | import plots
77 |
78 | # Physical constants in mks units
79 | PLANCK_CONSTANT = 6.6237e-34 # J-sec
80 | SPEED_OF_LIGHT = 2.997925e+08 # m/sec
81 | BOLTZMAN_CONSTANT = 1.3802e-23 # J/K
82 | SUN_TEMPERATURE = 5778.0 # K
83 |
84 | def blackbody_specific_intensity (wl_nm, T_K):
85 | '''Get the monochromatic specific intensity for a blackbody -
86 | wl_nm = wavelength [nm]
87 | T_K = temperature [K]
88 | This is the energy radiated per second per unit wavelength per unit solid angle.
89 | Reference - Shu, eq. 4.6, p. 78.'''
90 | # precalculations that could be made global
91 | a = (PLANCK_CONSTANT * SPEED_OF_LIGHT) / (BOLTZMAN_CONSTANT)
92 | b = (2.0 * PLANCK_CONSTANT * SPEED_OF_LIGHT * SPEED_OF_LIGHT)
93 | wl_m = wl_nm * 1.0e-9
94 | inv_exponent = (wl_m * T_K) / a
95 | # Very large exponents (small inv_exponent) result in nearly zero intensity.
96 | # Avoid the numeric troubles in this case and return zero intensity.
97 | if inv_exponent < 1.0 / 500.0:
98 | return 0.0
99 | exponent = 1.0 / inv_exponent
100 | specific_intensity = b / (math.pow (wl_m, 5) * (math.exp (exponent) - 1.0))
101 | return specific_intensity
102 |
103 | def blackbody_spectrum (T_K):
104 | '''Get the spectrum of a blackbody, as a numpy array.'''
105 | spectrum = ciexyz.empty_spectrum()
106 | num_wl = spectrum.shape[0]
107 | for i in range (0, num_wl):
108 | # Intensity per unit wavelength.
109 | specific_intensity = blackbody_specific_intensity (spectrum [i][0], T_K)
110 | # Scale by size of wavelength interval.
111 | spectrum [i][1] = specific_intensity * ciexyz.delta_wl_nm * 1.0e-9
112 | return spectrum
113 |
114 | def blackbody_color (T_K):
115 | '''Given a temperature (K), return the xyz color of a thermal blackbody.'''
116 | spectrum = blackbody_spectrum (T_K)
117 | xyz = ciexyz.xyz_from_spectrum (spectrum)
118 | return xyz
119 |
120 | #
121 | # Figures
122 | #
123 |
124 | def blackbody_patch_plot (T_list, title, filename):
125 | '''Draw a patch plot of blackbody colors for the given temperature range.'''
126 | xyz_colors = []
127 | color_names = []
128 | for Ti in T_list:
129 | xyz = blackbody_color (Ti)
130 | xyz_colors.append (xyz)
131 | name = '%g K' % (Ti)
132 | color_names.append (name)
133 | plots.xyz_patch_plot (xyz_colors, color_names, title, filename)
134 |
135 | def blackbody_color_vs_temperature_plot (T_list, title, filename):
136 | '''Draw a color vs temperature plot for the given temperature range.'''
137 | num_T = len (T_list)
138 | rgb_list = numpy.empty ((num_T, 3))
139 | for i in range (0, num_T):
140 | T_i = T_list [i]
141 | xyz = blackbody_color (T_i)
142 | rgb_list [i] = colormodels.rgb_from_xyz (xyz)
143 | # Note that b and g become negative for low T.
144 | # MatPlotLib skips those on the semilog plot.
145 | plots.color_vs_param_plot (
146 | T_list,
147 | rgb_list,
148 | title,
149 | filename,
150 | plotfunc = pylab.semilogy,
151 | tight = True,
152 | xlabel = r'Temperature (K)',
153 | ylabel = r'RGB Color')
154 |
155 | def blackbody_spectrum_plot (T_K):
156 | '''Draw the spectrum of a blackbody at the given temperature.'''
157 | spectrum = blackbody_spectrum (T_K)
158 | title = 'Blackbody Spectrum - T %d K' % (round (T_K))
159 | filename = 'BlackbodySpectrum-%dK' % (round (T_K))
160 | plots.spectrum_plot (
161 | spectrum,
162 | title,
163 | filename,
164 | xlabel = 'Wavelength (nm)',
165 | ylabel = 'Specific Intensity')
166 | #ylabel = 'Intensity ($W/m^2$)') # with LaTex symbols, the axis text gets too big...
167 |
168 | # Create sample figures
169 |
170 | def figures ():
171 | '''Create some blackbody plots.'''
172 | # Some patch plots.
173 | T_norm = plots.log_interpolate ( 1200.0, 20000.0, 48)
174 | T_hot = plots.log_interpolate (10000.0, 40000.0, 24)
175 | T_cool = plots.log_interpolate ( 950.0, 1200.0, 24)
176 | blackbody_patch_plot (T_norm, 'Blackbody Colors', 'Blackbody-Patch')
177 | blackbody_patch_plot (T_hot, 'Hot Blackbody Colors', 'Blackbody-HotPatch')
178 | blackbody_patch_plot (T_cool, 'Cool Blackbody Colors', 'Blackbody-CoolPatch')
179 |
180 | # Color vs temperature.
181 | T_norm = numpy.linspace( 1200.0, 16000.0, 300)
182 | T_hot = numpy.linspace(10000.0, 40000.0, 300)
183 | T_cool = numpy.linspace( 950.0, 1200.0, 300)
184 | blackbody_color_vs_temperature_plot (T_norm, 'Blackbody Colors', 'Blackbody-Colors')
185 | blackbody_color_vs_temperature_plot (T_hot, 'Hot Blackbody Colors', 'Blackbody-HotColors')
186 | blackbody_color_vs_temperature_plot (T_cool, 'Cool Blackbody Colors', 'Blackbody-CoolColors')
187 |
188 | # Spectrum for some specific temperatures.
189 | blackbody_spectrum_plot (2000.0)
190 | blackbody_spectrum_plot (3000.0) # Proxima Centauri.
191 | blackbody_spectrum_plot (SUN_TEMPERATURE) # Sun.
192 | blackbody_spectrum_plot (11000.0) # Rigel.
193 | blackbody_spectrum_plot (15000.0)
194 |
195 |
196 | if __name__ == '__main__':
197 | figures()
198 |
--------------------------------------------------------------------------------
/colorpy/data/CIEXYZ_1931_x2.txt:
--------------------------------------------------------------------------------
1 | l, nm x2bar(l)
2 | 380 0,001368
3 | 385 0,002236
4 | 390 0,004243
5 | 395 0,007650
6 | 400 0,014310
7 | 405 0,023190
8 | 410 0,043510
9 | 415 0,077630
10 | 420 0,134380
11 | 425 0,214770
12 | 430 0,283900
13 | 435 0,328500
14 | 440 0,348280
15 | 445 0,348060
16 | 450 0,336200
17 | 455 0,318700
18 | 460 0,290800
19 | 465 0,251100
20 | 470 0,195360
21 | 475 0,142100
22 | 480 0,095640
23 | 485 0,057950
24 | 490 0,032010
25 | 495 0,014700
26 | 500 0,004900
27 | 505 0,002400
28 | 510 0,009300
29 | 515 0,029100
30 | 520 0,063270
31 | 525 0,109600
32 | 530 0,165500
33 | 535 0,225750
34 | 540 0,290400
35 | 545 0,359700
36 | 550 0,433450
37 | 555 0,512050
38 | 560 0,594500
39 | 565 0,678400
40 | 570 0,762100
41 | 575 0,842500
42 | 580 0,916300
43 | 585 0,978600
44 | 590 1,026300
45 | 595 1,056700
46 | 600 1,062200
47 | 605 1,045600
48 | 610 1,002600
49 | 615 0,938400
50 | 620 0,854450
51 | 625 0,751400
52 | 630 0,642400
53 | 635 0,541900
54 | 640 0,447900
55 | 645 0,360800
56 | 650 0,283500
57 | 655 0,218700
58 | 660 0,164900
59 | 665 0,121200
60 | 670 0,087400
61 | 675 0,063600
62 | 680 0,046770
63 | 685 0,032900
64 | 690 0,022700
65 | 695 0,015840
66 | 700 0,011359
67 | 705 0,008111
68 | 710 0,005790
69 | 715 0,004109
70 | 720 0,002899
71 | 725 0,002049
72 | 730 0,001440
73 | 735 0,001000
74 | 740 0,000690
75 | 745 0,000476
76 | 750 0,000332
77 | 755 0,000235
78 | 760 0,000166
79 | 765 0,000117
80 | 770 0,000083
81 | 775 0,000059
82 | 780 0,000042
83 | Sum.: 21,371524
84 |
--------------------------------------------------------------------------------
/colorpy/data/CIEXYZ_1931_y2.txt:
--------------------------------------------------------------------------------
1 | l, nm y2bar(l)
2 | 380 0,000039
3 | 385 0,000064
4 | 390 0,000120
5 | 395 0,000217
6 | 400 0,000396
7 | 405 0,000640
8 | 410 0,001210
9 | 415 0,002180
10 | 420 0,004000
11 | 425 0,007300
12 | 430 0,011600
13 | 435 0,016840
14 | 440 0,023000
15 | 445 0,029800
16 | 450 0,038000
17 | 455 0,048000
18 | 460 0,060000
19 | 465 0,073900
20 | 470 0,090980
21 | 475 0,112600
22 | 480 0,139020
23 | 485 0,169300
24 | 490 0,208020
25 | 495 0,258600
26 | 500 0,323000
27 | 505 0,407300
28 | 510 0,503000
29 | 515 0,608200
30 | 520 0,710000
31 | 525 0,793200
32 | 530 0,862000
33 | 535 0,914850
34 | 540 0,954000
35 | 545 0,980300
36 | 550 0,994950
37 | 555 1,000000
38 | 560 0,995000
39 | 565 0,978600
40 | 570 0,952000
41 | 575 0,915400
42 | 580 0,870000
43 | 585 0,816300
44 | 590 0,757000
45 | 595 0,694900
46 | 600 0,631000
47 | 605 0,566800
48 | 610 0,503000
49 | 615 0,441200
50 | 620 0,381000
51 | 625 0,321000
52 | 630 0,265000
53 | 635 0,217000
54 | 640 0,175000
55 | 645 0,138200
56 | 650 0,107000
57 | 655 0,081600
58 | 660 0,061000
59 | 665 0,044580
60 | 670 0,032000
61 | 675 0,023200
62 | 680 0,017000
63 | 685 0,011920
64 | 690 0,008210
65 | 695 0,005723
66 | 700 0,004102
67 | 705 0,002929
68 | 710 0,002091
69 | 715 0,001484
70 | 720 0,001047
71 | 725 0,000740
72 | 730 0,000520
73 | 735 0,000361
74 | 740 0,000249
75 | 745 0,000172
76 | 750 0,000120
77 | 755 0,000085
78 | 760 0,000060
79 | 765 0,000042
80 | 770 0,000030
81 | 775 0,000021
82 | 780 0,000015
83 | Sum.: 21,371327
84 |
--------------------------------------------------------------------------------
/colorpy/data/CIEXYZ_1931_z2.txt:
--------------------------------------------------------------------------------
1 | l, nm z2bar(l)
2 | 380 0,006450
3 | 385 0,010550
4 | 390 0,020050
5 | 395 0,036210
6 | 400 0,067850
7 | 405 0,110200
8 | 410 0,207400
9 | 415 0,371300
10 | 420 0,645600
11 | 425 1,039050
12 | 430 1,385600
13 | 435 1,622960
14 | 440 1,747060
15 | 445 1,782600
16 | 450 1,772110
17 | 455 1,744100
18 | 460 1,669200
19 | 465 1,528100
20 | 470 1,287640
21 | 475 1,041900
22 | 480 0,812950
23 | 485 0,616200
24 | 490 0,465180
25 | 495 0,353300
26 | 500 0,272000
27 | 505 0,212300
28 | 510 0,158200
29 | 515 0,111700
30 | 520 0,078250
31 | 525 0,057250
32 | 530 0,042160
33 | 535 0,029840
34 | 540 0,020300
35 | 545 0,013400
36 | 550 0,008750
37 | 555 0,005750
38 | 560 0,003900
39 | 565 0,002750
40 | 570 0,002100
41 | 575 0,001800
42 | 580 0,001650
43 | 585 0,001400
44 | 590 0,001100
45 | 595 0,001000
46 | 600 0,000800
47 | 605 0,000600
48 | 610 0,000340
49 | 615 0,000240
50 | 620 0,000190
51 | 625 0,000100
52 | 630 0,000050
53 | 635 0,000030
54 | 640 0,000020
55 | 645 0,000010
56 | 650 0,000000
57 | 655 0,000000
58 | 660 0,000000
59 | 665 0,000000
60 | 670 0,000000
61 | 675 0,000000
62 | 680 0,000000
63 | 685 0,000000
64 | 690 0,000000
65 | 695 0,000000
66 | 700 0,000000
67 | 705 0,000000
68 | 710 0,000000
69 | 715 0,000000
70 | 720 0,000000
71 | 725 0,000000
72 | 730 0,000000
73 | 735 0,000000
74 | 740 0,000000
75 | 745 0,000000
76 | 750 0,000000
77 | 755 0,000000
78 | 760 0,000000
79 | 765 0,000000
80 | 770 0,000000
81 | 775 0,000000
82 | 780 0,000000
83 | Sum.: 21,37154
84 |
--------------------------------------------------------------------------------
/colorpy/data/Illuminanta.txt:
--------------------------------------------------------------------------------
1 | 300, 0.930483
2 | 301, 0.967643
3 | 302, 1.005970
4 | 303, 1.045490
5 | 304, 1.086230
6 | 305, 1.128210
7 | 306, 1.171470
8 | 307, 1.216020
9 | 308, 1.261880
10 | 309, 1.309100
11 | 310, 1.357690
12 | 311, 1.407680
13 | 312, 1.459100
14 | 313, 1.511980
15 | 314, 1.566330
16 | 315, 1.622190
17 | 316, 1.679590
18 | 317, 1.738550
19 | 318, 1.799100
20 | 319, 1.861270
21 | 320, 1.925080
22 | 321, 1.990570
23 | 322, 2.057760
24 | 323, 2.126670
25 | 324, 2.197340
26 | 325, 2.269800
27 | 326, 2.344060
28 | 327, 2.420170
29 | 328, 2.498140
30 | 329, 2.578010
31 | 330, 2.659810
32 | 331, 2.743550
33 | 332, 2.829280
34 | 333, 2.917010
35 | 334, 3.006780
36 | 335, 3.098610
37 | 336, 3.192530
38 | 337, 3.288570
39 | 338, 3.386760
40 | 339, 3.487120
41 | 340, 3.589680
42 | 341, 3.694470
43 | 342, 3.801520
44 | 343, 3.910850
45 | 344, 4.022500
46 | 345, 4.136480
47 | 346, 4.252820
48 | 347, 4.371560
49 | 348, 4.492720
50 | 349, 4.616310
51 | 350, 4.742380
52 | 351, 4.870950
53 | 352, 5.002040
54 | 353, 5.135680
55 | 354, 5.271890
56 | 355, 5.410700
57 | 356, 5.552130
58 | 357, 5.696220
59 | 358, 5.842980
60 | 359, 5.992440
61 | 360, 6.144620
62 | 361, 6.299550
63 | 362, 6.457240
64 | 363, 6.617740
65 | 364, 6.781050
66 | 365, 6.947200
67 | 366, 7.116210
68 | 367, 7.288110
69 | 368, 7.462920
70 | 369, 7.640660
71 | 370, 7.821350
72 | 371, 8.005010
73 | 372, 8.191670
74 | 373, 8.381340
75 | 374, 8.574040
76 | 375, 8.769800
77 | 376, 8.968640
78 | 377, 9.170560
79 | 378, 9.375610
80 | 379, 9.583780
81 | 380, 9.795100
82 | 381, 10.009600
83 | 382, 10.227300
84 | 383, 10.448100
85 | 384, 10.672200
86 | 385, 10.899600
87 | 386, 11.130200
88 | 387, 11.364000
89 | 388, 11.601200
90 | 389, 11.841600
91 | 390, 12.085300
92 | 391, 12.332400
93 | 392, 12.582800
94 | 393, 12.836600
95 | 394, 13.093800
96 | 395, 13.354300
97 | 396, 13.618200
98 | 397, 13.885500
99 | 398, 14.156300
100 | 399, 14.430400
101 | 400, 14.708000
102 | 401, 14.989100
103 | 402, 15.273600
104 | 403, 15.561600
105 | 404, 15.853000
106 | 405, 16.148000
107 | 406, 16.446400
108 | 407, 16.748400
109 | 408, 17.053800
110 | 409, 17.362800
111 | 410, 17.675300
112 | 411, 17.991300
113 | 412, 18.310800
114 | 413, 18.633900
115 | 414, 18.960500
116 | 415, 19.290700
117 | 416, 19.624400
118 | 417, 19.961700
119 | 418, 20.302600
120 | 419, 20.647000
121 | 420, 20.995000
122 | 421, 21.346500
123 | 422, 21.701600
124 | 423, 22.060300
125 | 424, 22.422500
126 | 425, 22.788300
127 | 426, 23.157700
128 | 427, 23.530700
129 | 428, 23.907200
130 | 429, 24.287300
131 | 430, 24.670900
132 | 431, 25.058100
133 | 432, 25.448900
134 | 433, 25.843200
135 | 434, 26.241100
136 | 435, 26.642500
137 | 436, 27.047500
138 | 437, 27.456000
139 | 438, 27.868100
140 | 439, 28.283600
141 | 440, 28.702700
142 | 441, 29.125300
143 | 442, 29.551500
144 | 443, 29.981100
145 | 444, 30.414200
146 | 445, 30.850800
147 | 446, 31.290900
148 | 447, 31.734500
149 | 448, 32.181500
150 | 449, 32.632000
151 | 450, 33.085900
152 | 451, 33.543200
153 | 452, 34.004000
154 | 453, 34.468200
155 | 454, 34.935800
156 | 455, 35.406800
157 | 456, 35.881100
158 | 457, 36.358800
159 | 458, 36.839900
160 | 459, 37.324300
161 | 460, 37.812100
162 | 461, 38.303100
163 | 462, 38.797500
164 | 463, 39.295100
165 | 464, 39.796000
166 | 465, 40.300200
167 | 466, 40.807600
168 | 467, 41.318200
169 | 468, 41.832000
170 | 469, 42.349100
171 | 470, 42.869300
172 | 471, 43.392600
173 | 472, 43.919200
174 | 473, 44.448800
175 | 474, 44.981600
176 | 475, 45.517400
177 | 476, 46.056300
178 | 477, 46.598300
179 | 478, 47.143300
180 | 479, 47.691300
181 | 480, 48.242300
182 | 481, 48.796300
183 | 482, 49.353300
184 | 483, 49.913200
185 | 484, 50.476000
186 | 485, 51.041800
187 | 486, 51.610400
188 | 487, 52.181800
189 | 488, 52.756100
190 | 489, 53.333200
191 | 490, 53.913200
192 | 491, 54.495800
193 | 492, 55.081300
194 | 493, 55.669400
195 | 494, 56.260300
196 | 495, 56.853900
197 | 496, 57.450100
198 | 497, 58.048900
199 | 498, 58.650400
200 | 499, 59.254500
201 | 500, 59.861100
202 | 501, 60.470300
203 | 502, 61.082000
204 | 503, 61.696200
205 | 504, 62.312800
206 | 505, 62.932000
207 | 506, 63.553500
208 | 507, 64.177500
209 | 508, 64.803800
210 | 509, 65.432500
211 | 510, 66.063500
212 | 511, 66.696800
213 | 512, 67.332400
214 | 513, 67.970200
215 | 514, 68.610200
216 | 515, 69.252500
217 | 516, 69.896900
218 | 517, 70.543500
219 | 518, 71.192200
220 | 519, 71.843000
221 | 520, 72.495900
222 | 521, 73.150800
223 | 522, 73.807700
224 | 523, 74.466600
225 | 524, 75.127500
226 | 525, 75.790300
227 | 526, 76.455100
228 | 527, 77.121700
229 | 528, 77.790200
230 | 529, 78.460500
231 | 530, 79.132600
232 | 531, 79.806500
233 | 532, 80.482100
234 | 533, 81.159500
235 | 534, 81.838600
236 | 535, 82.519300
237 | 536, 83.201700
238 | 537, 83.885600
239 | 538, 84.571200
240 | 539, 85.258400
241 | 540, 85.947000
242 | 541, 86.637200
243 | 542, 87.328800
244 | 543, 88.021900
245 | 544, 88.716500
246 | 545, 89.412400
247 | 546, 90.109700
248 | 547, 90.808300
249 | 548, 91.508200
250 | 549, 92.209500
251 | 550, 92.912000
252 | 551, 93.615700
253 | 552, 94.320600
254 | 553, 95.026700
255 | 554, 95.733900
256 | 555, 96.442300
257 | 556, 97.151800
258 | 557, 97.862300
259 | 558, 98.573900
260 | 559, 99.286400
261 | 560, 100.000000
262 | 561, 100.715000
263 | 562, 101.430000
264 | 563, 102.146000
265 | 564, 102.864000
266 | 565, 103.582000
267 | 566, 104.301000
268 | 567, 105.020000
269 | 568, 105.741000
270 | 569, 106.462000
271 | 570, 107.184000
272 | 571, 107.906000
273 | 572, 108.630000
274 | 573, 109.354000
275 | 574, 110.078000
276 | 575, 110.803000
277 | 576, 111.529000
278 | 577, 112.255000
279 | 578, 112.982000
280 | 579, 113.709000
281 | 580, 114.436000
282 | 581, 115.164000
283 | 582, 115.893000
284 | 583, 116.622000
285 | 584, 117.351000
286 | 585, 118.080000
287 | 586, 118.810000
288 | 587, 119.540000
289 | 588, 120.270000
290 | 589, 121.001000
291 | 590, 121.731000
292 | 591, 122.462000
293 | 592, 123.193000
294 | 593, 123.924000
295 | 594, 124.655000
296 | 595, 125.386000
297 | 596, 126.118000
298 | 597, 126.849000
299 | 598, 127.580000
300 | 599, 128.312000
301 | 600, 129.043000
302 | 601, 129.774000
303 | 602, 130.505000
304 | 603, 131.236000
305 | 604, 131.966000
306 | 605, 132.697000
307 | 606, 133.427000
308 | 607, 134.157000
309 | 608, 134.887000
310 | 609, 135.617000
311 | 610, 136.346000
312 | 611, 137.075000
313 | 612, 137.804000
314 | 613, 138.532000
315 | 614, 139.260000
316 | 615, 139.988000
317 | 616, 140.715000
318 | 617, 141.441000
319 | 618, 142.167000
320 | 619, 142.893000
321 | 620, 143.618000
322 | 621, 144.343000
323 | 622, 145.067000
324 | 623, 145.790000
325 | 624, 146.513000
326 | 625, 147.235000
327 | 626, 147.957000
328 | 627, 148.678000
329 | 628, 149.398000
330 | 629, 150.117000
331 | 630, 150.836000
332 | 631, 151.554000
333 | 632, 152.271000
334 | 633, 152.988000
335 | 634, 153.704000
336 | 635, 154.418000
337 | 636, 155.132000
338 | 637, 155.845000
339 | 638, 156.558000
340 | 639, 157.269000
341 | 640, 157.979000
342 | 641, 158.689000
343 | 642, 159.397000
344 | 643, 160.104000
345 | 644, 160.811000
346 | 645, 161.516000
347 | 646, 162.221000
348 | 647, 162.924000
349 | 648, 163.626000
350 | 649, 164.327000
351 | 650, 165.028000
352 | 651, 165.726000
353 | 652, 166.424000
354 | 653, 167.121000
355 | 654, 167.816000
356 | 655, 168.510000
357 | 656, 169.203000
358 | 657, 169.895000
359 | 658, 170.586000
360 | 659, 171.275000
361 | 660, 171.963000
362 | 661, 172.650000
363 | 662, 173.335000
364 | 663, 174.019000
365 | 664, 174.702000
366 | 665, 175.383000
367 | 666, 176.063000
368 | 667, 176.741000
369 | 668, 177.419000
370 | 669, 178.094000
371 | 670, 178.769000
372 | 671, 179.441000
373 | 672, 180.113000
374 | 673, 180.783000
375 | 674, 181.451000
376 | 675, 182.118000
377 | 676, 182.783000
378 | 677, 183.447000
379 | 678, 184.109000
380 | 679, 184.770000
381 | 680, 185.429000
382 | 681, 186.087000
383 | 682, 186.743000
384 | 683, 187.397000
385 | 684, 188.050000
386 | 685, 188.701000
387 | 686, 189.350000
388 | 687, 189.998000
389 | 688, 190.644000
390 | 689, 191.288000
391 | 690, 191.931000
392 | 691, 192.572000
393 | 692, 193.211000
394 | 693, 193.849000
395 | 694, 194.484000
396 | 695, 195.118000
397 | 696, 195.750000
398 | 697, 196.381000
399 | 698, 197.009000
400 | 699, 197.636000
401 | 700, 198.261000
402 | 701, 198.884000
403 | 702, 199.506000
404 | 703, 200.125000
405 | 704, 200.743000
406 | 705, 201.359000
407 | 706, 201.972000
408 | 707, 202.584000
409 | 708, 203.195000
410 | 709, 203.803000
411 | 710, 204.409000
412 | 711, 205.013000
413 | 712, 205.616000
414 | 713, 206.216000
415 | 714, 206.815000
416 | 715, 207.411000
417 | 716, 208.006000
418 | 717, 208.599000
419 | 718, 209.189000
420 | 719, 209.778000
421 | 720, 210.365000
422 | 721, 210.949000
423 | 722, 211.532000
424 | 723, 212.112000
425 | 724, 212.691000
426 | 725, 213.268000
427 | 726, 213.842000
428 | 727, 214.415000
429 | 728, 214.985000
430 | 729, 215.553000
431 | 730, 216.120000
432 | 731, 216.684000
433 | 732, 217.246000
434 | 733, 217.806000
435 | 734, 218.364000
436 | 735, 218.920000
437 | 736, 219.473000
438 | 737, 220.025000
439 | 738, 220.574000
440 | 739, 221.122000
441 | 740, 221.667000
442 | 741, 222.210000
443 | 742, 222.751000
444 | 743, 223.290000
445 | 744, 223.826000
446 | 745, 224.361000
447 | 746, 224.893000
448 | 747, 225.423000
449 | 748, 225.951000
450 | 749, 226.477000
451 | 750, 227.000000
452 | 751, 227.522000
453 | 752, 228.041000
454 | 753, 228.558000
455 | 754, 229.073000
456 | 755, 229.585000
457 | 756, 230.096000
458 | 757, 230.604000
459 | 758, 231.110000
460 | 759, 231.614000
461 | 760, 232.115000
462 | 761, 232.615000
463 | 762, 233.112000
464 | 763, 233.606000
465 | 764, 234.099000
466 | 765, 234.589000
467 | 766, 235.078000
468 | 767, 235.564000
469 | 768, 236.047000
470 | 769, 236.529000
471 | 770, 237.008000
472 | 771, 237.485000
473 | 772, 237.959000
474 | 773, 238.432000
475 | 774, 238.902000
476 | 775, 239.370000
477 | 776, 239.836000
478 | 777, 240.299000
479 | 778, 240.760000
480 | 779, 241.219000
481 | 780, 241.675000
482 | 781, 242.130000
483 | 782, 242.582000
484 | 783, 243.031000
485 | 784, 243.479000
486 | 785, 243.924000
487 | 786, 244.367000
488 | 787, 244.808000
489 | 788, 245.246000
490 | 789, 245.682000
491 | 790, 246.116000
492 | 791, 246.548000
493 | 792, 246.977000
494 | 793, 247.404000
495 | 794, 247.829000
496 | 795, 248.251000
497 | 796, 248.671000
498 | 797, 249.089000
499 | 798, 249.505000
500 | 799, 249.918000
501 | 800, 250.329000
502 | 801, 250.738000
503 | 802, 251.144000
504 | 803, 251.548000
505 | 804, 251.950000
506 | 805, 252.350000
507 | 806, 252.747000
508 | 807, 253.142000
509 | 808, 253.535000
510 | 809, 253.925000
511 | 810, 254.314000
512 | 811, 254.700000
513 | 812, 255.083000
514 | 813, 255.465000
515 | 814, 255.844000
516 | 815, 256.221000
517 | 816, 256.595000
518 | 817, 256.968000
519 | 818, 257.338000
520 | 819, 257.706000
521 | 820, 258.071000
522 | 821, 258.434000
523 | 822, 258.795000
524 | 823, 259.154000
525 | 824, 259.511000
526 | 825, 259.865000
527 | 826, 260.217000
528 | 827, 260.567000
529 | 828, 260.914000
530 | 829, 261.259000
531 | 830, 261.602000
532 |
--------------------------------------------------------------------------------
/colorpy/data/Illuminantd65.txt:
--------------------------------------------------------------------------------
1 | 300, 0.034100
2 | 301, 0.360140
3 | 302, 0.686180
4 | 303, 1.012220
5 | 304, 1.338260
6 | 305, 1.664300
7 | 306, 1.990340
8 | 307, 2.316380
9 | 308, 2.642420
10 | 309, 2.968460
11 | 310, 3.294500
12 | 311, 4.988650
13 | 312, 6.682800
14 | 313, 8.376950
15 | 314, 10.071100
16 | 315, 11.765200
17 | 316, 13.459400
18 | 317, 15.153500
19 | 318, 16.847700
20 | 319, 18.541800
21 | 320, 20.236000
22 | 321, 21.917700
23 | 322, 23.599500
24 | 323, 25.281200
25 | 324, 26.963000
26 | 325, 28.644700
27 | 326, 30.326500
28 | 327, 32.008200
29 | 328, 33.690000
30 | 329, 35.371700
31 | 330, 37.053500
32 | 331, 37.343000
33 | 332, 37.632600
34 | 333, 37.922100
35 | 334, 38.211600
36 | 335, 38.501100
37 | 336, 38.790700
38 | 337, 39.080200
39 | 338, 39.369700
40 | 339, 39.659300
41 | 340, 39.948800
42 | 341, 40.445100
43 | 342, 40.941400
44 | 343, 41.437700
45 | 344, 41.934000
46 | 345, 42.430200
47 | 346, 42.926500
48 | 347, 43.422800
49 | 348, 43.919100
50 | 349, 44.415400
51 | 350, 44.911700
52 | 351, 45.084400
53 | 352, 45.257000
54 | 353, 45.429700
55 | 354, 45.602300
56 | 355, 45.775000
57 | 356, 45.947700
58 | 357, 46.120300
59 | 358, 46.293000
60 | 359, 46.465600
61 | 360, 46.638300
62 | 361, 47.183400
63 | 362, 47.728500
64 | 363, 48.273500
65 | 364, 48.818600
66 | 365, 49.363700
67 | 366, 49.908800
68 | 367, 50.453900
69 | 368, 50.998900
70 | 369, 51.544000
71 | 370, 52.089100
72 | 371, 51.877700
73 | 372, 51.666400
74 | 373, 51.455000
75 | 374, 51.243700
76 | 375, 51.032300
77 | 376, 50.820900
78 | 377, 50.609600
79 | 378, 50.398200
80 | 379, 50.186900
81 | 380, 49.975500
82 | 381, 50.442800
83 | 382, 50.910000
84 | 383, 51.377300
85 | 384, 51.844600
86 | 385, 52.311800
87 | 386, 52.779100
88 | 387, 53.246400
89 | 388, 53.713700
90 | 389, 54.180900
91 | 390, 54.648200
92 | 391, 57.458900
93 | 392, 60.269500
94 | 393, 63.080200
95 | 394, 65.890900
96 | 395, 68.701500
97 | 396, 71.512200
98 | 397, 74.322900
99 | 398, 77.133600
100 | 399, 79.944200
101 | 400, 82.754900
102 | 401, 83.628000
103 | 402, 84.501100
104 | 403, 85.374200
105 | 404, 86.247300
106 | 405, 87.120400
107 | 406, 87.993600
108 | 407, 88.866700
109 | 408, 89.739800
110 | 409, 90.612900
111 | 410, 91.486000
112 | 411, 91.680600
113 | 412, 91.875200
114 | 413, 92.069700
115 | 414, 92.264300
116 | 415, 92.458900
117 | 416, 92.653500
118 | 417, 92.848100
119 | 418, 93.042600
120 | 419, 93.237200
121 | 420, 93.431800
122 | 421, 92.756800
123 | 422, 92.081900
124 | 423, 91.406900
125 | 424, 90.732000
126 | 425, 90.057000
127 | 426, 89.382100
128 | 427, 88.707100
129 | 428, 88.032200
130 | 429, 87.357200
131 | 430, 86.682300
132 | 431, 88.500600
133 | 432, 90.318800
134 | 433, 92.137100
135 | 434, 93.955400
136 | 435, 95.773600
137 | 436, 97.591900
138 | 437, 99.410200
139 | 438, 101.228000
140 | 439, 103.047000
141 | 440, 104.865000
142 | 441, 106.079000
143 | 442, 107.294000
144 | 443, 108.508000
145 | 444, 109.722000
146 | 445, 110.936000
147 | 446, 112.151000
148 | 447, 113.365000
149 | 448, 114.579000
150 | 449, 115.794000
151 | 450, 117.008000
152 | 451, 117.088000
153 | 452, 117.169000
154 | 453, 117.249000
155 | 454, 117.330000
156 | 455, 117.410000
157 | 456, 117.490000
158 | 457, 117.571000
159 | 458, 117.651000
160 | 459, 117.732000
161 | 460, 117.812000
162 | 461, 117.517000
163 | 462, 117.222000
164 | 463, 116.927000
165 | 464, 116.632000
166 | 465, 116.336000
167 | 466, 116.041000
168 | 467, 115.746000
169 | 468, 115.451000
170 | 469, 115.156000
171 | 470, 114.861000
172 | 471, 114.967000
173 | 472, 115.073000
174 | 473, 115.180000
175 | 474, 115.286000
176 | 475, 115.392000
177 | 476, 115.498000
178 | 477, 115.604000
179 | 478, 115.711000
180 | 479, 115.817000
181 | 480, 115.923000
182 | 481, 115.212000
183 | 482, 114.501000
184 | 483, 113.789000
185 | 484, 113.078000
186 | 485, 112.367000
187 | 486, 111.656000
188 | 487, 110.945000
189 | 488, 110.233000
190 | 489, 109.522000
191 | 490, 108.811000
192 | 491, 108.865000
193 | 492, 108.920000
194 | 493, 108.974000
195 | 494, 109.028000
196 | 495, 109.082000
197 | 496, 109.137000
198 | 497, 109.191000
199 | 498, 109.245000
200 | 499, 109.300000
201 | 500, 109.354000
202 | 501, 109.199000
203 | 502, 109.044000
204 | 503, 108.888000
205 | 504, 108.733000
206 | 505, 108.578000
207 | 506, 108.423000
208 | 507, 108.268000
209 | 508, 108.112000
210 | 509, 107.957000
211 | 510, 107.802000
212 | 511, 107.501000
213 | 512, 107.200000
214 | 513, 106.898000
215 | 514, 106.597000
216 | 515, 106.296000
217 | 516, 105.995000
218 | 517, 105.694000
219 | 518, 105.392000
220 | 519, 105.091000
221 | 520, 104.790000
222 | 521, 105.080000
223 | 522, 105.370000
224 | 523, 105.660000
225 | 524, 105.950000
226 | 525, 106.239000
227 | 526, 106.529000
228 | 527, 106.819000
229 | 528, 107.109000
230 | 529, 107.399000
231 | 530, 107.689000
232 | 531, 107.361000
233 | 532, 107.032000
234 | 533, 106.704000
235 | 534, 106.375000
236 | 535, 106.047000
237 | 536, 105.719000
238 | 537, 105.390000
239 | 538, 105.062000
240 | 539, 104.733000
241 | 540, 104.405000
242 | 541, 104.369000
243 | 542, 104.333000
244 | 543, 104.297000
245 | 544, 104.261000
246 | 545, 104.225000
247 | 546, 104.190000
248 | 547, 104.154000
249 | 548, 104.118000
250 | 549, 104.082000
251 | 550, 104.046000
252 | 551, 103.641000
253 | 552, 103.237000
254 | 553, 102.832000
255 | 554, 102.428000
256 | 555, 102.023000
257 | 556, 101.618000
258 | 557, 101.214000
259 | 558, 100.809000
260 | 559, 100.405000
261 | 560, 100.000000
262 | 561, 99.633400
263 | 562, 99.266800
264 | 563, 98.900300
265 | 564, 98.533700
266 | 565, 98.167100
267 | 566, 97.800500
268 | 567, 97.433900
269 | 568, 97.067400
270 | 569, 96.700800
271 | 570, 96.334200
272 | 571, 96.279600
273 | 572, 96.225000
274 | 573, 96.170300
275 | 574, 96.115700
276 | 575, 96.061100
277 | 576, 96.006500
278 | 577, 95.951900
279 | 578, 95.897200
280 | 579, 95.842600
281 | 580, 95.788000
282 | 581, 95.077800
283 | 582, 94.367500
284 | 583, 93.657300
285 | 584, 92.947000
286 | 585, 92.236800
287 | 586, 91.526600
288 | 587, 90.816300
289 | 588, 90.106100
290 | 589, 89.395800
291 | 590, 88.685600
292 | 591, 88.817700
293 | 592, 88.949700
294 | 593, 89.081800
295 | 594, 89.213800
296 | 595, 89.345900
297 | 596, 89.478000
298 | 597, 89.610000
299 | 598, 89.742100
300 | 599, 89.874100
301 | 600, 90.006200
302 | 601, 89.965500
303 | 602, 89.924800
304 | 603, 89.884100
305 | 604, 89.843400
306 | 605, 89.802600
307 | 606, 89.761900
308 | 607, 89.721200
309 | 608, 89.680500
310 | 609, 89.639800
311 | 610, 89.599100
312 | 611, 89.409100
313 | 612, 89.219000
314 | 613, 89.029000
315 | 614, 88.838900
316 | 615, 88.648900
317 | 616, 88.458900
318 | 617, 88.268800
319 | 618, 88.078800
320 | 619, 87.888700
321 | 620, 87.698700
322 | 621, 87.257700
323 | 622, 86.816700
324 | 623, 86.375700
325 | 624, 85.934700
326 | 625, 85.493600
327 | 626, 85.052600
328 | 627, 84.611600
329 | 628, 84.170600
330 | 629, 83.729600
331 | 630, 83.288600
332 | 631, 83.329700
333 | 632, 83.370700
334 | 633, 83.411800
335 | 634, 83.452800
336 | 635, 83.493900
337 | 636, 83.535000
338 | 637, 83.576000
339 | 638, 83.617100
340 | 639, 83.658100
341 | 640, 83.699200
342 | 641, 83.332000
343 | 642, 82.964700
344 | 643, 82.597500
345 | 644, 82.230200
346 | 645, 81.863000
347 | 646, 81.495800
348 | 647, 81.128500
349 | 648, 80.761300
350 | 649, 80.394000
351 | 650, 80.026800
352 | 651, 80.045600
353 | 652, 80.064400
354 | 653, 80.083100
355 | 654, 80.101900
356 | 655, 80.120700
357 | 656, 80.139500
358 | 657, 80.158300
359 | 658, 80.177000
360 | 659, 80.195800
361 | 660, 80.214600
362 | 661, 80.420900
363 | 662, 80.627200
364 | 663, 80.833600
365 | 664, 81.039900
366 | 665, 81.246200
367 | 666, 81.452500
368 | 667, 81.658800
369 | 668, 81.865200
370 | 669, 82.071500
371 | 670, 82.277800
372 | 671, 81.878400
373 | 672, 81.479100
374 | 673, 81.079700
375 | 674, 80.680400
376 | 675, 80.281000
377 | 676, 79.881600
378 | 677, 79.482300
379 | 678, 79.082900
380 | 679, 78.683600
381 | 680, 78.284200
382 | 681, 77.427900
383 | 682, 76.571600
384 | 683, 75.715300
385 | 684, 74.859000
386 | 685, 74.002700
387 | 686, 73.146500
388 | 687, 72.290200
389 | 688, 71.433900
390 | 689, 70.577600
391 | 690, 69.721300
392 | 691, 69.910100
393 | 692, 70.098900
394 | 693, 70.287600
395 | 694, 70.476400
396 | 695, 70.665200
397 | 696, 70.854000
398 | 697, 71.042800
399 | 698, 71.231500
400 | 699, 71.420300
401 | 700, 71.609100
402 | 701, 71.883100
403 | 702, 72.157100
404 | 703, 72.431100
405 | 704, 72.705100
406 | 705, 72.979000
407 | 706, 73.253000
408 | 707, 73.527000
409 | 708, 73.801000
410 | 709, 74.075000
411 | 710, 74.349000
412 | 711, 73.074500
413 | 712, 71.800000
414 | 713, 70.525500
415 | 714, 69.251000
416 | 715, 67.976500
417 | 716, 66.702000
418 | 717, 65.427500
419 | 718, 64.153000
420 | 719, 62.878500
421 | 720, 61.604000
422 | 721, 62.432200
423 | 722, 63.260300
424 | 723, 64.088500
425 | 724, 64.916600
426 | 725, 65.744800
427 | 726, 66.573000
428 | 727, 67.401100
429 | 728, 68.229300
430 | 729, 69.057400
431 | 730, 69.885600
432 | 731, 70.405700
433 | 732, 70.925900
434 | 733, 71.446000
435 | 734, 71.966200
436 | 735, 72.486300
437 | 736, 73.006400
438 | 737, 73.526600
439 | 738, 74.046700
440 | 739, 74.566900
441 | 740, 75.087000
442 | 741, 73.937600
443 | 742, 72.788100
444 | 743, 71.638700
445 | 744, 70.489300
446 | 745, 69.339800
447 | 746, 68.190400
448 | 747, 67.041000
449 | 748, 65.891600
450 | 749, 64.742100
451 | 750, 63.592700
452 | 751, 61.875200
453 | 752, 60.157800
454 | 753, 58.440300
455 | 754, 56.722900
456 | 755, 55.005400
457 | 756, 53.288000
458 | 757, 51.570500
459 | 758, 49.853100
460 | 759, 48.135600
461 | 760, 46.418200
462 | 761, 48.456900
463 | 762, 50.495600
464 | 763, 52.534400
465 | 764, 54.573100
466 | 765, 56.611800
467 | 766, 58.650500
468 | 767, 60.689200
469 | 768, 62.728000
470 | 769, 64.766700
471 | 770, 66.805400
472 | 771, 66.463100
473 | 772, 66.120900
474 | 773, 65.778600
475 | 774, 65.436400
476 | 775, 65.094100
477 | 776, 64.751800
478 | 777, 64.409600
479 | 778, 64.067300
480 | 779, 63.725100
481 | 780, 63.382800
482 | 781, 63.474900
483 | 782, 63.567000
484 | 783, 63.659200
485 | 784, 63.751300
486 | 785, 63.843400
487 | 786, 63.935500
488 | 787, 64.027600
489 | 788, 64.119800
490 | 789, 64.211900
491 | 790, 64.304000
492 | 791, 63.818800
493 | 792, 63.333600
494 | 793, 62.848400
495 | 794, 62.363200
496 | 795, 61.877900
497 | 796, 61.392700
498 | 797, 60.907500
499 | 798, 60.422300
500 | 799, 59.937100
501 | 800, 59.451900
502 | 801, 58.702600
503 | 802, 57.953300
504 | 803, 57.204000
505 | 804, 56.454700
506 | 805, 55.705400
507 | 806, 54.956200
508 | 807, 54.206900
509 | 808, 53.457600
510 | 809, 52.708300
511 | 810, 51.959000
512 | 811, 52.507200
513 | 812, 53.055300
514 | 813, 53.603500
515 | 814, 54.151600
516 | 815, 54.699800
517 | 816, 55.248000
518 | 817, 55.796100
519 | 818, 56.344300
520 | 819, 56.892400
521 | 820, 57.440600
522 | 821, 57.727800
523 | 822, 58.015000
524 | 823, 58.302200
525 | 824, 58.589400
526 | 825, 58.876500
527 | 826, 59.163700
528 | 827, 59.450900
529 | 828, 59.738100
530 | 829, 60.025300
531 | 830, 60.312500
532 |
--------------------------------------------------------------------------------
/colorpy/data/ciexyz31_1.txt:
--------------------------------------------------------------------------------
1 | 360, 0.000129900000, 0.000003917000, 0.000606100000
2 | 361, 0.000145847000, 0.000004393581, 0.000680879200
3 | 362, 0.000163802100, 0.000004929604, 0.000765145600
4 | 363, 0.000184003700, 0.000005532136, 0.000860012400
5 | 364, 0.000206690200, 0.000006208245, 0.000966592800
6 | 365, 0.000232100000, 0.000006965000, 0.001086000000
7 | 366, 0.000260728000, 0.000007813219, 0.001220586000
8 | 367, 0.000293075000, 0.000008767336, 0.001372729000
9 | 368, 0.000329388000, 0.000009839844, 0.001543579000
10 | 369, 0.000369914000, 0.000011043230, 0.001734286000
11 | 370, 0.000414900000, 0.000012390000, 0.001946000000
12 | 371, 0.000464158700, 0.000013886410, 0.002177777000
13 | 372, 0.000518986000, 0.000015557280, 0.002435809000
14 | 373, 0.000581854000, 0.000017442960, 0.002731953000
15 | 374, 0.000655234700, 0.000019583750, 0.003078064000
16 | 375, 0.000741600000, 0.000022020000, 0.003486000000
17 | 376, 0.000845029600, 0.000024839650, 0.003975227000
18 | 377, 0.000964526800, 0.000028041260, 0.004540880000
19 | 378, 0.001094949000, 0.000031531040, 0.005158320000
20 | 379, 0.001231154000, 0.000035215210, 0.005802907000
21 | 380, 0.001368000000, 0.000039000000, 0.006450001000
22 | 381, 0.001502050000, 0.000042826400, 0.007083216000
23 | 382, 0.001642328000, 0.000046914600, 0.007745488000
24 | 383, 0.001802382000, 0.000051589600, 0.008501152000
25 | 384, 0.001995757000, 0.000057176400, 0.009414544000
26 | 385, 0.002236000000, 0.000064000000, 0.010549990000
27 | 386, 0.002535385000, 0.000072344210, 0.011965800000
28 | 387, 0.002892603000, 0.000082212240, 0.013655870000
29 | 388, 0.003300829000, 0.000093508160, 0.015588050000
30 | 389, 0.003753236000, 0.000106136100, 0.017730150000
31 | 390, 0.004243000000, 0.000120000000, 0.020050010000
32 | 391, 0.004762389000, 0.000134984000, 0.022511360000
33 | 392, 0.005330048000, 0.000151492000, 0.025202880000
34 | 393, 0.005978712000, 0.000170208000, 0.028279720000
35 | 394, 0.006741117000, 0.000191816000, 0.031897040000
36 | 395, 0.007650000000, 0.000217000000, 0.036210000000
37 | 396, 0.008751373000, 0.000246906700, 0.041437710000
38 | 397, 0.010028880000, 0.000281240000, 0.047503720000
39 | 398, 0.011421700000, 0.000318520000, 0.054119880000
40 | 399, 0.012869010000, 0.000357266700, 0.060998030000
41 | 400, 0.014310000000, 0.000396000000, 0.067850010000
42 | 401, 0.015704430000, 0.000433714700, 0.074486320000
43 | 402, 0.017147440000, 0.000473024000, 0.081361560000
44 | 403, 0.018781220000, 0.000517876000, 0.089153640000
45 | 404, 0.020748010000, 0.000572218700, 0.098540480000
46 | 405, 0.023190000000, 0.000640000000, 0.110200000000
47 | 406, 0.026207360000, 0.000724560000, 0.124613300000
48 | 407, 0.029782480000, 0.000825500000, 0.141701700000
49 | 408, 0.033880920000, 0.000941160000, 0.161303500000
50 | 409, 0.038468240000, 0.001069880000, 0.183256800000
51 | 410, 0.043510000000, 0.001210000000, 0.207400000000
52 | 411, 0.048995600000, 0.001362091000, 0.233692100000
53 | 412, 0.055022600000, 0.001530752000, 0.262611400000
54 | 413, 0.061718800000, 0.001720368000, 0.294774600000
55 | 414, 0.069212000000, 0.001935323000, 0.330798500000
56 | 415, 0.077630000000, 0.002180000000, 0.371300000000
57 | 416, 0.086958110000, 0.002454800000, 0.416209100000
58 | 417, 0.097176720000, 0.002764000000, 0.465464200000
59 | 418, 0.108406300000, 0.003117800000, 0.519694800000
60 | 419, 0.120767200000, 0.003526400000, 0.579530300000
61 | 420, 0.134380000000, 0.004000000000, 0.645600000000
62 | 421, 0.149358200000, 0.004546240000, 0.718483800000
63 | 422, 0.165395700000, 0.005159320000, 0.796713300000
64 | 423, 0.181983100000, 0.005829280000, 0.877845900000
65 | 424, 0.198611000000, 0.006546160000, 0.959439000000
66 | 425, 0.214770000000, 0.007300000000, 1.039050100000
67 | 426, 0.230186800000, 0.008086507000, 1.115367300000
68 | 427, 0.244879700000, 0.008908720000, 1.188497100000
69 | 428, 0.258777300000, 0.009767680000, 1.258123300000
70 | 429, 0.271807900000, 0.010664430000, 1.323929600000
71 | 430, 0.283900000000, 0.011600000000, 1.385600000000
72 | 431, 0.294943800000, 0.012573170000, 1.442635200000
73 | 432, 0.304896500000, 0.013582720000, 1.494803500000
74 | 433, 0.313787300000, 0.014629680000, 1.542190300000
75 | 434, 0.321645400000, 0.015715090000, 1.584880700000
76 | 435, 0.328500000000, 0.016840000000, 1.622960000000
77 | 436, 0.334351300000, 0.018007360000, 1.656404800000
78 | 437, 0.339210100000, 0.019214480000, 1.685295900000
79 | 438, 0.343121300000, 0.020453920000, 1.709874500000
80 | 439, 0.346129600000, 0.021718240000, 1.730382100000
81 | 440, 0.348280000000, 0.023000000000, 1.747060000000
82 | 441, 0.349599900000, 0.024294610000, 1.760044600000
83 | 442, 0.350147400000, 0.025610240000, 1.769623300000
84 | 443, 0.350013000000, 0.026958570000, 1.776263700000
85 | 444, 0.349287000000, 0.028351250000, 1.780433400000
86 | 445, 0.348060000000, 0.029800000000, 1.782600000000
87 | 446, 0.346373300000, 0.031310830000, 1.782968200000
88 | 447, 0.344262400000, 0.032883680000, 1.781699800000
89 | 448, 0.341808800000, 0.034521120000, 1.779198200000
90 | 449, 0.339094100000, 0.036225710000, 1.775867100000
91 | 450, 0.336200000000, 0.038000000000, 1.772110000000
92 | 451, 0.333197700000, 0.039846670000, 1.768258900000
93 | 452, 0.330041100000, 0.041768000000, 1.764039000000
94 | 453, 0.326635700000, 0.043766000000, 1.758943800000
95 | 454, 0.322886800000, 0.045842670000, 1.752466300000
96 | 455, 0.318700000000, 0.048000000000, 1.744100000000
97 | 456, 0.314025100000, 0.050243680000, 1.733559500000
98 | 457, 0.308884000000, 0.052573040000, 1.720858100000
99 | 458, 0.303290400000, 0.054980560000, 1.705936900000
100 | 459, 0.297257900000, 0.057458720000, 1.688737200000
101 | 460, 0.290800000000, 0.060000000000, 1.669200000000
102 | 461, 0.283970100000, 0.062601970000, 1.647528700000
103 | 462, 0.276721400000, 0.065277520000, 1.623412700000
104 | 463, 0.268917800000, 0.068042080000, 1.596022300000
105 | 464, 0.260422700000, 0.070911090000, 1.564528000000
106 | 465, 0.251100000000, 0.073900000000, 1.528100000000
107 | 466, 0.240847500000, 0.077016000000, 1.486111400000
108 | 467, 0.229851200000, 0.080266400000, 1.439521500000
109 | 468, 0.218407200000, 0.083666800000, 1.389879900000
110 | 469, 0.206811500000, 0.087232800000, 1.338736200000
111 | 470, 0.195360000000, 0.090980000000, 1.287640000000
112 | 471, 0.184213600000, 0.094917550000, 1.237422300000
113 | 472, 0.173327300000, 0.099045840000, 1.187824300000
114 | 473, 0.162688100000, 0.103367400000, 1.138761100000
115 | 474, 0.152283300000, 0.107884600000, 1.090148000000
116 | 475, 0.142100000000, 0.112600000000, 1.041900000000
117 | 476, 0.132178600000, 0.117532000000, 0.994197600000
118 | 477, 0.122569600000, 0.122674400000, 0.947347300000
119 | 478, 0.113275200000, 0.127992800000, 0.901453100000
120 | 479, 0.104297900000, 0.133452800000, 0.856619300000
121 | 480, 0.095640000000, 0.139020000000, 0.812950100000
122 | 481, 0.087299550000, 0.144676400000, 0.770517300000
123 | 482, 0.079308040000, 0.150469300000, 0.729444800000
124 | 483, 0.071717760000, 0.156461900000, 0.689913600000
125 | 484, 0.064580990000, 0.162717700000, 0.652104900000
126 | 485, 0.057950010000, 0.169300000000, 0.616200000000
127 | 486, 0.051862110000, 0.176243100000, 0.582328600000
128 | 487, 0.046281520000, 0.183558100000, 0.550416200000
129 | 488, 0.041150880000, 0.191273500000, 0.520337600000
130 | 489, 0.036412830000, 0.199418000000, 0.491967300000
131 | 490, 0.032010000000, 0.208020000000, 0.465180000000
132 | 491, 0.027917200000, 0.217119900000, 0.439924600000
133 | 492, 0.024144400000, 0.226734500000, 0.416183600000
134 | 493, 0.020687000000, 0.236857100000, 0.393882200000
135 | 494, 0.017540400000, 0.247481200000, 0.372945900000
136 | 495, 0.014700000000, 0.258600000000, 0.353300000000
137 | 496, 0.012161790000, 0.270184900000, 0.334857800000
138 | 497, 0.009919960000, 0.282293900000, 0.317552100000
139 | 498, 0.007967240000, 0.295050500000, 0.301337500000
140 | 499, 0.006296346000, 0.308578000000, 0.286168600000
141 | 500, 0.004900000000, 0.323000000000, 0.272000000000
142 | 501, 0.003777173000, 0.338402100000, 0.258817100000
143 | 502, 0.002945320000, 0.354685800000, 0.246483800000
144 | 503, 0.002424880000, 0.371698600000, 0.234771800000
145 | 504, 0.002236293000, 0.389287500000, 0.223453300000
146 | 505, 0.002400000000, 0.407300000000, 0.212300000000
147 | 506, 0.002925520000, 0.425629900000, 0.201169200000
148 | 507, 0.003836560000, 0.444309600000, 0.190119600000
149 | 508, 0.005174840000, 0.463394400000, 0.179225400000
150 | 509, 0.006982080000, 0.482939500000, 0.168560800000
151 | 510, 0.009300000000, 0.503000000000, 0.158200000000
152 | 511, 0.012149490000, 0.523569300000, 0.148138300000
153 | 512, 0.015535880000, 0.544512000000, 0.138375800000
154 | 513, 0.019477520000, 0.565690000000, 0.128994200000
155 | 514, 0.023992770000, 0.586965300000, 0.120075100000
156 | 515, 0.029100000000, 0.608200000000, 0.111700000000
157 | 516, 0.034814850000, 0.629345600000, 0.103904800000
158 | 517, 0.041120160000, 0.650306800000, 0.096667480000
159 | 518, 0.047985040000, 0.670875200000, 0.089982720000
160 | 519, 0.055378610000, 0.690842400000, 0.083845310000
161 | 520, 0.063270000000, 0.710000000000, 0.078249990000
162 | 521, 0.071635010000, 0.728185200000, 0.073208990000
163 | 522, 0.080462240000, 0.745463600000, 0.068678160000
164 | 523, 0.089739960000, 0.761969400000, 0.064567840000
165 | 524, 0.099456450000, 0.777836800000, 0.060788350000
166 | 525, 0.109600000000, 0.793200000000, 0.057250010000
167 | 526, 0.120167400000, 0.808110400000, 0.053904350000
168 | 527, 0.131114500000, 0.822496200000, 0.050746640000
169 | 528, 0.142367900000, 0.836306800000, 0.047752760000
170 | 529, 0.153854200000, 0.849491600000, 0.044898590000
171 | 530, 0.165500000000, 0.862000000000, 0.042160000000
172 | 531, 0.177257100000, 0.873810800000, 0.039507280000
173 | 532, 0.189140000000, 0.884962400000, 0.036935640000
174 | 533, 0.201169400000, 0.895493600000, 0.034458360000
175 | 534, 0.213365800000, 0.905443200000, 0.032088720000
176 | 535, 0.225749900000, 0.914850100000, 0.029840000000
177 | 536, 0.238320900000, 0.923734800000, 0.027711810000
178 | 537, 0.251066800000, 0.932092400000, 0.025694440000
179 | 538, 0.263992200000, 0.939922600000, 0.023787160000
180 | 539, 0.277101700000, 0.947225200000, 0.021989250000
181 | 540, 0.290400000000, 0.954000000000, 0.020300000000
182 | 541, 0.303891200000, 0.960256100000, 0.018718050000
183 | 542, 0.317572600000, 0.966007400000, 0.017240360000
184 | 543, 0.331438400000, 0.971260600000, 0.015863640000
185 | 544, 0.345482800000, 0.976022500000, 0.014584610000
186 | 545, 0.359700000000, 0.980300000000, 0.013400000000
187 | 546, 0.374083900000, 0.984092400000, 0.012307230000
188 | 547, 0.388639600000, 0.987418200000, 0.011301880000
189 | 548, 0.403378400000, 0.990312800000, 0.010377920000
190 | 549, 0.418311500000, 0.992811600000, 0.009529306000
191 | 550, 0.433449900000, 0.994950100000, 0.008749999000
192 | 551, 0.448795300000, 0.996710800000, 0.008035200000
193 | 552, 0.464336000000, 0.998098300000, 0.007381600000
194 | 553, 0.480064000000, 0.999112000000, 0.006785400000
195 | 554, 0.495971300000, 0.999748200000, 0.006242800000
196 | 555, 0.512050100000, 1.000000000000, 0.005749999000
197 | 556, 0.528295900000, 0.999856700000, 0.005303600000
198 | 557, 0.544691600000, 0.999304600000, 0.004899800000
199 | 558, 0.561209400000, 0.998325500000, 0.004534200000
200 | 559, 0.577821500000, 0.996898700000, 0.004202400000
201 | 560, 0.594500000000, 0.995000000000, 0.003900000000
202 | 561, 0.611220900000, 0.992600500000, 0.003623200000
203 | 562, 0.627975800000, 0.989742600000, 0.003370600000
204 | 563, 0.644760200000, 0.986444400000, 0.003141400000
205 | 564, 0.661569700000, 0.982724100000, 0.002934800000
206 | 565, 0.678400000000, 0.978600000000, 0.002749999000
207 | 566, 0.695239200000, 0.974083700000, 0.002585200000
208 | 567, 0.712058600000, 0.969171200000, 0.002438600000
209 | 568, 0.728828400000, 0.963856800000, 0.002309400000
210 | 569, 0.745518800000, 0.958134900000, 0.002196800000
211 | 570, 0.762100000000, 0.952000000000, 0.002100000000
212 | 571, 0.778543200000, 0.945450400000, 0.002017733000
213 | 572, 0.794825600000, 0.938499200000, 0.001948200000
214 | 573, 0.810926400000, 0.931162800000, 0.001889800000
215 | 574, 0.826824800000, 0.923457600000, 0.001840933000
216 | 575, 0.842500000000, 0.915400000000, 0.001800000000
217 | 576, 0.857932500000, 0.907006400000, 0.001766267000
218 | 577, 0.873081600000, 0.898277200000, 0.001737800000
219 | 578, 0.887894400000, 0.889204800000, 0.001711200000
220 | 579, 0.902318100000, 0.879781600000, 0.001683067000
221 | 580, 0.916300000000, 0.870000000000, 0.001650001000
222 | 581, 0.929799500000, 0.859861300000, 0.001610133000
223 | 582, 0.942798400000, 0.849392000000, 0.001564400000
224 | 583, 0.955277600000, 0.838622000000, 0.001513600000
225 | 584, 0.967217900000, 0.827581300000, 0.001458533000
226 | 585, 0.978600000000, 0.816300000000, 0.001400000000
227 | 586, 0.989385600000, 0.804794700000, 0.001336667000
228 | 587, 0.999548800000, 0.793082000000, 0.001270000000
229 | 588, 1.009089200000, 0.781192000000, 0.001205000000
230 | 589, 1.018006400000, 0.769154700000, 0.001146667000
231 | 590, 1.026300000000, 0.757000000000, 0.001100000000
232 | 591, 1.033982700000, 0.744754100000, 0.001068800000
233 | 592, 1.040986000000, 0.732422400000, 0.001049400000
234 | 593, 1.047188000000, 0.720003600000, 0.001035600000
235 | 594, 1.052466700000, 0.707496500000, 0.001021200000
236 | 595, 1.056700000000, 0.694900000000, 0.001000000000
237 | 596, 1.059794400000, 0.682219200000, 0.000968640000
238 | 597, 1.061799200000, 0.669471600000, 0.000929920000
239 | 598, 1.062806800000, 0.656674400000, 0.000886880000
240 | 599, 1.062909600000, 0.643844800000, 0.000842560000
241 | 600, 1.062200000000, 0.631000000000, 0.000800000000
242 | 601, 1.060735200000, 0.618155500000, 0.000760960000
243 | 602, 1.058443600000, 0.605314400000, 0.000723680000
244 | 603, 1.055224400000, 0.592475600000, 0.000685920000
245 | 604, 1.050976800000, 0.579637900000, 0.000645440000
246 | 605, 1.045600000000, 0.566800000000, 0.000600000000
247 | 606, 1.039036900000, 0.553961100000, 0.000547866700
248 | 607, 1.031360800000, 0.541137200000, 0.000491600000
249 | 608, 1.022666200000, 0.528352800000, 0.000435400000
250 | 609, 1.013047700000, 0.515632300000, 0.000383466700
251 | 610, 1.002600000000, 0.503000000000, 0.000340000000
252 | 611, 0.991367500000, 0.490468800000, 0.000307253300
253 | 612, 0.979331400000, 0.478030400000, 0.000283160000
254 | 613, 0.966491600000, 0.465677600000, 0.000265440000
255 | 614, 0.952847900000, 0.453403200000, 0.000251813300
256 | 615, 0.938400000000, 0.441200000000, 0.000240000000
257 | 616, 0.923194000000, 0.429080000000, 0.000229546700
258 | 617, 0.907244000000, 0.417036000000, 0.000220640000
259 | 618, 0.890502000000, 0.405032000000, 0.000211960000
260 | 619, 0.872920000000, 0.393032000000, 0.000202186700
261 | 620, 0.854449900000, 0.381000000000, 0.000190000000
262 | 621, 0.835084000000, 0.368918400000, 0.000174213300
263 | 622, 0.814946000000, 0.356827200000, 0.000155640000
264 | 623, 0.794186000000, 0.344776800000, 0.000135960000
265 | 624, 0.772954000000, 0.332817600000, 0.000116853300
266 | 625, 0.751400000000, 0.321000000000, 0.000100000000
267 | 626, 0.729583600000, 0.309338100000, 0.000086133330
268 | 627, 0.707588800000, 0.297850400000, 0.000074600000
269 | 628, 0.685602200000, 0.286593600000, 0.000065000000
270 | 629, 0.663810400000, 0.275624500000, 0.000056933330
271 | 630, 0.642400000000, 0.265000000000, 0.000049999990
272 | 631, 0.621514900000, 0.254763200000, 0.000044160000
273 | 632, 0.601113800000, 0.244889600000, 0.000039480000
274 | 633, 0.581105200000, 0.235334400000, 0.000035720000
275 | 634, 0.561397700000, 0.226052800000, 0.000032640000
276 | 635, 0.541900000000, 0.217000000000, 0.000030000000
277 | 636, 0.522599500000, 0.208161600000, 0.000027653330
278 | 637, 0.503546400000, 0.199548800000, 0.000025560000
279 | 638, 0.484743600000, 0.191155200000, 0.000023640000
280 | 639, 0.466193900000, 0.182974400000, 0.000021813330
281 | 640, 0.447900000000, 0.175000000000, 0.000020000000
282 | 641, 0.429861300000, 0.167223500000, 0.000018133330
283 | 642, 0.412098000000, 0.159646400000, 0.000016200000
284 | 643, 0.394644000000, 0.152277600000, 0.000014200000
285 | 644, 0.377533300000, 0.145125900000, 0.000012133330
286 | 645, 0.360800000000, 0.138200000000, 0.000010000000
287 | 646, 0.344456300000, 0.131500300000, 0.000007733333
288 | 647, 0.328516800000, 0.125024800000, 0.000005400000
289 | 648, 0.313019200000, 0.118779200000, 0.000003200000
290 | 649, 0.298001100000, 0.112769100000, 0.000001333333
291 | 650, 0.283500000000, 0.107000000000, 0.000000000000
292 | 651, 0.269544800000, 0.101476200000, 0.000000000000
293 | 652, 0.256118400000, 0.096188640000, 0.000000000000
294 | 653, 0.243189600000, 0.091122960000, 0.000000000000
295 | 654, 0.230727200000, 0.086264850000, 0.000000000000
296 | 655, 0.218700000000, 0.081600000000, 0.000000000000
297 | 656, 0.207097100000, 0.077120640000, 0.000000000000
298 | 657, 0.195923200000, 0.072825520000, 0.000000000000
299 | 658, 0.185170800000, 0.068710080000, 0.000000000000
300 | 659, 0.174832300000, 0.064769760000, 0.000000000000
301 | 660, 0.164900000000, 0.061000000000, 0.000000000000
302 | 661, 0.155366700000, 0.057396210000, 0.000000000000
303 | 662, 0.146230000000, 0.053955040000, 0.000000000000
304 | 663, 0.137490000000, 0.050673760000, 0.000000000000
305 | 664, 0.129146700000, 0.047549650000, 0.000000000000
306 | 665, 0.121200000000, 0.044580000000, 0.000000000000
307 | 666, 0.113639700000, 0.041758720000, 0.000000000000
308 | 667, 0.106465000000, 0.039084960000, 0.000000000000
309 | 668, 0.099690440000, 0.036563840000, 0.000000000000
310 | 669, 0.093330610000, 0.034200480000, 0.000000000000
311 | 670, 0.087400000000, 0.032000000000, 0.000000000000
312 | 671, 0.081900960000, 0.029962610000, 0.000000000000
313 | 672, 0.076804280000, 0.028076640000, 0.000000000000
314 | 673, 0.072077120000, 0.026329360000, 0.000000000000
315 | 674, 0.067686640000, 0.024708050000, 0.000000000000
316 | 675, 0.063600000000, 0.023200000000, 0.000000000000
317 | 676, 0.059806850000, 0.021800770000, 0.000000000000
318 | 677, 0.056282160000, 0.020501120000, 0.000000000000
319 | 678, 0.052971040000, 0.019281080000, 0.000000000000
320 | 679, 0.049818610000, 0.018120690000, 0.000000000000
321 | 680, 0.046770000000, 0.017000000000, 0.000000000000
322 | 681, 0.043784050000, 0.015903790000, 0.000000000000
323 | 682, 0.040875360000, 0.014837180000, 0.000000000000
324 | 683, 0.038072640000, 0.013810680000, 0.000000000000
325 | 684, 0.035404610000, 0.012834780000, 0.000000000000
326 | 685, 0.032900000000, 0.011920000000, 0.000000000000
327 | 686, 0.030564190000, 0.011068310000, 0.000000000000
328 | 687, 0.028380560000, 0.010273390000, 0.000000000000
329 | 688, 0.026344840000, 0.009533311000, 0.000000000000
330 | 689, 0.024452750000, 0.008846157000, 0.000000000000
331 | 690, 0.022700000000, 0.008210000000, 0.000000000000
332 | 691, 0.021084290000, 0.007623781000, 0.000000000000
333 | 692, 0.019599880000, 0.007085424000, 0.000000000000
334 | 693, 0.018237320000, 0.006591476000, 0.000000000000
335 | 694, 0.016987170000, 0.006138485000, 0.000000000000
336 | 695, 0.015840000000, 0.005723000000, 0.000000000000
337 | 696, 0.014790640000, 0.005343059000, 0.000000000000
338 | 697, 0.013831320000, 0.004995796000, 0.000000000000
339 | 698, 0.012948680000, 0.004676404000, 0.000000000000
340 | 699, 0.012129200000, 0.004380075000, 0.000000000000
341 | 700, 0.011359160000, 0.004102000000, 0.000000000000
342 | 701, 0.010629350000, 0.003838453000, 0.000000000000
343 | 702, 0.009938846000, 0.003589099000, 0.000000000000
344 | 703, 0.009288422000, 0.003354219000, 0.000000000000
345 | 704, 0.008678854000, 0.003134093000, 0.000000000000
346 | 705, 0.008110916000, 0.002929000000, 0.000000000000
347 | 706, 0.007582388000, 0.002738139000, 0.000000000000
348 | 707, 0.007088746000, 0.002559876000, 0.000000000000
349 | 708, 0.006627313000, 0.002393244000, 0.000000000000
350 | 709, 0.006195408000, 0.002237275000, 0.000000000000
351 | 710, 0.005790346000, 0.002091000000, 0.000000000000
352 | 711, 0.005409826000, 0.001953587000, 0.000000000000
353 | 712, 0.005052583000, 0.001824580000, 0.000000000000
354 | 713, 0.004717512000, 0.001703580000, 0.000000000000
355 | 714, 0.004403507000, 0.001590187000, 0.000000000000
356 | 715, 0.004109457000, 0.001484000000, 0.000000000000
357 | 716, 0.003833913000, 0.001384496000, 0.000000000000
358 | 717, 0.003575748000, 0.001291268000, 0.000000000000
359 | 718, 0.003334342000, 0.001204092000, 0.000000000000
360 | 719, 0.003109075000, 0.001122744000, 0.000000000000
361 | 720, 0.002899327000, 0.001047000000, 0.000000000000
362 | 721, 0.002704348000, 0.000976589600, 0.000000000000
363 | 722, 0.002523020000, 0.000911108800, 0.000000000000
364 | 723, 0.002354168000, 0.000850133200, 0.000000000000
365 | 724, 0.002196616000, 0.000793238400, 0.000000000000
366 | 725, 0.002049190000, 0.000740000000, 0.000000000000
367 | 726, 0.001910960000, 0.000690082700, 0.000000000000
368 | 727, 0.001781438000, 0.000643310000, 0.000000000000
369 | 728, 0.001660110000, 0.000599496000, 0.000000000000
370 | 729, 0.001546459000, 0.000558454700, 0.000000000000
371 | 730, 0.001439971000, 0.000520000000, 0.000000000000
372 | 731, 0.001340042000, 0.000483913600, 0.000000000000
373 | 732, 0.001246275000, 0.000450052800, 0.000000000000
374 | 733, 0.001158471000, 0.000418345200, 0.000000000000
375 | 734, 0.001076430000, 0.000388718400, 0.000000000000
376 | 735, 0.000999949300, 0.000361100000, 0.000000000000
377 | 736, 0.000928735800, 0.000335383500, 0.000000000000
378 | 737, 0.000862433200, 0.000311440400, 0.000000000000
379 | 738, 0.000800750300, 0.000289165600, 0.000000000000
380 | 739, 0.000743396000, 0.000268453900, 0.000000000000
381 | 740, 0.000690078600, 0.000249200000, 0.000000000000
382 | 741, 0.000640515600, 0.000231301900, 0.000000000000
383 | 742, 0.000594502100, 0.000214685600, 0.000000000000
384 | 743, 0.000551864600, 0.000199288400, 0.000000000000
385 | 744, 0.000512429000, 0.000185047500, 0.000000000000
386 | 745, 0.000476021300, 0.000171900000, 0.000000000000
387 | 746, 0.000442453600, 0.000159778100, 0.000000000000
388 | 747, 0.000411511700, 0.000148604400, 0.000000000000
389 | 748, 0.000382981400, 0.000138301600, 0.000000000000
390 | 749, 0.000356649100, 0.000128792500, 0.000000000000
391 | 750, 0.000332301100, 0.000120000000, 0.000000000000
392 | 751, 0.000309758600, 0.000111859500, 0.000000000000
393 | 752, 0.000288887100, 0.000104322400, 0.000000000000
394 | 753, 0.000269539400, 0.000097335600, 0.000000000000
395 | 754, 0.000251568200, 0.000090845870, 0.000000000000
396 | 755, 0.000234826100, 0.000084800000, 0.000000000000
397 | 756, 0.000219171000, 0.000079146670, 0.000000000000
398 | 757, 0.000204525800, 0.000073858000, 0.000000000000
399 | 758, 0.000190840500, 0.000068916000, 0.000000000000
400 | 759, 0.000178065400, 0.000064302670, 0.000000000000
401 | 760, 0.000166150500, 0.000060000000, 0.000000000000
402 | 761, 0.000155023600, 0.000055981870, 0.000000000000
403 | 762, 0.000144621900, 0.000052225600, 0.000000000000
404 | 763, 0.000134909800, 0.000048718400, 0.000000000000
405 | 764, 0.000125852000, 0.000045447470, 0.000000000000
406 | 765, 0.000117413000, 0.000042400000, 0.000000000000
407 | 766, 0.000109551500, 0.000039561040, 0.000000000000
408 | 767, 0.000102224500, 0.000036915120, 0.000000000000
409 | 768, 0.000095394450, 0.000034448680, 0.000000000000
410 | 769, 0.000089023900, 0.000032148160, 0.000000000000
411 | 770, 0.000083075270, 0.000030000000, 0.000000000000
412 | 771, 0.000077512690, 0.000027991250, 0.000000000000
413 | 772, 0.000072313040, 0.000026113560, 0.000000000000
414 | 773, 0.000067457780, 0.000024360240, 0.000000000000
415 | 774, 0.000062928440, 0.000022724610, 0.000000000000
416 | 775, 0.000058706520, 0.000021200000, 0.000000000000
417 | 776, 0.000054770280, 0.000019778550, 0.000000000000
418 | 777, 0.000051099180, 0.000018452850, 0.000000000000
419 | 778, 0.000047676540, 0.000017216870, 0.000000000000
420 | 779, 0.000044485670, 0.000016064590, 0.000000000000
421 | 780, 0.000041509940, 0.000014990000, 0.000000000000
422 | 781, 0.000038733240, 0.000013987280, 0.000000000000
423 | 782, 0.000036142030, 0.000013051550, 0.000000000000
424 | 783, 0.000033723520, 0.000012178180, 0.000000000000
425 | 784, 0.000031464870, 0.000011362540, 0.000000000000
426 | 785, 0.000029353260, 0.000010600000, 0.000000000000
427 | 786, 0.000027375730, 0.000009885877, 0.000000000000
428 | 787, 0.000025524330, 0.000009217304, 0.000000000000
429 | 788, 0.000023793760, 0.000008592362, 0.000000000000
430 | 789, 0.000022178700, 0.000008009133, 0.000000000000
431 | 790, 0.000020673830, 0.000007465700, 0.000000000000
432 | 791, 0.000019272260, 0.000006959567, 0.000000000000
433 | 792, 0.000017966400, 0.000006487995, 0.000000000000
434 | 793, 0.000016749910, 0.000006048699, 0.000000000000
435 | 794, 0.000015616480, 0.000005639396, 0.000000000000
436 | 795, 0.000014559770, 0.000005257800, 0.000000000000
437 | 796, 0.000013573870, 0.000004901771, 0.000000000000
438 | 797, 0.000012654360, 0.000004569720, 0.000000000000
439 | 798, 0.000011797230, 0.000004260194, 0.000000000000
440 | 799, 0.000010998440, 0.000003971739, 0.000000000000
441 | 800, 0.000010253980, 0.000003702900, 0.000000000000
442 | 801, 0.000009559646, 0.000003452163, 0.000000000000
443 | 802, 0.000008912044, 0.000003218302, 0.000000000000
444 | 803, 0.000008308358, 0.000003000300, 0.000000000000
445 | 804, 0.000007745769, 0.000002797139, 0.000000000000
446 | 805, 0.000007221456, 0.000002607800, 0.000000000000
447 | 806, 0.000006732475, 0.000002431220, 0.000000000000
448 | 807, 0.000006276423, 0.000002266531, 0.000000000000
449 | 808, 0.000005851304, 0.000002113013, 0.000000000000
450 | 809, 0.000005455118, 0.000001969943, 0.000000000000
451 | 810, 0.000005085868, 0.000001836600, 0.000000000000
452 | 811, 0.000004741466, 0.000001712230, 0.000000000000
453 | 812, 0.000004420236, 0.000001596228, 0.000000000000
454 | 813, 0.000004120783, 0.000001488090, 0.000000000000
455 | 814, 0.000003841716, 0.000001387314, 0.000000000000
456 | 815, 0.000003581652, 0.000001293400, 0.000000000000
457 | 816, 0.000003339127, 0.000001205820, 0.000000000000
458 | 817, 0.000003112949, 0.000001124143, 0.000000000000
459 | 818, 0.000002902121, 0.000001048009, 0.000000000000
460 | 819, 0.000002705645, 0.000000977058, 0.000000000000
461 | 820, 0.000002522525, 0.000000910930, 0.000000000000
462 | 821, 0.000002351726, 0.000000849251, 0.000000000000
463 | 822, 0.000002192415, 0.000000791721, 0.000000000000
464 | 823, 0.000002043902, 0.000000738090, 0.000000000000
465 | 824, 0.000001905497, 0.000000688110, 0.000000000000
466 | 825, 0.000001776509, 0.000000641530, 0.000000000000
467 | 826, 0.000001656215, 0.000000598090, 0.000000000000
468 | 827, 0.000001544022, 0.000000557575, 0.000000000000
469 | 828, 0.000001439440, 0.000000519808, 0.000000000000
470 | 829, 0.000001341977, 0.000000484612, 0.000000000000
471 | 830, 0.000001251141, 0.000000451810, 0.000000000000
472 |
--------------------------------------------------------------------------------
/colorpy/data/massage_CIEXYZ.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | '''
3 | massage_CIEXYZ.py - Convert CIE XYZ tables (1931 matching functions, D65)
4 | into appropriate Python syntax to be inserted into ColorPy.
5 |
6 | This was used in developing ColorPy.
7 |
8 | References:
9 |
10 | CVRL Color and Vision Database - http://cvrl.ioo.ucl.ac.uk/index.htm - (accessed 17 Sep 2008)
11 | Color and Vision Research Laboratories.
12 | Provides a set of data sets related to color vision.
13 | ColorPy uses the tables from this site for the 1931 CIE XYZ matching functions,
14 | and for Illuminant D65, both at 1 nm wavelength increments.
15 |
16 | CIE Standards - http://cvrl.ioo.ucl.ac.uk/cie.htm - (accessed 17 Sep 2008)
17 | CIE standards as maintained by CVRL.
18 | The 1931 CIE XYZ and D65 tables that ColorPy uses were obtained from the following files, linked here:
19 | http://cvrl.ioo.ucl.ac.uk/database/data/cmfs/ciexyz31_1.txt
20 | http://cvrl.ioo.ucl.ac.uk/database/data/cie/Illuminantd65.txt
21 |
22 | CIE International Commission on Illumination - http://www.cie.co.at/ - (accessed 17 Sep 2008)
23 | Official website of the CIE.
24 | There are tables of the standard functions (matching functions, illuminants) here:
25 | http://www.cie.co.at/main/freepubs.html
26 | http://www.cie.co.at/publ/abst/datatables15_2004/x2.txt
27 | http://www.cie.co.at/publ/abst/datatables15_2004/y2.txt
28 | http://www.cie.co.at/publ/abst/datatables15_2004/z2.txt
29 | http://www.cie.co.at/publ/abst/datatables15_2004/sid65.txt
30 | ColorPy does not use these specific files.
31 |
32 | License:
33 |
34 | Copyright (C) 2008 Mark Kness
35 |
36 | Author - Mark Kness - mkness@alumni.utexas.net
37 |
38 | This file is part of ColorPy.
39 |
40 | ColorPy is free software: you can redistribute it and/or modify
41 | it under the terms of the GNU Lesser General Public License as
42 | published by the Free Software Foundation, either version 3 of
43 | the License, or (at your option) any later version.
44 |
45 | ColorPy is distributed in the hope that it will be useful,
46 | but WITHOUT ANY WARRANTY; without even the implied warranty of
47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 | GNU Lesser General Public License for more details.
49 |
50 | You should have received a copy of the GNU Lesser General Public License
51 | along with ColorPy. If not, see .
52 | '''
53 | from __future__ import print_function
54 |
55 | # Conversions for data (5 nm increments) from CIE website:
56 | # http://www.cie.co.at/main/freepubs.html
57 | # http://www.cie.co.at/publ/abst/datatables15_2004/x2.txt
58 | # http://www.cie.co.at/publ/abst/datatables15_2004/y2.txt
59 | # http://www.cie.co.at/publ/abst/datatables15_2004/z2.txt
60 | # ColorPy is not using this data.
61 |
62 | # filenames as downloaded
63 | CIE_x = 'CIEXYZ_1931_x2.txt'
64 | CIE_y = 'CIEXYZ_1931_y2.txt'
65 | CIE_z = 'CIEXYZ_1931_z2.txt'
66 |
67 | def read_CIE_file (filename):
68 | rtn = dict()
69 | f = open (filename, 'r')
70 | lines = f.readlines()
71 | f.close()
72 | # discard first and last lines
73 | lines = lines [1:-1]
74 | for i in lines:
75 | # fields are: wl (nm), intensity (with comma as decimal separator)
76 | fields = i.split()
77 | wl_nm = int (fields [0])
78 | intensity = fields[1].replace (',', '.')
79 | rtn [wl_nm] = intensity
80 | return rtn
81 |
82 | def create_CIE_XYZ_1931_table_5nm ():
83 | '''Create the table, in (mostly) correct Python.'''
84 | msgs = []
85 | dict_x = read_CIE_file (CIE_x)
86 | dict_y = read_CIE_file (CIE_y)
87 | dict_z = read_CIE_file (CIE_z)
88 | # get keys
89 | keys = dict_x.keys() # all should be the same
90 | keys.sort()
91 | msgs.append ('_CIEXYZ_1931_table = [\n')
92 | for i in xrange (0, len (keys)):
93 | ikey = keys [i]
94 | wl_nm = ikey
95 | x = dict_x [ikey]
96 | y = dict_y [ikey]
97 | z = dict_z [ikey]
98 | sep = ','
99 | if i == len (keys)-1:
100 | sep = ''
101 | msgs.append (' [ %3d, %s, %s, %s ]%s\n' % (
102 | wl_nm, x, y, z, sep))
103 | msgs.append (']\n')
104 | return msgs
105 |
106 | def doit_CIE_XYZ_1931_5nm ():
107 | '''Create tables from the official CIE data.'''
108 | msgs = create_CIE_XYZ_1931_table_5nm()
109 | for i in msgs:
110 | print (i, end='')
111 | f = open ('CIE_XYZ_1931_5nm.txt', 'w')
112 | f.writelines (msgs)
113 | f.close()
114 |
115 | # Conversions for data (1 nm increments) from CVRL (Color and Vision Research Laboratories)
116 | # http://cvrl.ioo.ucl.ac.uk/database/data/cmfs/ciexyz31_1.txt
117 | # http://cvrl.ioo.ucl.ac.uk/database/data/cie/Illuminantd65.txt
118 | # ColorPy IS using this data.
119 |
120 | def create_CVRL_XYZ_1931_table_1nm ():
121 | msgs = []
122 | filename = 'ciexyz31_1.txt'
123 | f = open (filename, 'r')
124 | lines = f.readlines()
125 | f.close()
126 | msgs.append ('_CIEXYZ_1931_table = [\n')
127 | for i in xrange (0, len (lines)):
128 | iline = lines [i].rstrip()
129 | sep = ','
130 | if i == len (lines)-1:
131 | sep = ''
132 | msgs.append (' [ %s ]%s\n' % (iline, sep))
133 | msgs.append (']\n')
134 | return msgs
135 |
136 | def doit_CVRL_XYZ_1931_table_1nm ():
137 | msgs = create_CVRL_XYZ_1931_table_1nm()
138 | for i in msgs:
139 | print (i, end='')
140 | f = open ('CVRL_XYZ_1931_1nm.txt', 'w')
141 | f.writelines (msgs)
142 | f.close()
143 |
144 | # Data for CIE Illuminant D65
145 |
146 | def create_CVRL_D65_table_1nm ():
147 | msgs = []
148 | filename = 'Illuminantd65.txt'
149 | f = open (filename, 'r')
150 | lines = f.readlines()
151 | f.close()
152 | msgs.append ('_Illuminant_D65_table = [\n')
153 | for i in xrange (0, len (lines)):
154 | iline = lines [i].rstrip()
155 | sep = ','
156 | if i == len (lines)-1:
157 | sep = ''
158 | msgs.append (' [ %s ]%s\n' % (iline, sep))
159 | msgs.append (']\n')
160 | return msgs
161 |
162 | def doit_CVRL_D65_table_1nm ():
163 | msgs = create_CVRL_D65_table_1nm()
164 | for i in msgs:
165 | print (i, end='')
166 | f = open ('CVRL_D65_1nm.txt', 'w')
167 | f.writelines (msgs)
168 | f.close()
169 |
170 | # Main - perform all of the conversions.
171 | # The resulting source files are manually incorporated into the ColorPy code.
172 |
173 | def main ():
174 | doit_CIE_XYZ_1931_5nm ()
175 | doit_CVRL_XYZ_1931_table_1nm ()
176 | doit_CVRL_D65_table_1nm ()
177 |
178 |
179 | if __name__ == '__main__':
180 | main()
181 |
--------------------------------------------------------------------------------
/colorpy/dist/colorpy-0.1.0.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markkness/ColorPy/f2dad2c268895d4b046b767f3aa884f2889b84cb/colorpy/dist/colorpy-0.1.0.tar.gz
--------------------------------------------------------------------------------
/colorpy/dist/colorpy-0.1.0.win32.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markkness/ColorPy/f2dad2c268895d4b046b767f3aa884f2889b84cb/colorpy/dist/colorpy-0.1.0.win32.exe
--------------------------------------------------------------------------------
/colorpy/dist/colorpy-0.1.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markkness/ColorPy/f2dad2c268895d4b046b767f3aa884f2889b84cb/colorpy/dist/colorpy-0.1.0.zip
--------------------------------------------------------------------------------
/colorpy/figures.py:
--------------------------------------------------------------------------------
1 | '''
2 | figures.py - Create all the ColorPy sample figures.
3 |
4 | Description:
5 |
6 | Creates the sample figures.
7 |
8 | This can also create the figures with some non-default initialization conditions.
9 |
10 | Functions:
11 |
12 | figures() -
13 | Create all the sample figures.
14 |
15 | figures_clip_clamp_to_zero () -
16 | Adjust the color clipping method, and create the sample figures.
17 |
18 | figures_gamma_245 () -
19 | Adjust the gamma correction to a power law gamma = 2.45 and create samples.
20 |
21 | figures_white_A () -
22 | Adjust the white point (for Luv/Lab) and create sample figures.
23 |
24 | License:
25 |
26 | Copyright (C) 2008 Mark Kness
27 |
28 | Author - Mark Kness - mkness@alumni.utexas.net
29 |
30 | This file is part of ColorPy.
31 |
32 | ColorPy is free software: you can redistribute it and/or modify
33 | it under the terms of the GNU Lesser General Public License as
34 | published by the Free Software Foundation, either version 3 of
35 | the License, or (at your option) any later version.
36 |
37 | ColorPy is distributed in the hope that it will be useful,
38 | but WITHOUT ANY WARRANTY; without even the implied warranty of
39 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 | GNU Lesser General Public License for more details.
41 |
42 | You should have received a copy of the GNU Lesser General Public License
43 | along with ColorPy. If not, see .
44 | '''
45 | import colormodels
46 | import illuminants
47 | import plots
48 | import blackbody
49 | import rayleigh
50 | import thinfilm
51 | import misc
52 |
53 | def figures ():
54 | '''Create all the ColorPy sample figures.'''
55 | # no figures for colormodels and ciexyz
56 | colormodels.init() # default
57 | illuminants.figures()
58 | plots.figures()
59 | blackbody.figures()
60 | rayleigh.figures()
61 | thinfilm.figures()
62 | misc.figures()
63 |
64 | def figures_clip_clamp_to_zero ():
65 | '''Adjust the color clipping method, and create the sample figures.'''
66 | colormodels.init()
67 | colormodels.init_clipping (colormodels.CLIP_CLAMP_TO_ZERO)
68 | figures()
69 |
70 | def figures_gamma_245 ():
71 | '''Adjust the gamma correction to a power law gamma = 2.45 and create samples.'''
72 | colormodels.init()
73 | colormodels.init_gamma_correction (
74 | display_from_linear_function = colormodels.simple_gamma_invert,
75 | linear_from_display_function = colormodels.simple_gamma_correct,
76 | gamma = 2.45)
77 | figures()
78 |
79 | def figures_white_A ():
80 | '''Adjust the white point (for Luv/Lab) and create sample figures.'''
81 | colormodels.init()
82 | colormodels.init_Luv_Lab_white_point (colormodels.WhiteA)
83 | figures()
84 |
85 |
86 | if __name__ == '__main__':
87 | figures()
88 |
--------------------------------------------------------------------------------
/colorpy/illuminants.py:
--------------------------------------------------------------------------------
1 | '''
2 | illuminants.py - Definitions of some standard illuminants.
3 |
4 | Description:
5 |
6 | Illuminants are spectrums, normalized so that Y = 1.0.
7 |
8 | Spectrums are 2D numpy arrays, with one row for each wavelength,
9 | with the first column holding the wavelength in nm, and the
10 | second column the intensity.
11 |
12 | The spectrums have a wavelength increment of 1 nm.
13 |
14 | Functions:
15 |
16 | init () -
17 | Initialize CIE Illuminant D65. This runs on module startup.
18 |
19 | get_illuminant_D65 () -
20 | Get CIE Illuminant D65, as a spectrum, normalized to Y = 1.0.
21 |
22 | CIE standard illuminant D65 represents a phase of natural daylight
23 | with a correlated color temperature of approximately 6504 K. (Wyszecki, p. 144)
24 |
25 | In the interest of standardization the CIE recommends that D65 be used
26 | whenever possible. Otherwise, D55 or D75 are recommended. (Wyszecki, p. 145)
27 |
28 | (ColorPy does not currently provide D55 or D75, however.)
29 |
30 | get_illuminant_A () -
31 | Get CIE Illuminant A, as a spectrum, normalized to Y = 1.0.
32 | This is actually a blackbody illuminant for T = 2856 K. (Wyszecki, p. 143)
33 |
34 | get_blackbody_illuminant (T_K) -
35 | Get the spectrum of a blackbody at the given temperature, normalized to Y = 1.0.
36 |
37 | get_constant_illuminant () -
38 | Get an illuminant, with spectrum constant over wavelength, normalized to Y = 1.0.
39 |
40 | scale_illuminant (illuminant, scaling) -
41 | Scale the illuminant intensity by the specfied factor.
42 |
43 | References:
44 |
45 | Wyszecki and Stiles, Color Science: Concepts and Methods, Quantitative Data and Formulae,
46 | 2nd edition, John Wiley, 1982. Wiley Classics Library Edition 2000. ISBN 0-471-39918-3.
47 |
48 | CVRL Color and Vision Database - http://cvrl.ioo.ucl.ac.uk/index.htm - (accessed 17 Sep 2008)
49 | Color and Vision Research Laboratories.
50 | Provides a set of data sets related to color vision.
51 | ColorPy uses the tables from this site for the 1931 CIE XYZ matching functions,
52 | and for Illuminant D65, both at 1 nm wavelength increments.
53 |
54 | CIE Standards - http://cvrl.ioo.ucl.ac.uk/cie.htm - (accessed 17 Sep 2008)
55 | CIE standards as maintained by CVRL.
56 | The 1931 CIE XYZ and D65 tables that ColorPy uses were obtained from the following files, linked here:
57 | http://cvrl.ioo.ucl.ac.uk/database/data/cmfs/ciexyz31_1.txt
58 | http://cvrl.ioo.ucl.ac.uk/database/data/cie/Illuminantd65.txt
59 |
60 | CIE International Commission on Illumination - http://www.cie.co.at/ - (accessed 17 Sep 2008)
61 | Official website of the CIE.
62 | There are tables of the standard functions (matching functions, illuminants) here:
63 | http://www.cie.co.at/main/freepubs.html
64 | http://www.cie.co.at/publ/abst/datatables15_2004/x2.txt
65 | http://www.cie.co.at/publ/abst/datatables15_2004/y2.txt
66 | http://www.cie.co.at/publ/abst/datatables15_2004/z2.txt
67 | http://www.cie.co.at/publ/abst/datatables15_2004/sid65.txt
68 | ColorPy does not use these specific files.
69 |
70 | License:
71 |
72 | Copyright (C) 2008 Mark Kness
73 |
74 | Author - Mark Kness - mkness@alumni.utexas.net
75 |
76 | This file is part of ColorPy.
77 |
78 | ColorPy is free software: you can redistribute it and/or modify
79 | it under the terms of the GNU Lesser General Public License as
80 | published by the Free Software Foundation, either version 3 of
81 | the License, or (at your option) any later version.
82 |
83 | ColorPy is distributed in the hope that it will be useful,
84 | but WITHOUT ANY WARRANTY; without even the implied warranty of
85 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86 | GNU Lesser General Public License for more details.
87 |
88 | You should have received a copy of the GNU Lesser General Public License
89 | along with ColorPy. If not, see .
90 | '''
91 | import ciexyz
92 | import blackbody
93 | import plots
94 |
95 | # table of CIE Illuminant D65 spectrum.
96 | # data from: http://cvrl.ioo.ucl.ac.uk/database/data/cie/Illuminantd65.txt
97 | # massaged into this format.
98 | _Illuminant_D65_table = [
99 | [ 300, 0.034100 ],
100 | [ 301, 0.360140 ],
101 | [ 302, 0.686180 ],
102 | [ 303, 1.012220 ],
103 | [ 304, 1.338260 ],
104 | [ 305, 1.664300 ],
105 | [ 306, 1.990340 ],
106 | [ 307, 2.316380 ],
107 | [ 308, 2.642420 ],
108 | [ 309, 2.968460 ],
109 | [ 310, 3.294500 ],
110 | [ 311, 4.988650 ],
111 | [ 312, 6.682800 ],
112 | [ 313, 8.376950 ],
113 | [ 314, 10.071100 ],
114 | [ 315, 11.765200 ],
115 | [ 316, 13.459400 ],
116 | [ 317, 15.153500 ],
117 | [ 318, 16.847700 ],
118 | [ 319, 18.541800 ],
119 | [ 320, 20.236000 ],
120 | [ 321, 21.917700 ],
121 | [ 322, 23.599500 ],
122 | [ 323, 25.281200 ],
123 | [ 324, 26.963000 ],
124 | [ 325, 28.644700 ],
125 | [ 326, 30.326500 ],
126 | [ 327, 32.008200 ],
127 | [ 328, 33.690000 ],
128 | [ 329, 35.371700 ],
129 | [ 330, 37.053500 ],
130 | [ 331, 37.343000 ],
131 | [ 332, 37.632600 ],
132 | [ 333, 37.922100 ],
133 | [ 334, 38.211600 ],
134 | [ 335, 38.501100 ],
135 | [ 336, 38.790700 ],
136 | [ 337, 39.080200 ],
137 | [ 338, 39.369700 ],
138 | [ 339, 39.659300 ],
139 | [ 340, 39.948800 ],
140 | [ 341, 40.445100 ],
141 | [ 342, 40.941400 ],
142 | [ 343, 41.437700 ],
143 | [ 344, 41.934000 ],
144 | [ 345, 42.430200 ],
145 | [ 346, 42.926500 ],
146 | [ 347, 43.422800 ],
147 | [ 348, 43.919100 ],
148 | [ 349, 44.415400 ],
149 | [ 350, 44.911700 ],
150 | [ 351, 45.084400 ],
151 | [ 352, 45.257000 ],
152 | [ 353, 45.429700 ],
153 | [ 354, 45.602300 ],
154 | [ 355, 45.775000 ],
155 | [ 356, 45.947700 ],
156 | [ 357, 46.120300 ],
157 | [ 358, 46.293000 ],
158 | [ 359, 46.465600 ],
159 | [ 360, 46.638300 ],
160 | [ 361, 47.183400 ],
161 | [ 362, 47.728500 ],
162 | [ 363, 48.273500 ],
163 | [ 364, 48.818600 ],
164 | [ 365, 49.363700 ],
165 | [ 366, 49.908800 ],
166 | [ 367, 50.453900 ],
167 | [ 368, 50.998900 ],
168 | [ 369, 51.544000 ],
169 | [ 370, 52.089100 ],
170 | [ 371, 51.877700 ],
171 | [ 372, 51.666400 ],
172 | [ 373, 51.455000 ],
173 | [ 374, 51.243700 ],
174 | [ 375, 51.032300 ],
175 | [ 376, 50.820900 ],
176 | [ 377, 50.609600 ],
177 | [ 378, 50.398200 ],
178 | [ 379, 50.186900 ],
179 | [ 380, 49.975500 ],
180 | [ 381, 50.442800 ],
181 | [ 382, 50.910000 ],
182 | [ 383, 51.377300 ],
183 | [ 384, 51.844600 ],
184 | [ 385, 52.311800 ],
185 | [ 386, 52.779100 ],
186 | [ 387, 53.246400 ],
187 | [ 388, 53.713700 ],
188 | [ 389, 54.180900 ],
189 | [ 390, 54.648200 ],
190 | [ 391, 57.458900 ],
191 | [ 392, 60.269500 ],
192 | [ 393, 63.080200 ],
193 | [ 394, 65.890900 ],
194 | [ 395, 68.701500 ],
195 | [ 396, 71.512200 ],
196 | [ 397, 74.322900 ],
197 | [ 398, 77.133600 ],
198 | [ 399, 79.944200 ],
199 | [ 400, 82.754900 ],
200 | [ 401, 83.628000 ],
201 | [ 402, 84.501100 ],
202 | [ 403, 85.374200 ],
203 | [ 404, 86.247300 ],
204 | [ 405, 87.120400 ],
205 | [ 406, 87.993600 ],
206 | [ 407, 88.866700 ],
207 | [ 408, 89.739800 ],
208 | [ 409, 90.612900 ],
209 | [ 410, 91.486000 ],
210 | [ 411, 91.680600 ],
211 | [ 412, 91.875200 ],
212 | [ 413, 92.069700 ],
213 | [ 414, 92.264300 ],
214 | [ 415, 92.458900 ],
215 | [ 416, 92.653500 ],
216 | [ 417, 92.848100 ],
217 | [ 418, 93.042600 ],
218 | [ 419, 93.237200 ],
219 | [ 420, 93.431800 ],
220 | [ 421, 92.756800 ],
221 | [ 422, 92.081900 ],
222 | [ 423, 91.406900 ],
223 | [ 424, 90.732000 ],
224 | [ 425, 90.057000 ],
225 | [ 426, 89.382100 ],
226 | [ 427, 88.707100 ],
227 | [ 428, 88.032200 ],
228 | [ 429, 87.357200 ],
229 | [ 430, 86.682300 ],
230 | [ 431, 88.500600 ],
231 | [ 432, 90.318800 ],
232 | [ 433, 92.137100 ],
233 | [ 434, 93.955400 ],
234 | [ 435, 95.773600 ],
235 | [ 436, 97.591900 ],
236 | [ 437, 99.410200 ],
237 | [ 438, 101.228000 ],
238 | [ 439, 103.047000 ],
239 | [ 440, 104.865000 ],
240 | [ 441, 106.079000 ],
241 | [ 442, 107.294000 ],
242 | [ 443, 108.508000 ],
243 | [ 444, 109.722000 ],
244 | [ 445, 110.936000 ],
245 | [ 446, 112.151000 ],
246 | [ 447, 113.365000 ],
247 | [ 448, 114.579000 ],
248 | [ 449, 115.794000 ],
249 | [ 450, 117.008000 ],
250 | [ 451, 117.088000 ],
251 | [ 452, 117.169000 ],
252 | [ 453, 117.249000 ],
253 | [ 454, 117.330000 ],
254 | [ 455, 117.410000 ],
255 | [ 456, 117.490000 ],
256 | [ 457, 117.571000 ],
257 | [ 458, 117.651000 ],
258 | [ 459, 117.732000 ],
259 | [ 460, 117.812000 ],
260 | [ 461, 117.517000 ],
261 | [ 462, 117.222000 ],
262 | [ 463, 116.927000 ],
263 | [ 464, 116.632000 ],
264 | [ 465, 116.336000 ],
265 | [ 466, 116.041000 ],
266 | [ 467, 115.746000 ],
267 | [ 468, 115.451000 ],
268 | [ 469, 115.156000 ],
269 | [ 470, 114.861000 ],
270 | [ 471, 114.967000 ],
271 | [ 472, 115.073000 ],
272 | [ 473, 115.180000 ],
273 | [ 474, 115.286000 ],
274 | [ 475, 115.392000 ],
275 | [ 476, 115.498000 ],
276 | [ 477, 115.604000 ],
277 | [ 478, 115.711000 ],
278 | [ 479, 115.817000 ],
279 | [ 480, 115.923000 ],
280 | [ 481, 115.212000 ],
281 | [ 482, 114.501000 ],
282 | [ 483, 113.789000 ],
283 | [ 484, 113.078000 ],
284 | [ 485, 112.367000 ],
285 | [ 486, 111.656000 ],
286 | [ 487, 110.945000 ],
287 | [ 488, 110.233000 ],
288 | [ 489, 109.522000 ],
289 | [ 490, 108.811000 ],
290 | [ 491, 108.865000 ],
291 | [ 492, 108.920000 ],
292 | [ 493, 108.974000 ],
293 | [ 494, 109.028000 ],
294 | [ 495, 109.082000 ],
295 | [ 496, 109.137000 ],
296 | [ 497, 109.191000 ],
297 | [ 498, 109.245000 ],
298 | [ 499, 109.300000 ],
299 | [ 500, 109.354000 ],
300 | [ 501, 109.199000 ],
301 | [ 502, 109.044000 ],
302 | [ 503, 108.888000 ],
303 | [ 504, 108.733000 ],
304 | [ 505, 108.578000 ],
305 | [ 506, 108.423000 ],
306 | [ 507, 108.268000 ],
307 | [ 508, 108.112000 ],
308 | [ 509, 107.957000 ],
309 | [ 510, 107.802000 ],
310 | [ 511, 107.501000 ],
311 | [ 512, 107.200000 ],
312 | [ 513, 106.898000 ],
313 | [ 514, 106.597000 ],
314 | [ 515, 106.296000 ],
315 | [ 516, 105.995000 ],
316 | [ 517, 105.694000 ],
317 | [ 518, 105.392000 ],
318 | [ 519, 105.091000 ],
319 | [ 520, 104.790000 ],
320 | [ 521, 105.080000 ],
321 | [ 522, 105.370000 ],
322 | [ 523, 105.660000 ],
323 | [ 524, 105.950000 ],
324 | [ 525, 106.239000 ],
325 | [ 526, 106.529000 ],
326 | [ 527, 106.819000 ],
327 | [ 528, 107.109000 ],
328 | [ 529, 107.399000 ],
329 | [ 530, 107.689000 ],
330 | [ 531, 107.361000 ],
331 | [ 532, 107.032000 ],
332 | [ 533, 106.704000 ],
333 | [ 534, 106.375000 ],
334 | [ 535, 106.047000 ],
335 | [ 536, 105.719000 ],
336 | [ 537, 105.390000 ],
337 | [ 538, 105.062000 ],
338 | [ 539, 104.733000 ],
339 | [ 540, 104.405000 ],
340 | [ 541, 104.369000 ],
341 | [ 542, 104.333000 ],
342 | [ 543, 104.297000 ],
343 | [ 544, 104.261000 ],
344 | [ 545, 104.225000 ],
345 | [ 546, 104.190000 ],
346 | [ 547, 104.154000 ],
347 | [ 548, 104.118000 ],
348 | [ 549, 104.082000 ],
349 | [ 550, 104.046000 ],
350 | [ 551, 103.641000 ],
351 | [ 552, 103.237000 ],
352 | [ 553, 102.832000 ],
353 | [ 554, 102.428000 ],
354 | [ 555, 102.023000 ],
355 | [ 556, 101.618000 ],
356 | [ 557, 101.214000 ],
357 | [ 558, 100.809000 ],
358 | [ 559, 100.405000 ],
359 | [ 560, 100.000000 ],
360 | [ 561, 99.633400 ],
361 | [ 562, 99.266800 ],
362 | [ 563, 98.900300 ],
363 | [ 564, 98.533700 ],
364 | [ 565, 98.167100 ],
365 | [ 566, 97.800500 ],
366 | [ 567, 97.433900 ],
367 | [ 568, 97.067400 ],
368 | [ 569, 96.700800 ],
369 | [ 570, 96.334200 ],
370 | [ 571, 96.279600 ],
371 | [ 572, 96.225000 ],
372 | [ 573, 96.170300 ],
373 | [ 574, 96.115700 ],
374 | [ 575, 96.061100 ],
375 | [ 576, 96.006500 ],
376 | [ 577, 95.951900 ],
377 | [ 578, 95.897200 ],
378 | [ 579, 95.842600 ],
379 | [ 580, 95.788000 ],
380 | [ 581, 95.077800 ],
381 | [ 582, 94.367500 ],
382 | [ 583, 93.657300 ],
383 | [ 584, 92.947000 ],
384 | [ 585, 92.236800 ],
385 | [ 586, 91.526600 ],
386 | [ 587, 90.816300 ],
387 | [ 588, 90.106100 ],
388 | [ 589, 89.395800 ],
389 | [ 590, 88.685600 ],
390 | [ 591, 88.817700 ],
391 | [ 592, 88.949700 ],
392 | [ 593, 89.081800 ],
393 | [ 594, 89.213800 ],
394 | [ 595, 89.345900 ],
395 | [ 596, 89.478000 ],
396 | [ 597, 89.610000 ],
397 | [ 598, 89.742100 ],
398 | [ 599, 89.874100 ],
399 | [ 600, 90.006200 ],
400 | [ 601, 89.965500 ],
401 | [ 602, 89.924800 ],
402 | [ 603, 89.884100 ],
403 | [ 604, 89.843400 ],
404 | [ 605, 89.802600 ],
405 | [ 606, 89.761900 ],
406 | [ 607, 89.721200 ],
407 | [ 608, 89.680500 ],
408 | [ 609, 89.639800 ],
409 | [ 610, 89.599100 ],
410 | [ 611, 89.409100 ],
411 | [ 612, 89.219000 ],
412 | [ 613, 89.029000 ],
413 | [ 614, 88.838900 ],
414 | [ 615, 88.648900 ],
415 | [ 616, 88.458900 ],
416 | [ 617, 88.268800 ],
417 | [ 618, 88.078800 ],
418 | [ 619, 87.888700 ],
419 | [ 620, 87.698700 ],
420 | [ 621, 87.257700 ],
421 | [ 622, 86.816700 ],
422 | [ 623, 86.375700 ],
423 | [ 624, 85.934700 ],
424 | [ 625, 85.493600 ],
425 | [ 626, 85.052600 ],
426 | [ 627, 84.611600 ],
427 | [ 628, 84.170600 ],
428 | [ 629, 83.729600 ],
429 | [ 630, 83.288600 ],
430 | [ 631, 83.329700 ],
431 | [ 632, 83.370700 ],
432 | [ 633, 83.411800 ],
433 | [ 634, 83.452800 ],
434 | [ 635, 83.493900 ],
435 | [ 636, 83.535000 ],
436 | [ 637, 83.576000 ],
437 | [ 638, 83.617100 ],
438 | [ 639, 83.658100 ],
439 | [ 640, 83.699200 ],
440 | [ 641, 83.332000 ],
441 | [ 642, 82.964700 ],
442 | [ 643, 82.597500 ],
443 | [ 644, 82.230200 ],
444 | [ 645, 81.863000 ],
445 | [ 646, 81.495800 ],
446 | [ 647, 81.128500 ],
447 | [ 648, 80.761300 ],
448 | [ 649, 80.394000 ],
449 | [ 650, 80.026800 ],
450 | [ 651, 80.045600 ],
451 | [ 652, 80.064400 ],
452 | [ 653, 80.083100 ],
453 | [ 654, 80.101900 ],
454 | [ 655, 80.120700 ],
455 | [ 656, 80.139500 ],
456 | [ 657, 80.158300 ],
457 | [ 658, 80.177000 ],
458 | [ 659, 80.195800 ],
459 | [ 660, 80.214600 ],
460 | [ 661, 80.420900 ],
461 | [ 662, 80.627200 ],
462 | [ 663, 80.833600 ],
463 | [ 664, 81.039900 ],
464 | [ 665, 81.246200 ],
465 | [ 666, 81.452500 ],
466 | [ 667, 81.658800 ],
467 | [ 668, 81.865200 ],
468 | [ 669, 82.071500 ],
469 | [ 670, 82.277800 ],
470 | [ 671, 81.878400 ],
471 | [ 672, 81.479100 ],
472 | [ 673, 81.079700 ],
473 | [ 674, 80.680400 ],
474 | [ 675, 80.281000 ],
475 | [ 676, 79.881600 ],
476 | [ 677, 79.482300 ],
477 | [ 678, 79.082900 ],
478 | [ 679, 78.683600 ],
479 | [ 680, 78.284200 ],
480 | [ 681, 77.427900 ],
481 | [ 682, 76.571600 ],
482 | [ 683, 75.715300 ],
483 | [ 684, 74.859000 ],
484 | [ 685, 74.002700 ],
485 | [ 686, 73.146500 ],
486 | [ 687, 72.290200 ],
487 | [ 688, 71.433900 ],
488 | [ 689, 70.577600 ],
489 | [ 690, 69.721300 ],
490 | [ 691, 69.910100 ],
491 | [ 692, 70.098900 ],
492 | [ 693, 70.287600 ],
493 | [ 694, 70.476400 ],
494 | [ 695, 70.665200 ],
495 | [ 696, 70.854000 ],
496 | [ 697, 71.042800 ],
497 | [ 698, 71.231500 ],
498 | [ 699, 71.420300 ],
499 | [ 700, 71.609100 ],
500 | [ 701, 71.883100 ],
501 | [ 702, 72.157100 ],
502 | [ 703, 72.431100 ],
503 | [ 704, 72.705100 ],
504 | [ 705, 72.979000 ],
505 | [ 706, 73.253000 ],
506 | [ 707, 73.527000 ],
507 | [ 708, 73.801000 ],
508 | [ 709, 74.075000 ],
509 | [ 710, 74.349000 ],
510 | [ 711, 73.074500 ],
511 | [ 712, 71.800000 ],
512 | [ 713, 70.525500 ],
513 | [ 714, 69.251000 ],
514 | [ 715, 67.976500 ],
515 | [ 716, 66.702000 ],
516 | [ 717, 65.427500 ],
517 | [ 718, 64.153000 ],
518 | [ 719, 62.878500 ],
519 | [ 720, 61.604000 ],
520 | [ 721, 62.432200 ],
521 | [ 722, 63.260300 ],
522 | [ 723, 64.088500 ],
523 | [ 724, 64.916600 ],
524 | [ 725, 65.744800 ],
525 | [ 726, 66.573000 ],
526 | [ 727, 67.401100 ],
527 | [ 728, 68.229300 ],
528 | [ 729, 69.057400 ],
529 | [ 730, 69.885600 ],
530 | [ 731, 70.405700 ],
531 | [ 732, 70.925900 ],
532 | [ 733, 71.446000 ],
533 | [ 734, 71.966200 ],
534 | [ 735, 72.486300 ],
535 | [ 736, 73.006400 ],
536 | [ 737, 73.526600 ],
537 | [ 738, 74.046700 ],
538 | [ 739, 74.566900 ],
539 | [ 740, 75.087000 ],
540 | [ 741, 73.937600 ],
541 | [ 742, 72.788100 ],
542 | [ 743, 71.638700 ],
543 | [ 744, 70.489300 ],
544 | [ 745, 69.339800 ],
545 | [ 746, 68.190400 ],
546 | [ 747, 67.041000 ],
547 | [ 748, 65.891600 ],
548 | [ 749, 64.742100 ],
549 | [ 750, 63.592700 ],
550 | [ 751, 61.875200 ],
551 | [ 752, 60.157800 ],
552 | [ 753, 58.440300 ],
553 | [ 754, 56.722900 ],
554 | [ 755, 55.005400 ],
555 | [ 756, 53.288000 ],
556 | [ 757, 51.570500 ],
557 | [ 758, 49.853100 ],
558 | [ 759, 48.135600 ],
559 | [ 760, 46.418200 ],
560 | [ 761, 48.456900 ],
561 | [ 762, 50.495600 ],
562 | [ 763, 52.534400 ],
563 | [ 764, 54.573100 ],
564 | [ 765, 56.611800 ],
565 | [ 766, 58.650500 ],
566 | [ 767, 60.689200 ],
567 | [ 768, 62.728000 ],
568 | [ 769, 64.766700 ],
569 | [ 770, 66.805400 ],
570 | [ 771, 66.463100 ],
571 | [ 772, 66.120900 ],
572 | [ 773, 65.778600 ],
573 | [ 774, 65.436400 ],
574 | [ 775, 65.094100 ],
575 | [ 776, 64.751800 ],
576 | [ 777, 64.409600 ],
577 | [ 778, 64.067300 ],
578 | [ 779, 63.725100 ],
579 | [ 780, 63.382800 ],
580 | [ 781, 63.474900 ],
581 | [ 782, 63.567000 ],
582 | [ 783, 63.659200 ],
583 | [ 784, 63.751300 ],
584 | [ 785, 63.843400 ],
585 | [ 786, 63.935500 ],
586 | [ 787, 64.027600 ],
587 | [ 788, 64.119800 ],
588 | [ 789, 64.211900 ],
589 | [ 790, 64.304000 ],
590 | [ 791, 63.818800 ],
591 | [ 792, 63.333600 ],
592 | [ 793, 62.848400 ],
593 | [ 794, 62.363200 ],
594 | [ 795, 61.877900 ],
595 | [ 796, 61.392700 ],
596 | [ 797, 60.907500 ],
597 | [ 798, 60.422300 ],
598 | [ 799, 59.937100 ],
599 | [ 800, 59.451900 ],
600 | [ 801, 58.702600 ],
601 | [ 802, 57.953300 ],
602 | [ 803, 57.204000 ],
603 | [ 804, 56.454700 ],
604 | [ 805, 55.705400 ],
605 | [ 806, 54.956200 ],
606 | [ 807, 54.206900 ],
607 | [ 808, 53.457600 ],
608 | [ 809, 52.708300 ],
609 | [ 810, 51.959000 ],
610 | [ 811, 52.507200 ],
611 | [ 812, 53.055300 ],
612 | [ 813, 53.603500 ],
613 | [ 814, 54.151600 ],
614 | [ 815, 54.699800 ],
615 | [ 816, 55.248000 ],
616 | [ 817, 55.796100 ],
617 | [ 818, 56.344300 ],
618 | [ 819, 56.892400 ],
619 | [ 820, 57.440600 ],
620 | [ 821, 57.727800 ],
621 | [ 822, 58.015000 ],
622 | [ 823, 58.302200 ],
623 | [ 824, 58.589400 ],
624 | [ 825, 58.876500 ],
625 | [ 826, 59.163700 ],
626 | [ 827, 59.450900 ],
627 | [ 828, 59.738100 ],
628 | [ 829, 60.025300 ],
629 | [ 830, 60.312500 ]
630 | ]
631 |
632 | _Illuminant_D65 = None
633 |
634 | def init ():
635 | '''Initialize CIE Illuminant D65. This runs on module startup.'''
636 | first_wl = _Illuminant_D65_table [0][0]
637 | # for now, only consider the part in the normal visible range (360-830 nm)
638 | first_index = ciexyz.start_wl_nm - first_wl
639 | table_first = _Illuminant_D65_table [first_index][0]
640 | assert (table_first == 360), 'Mismatch finding 360 nm entry in D65 table'
641 | global _Illuminant_D65
642 | _Illuminant_D65 = ciexyz.empty_spectrum()
643 | (num_wl, num_cols) = _Illuminant_D65.shape
644 | for i in range (0, num_wl):
645 | _Illuminant_D65 [i][1] = _Illuminant_D65_table [first_index + i][1]
646 | # normalization - illuminant is scaled so that Y = 1.0
647 | xyz = ciexyz.xyz_from_spectrum (_Illuminant_D65)
648 | scaling = 1.0 / xyz [1]
649 | _Illuminant_D65 [:,1] *= scaling
650 |
651 | #
652 | # Get any of the available illuminants - D65, A, any blackbody, or a constant spectrum.
653 | # ColorPy does not currently provide D55 or D75.
654 | #
655 |
656 | def get_illuminant_D65 ():
657 | '''Get CIE Illuminant D65, as a spectrum, normalized to Y = 1.0.
658 |
659 | CIE standard illuminant D65 represents a phase of natural daylight
660 | with a correlated color temperature of approximately 6504 K. (Wyszecki, p. 144)
661 |
662 | In the interest of standardization the CIE recommends that D65 be used
663 | whenever possible. Otherwise, D55 or D75 are recommended. (Wyszecki, p. 145)
664 |
665 | (ColorPy does not currently provide D55 or D75, however.)'''
666 | illuminant = _Illuminant_D65.copy()
667 | return illuminant
668 |
669 | def get_illuminant_A ():
670 | '''Get CIE Illuminant A, as a spectrum, normalized to Y = 1.0.
671 | This is actually a blackbody illuminant for T = 2856 K. (Wyszecki, p. 143)'''
672 | illuminant = get_blackbody_illuminant (2856.0)
673 | return illuminant
674 |
675 | def get_blackbody_illuminant (T_K):
676 | '''Get the spectrum of a blackbody at the given temperature, normalized to Y = 1.0.'''
677 | illuminant = blackbody.blackbody_spectrum (T_K)
678 | xyz = ciexyz.xyz_from_spectrum (illuminant)
679 | if xyz [1] != 0.0:
680 | scaling = 1.0 / xyz [1]
681 | illuminant [:,1] *= scaling
682 | return illuminant
683 |
684 | def get_constant_illuminant ():
685 | '''Get an illuminant, with spectrum constant over wavelength, normalized to Y = 1.0.'''
686 | illuminant = ciexyz.empty_spectrum()
687 | (num_wl, num_cols) = illuminant.shape
688 | for i in range (0, num_wl):
689 | illuminant [i][1] = 1.0
690 | xyz = ciexyz.xyz_from_spectrum (illuminant)
691 | if xyz [1] != 0.0:
692 | scaling = 1.0 / xyz [1]
693 | illuminant [:,1] *= scaling
694 | return illuminant
695 |
696 | # Scale an illuminant by an arbitrary factor
697 |
698 | def scale_illuminant (illuminant, scaling):
699 | '''Scale the illuminant intensity by the specfied factor.'''
700 | illuminant [:,1] *= scaling
701 | return illuminant
702 |
703 | # Initialize at module startup
704 | init()
705 |
706 | # Figures - Plot some of the illuminants
707 |
708 | def figures ():
709 | '''Plot spectra for several illuminants.'''
710 | # D65
711 | plots.spectrum_plot (
712 | get_illuminant_D65(), 'CIE Illuminant D65', 'Illuminant-D65')
713 | # A
714 | plots.spectrum_plot (
715 | get_illuminant_A(), 'CIE Illuminant A', 'Illuminant-A')
716 | # Constant
717 | plots.spectrum_plot (
718 | get_constant_illuminant(), 'Constant Illuminant', 'Illuminant-Const')
719 | # Blackbody (5778)
720 | plots.spectrum_plot (
721 | get_blackbody_illuminant (5778.0), '5778 K Illuminant', 'Illuminant-5778')
722 |
--------------------------------------------------------------------------------
/colorpy/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ColorPy
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/colorpy/license.txt:
--------------------------------------------------------------------------------
1 | License:
2 |
3 | Copyright (C) 2008 Mark Kness
4 |
5 | Author - Mark Kness - mkness@alumni.utexas.net
6 |
7 | This file is part of ColorPy.
8 |
9 | ColorPy is free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Lesser General Public License as
11 | published by the Free Software Foundation, either version 3 of
12 | the License, or (at your option) any later version.
13 |
14 | ColorPy is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Lesser General Public License for more details.
18 |
19 | You should have received a copy of the GNU Lesser General Public License
20 | along with ColorPy. If not, see .
21 |
--------------------------------------------------------------------------------
/colorpy/misc.py:
--------------------------------------------------------------------------------
1 | '''
2 | misc.py - Miscellaneous color plots.
3 |
4 | Description:
5 |
6 | Some miscellaneous plots.
7 |
8 | colorstring_patch_plot (colorstrings, color_names, title, filename, num_across=6) -
9 | Color patch plot for colors specified as hex strings.
10 |
11 | MacBeth_ColorChecker_patch_plot () -
12 | MacBeth ColorChecker Chart.
13 | The xyz values are from Hall p. 119. I do not know for what lighting conditions this applies.
14 |
15 | chemical_solutions_patch_plot () -
16 | Colors of some chemical solutions.
17 | Darren L. Williams et. al., 'Beyond lambda-max: Transforming Visible Spectra into 24-bit Color Values'.
18 | Journal of Chemical Education, Vol 84, No 11, Nov 2007, p1873-1877.
19 | A student laboratory experiment to measure the transmission spectra of some common chemical solutions,
20 | and determine the rgb values.
21 |
22 | universe_patch_plot () -
23 | The average color of the universe.
24 | Karl Glazebrook and Ivan Baldry
25 | http://www.pha.jhu.edu/~kgb/cosspec/ (accessed 17 Sep 2008)
26 | The color of the sum of all light in the universe.
27 | This originally caused some controversy when the (correct) xyz color was incorrectly reported as light green.
28 | The authors also consider several other white points, here we just use the default (normally D65).
29 |
30 | spectral_colors_patch_plot () -
31 | Colors of the pure spectral lines.
32 |
33 | spectral_colors_plus_purples_patch_plot () -
34 | Colors of the pure spectral lines plus purples.
35 |
36 | perceptually_uniform_spectral_colors () -
37 | Patch plot of (nearly) perceptually equally spaced colors, covering the pure spectral lines plus purples.
38 |
39 | spectral_line_555nm_plot () -
40 | Plot a spectrum that has mostly only a line at 555 nm.
41 | It is widened a bit only so the plot looks nicer, otherwise the black curve covers up the color.
42 |
43 | License:
44 |
45 | Copyright (C) 2008 Mark Kness
46 |
47 | Author - Mark Kness - mkness@alumni.utexas.net
48 |
49 | This file is part of ColorPy.
50 |
51 | ColorPy is free software: you can redistribute it and/or modify
52 | it under the terms of the GNU Lesser General Public License as
53 | published by the Free Software Foundation, either version 3 of
54 | the License, or (at your option) any later version.
55 |
56 | ColorPy is distributed in the hope that it will be useful,
57 | but WITHOUT ANY WARRANTY; without even the implied warranty of
58 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59 | GNU Lesser General Public License for more details.
60 |
61 | You should have received a copy of the GNU Lesser General Public License
62 | along with ColorPy. If not, see .
63 | '''
64 | import math, numpy
65 |
66 | import colormodels
67 | import ciexyz
68 | import plots
69 |
70 | # Some sample lists of displayable RGB colors as hex strings
71 |
72 | # default colors in Matplotlib
73 | matplotlib_colors = [
74 | '#0000FF', # b
75 | '#008000', # g
76 | '#FF0000', # r
77 | '#00BFBF', # c
78 | '#BF00BF', # m
79 | '#BFBF00', # y
80 | '#000000' # k
81 | ]
82 |
83 | matplotlib_names = [ 'b', 'g', 'r', 'c', 'm', 'y', 'k' ]
84 |
85 | # Following determined by sampling rgb values of a MATLAB gif of their colormaps - this is imperfect for several reasons...
86 | hsv_colors = [
87 | '#FF0000', # red
88 | '#FF6300', # orange
89 | '#FFBD00', # yellow-orange
90 | '#DEFF00', # yellow
91 | '#84FF00', # yellow-green
92 | '#21FF00', # green
93 | '#00FF42', # green
94 | '#00FF9C', # green
95 | '#00FFFF', # cyan
96 | '#009CFF', # light blue
97 | '#0042FF', # blue
98 | '#2100FF', # blue
99 | '#8400FF', # violet
100 | '#DE00FF', # magenta
101 | '#FF00BD', # hot pink
102 | '#FF0063' # red
103 | ]
104 |
105 | # Following determined by sampling rgb values of a MATLAB gif of their colormaps - this is imperfect for several reasons...
106 | # The jet colormap is associated with an astrophysical fluid jet simulation from the National Center for Supercomputer Applications.
107 | jet_colors = [
108 | '#0000BD', '#0000FF', '#0042FF', '#0084FF',
109 | '#00DBFF', '#00FFFF', '#08FFEF', '#42FFBD',
110 | '#84FF84', '#BDFF42', '#FFFF00', '#FFBD00',
111 | '#FF8400', '#FF4200', '#FF0000', '#BD0000',
112 | '#840000'
113 | ]
114 |
115 | # some primary colors, convenient for printer ribbon tests and calibration
116 | primary_colors = [
117 | '#000000',
118 | '#FF0000',
119 | '#00FF00',
120 | '#0000FF',
121 | '#FFFF00',
122 | '#FF00FF',
123 | '#00FFFF',
124 | '#FFFFFF'
125 | ]
126 |
127 | primary_names = [ 'Black', 'Red', 'Green', 'Blue', 'Yellow', 'Magenta', 'Cyan', 'White' ]
128 |
129 | def colorstring_patch_plot (colorstrings, color_names, title, filename, num_across=6):
130 | '''Color patch plot for colors specified as hex strings.'''
131 | rgb_colors = []
132 | for color in colorstrings:
133 | irgb = colormodels.irgb_from_irgb_string (color)
134 | rgb = colormodels.rgb_from_irgb (irgb)
135 | rgb_colors.append (rgb)
136 | plots.rgb_patch_plot (
137 | rgb_colors,
138 | color_names,
139 | title,
140 | filename,
141 | num_across=num_across)
142 |
143 | # Patch plots from xyz color values
144 |
145 | def MacBeth_ColorChecker_patch_plot ():
146 | '''MacBeth ColorChecker Chart.
147 | The xyz values are from Hall p. 119. I do not know for what lighting conditions this applies.'''
148 | xyz_colors = []
149 | xyz_colors.append (colormodels.xyz_color (0.092, 0.081, 0.058))
150 | xyz_colors.append (colormodels.xyz_color (0.411, 0.376, 0.303))
151 | xyz_colors.append (colormodels.xyz_color (0.183, 0.186, 0.373))
152 | xyz_colors.append (colormodels.xyz_color (0.094, 0.117, 0.067))
153 | xyz_colors.append (colormodels.xyz_color (0.269, 0.244, 0.503))
154 | xyz_colors.append (colormodels.xyz_color (0.350, 0.460, 0.531))
155 | xyz_colors.append (colormodels.xyz_color (0.386, 0.311, 0.066))
156 | xyz_colors.append (colormodels.xyz_color (0.123, 0.102, 0.359))
157 | xyz_colors.append (colormodels.xyz_color (0.284, 0.192, 0.151))
158 | xyz_colors.append (colormodels.xyz_color (0.059, 0.040, 0.102))
159 | xyz_colors.append (colormodels.xyz_color (0.368, 0.474, 0.127))
160 | xyz_colors.append (colormodels.xyz_color (0.497, 0.460, 0.094))
161 | xyz_colors.append (colormodels.xyz_color (0.050, 0.035, 0.183))
162 | xyz_colors.append (colormodels.xyz_color (0.149, 0.234, 0.106))
163 | xyz_colors.append (colormodels.xyz_color (0.176, 0.102, 0.048))
164 | xyz_colors.append (colormodels.xyz_color (0.614, 0.644, 0.112))
165 | xyz_colors.append (colormodels.xyz_color (0.300, 0.192, 0.332))
166 | xyz_colors.append (colormodels.xyz_color (0.149, 0.192, 0.421))
167 | xyz_colors.append (colormodels.xyz_color (0.981, 1.000, 1.184))
168 | xyz_colors.append (colormodels.xyz_color (0.632, 0.644, 0.763))
169 | xyz_colors.append (colormodels.xyz_color (0.374, 0.381, 0.451))
170 | xyz_colors.append (colormodels.xyz_color (0.189, 0.192, 0.227))
171 | xyz_colors.append (colormodels.xyz_color (0.067, 0.068, 0.080))
172 | xyz_colors.append (colormodels.xyz_color (0.000, 0.000, 0.000))
173 |
174 | color_names = []
175 | color_names.append ('dark skin')
176 | color_names.append ('light skin')
177 | color_names.append ('blue sky')
178 | color_names.append ('foliage')
179 | color_names.append ('blue flower')
180 | color_names.append ('bluish green')
181 | color_names.append ('orange')
182 | color_names.append ('purplish blue')
183 | color_names.append ('moderate red')
184 | color_names.append ('purple')
185 | color_names.append ('yellow green')
186 | color_names.append ('orange yellow')
187 | color_names.append ('blue')
188 | color_names.append ('green')
189 | color_names.append ('red')
190 | color_names.append ('yellow')
191 | color_names.append ('magenta')
192 | color_names.append ('cyan')
193 | color_names.append ('white')
194 | color_names.append ('neutral 8')
195 | color_names.append ('neutral 6.5')
196 | color_names.append ('neutral 5')
197 | color_names.append ('neutral 3.5')
198 | color_names.append ('black')
199 |
200 | plots.xyz_patch_plot (
201 | xyz_colors,
202 | color_names,
203 | 'MacBeth ColorChecker Chart',
204 | 'MacBeth')
205 |
206 | def chemical_solutions_patch_plot ():
207 | '''Colors of some chemical solutions.
208 | Darren L. Williams et. al., 'Beyond lambda-max: Transforming Visible Spectra into 24-bit Color Values'.
209 | Journal of Chemical Education, Vol 84, No 11, Nov 2007, p1873-1877.
210 | A student laboratory experiment to measure the transmission spectra of some common chemical solutions,
211 | and determine the rgb values.'''
212 | xyz_colors = []
213 | xyz_colors.append (colormodels.xyz_color (0.360, 0.218, 0.105))
214 | xyz_colors.append (colormodels.xyz_color (0.458, 0.691, 0.587))
215 | xyz_colors.append (colormodels.xyz_color (0.445, 0.621, 1.052))
216 | xyz_colors.append (colormodels.xyz_color (0.742, 0.579, 0.905))
217 | xyz_colors.append (colormodels.xyz_color (0.949, 1.000, 1.087))
218 | color_names = []
219 | color_names.append ('1 M CoCl2')
220 | color_names.append ('1 M NiCl2')
221 | color_names.append ('1 M CuSO4')
222 | color_names.append ('0.005 M KMnO4')
223 | color_names.append ('H2O')
224 | plots.xyz_patch_plot (
225 | xyz_colors,
226 | color_names,
227 | 'Colors of some chemical solutions\nJ. Chem. Ed., Vol 84, No 11, Nov 2007, p 1873-1877.',
228 | 'ChemSolutions')
229 |
230 | def universe_patch_plot ():
231 | '''The average color of the universe.
232 | Karl Glazebrook and Ivan Baldry
233 | http://www.pha.jhu.edu/~kgb/cosspec/ (accessed 17 Sep 2008)
234 | The color of the sum of all light in the universe.
235 | This caused some controversy when the (correct) xyz color was incorrectly reported as light green.
236 | The authors also consider several other white points, here we just use the default (normally D65).'''
237 | # use the published chromaticity but Y=1.0
238 | xyz_colors = [colormodels.xyz_color_from_xyY (0.345, 0.345, 1.0)]
239 | color_names = ['The Universe']
240 | plots.xyz_patch_plot (
241 | xyz_colors,
242 | color_names,
243 | 'Average Color of the Universe\nhttp://www.pha.jhu.edu/~kgb/cosspec/',
244 | 'Universe')
245 |
246 | # Pure spectral colors
247 |
248 | def spectral_colors_patch_plot ():
249 | '''Colors of the pure spectral lines.'''
250 | xyzs = ciexyz.get_normalized_spectral_line_colors (brightness=1.0, num_purples=0, dwl_angstroms=10)
251 | plots.xyz_patch_plot (
252 | xyzs, None, 'Colors of pure spectral lines', 'Spectral', num_across=20)
253 |
254 |
255 | def spectral_colors_plus_purples_patch_plot ():
256 | '''Colors of the pure spectral lines plus purples.'''
257 | xyzs = ciexyz.get_normalized_spectral_line_colors (brightness=1.0, num_purples=200, dwl_angstroms=10)
258 | plots.xyz_patch_plot (
259 | xyzs, None, 'Colors of pure spectral lines plus purples', 'SpectralPlusPurples', num_across=20)
260 |
261 | # An attempt to get a perceptually equally spaced (almost) subset of the pure spectral colors
262 |
263 | def perceptually_uniform_spectral_colors (
264 | brightness = 1.0,
265 | plot_name = 'PerceptuallyEqualColors',
266 | plot_title = 'Perceptually (almost) Equally Spaced Pure Colors',
267 | table_name = 'percep_equal_names.txt'):
268 | '''Patch plot of (nearly) perceptually equally spaced colors, covering the pure spectral lines plus purples.'''
269 | # TODO - This may or may not be quite right...
270 | # get pure colors
271 | # xyzs = ciexyz.get_normalized_spectral_line_colors (brightness=1.0, num_purples=200, dwl_angstroms=1)
272 | (xyzs, names) = ciexyz.get_normalized_spectral_line_colors_annotated (brightness=brightness, num_purples=200, dwl_angstroms=1)
273 | (num_colors, num_columns) = xyzs.shape
274 |
275 | # pick these two functions for either Luv or Lab
276 | uniform_from_xyz = colormodels.luv_from_xyz
277 | xyz_from_uniform = colormodels.xyz_from_luv
278 | #uniform_from_xyz = colormodels.lab_from_xyz
279 | #xyz_from_uniform = colormodels.xyz_from_lab
280 |
281 | # convert colors to a nearly perceptually uniform space
282 | uniforms = numpy.empty ((num_colors, 3))
283 | for i in range (0, num_colors):
284 | uniforms [i] = uniform_from_xyz (xyzs [i])
285 | # determine spacing
286 | sum_ds = 0.0
287 | dss = numpy.empty ((num_colors, 1))
288 | for i in range (0, num_colors-1):
289 | dri = uniforms [i+1] - uniforms [i]
290 | dsi = math.sqrt (numpy.dot (dri, dri))
291 | dss [i] = dsi
292 | sum_ds += dsi
293 | # last point closes the curve
294 | dri = uniforms [0] - uniforms [num_colors - 1]
295 | dsi = math.sqrt (numpy.dot (dri, dri))
296 | dss [num_colors - 1] = dsi
297 | sum_ds += dsi
298 | # pick out subsamples as evenly spaced as possible
299 | num_samples = 160
300 | ds_avg = sum_ds / float (num_samples - 1)
301 | E_indices = []
302 | index = 0
303 | count = 0
304 | need = 0.0
305 | while True:
306 | while need > 1.0e-10:
307 | need -= dss [index]
308 | index += 1
309 | E_indices.append (index)
310 | need += ds_avg
311 | count += 1
312 | if count >= num_samples:
313 | break
314 | # patch plot and save names
315 | xyz_list = []
316 | fil = open (table_name, 'wt')
317 | fil.write ('%s\n' % plot_title)
318 | fil.write ('Name iRGB\n')
319 | fil.write ('\n')
320 | for index in E_indices:
321 | uniform_color = uniforms [index]
322 | uniform_xyz = xyz_from_uniform (uniform_color)
323 | uniform_irgb = colormodels.irgb_from_xyz (uniform_xyz)
324 | uniform_name = names [index]
325 | xyz_list.append (uniform_xyz)
326 | fil.write ('%s %s\n' % (uniform_name, str (uniform_irgb)))
327 | fil.close ()
328 | plots.xyz_patch_plot (
329 | xyz_list, None, plot_title, plot_name, num_across=20)
330 |
331 | def perceptually_uniform_spectral_color_plots ():
332 | brightness_list = [1.0, 0.9, 0.8, 0.75, 0.6, 0.5, 0.4, 0.3, 0.25]
333 | for brightness in brightness_list:
334 | ibright = math.floor (100.0 * brightness + 0.5)
335 | plot_name = 'PerceptuallyEqualColors_%d' % ibright
336 | plot_title = 'Perceptually (almost) Equally Spaced Pure Colors %d%%' % ibright
337 | table_name = 'percep_equal_names_%d.txt' % ibright
338 | perceptually_uniform_spectral_colors (brightness, plot_name, plot_title, table_name)
339 |
340 | # A sample spectrum that doesn't have equally spaced wavelengths
341 |
342 | def spectral_line_555nm_plot ():
343 | '''Plot a spectrum that has mostly only a line at 555 nm.
344 | It is widened a bit only so the plot looks nicer, otherwise the black curve covers up the color.'''
345 | spectrum_list = [
346 | [360.0, 0.0],
347 | [549.0, 0.0],
348 | [552.0, 100.0],
349 | [553.0, 100.0],
350 | [554.0, 100.0],
351 | [555.0, 100.0],
352 | [556.0, 100.0],
353 | [557.0, 100.0],
354 | [558.0, 100.0],
355 | [557.0, 0.0],
356 | [830.0, 0.0]]
357 | spectrum = numpy.array (spectrum_list)
358 | plots.spectrum_plot (spectrum, '555 nm Spectral Line', 'line555nm')
359 |
360 | #
361 |
362 | def figures ():
363 | '''Draw the various miscellaneous figures.'''
364 | # patch plots of lists of color hex strings
365 | colorstring_patch_plot (matplotlib_colors, matplotlib_names, 'Default MatPlotLib Colormap', 'matplotlib', num_across=7)
366 | colorstring_patch_plot (hsv_colors, None, 'HSV Colormap', 'hsv')
367 | colorstring_patch_plot (jet_colors, None, 'Jet Colormap', 'jet')
368 | colorstring_patch_plot (primary_colors, primary_names, 'Primary Colors', 'primary', num_across=4)
369 | # patch charts of xyz color tables
370 | MacBeth_ColorChecker_patch_plot ()
371 | chemical_solutions_patch_plot ()
372 | universe_patch_plot ()
373 | # pure colors
374 | spectral_colors_patch_plot ()
375 | spectral_colors_plus_purples_patch_plot ()
376 | perceptually_uniform_spectral_color_plots ()
377 | spectral_line_555nm_plot ()
378 |
--------------------------------------------------------------------------------
/colorpy/plots.py:
--------------------------------------------------------------------------------
1 | '''
2 | plots.py - Various types of plots.
3 |
4 | Description:
5 |
6 | Functions to draw various types of plots for light spectra.
7 |
8 | Functions:
9 |
10 | log_interpolate (y0, y1, num_values) -
11 | Return a list of values, num_values in size, logarithmically interpolated
12 | between y0 and y1. The first value will be y0, the last y1.
13 |
14 | tighten_x_axis (x_list) -
15 | Tighten the x axis (only) of the current plot to match the given range of x values.
16 | The y axis limits are not affected.
17 |
18 | General plots:
19 |
20 | rgb_patch_plot (
21 | rgb_colors,
22 | color_names,
23 | title,
24 | filename,
25 | patch_gap = 0.05,
26 | num_across = 6) -
27 | Draw a set of color patches, specified as linear rgb colors.
28 |
29 | xyz_patch_plot (
30 | xyz_colors,
31 | color_names,
32 | title,
33 | filename,
34 | patch_gap = 0.05,
35 | num_across = 6) -
36 | Draw a set of color patches specified as xyz colors.
37 |
38 | spectrum_subplot (spectrum) -
39 | Plot a spectrum, with x-axis the wavelength, and y-axis the intensity.
40 | The curve is colored at that wavelength by the (approximate) color of a
41 | pure spectral color at that wavelength, with intensity constant over wavelength.
42 | (This means that dark looking colors here mean that wavelength is poorly viewed by the eye.
43 | This is not a complete plotting function, e.g. no file is saved, etc.
44 | It is assumed that this function is being called by one that handles those things.
45 |
46 | spectrum_plot (
47 | spectrum,
48 | title,
49 | filename,
50 | xlabel = 'Wavelength ($nm$)',
51 | ylabel = 'Intensity ($W/m^2$)') -
52 |
53 | Plot for a single spectrum -
54 | In a two part graph, plot:
55 | top: color of the spectrum, as a large patch.
56 | low: graph of spectrum intensity vs wavelength (x axis).
57 | The graph is colored by the (approximated) color of each wavelength.
58 | Each wavelength has equal physical intensity, so the variation in
59 | apparent intensity (e.g. 400, 800 nm are very dark, 550 nm is bright),
60 | is due to perceptual factors in the eye. This helps show how much
61 | each wavelength contributes to the percieved color.
62 |
63 | spectrum - spectrum to plot
64 | title - title for plot
65 | filename - filename to save plot to
66 | xlabel - label for x axis
67 | ylabel - label for y axis
68 |
69 | color_vs_param_plot (
70 | param_list,
71 | rgb_colors,
72 | title,
73 | filename,
74 | tight = False,
75 | plotfunc = pylab.plot,
76 | xlabel = 'param',
77 | ylabel = 'RGB Color') -
78 |
79 | Plot for a color that varies with a parameter -
80 | In a two part figure, draw:
81 | top: color as it varies with parameter (x axis)
82 | low: r,g,b values, as linear 0.0-1.0 values, of the attempted color.
83 |
84 | param_list - list of parameters (x axis)
85 | rgb_colors - numpy array, one row for each param in param_list
86 | title - title for plot
87 | filename - filename to save plot to
88 | plotfunc - optional plot function to use (default pylab.plot)
89 | xlabel - label for x axis
90 | ylabel - label for y axis (default 'RGB Color')
91 |
92 | Specialized plots:
93 |
94 | visible_spectrum_plot () -
95 | Plot the visible spectrum, as a plot vs wavelength.
96 |
97 | cie_matching_functions_plot () -
98 | Plot the CIE XYZ matching functions, as three spectral subplots.
99 |
100 | shark_fin_plot () -
101 | Draw the 'shark fin' CIE chromaticity diagram of the pure spectral lines (plus purples) in xy space.
102 |
103 | License:
104 |
105 | Copyright (C) 2008 Mark Kness
106 |
107 | Author - Mark Kness - mkness@alumni.utexas.net
108 |
109 | This file is part of ColorPy.
110 |
111 | ColorPy is free software: you can redistribute it and/or modify
112 | it under the terms of the GNU Lesser General Public License as
113 | published by the Free Software Foundation, either version 3 of
114 | the License, or (at your option) any later version.
115 |
116 | ColorPy is distributed in the hope that it will be useful,
117 | but WITHOUT ANY WARRANTY; without even the implied warranty of
118 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119 | GNU Lesser General Public License for more details.
120 |
121 | You should have received a copy of the GNU Lesser General Public License
122 | along with ColorPy. If not, see .
123 | '''
124 | from __future__ import print_function
125 |
126 | import math
127 | import numpy, pylab
128 |
129 | import colormodels
130 | import ciexyz
131 |
132 | # Miscellaneous utilities for plots
133 |
134 | def log_interpolate (y0, y1, num_values):
135 | '''Return a list of values, num_values in size, logarithmically interpolated
136 | between y0 and y1. The first value will be y0, the last y1.'''
137 | rtn = []
138 | if num_values <= 0:
139 | raise ValueError('Invalid number of divisions %s in log_interpolate' % (str (num_values)))
140 | if num_values == 1:
141 | # can't use both endpoints, too constrained
142 | yi = math.sqrt (y0 * y1)
143 | rtn.append (yi)
144 | else:
145 | # normal case
146 | beta = math.log (y1 / y0) / float (num_values - 1)
147 | for i in range (0, num_values):
148 | yi = y0 * math.exp (beta * float (i))
149 | rtn.append (yi)
150 | return rtn
151 |
152 | def tighten_x_axis (x_list):
153 | '''Tighten the x axis (only) of the current plot to match the given range of x values.
154 | The y axis limits are not affected.'''
155 | x_min = min (x_list)
156 | x_max = max (x_list)
157 | pylab.xlim ((x_min, x_max))
158 |
159 | #
160 | # Patch plots - Plots with each color value as a solid patch, with optional labels.
161 | #
162 |
163 | def rgb_patch_plot (
164 | rgb_colors,
165 | color_names,
166 | title,
167 | filename,
168 | patch_gap = 0.05,
169 | num_across = 6):
170 | '''Draw a set of color patches, specified as linear rgb colors.'''
171 |
172 | def draw_patch (x0, y0, color, name, patch_gap):
173 | '''Draw a patch of color.'''
174 | # patch relative vertices
175 | m = patch_gap
176 | omm = 1.0 - m
177 | poly_dx = [m, m, omm, omm]
178 | poly_dy = [m, omm, omm, m]
179 | # construct vertices
180 | poly_x = [ x0 + dx_i for dx_i in poly_dx ]
181 | poly_y = [ y0 + dy_i for dy_i in poly_dy ]
182 | pylab.fill (poly_x, poly_y, color)
183 | if name != None:
184 | dtext = 0.1
185 | pylab.text (x0+dtext, y0+dtext, name, size=8.0)
186 |
187 | # make plot with each color with one patch
188 | pylab.clf()
189 | num_colors = len (rgb_colors)
190 | for i in range (0, num_colors):
191 | (iy, ix) = divmod (i, num_across)
192 | # get color as a displayable string
193 | colorstring = colormodels.irgb_string_from_rgb (rgb_colors [i])
194 | if color_names != None:
195 | name = color_names [i]
196 | else:
197 | name = None
198 | draw_patch (float (ix), float (-iy), colorstring, name, patch_gap)
199 | pylab.axis ('off')
200 | pylab.title (title)
201 | print ('Saving plot %s' % str (filename))
202 | pylab.savefig (filename)
203 |
204 | def xyz_patch_plot (
205 | xyz_colors,
206 | color_names,
207 | title,
208 | filename,
209 | patch_gap = 0.05,
210 | num_across = 6):
211 | '''Draw a set of color patches specified as xyz colors.'''
212 | rgb_colors = []
213 | for xyz in xyz_colors:
214 | rgb = colormodels.rgb_from_xyz (xyz)
215 | rgb_colors.append (rgb)
216 | rgb_patch_plot (rgb_colors, color_names, title, filename, patch_gap=patch_gap, num_across=num_across)
217 |
218 | #
219 | # Spectrum plots
220 | #
221 |
222 | def spectrum_subplot (spectrum):
223 | '''Plot a spectrum, with x-axis the wavelength, and y-axis the intensity.
224 | The curve is colored at that wavelength by the (approximate) color of a
225 | pure spectral color at that wavelength, with intensity constant over wavelength.
226 | (This means that dark looking colors here mean that wavelength is poorly viewed by the eye.
227 |
228 | This is not a complete plotting function, e.g. no file is saved, etc.
229 | It is assumed that this function is being called by one that handles those things.'''
230 | (num_wl, num_cols) = spectrum.shape
231 | # get rgb colors for each wavelength
232 | rgb_colors = numpy.empty ((num_wl, 3))
233 | for i in range (0, num_wl):
234 | wl_nm = spectrum [i][0]
235 | xyz = ciexyz.xyz_from_wavelength (wl_nm)
236 | rgb_colors [i] = colormodels.rgb_from_xyz (xyz)
237 | # scale to make brightest rgb value = 1.0
238 | rgb_max = numpy.max (rgb_colors)
239 | scaling = 1.0 / rgb_max
240 | rgb_colors *= scaling
241 | # draw color patches (thin vertical lines matching the spectrum curve) in color
242 | for i in range (0, num_wl-1): # skipping the last one here to stay in range
243 | x0 = spectrum [i][0]
244 | x1 = spectrum [i+1][0]
245 | y0 = spectrum [i][1]
246 | y1 = spectrum [i+1][1]
247 | poly_x = [x0, x1, x1, x0]
248 | poly_y = [0.0, 0.0, y1, y0]
249 | color_string = colormodels.irgb_string_from_rgb (rgb_colors [i])
250 | pylab.fill (poly_x, poly_y, color_string, edgecolor=color_string)
251 | # plot intensity as a curve
252 | pylab.plot (
253 | spectrum [:,0], spectrum [:,1],
254 | color='k', linewidth=2.0, antialiased=True)
255 |
256 | def spectrum_plot (
257 | spectrum,
258 | title,
259 | filename,
260 | xlabel = 'Wavelength ($nm$)',
261 | ylabel = 'Intensity ($W/m^2$)'):
262 | '''Plot for a single spectrum -
263 | In a two part graph, plot:
264 | top: color of the spectrum, as a large patch.
265 | low: graph of spectrum intensity vs wavelength (x axis).
266 | The graph is colored by the (approximated) color of each wavelength.
267 | Each wavelength has equal physical intensity, so the variation in
268 | apparent intensity (e.g. 400, 800 nm are very dark, 550 nm is bright),
269 | is due to perceptual factors in the eye. This helps show how much
270 | each wavelength contributes to the percieved color.
271 |
272 | spectrum - spectrum to plot
273 | title - title for plot
274 | filename - filename to save plot to
275 | xlabel - label for x axis
276 | ylabel - label for y axis
277 | '''
278 | pylab.clf ()
279 | # upper plot - solid patch of color that matches the spectrum color
280 | pylab.subplot (2,1,1)
281 | pylab.title (title)
282 | color_string = colormodels.irgb_string_from_rgb (
283 | colormodels.rgb_from_xyz (ciexyz.xyz_from_spectrum (spectrum)))
284 | poly_x = [0.0, 1.0, 1.0, 0.0]
285 | poly_y = [0.0, 0.0, 1.0, 1.0]
286 | pylab.fill (poly_x, poly_y, color_string)
287 | # draw a solid line around the patch to look nicer
288 | pylab.plot (poly_x, poly_y, color='k', linewidth=2.0)
289 | pylab.axis ('off')
290 | # lower plot - spectrum vs wavelength, with colors of the associated spectral lines below
291 | pylab.subplot (2,1,2)
292 | spectrum_subplot (spectrum)
293 | tighten_x_axis (spectrum [:,0])
294 | pylab.xlabel (xlabel)
295 | pylab.ylabel (ylabel)
296 | # done
297 | print ('Saving plot %s' % str (filename))
298 | pylab.savefig (filename)
299 |
300 | #
301 | # Color vs param plot
302 | #
303 |
304 | def color_vs_param_plot (
305 | param_list,
306 | rgb_colors,
307 | title,
308 | filename,
309 | tight = False,
310 | plotfunc = pylab.plot,
311 | xlabel = 'param',
312 | ylabel = 'RGB Color'):
313 | '''Plot for a color that varies with a parameter -
314 | In a two part figure, draw:
315 | top: color as it varies with parameter (x axis)
316 | low: r,g,b values, as linear 0.0-1.0 values, of the attempted color.
317 |
318 | param_list - list of parameters (x axis)
319 | rgb_colors - numpy array, one row for each param in param_list
320 | title - title for plot
321 | filename - filename to save plot to
322 | plotfunc - optional plot function to use (default pylab.plot)
323 | xlabel - label for x axis
324 | ylabel - label for y axis (default 'RGB Color')
325 | '''
326 | pylab.clf ()
327 | # draw color bars in upper plot
328 | pylab.subplot (2,1,1)
329 | pylab.title (title)
330 | # no xlabel, ylabel in upper plot
331 | num_points = len (param_list)
332 | for i in range (0, num_points-1):
333 | x0 = param_list [i]
334 | x1 = param_list [i+1]
335 | y0 = 0.0
336 | y1 = 1.0
337 | poly_x = [x0, x1, x1, x0]
338 | poly_y = [y0, y0, y1, y1]
339 | color_string = colormodels.irgb_string_from_rgb (rgb_colors [i])
340 | pylab.fill (poly_x, poly_y, color_string, edgecolor=color_string)
341 | if tight:
342 | tighten_x_axis (param_list)
343 | # draw rgb curves in lower plot
344 | pylab.subplot (2,1,2)
345 | # no title in lower plot
346 | plotfunc (param_list, rgb_colors [:,0], color='r', label='Red')
347 | plotfunc (param_list, rgb_colors [:,1], color='g', label='Green')
348 | plotfunc (param_list, rgb_colors [:,2], color='b', label='Blue')
349 | if tight:
350 | tighten_x_axis (param_list)
351 | pylab.xlabel (xlabel)
352 | pylab.ylabel (ylabel)
353 | print ('Saving plot %s' % str (filename))
354 | pylab.savefig (filename)
355 |
356 | #
357 | # Some specialized plots
358 | #
359 |
360 | def visible_spectrum_plot ():
361 | '''Plot the visible spectrum, as a plot vs wavelength.'''
362 | spectrum = ciexyz.empty_spectrum()
363 | (num_wl, num_cols) = spectrum.shape
364 | # get rgb colors for each wavelength
365 | rgb_colors = numpy.empty ((num_wl, 3))
366 | for i in range (0, num_wl):
367 | xyz = ciexyz.xyz_from_wavelength (spectrum [i][0])
368 | rgb = colormodels.rgb_from_xyz (xyz)
369 | rgb_colors [i] = rgb
370 | # scale to make brightest rgb value = 1.0
371 | rgb_max = numpy.max (rgb_colors)
372 | scaling = 1.0 / rgb_max
373 | rgb_colors *= scaling
374 | # plot colors and rgb values vs wavelength
375 | color_vs_param_plot (
376 | spectrum [:,0],
377 | rgb_colors,
378 | 'The Visible Spectrum',
379 | 'VisibleSpectrum',
380 | tight = True,
381 | xlabel = r'Wavelength (nm)',
382 | ylabel = r'RGB Color')
383 |
384 | def cie_matching_functions_plot ():
385 | '''Plot the CIE XYZ matching functions, as three spectral subplots.'''
386 | # get 'spectra' for x,y,z matching functions
387 | spectrum_x = ciexyz.empty_spectrum()
388 | spectrum_y = ciexyz.empty_spectrum()
389 | spectrum_z = ciexyz.empty_spectrum()
390 | (num_wl, num_cols) = spectrum_x.shape
391 | for i in range (0, num_wl):
392 | wl_nm = spectrum_x [i][0]
393 | xyz = ciexyz.xyz_from_wavelength (wl_nm)
394 | spectrum_x [i][1] = xyz [0]
395 | spectrum_y [i][1] = xyz [1]
396 | spectrum_z [i][1] = xyz [2]
397 | # Plot three separate subplots, with CIE X in the first, CIE Y in the second, and CIE Z in the third.
398 | # Label appropriately for the whole plot.
399 | pylab.clf ()
400 | # X
401 | pylab.subplot (3,1,1)
402 | pylab.title ('1931 CIE XYZ Matching Functions')
403 | pylab.ylabel ('CIE $X$')
404 | spectrum_subplot (spectrum_x)
405 | tighten_x_axis (spectrum_x [:,0])
406 | # Y
407 | pylab.subplot (3,1,2)
408 | pylab.ylabel ('CIE $Y$')
409 | spectrum_subplot (spectrum_y)
410 | tighten_x_axis (spectrum_x [:,0])
411 | # Z
412 | pylab.subplot (3,1,3)
413 | pylab.xlabel ('Wavelength (nm)')
414 | pylab.ylabel ('CIE $Z$')
415 | spectrum_subplot (spectrum_z)
416 | tighten_x_axis (spectrum_x [:,0])
417 | # done
418 | filename = 'CIEXYZ_Matching'
419 | print ('Saving plot %s' % str (filename))
420 | pylab.savefig (filename)
421 |
422 | def scattered_visual_brightness ():
423 | '''Plot the perceptual brightness of Rayleigh scattered light.'''
424 | # get 'spectra' for y matching functions and multiply by 1/wl^4
425 | spectrum_y = ciexyz.empty_spectrum()
426 | (num_wl, num_cols) = spectrum_y.shape
427 | for i in range (0, num_wl):
428 | wl_nm = spectrum_y [i][0]
429 | rayleigh = math.pow (550.0 / wl_nm, 4)
430 | xyz = ciexyz.xyz_from_wavelength (wl_nm)
431 | spectrum_y [i][1] = xyz [1] * rayleigh
432 | pylab.clf ()
433 | pylab.title ('Perceptual Brightness of Rayleigh Scattered Light')
434 | pylab.xlabel ('Wavelength (nm)')
435 | pylab.ylabel ('CIE $Y$ / $\lambda^4$')
436 | spectrum_subplot (spectrum_y)
437 | tighten_x_axis (spectrum_y [:,0])
438 | # done
439 | filename = 'Visual_scattering'
440 | print ('Saving plot %s' % str (filename))
441 | pylab.savefig (filename)
442 |
443 | def shark_fin_plot ():
444 | '''Draw the 'shark fin' CIE chromaticity diagram of the pure spectral lines (plus purples) in xy space.'''
445 | # get array of (approximate) colors for the boundary of the fin
446 | xyz_list = ciexyz.get_normalized_spectral_line_colors (brightness=1.0, num_purples=200, dwl_angstroms=2)
447 | # get normalized colors
448 | xy_list = xyz_list.copy()
449 | (num_colors, num_cols) = xy_list.shape
450 | for i in range (0, num_colors):
451 | colormodels.xyz_normalize (xy_list [i])
452 | # get phosphor colors and normalize
453 | red = colormodels.PhosphorRed
454 | green = colormodels.PhosphorGreen
455 | blue = colormodels.PhosphorBlue
456 | white = colormodels.PhosphorWhite
457 | colormodels.xyz_normalize (red)
458 | colormodels.xyz_normalize (green)
459 | colormodels.xyz_normalize (blue)
460 | colormodels.xyz_normalize (white)
461 |
462 | def get_direc_to_white (xyz):
463 | '''Get unit vector (xy plane) in direction of the white point.'''
464 | direc = white - xyz
465 | mag = math.hypot (direc [0], direc [1])
466 | if mag != 0.0:
467 | direc /= mag
468 | return (direc[0], direc[1])
469 |
470 | # plot
471 | pylab.clf ()
472 |
473 | # draw best attempt at pure spectral colors on inner edge of shark fin
474 | s = 0.025 # distance in xy plane towards white point
475 | for i in range (0, len (xy_list)-1):
476 | x0 = xy_list [i][0]
477 | y0 = xy_list [i][1]
478 | x1 = xy_list [i+1][0]
479 | y1 = xy_list [i+1][1]
480 | # get unit vectors in direction of white point
481 | (dir_x0, dir_y0) = get_direc_to_white (xy_list [i])
482 | (dir_x1, dir_y1) = get_direc_to_white (xy_list [i+1])
483 | # polygon vertices
484 | poly_x = [x0, x1, x1 + s*dir_x1, x0 + s*dir_x0]
485 | poly_y = [y0, y1, y1 + s*dir_y1, y0 + s*dir_y0]
486 | # draw (using full color, not normalized value)
487 | color_string = colormodels.irgb_string_from_rgb (
488 | colormodels.rgb_from_xyz (xyz_list [i]))
489 | pylab.fill (poly_x, poly_y, color_string, edgecolor=color_string)
490 |
491 | # fill in the monitor gamut with true colors
492 | def get_brightest_irgb_string (xyz):
493 | '''Convert the xyz color to rgb, scale to maximum displayable brightness, and convert to a string.'''
494 | rgb = colormodels.brightest_rgb_from_xyz (xyz)
495 | color_string = colormodels.irgb_string_from_rgb (rgb)
496 | return color_string
497 |
498 | def fill_gamut_slice (v0, v1, v2):
499 | '''Fill in a slice of the monitor gamut with the correct colors.'''
500 | #num_s, num_t = 10, 10
501 | #num_s, num_t = 25, 25
502 | num_s, num_t = 50, 50
503 | dv10 = v1 - v0
504 | dv21 = v2 - v1
505 | for i_s in range (num_s):
506 | s_a = float (i_s) / float (num_s)
507 | s_b = float (i_s+1) / float (num_s)
508 | for i_t in range (num_t):
509 | t_a = float (i_t) / float (num_t)
510 | t_b = float (i_t+1) / float (num_t)
511 | # vertex coords
512 | v_aa = v0 + t_a * (dv10 + s_a * dv21)
513 | v_ab = v0 + t_b * (dv10 + s_a * dv21)
514 | v_ba = v0 + t_a * (dv10 + s_b * dv21)
515 | v_bb = v0 + t_b * (dv10 + s_b * dv21)
516 | # poly coords
517 | poly_x = [v_aa [0], v_ba [0], v_bb [0], v_ab [0]]
518 | poly_y = [v_aa [1], v_ba [1], v_bb [1], v_ab [1]]
519 | # average color
520 | avg = 0.25 * (v_aa + v_ab + v_ba + v_bb)
521 | # convert to rgb and scale to maximum displayable brightness
522 | color_string = get_brightest_irgb_string (avg)
523 | pylab.fill (poly_x, poly_y, color_string, edgecolor=color_string)
524 | fill_gamut_slice (white, blue, green)
525 | fill_gamut_slice (white, green, red)
526 | fill_gamut_slice (white, red, blue)
527 |
528 | # draw the curve of the xy values of the spectral lines and purples
529 | pylab.plot (xy_list [:,0], xy_list [:,1], color='#808080', linewidth=3.0)
530 | # draw monitor gamut and white point
531 | pylab.plot ([red [0], green[0]], [red [1], green[1]], 'o-', color='k')
532 | pylab.plot ([green[0], blue [0]], [green[1], blue [1]], 'o-', color='k')
533 | pylab.plot ([blue [0], red [0]], [blue [1], red [1]], 'o-', color='k')
534 | pylab.plot ([white[0], white[0]], [white[1], white[1]], 'o-', color='k')
535 | # label phosphors
536 | dx = 0.01
537 | dy = 0.01
538 | pylab.text (red [0] + dx, red [1], 'Red', ha='left', va='center')
539 | pylab.text (green [0], green [1] + dy, 'Green', ha='center', va='bottom')
540 | pylab.text (blue [0] - dx, blue [1], 'Blue', ha='right', va='center')
541 | pylab.text (white [0], white [1] + dy, 'White', ha='center', va='bottom')
542 | # titles etc
543 | pylab.axis ([0.0, 0.85, 0.0, 0.85])
544 | pylab.xlabel (r'CIE $x$')
545 | pylab.ylabel (r'CIE $y$')
546 | pylab.title (r'CIE Chromaticity Diagram')
547 | filename = 'ChromaticityDiagram'
548 | print ('Saving plot %s' % (str (filename)))
549 | pylab.savefig (filename)
550 |
551 | # Special figures
552 |
553 | def figures ():
554 | '''Draw specific figures not used anywhere else.'''
555 | visible_spectrum_plot()
556 | cie_matching_functions_plot()
557 | shark_fin_plot()
558 | scattered_visual_brightness()
559 |
560 | #
561 | # HTML
562 | #
563 |
564 | def get_color_hex_string (red, green, blue):
565 | '''Convert color values to a hex string.'''
566 | hexstr = '#%02X%02X%02X' % (red, green, blue)
567 | return hexstr
568 |
569 | def visible_spectrum_table (filename='visible_spectrum.html'):
570 | '''Write an HTML table with the visible spectrum colors.'''
571 | spectrum = ciexyz.empty_spectrum()
572 | (num_wl, num_cols) = spectrum.shape
573 | # get rgb colors for each wavelength
574 | rgb_colors_1 = numpy.empty ((num_wl, 3))
575 | rgb_colors_2 = numpy.empty ((num_wl, 3))
576 | for i in range (0, num_wl):
577 | xyz = ciexyz.xyz_from_wavelength (spectrum [i][0])
578 | rgb_1 = colormodels.rgb_from_xyz (xyz)
579 | rgb_2 = colormodels.brightest_rgb_from_xyz (xyz)
580 | rgb_colors_1 [i] = rgb_1
581 | rgb_colors_2 [i] = rgb_2
582 | # scale 1 to make brightest rgb value = 1.0
583 | rgb_max = numpy.max (rgb_colors_1)
584 | scaling = 1.0 / rgb_max
585 | rgb_colors_1 *= scaling
586 | # write HTML file
587 |
588 | def write_link (f, url, text):
589 | '''Write an html link.'''
590 | link = '%s
\n' % (url, text)
591 | f.write (link)
592 |
593 | f = open (filename, 'w')
594 | # html headers
595 | f.write ('\n')
596 | f.write ('\n')
597 | f.write ('Colors of Pure Spectral Lines\n')
598 | f.write ('\n')
599 | f.write ('\n')
600 | f.write ('Colors of Pure Spectral Lines
\n')
601 | f.write ('%s
\n' % 'White added to undisplayable pure colors to fit into rgb space.')
602 | f.write ('
\n')
603 | # table header
604 | f.write ('\n')
605 | f.write ('\n')
606 | f.write ('Wavelength | \n')
607 | f.write ('R | \n')
608 | f.write ('G | \n')
609 | f.write ('B | \n')
610 | f.write ('Hex Code | \n')
611 | f.write ('Full Brightness | \n')
612 | f.write ('Perceptual Brightness | \n')
613 | f.write ('
\n')
614 | # each row
615 |
616 | for i in range (0, num_wl):
617 | irgb_1 = colormodels.irgb_from_rgb (rgb_colors_1 [i])
618 | irgb_2 = colormodels.irgb_from_rgb (rgb_colors_2 [i])
619 | red = irgb_2 [0]
620 | green = irgb_2 [1]
621 | blue = irgb_2 [2]
622 | hexstr_1 = colormodels.irgb_string_from_irgb (irgb_1)
623 | hexstr_2 = colormodels.irgb_string_from_irgb (irgb_2)
624 |
625 | iwl = spectrum [i][0]
626 | code = '%.1f nm' % iwl
627 |
628 | f.write ('\n')
629 | f.write ('%s | \n' % (code))
630 | f.write ('%d | \n' % (red))
631 | f.write ('%d | \n' % (green))
632 | f.write ('%d | \n' % (blue))
633 | f.write ('%s | \n' % (hexstr_2))
634 | swatch = " "
635 | f.write ('%s | \n' % (hexstr_2, swatch))
636 | f.write ('%s | \n' % (hexstr_1, swatch))
637 | f.write ('
\n')
638 |
639 | f.write ('
\n')
640 | # references
641 | f.write ('
\n')
642 | f.write ('References
\n')
643 | # one source for data
644 | write_link (f, 'http://goffgrafix.com/pantone-rgb-100.php', 'Goffgrafix.com')
645 | # another source with basically the same data
646 | write_link (f, 'http://www.sandaleo.com/pantone.asp', 'Sandaleo.com')
647 | # one with more colors including metallic (also some errors), not quite consistent with the first two
648 | write_link (f, 'http://www.loral.org/Z/Colors/100.html',
649 | 'Loral.org - Conversions based on CorelDRAW v12 Pantone Solid Coated or Pastel Coated tables and sRGB color space.')
650 | # some colors for various sports teams
651 | write_link (f, 'http://www.pennjersey.info/forums/questions-answers/7895-pantone-colors-colleges-university-mlb-nfl-teams.html',
652 | 'Pantone colors for some sports teams.')
653 | # some colors for various national flags
654 | write_link (f, 'http://desktoppub.about.com/od/colorpalettes/l/aa_flagcolors.htm', 'What color is your flag? Pantone colors for some flags.')
655 | write_link (f, 'http://desktoppub.about.com/library/weekly/blcpflagsrwb.htm', 'Red, White, & Blue - Pantone colors for some flags.')
656 | write_link (f, 'http://desktoppub.about.com/library/weekly/blcpflagsyellow.htm', 'Yellow or Gold - Pantone colors for some flags.')
657 | write_link (f, 'http://desktoppub.about.com/library/weekly/blcpflagsgreen.htm', 'Green - Pantone colors for some flags.')
658 | write_link (f, 'http://desktoppub.about.com/library/weekly/blcpatrioticswatches.htm', 'Color swatches - Pantone colors for some flags.')
659 | # official Pantone webpages
660 | write_link (f, 'http://pantone.com/pages/pantone/Pantone.aspx?pg=19970&ca=25', 'An official PANTONE page')
661 | write_link (f, 'http://pantone.com/pages/products/product.aspx?ca=1&pid=293&', 'Another official PANTONE page')
662 | # html ending
663 | f.write ('\n')
664 | f.write ('\n')
665 | f.close()
666 |
667 | def vst ():
668 | visible_spectrum_table ()
669 |
670 |
671 | if __name__ == '__main__':
672 | figures()
673 |
--------------------------------------------------------------------------------
/colorpy/rayleigh.py:
--------------------------------------------------------------------------------
1 | '''
2 | rayleigh.py - Rayleigh scattering
3 |
4 | Description:
5 |
6 | Calculation of the scattering by very small particles (compared to the wavelength).
7 | Also known as Rayleigh scattering.
8 | The scattering intensity is proportional to 1/wavelength^4.
9 | It is scaled so that the scattering factor for 555.0 nm is 1.0.
10 | This is the basic physical reason that the sky is blue.
11 |
12 | Functions:
13 |
14 | rayleigh_scattering (wl_nm) -
15 | Get the Rayleigh scattering factor for the wavelength.
16 | Scattering is proportional to 1/wavelength^4.
17 | The scattering is scaled so that the factor for wl_nm = 555.0 is 1.0.
18 |
19 | rayleigh_scattering_spectrum () -
20 | Get the Rayleigh scattering spectrum (independent of illuminant), as a numpy array.
21 |
22 | rayleigh_illuminated_spectrum (illuminant) -
23 | Get the spectrum when illuminated by the specified illuminant.
24 |
25 | rayleigh_illuminated_color (illuminant) -
26 | Get the xyz color when illuminated by the specified illuminant.
27 |
28 | Plots:
29 |
30 | rayleigh_patch_plot (named_illuminant_list, title, filename) -
31 | Make a patch plot of the Rayleigh scattering color for each illuminant.
32 |
33 | rayleigh_color_vs_illuminant_temperature_plot (T_list, title, filename) -
34 | Make a plot of the Rayleigh scattered color vs. temperature of blackbody illuminant.
35 |
36 | rayleigh_spectrum_plot (illuminant, title, filename) -
37 | Plot the spectrum of Rayleigh scattering of the specified illuminant.
38 |
39 | References:
40 |
41 | H.C. van de Hulst, Light Scattering by Small Particles,
42 | Dover Publications, New York, 1981. ISBN 0-486-64228-3.
43 |
44 | License:
45 |
46 | Copyright (C) 2008 Mark Kness
47 |
48 | Author - Mark Kness - mkness@alumni.utexas.net
49 |
50 | This file is part of ColorPy.
51 |
52 | ColorPy is free software: you can redistribute it and/or modify
53 | it under the terms of the GNU Lesser General Public License as
54 | published by the Free Software Foundation, either version 3 of
55 | the License, or (at your option) any later version.
56 |
57 | ColorPy is distributed in the hope that it will be useful,
58 | but WITHOUT ANY WARRANTY; without even the implied warranty of
59 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 | GNU Lesser General Public License for more details.
61 |
62 | You should have received a copy of the GNU Lesser General Public License
63 | along with ColorPy. If not, see .
64 | '''
65 | import math
66 | import numpy, pylab
67 |
68 | import colormodels
69 | import ciexyz
70 | import illuminants
71 | import blackbody
72 | import plots
73 |
74 | def rayleigh_scattering (wl_nm):
75 | '''Get the Rayleigh scattering factor for the wavelength.
76 | Scattering is proportional to 1/wavelength^4.
77 | The scattering is scaled so that the factor for wl_nm = 555.0 is 1.0.'''
78 | wl_0_nm = 555.0
79 | wl_rel = wl_nm / wl_0_nm
80 | rayleigh_factor = math.pow (wl_rel, -4)
81 | return rayleigh_factor
82 |
83 | def rayleigh_scattering_spectrum ():
84 | '''Get the Rayleigh scattering spectrum (independent of illuminant), as a numpy array.'''
85 | spectrum = ciexyz.empty_spectrum()
86 | num_wl = spectrum.shape[0]
87 | for i in range (0, num_wl):
88 | spectrum [i][1] = rayleigh_scattering (spectrum [i][0])
89 | return spectrum
90 |
91 | def rayleigh_illuminated_spectrum (illuminant):
92 | '''Get the spectrum when illuminated by the specified illuminant.'''
93 | spectrum = rayleigh_scattering_spectrum()
94 | num_wl = spectrum.shape[0]
95 | for i in range (0, num_wl):
96 | spectrum [i][1] *= illuminant [i][1]
97 | return spectrum
98 |
99 | def rayleigh_illuminated_color (illuminant):
100 | '''Get the xyz color when illuminated by the specified illuminant.'''
101 | spectrum = rayleigh_illuminated_spectrum (illuminant)
102 | xyz = ciexyz.xyz_from_spectrum (spectrum)
103 | return xyz
104 |
105 | #
106 | # Figures
107 | #
108 |
109 | def rayleigh_patch_plot (named_illuminant_list, title, filename):
110 | '''Make a patch plot of the Rayleigh scattering color for each illuminant.'''
111 | xyz_colors = []
112 | color_names = []
113 | for (illuminant, name) in named_illuminant_list:
114 | xyz = rayleigh_illuminated_color (illuminant)
115 | xyz_colors.append (xyz)
116 | color_names.append (name)
117 | plots.xyz_patch_plot (xyz_colors, color_names, title, filename)
118 |
119 | def rayleigh_color_vs_illuminant_temperature_plot (T_list, title, filename):
120 | '''Make a plot of the Rayleigh scattered color vs. temperature of blackbody illuminant.'''
121 | num_T = len (T_list)
122 | rgb_list = numpy.empty ((num_T, 3))
123 | for i in range (0, num_T):
124 | T_i = T_list [i]
125 | illuminant = illuminants.get_blackbody_illuminant (T_i)
126 | xyz = rayleigh_illuminated_color (illuminant)
127 | rgb_list [i] = colormodels.rgb_from_xyz (xyz)
128 | plots.color_vs_param_plot (
129 | T_list,
130 | rgb_list,
131 | title,
132 | filename,
133 | tight = True,
134 | plotfunc = pylab.plot,
135 | xlabel = r'Illuminant Temperature (K)',
136 | ylabel = r'RGB Color')
137 |
138 | def rayleigh_spectrum_plot (illuminant, title, filename):
139 | '''Plot the spectrum of Rayleigh scattering of the specified illuminant.'''
140 | spectrum = rayleigh_illuminated_spectrum (illuminant)
141 | plots.spectrum_plot (
142 | spectrum,
143 | title,
144 | filename,
145 | xlabel = 'Wavelength (nm)',
146 | ylabel = 'Intensity ($W/m^2$)')
147 |
148 | def figures ():
149 | '''Draw some plots of Rayleigh scattering.'''
150 | # Patch plots for some illuminants.
151 | rayleigh_patch_plot (
152 | [(illuminants.get_blackbody_illuminant (blackbody.SUN_TEMPERATURE), 'Sun')],
153 | 'Rayleigh Scattering by the Sun', 'Rayleigh-PatchSun')
154 |
155 | rayleigh_patch_plot (
156 | [(illuminants.get_illuminant_D65 (), 'D65'),
157 | (illuminants.get_blackbody_illuminant (2000.0), '2000 K'),
158 | (illuminants.get_blackbody_illuminant (3500.0), '3500 K'),
159 | (illuminants.get_blackbody_illuminant (blackbody.SUN_TEMPERATURE), 'Sun'),
160 | (illuminants.get_blackbody_illuminant (6500.0), '6500 K'),
161 | (illuminants.get_blackbody_illuminant (15000.0), '15000 K')],
162 | 'Rayleigh Scattering by Various Illuminants', 'Rayleigh-PatchVarious')
163 |
164 | # Scattered color vs blackbody illuminant temperature.
165 | T_list = numpy.linspace(1200.0, 16000.0, 300)
166 | rayleigh_color_vs_illuminant_temperature_plot (
167 | T_list, 'Rayleigh Scattering Sky Colors', 'Rayleigh-SkyColors')
168 |
169 | # Spectra for several illuminants.
170 | T_list = [2000.0, 3000.0, blackbody.SUN_TEMPERATURE, 6500.0, 11000.0, 15000.0]
171 | for T in T_list:
172 | T_label = '%dK' % (round(T))
173 | rayleigh_spectrum_plot (
174 | illuminants.get_blackbody_illuminant (T),
175 | 'Rayleigh Scattering\nIlluminant %g K' % (T),
176 | 'Rayleigh-Spectrum-%s' % (T_label))
177 |
178 |
179 | if __name__ == '__main__':
180 | figures()
181 |
--------------------------------------------------------------------------------
/colorpy/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | '''
3 | setup.py - Setup script to install the ColorPy package.
4 |
5 | To install the ColorPy package:
6 | From the directory in which the ColorPy distribution was unpacked, run:
7 |
8 | python setup.py install
9 |
10 | You should now be able to say 'import colorpy' in your programs and use the package.
11 |
12 | Creating the distribution:
13 |
14 | python setup.py sdist --formats=zip
15 | python setup.py sdist --formats=gztar
16 | python setup.py bdist_wininst
17 | '''
18 |
19 | from distutils.core import setup
20 |
21 | data_files = [
22 | 'README.txt',
23 | 'COPYING.txt',
24 | 'COPYING.LESSER.txt',
25 | 'license.txt',
26 | 'ColorPy.html',
27 | ]
28 |
29 | long_description = '''
30 | ColorPy is a Python package to convert physical descriptions of light -
31 | spectra of light intensity vs. wavelength - into RGB colors that can
32 | be drawn on a computer screen.
33 | It provides a nice set of attractive plots that you can make of such
34 | spectra, and some other color related functions as well.
35 | '''
36 |
37 | setup (
38 | name='colorpy',
39 | version='0.1.0',
40 | description='Color calculations with physical descriptions of light spectra',
41 | long_description=long_description,
42 | author='Mark Kness',
43 | author_email='mkness@alumni.utexas.net',
44 | url='http://markkness.net/colorpy/',
45 | license='GNU Lesser GPL Version 3',
46 | package_dir={'colorpy': ''},
47 | packages=['colorpy'],
48 | package_data={'colorpy': data_files},
49 | )
50 |
--------------------------------------------------------------------------------
/colorpy/test.py:
--------------------------------------------------------------------------------
1 | '''
2 | test.py - Run all ColorPy test cases.
3 |
4 | Functions:
5 |
6 | test() -
7 | Run all the test cases.
8 |
9 | License:
10 |
11 | Copyright (C) 2008 Mark Kness
12 |
13 | Author - Mark Kness - mkness@alumni.utexas.net
14 |
15 | This file is part of ColorPy.
16 |
17 | ColorPy is free software: you can redistribute it and/or modify
18 | it under the terms of the GNU Lesser General Public License as
19 | published by the Free Software Foundation, either version 3 of
20 | the License, or (at your option) any later version.
21 |
22 | ColorPy is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU Lesser General Public License for more details.
26 |
27 | You should have received a copy of the GNU Lesser General Public License
28 | along with ColorPy. If not, see .
29 | '''
30 | from __future__ import print_function
31 |
32 | import unittest
33 |
34 | import test_colormodels
35 | import test_ciexyz
36 | import test_illuminants
37 | import test_blackbody
38 | import test_rayleigh
39 | import test_thinfilm
40 |
41 | def test ():
42 | # no test cases for plots/misc - but figures.py will exercise those.
43 | # Explicitly run the unittest cases in the modules.
44 | # This is perhaps a bit clumsy.
45 | # A more conventional way to run all of the tests, is at the command line:
46 | # python -m unittest discover
47 | modules = [
48 | test_blackbody,
49 | test_ciexyz,
50 | test_colormodels,
51 | test_illuminants,
52 | test_rayleigh,
53 | test_thinfilm,
54 | ]
55 | for module in modules:
56 | result = unittest.TestResult()
57 | loader = unittest.TestLoader()
58 | suite = loader.loadTestsFromModule(module)
59 | suite.run(result)
60 | # Print results.
61 | msg = 'Module: %s Errors: %s Failures: %s' % (
62 | module.__name__, result.errors, result.failures)
63 | print (msg)
64 | print (str(result))
65 | # Raise an exception if there were problems.
66 | ok = (len(result.errors) == 0) and (len(result.failures) == 0)
67 | if not ok:
68 | # Perhaps not the right exception type...
69 | raise ValueError(msg)
70 |
71 |
72 | if __name__ == '__main__':
73 | test()
74 |
--------------------------------------------------------------------------------
/colorpy/test_blackbody.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_blackbody.py - Test cases for blackbody.py
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import math
28 | import numpy
29 | import unittest
30 |
31 | import blackbody
32 | import colormodels
33 |
34 | # FIXME: The following calculation is not working currently.
35 | # It is an attempt to get the scale of the intensity correct.
36 | # It needs more investigation.
37 |
38 | STEFAN_BOLTZMAN = 5.670e-8 # W/(m^2 K^4)
39 |
40 | def blackbody_total_intensity (T_K, start_wl_nm, end_wl_nm):
41 | '''Get the sum of the specific intensity, at 1 nm increments, from start_wl_nm to end_wl_nm.'''
42 | total = 0.0
43 | for wl_nm in range (start_wl_nm, end_wl_nm+1):
44 | specific = blackbody.blackbody_specific_intensity (wl_nm, T_K)
45 | total += specific
46 | return total
47 |
48 | def blackbody_total_intensity_stefan_boltzman (T_K):
49 | '''Get the sum of the intensities over all wavelengths, assuming the Stefan-Boltzman law.'''
50 | total = STEFAN_BOLTZMAN * math.pow (T_K, 4)
51 | # TODO - What (if any) scaling is required of this result to correspond to blackbody_specific_intensity()?
52 | # I am not sure, and there is a mismatch.
53 | # not entirely sure about the following scaling... See Shu.
54 | scaling = blackbody.SPEED_OF_LIGHT # almost
55 | total *= scaling
56 | return total
57 |
58 | def test_stefan_boltzman():
59 | '''Test that the total intensity over many wavelengths matches the Stefan-Boltman formula.
60 | NOTE - This currently does not match. I am not sure what the situation is.'''
61 | T = 100.0
62 | sb_test0 = blackbody_total_intensity_stefan_boltzman (T)
63 | print ('sb_test0', sb_test0)
64 | sb_test1 = blackbody_total_intensity (T, 0, 1000)
65 | print ('sb_test1', sb_test1)
66 | sb_test2 = blackbody_total_intensity (T, 0, 10000)
67 | print ('sb_test2', sb_test2)
68 | sb_test3 = blackbody_total_intensity (T, 0, 100000)
69 | print ('sb_test3', sb_test3)
70 | # following start to get slow...
71 | #sb_test4 = blackbody_total_intensity (T, 0, 1000000)
72 | #print ('sb_test4', sb_test4)
73 | #sb_test5 = blackbody_total_intensity (T, 0, 10000000)
74 | #print ('sb_test5', sb_test5)
75 |
76 | # compare the computed result with the stefan-boltzman formula
77 | # TODO - these do not match, although the T^4 behavior is observed...
78 | T_list = [100.0, 1000.0, 4000.0, 6500.0, 10000.0, 15000.0]
79 | for T in T_list:
80 | total_sb = blackbody_total_intensity_stefan_boltzman (T)
81 | # larger wavelength intervals capture more of the total power
82 | total1 = blackbody_total_intensity (T, 360, 830)
83 | total2 = blackbody_total_intensity (T, 1, 1000)
84 | total3 = blackbody_total_intensity (T, 1, 10000)
85 | total4 = blackbody_total_intensity (T, 1, 100000)
86 | ratio = total4 / total_sb
87 | print ('T', T)
88 | print ('total_sb', total_sb)
89 | print ('total1', total1)
90 | print ('total2', total2)
91 | print ('total3', total3)
92 | print ('total4', total4)
93 | print ('ratio', ratio)
94 |
95 |
96 | # Table of xy chromaticities for blackbodies. From (I think):
97 | # Judd and Wyszecki, Color in Business, Science and Industry, 1975, p. 164.
98 |
99 | Judd_Wyszeki_blackbody_chromaticity_table = numpy.array ([
100 | [ 1000.0, 0.6528, 0.3444],
101 | [ 1400.0, 0.5985, 0.3858],
102 | [ 1600.0, 0.5732, 0.3993],
103 | [ 1800.0, 0.5493, 0.4082],
104 | [ 2000.0, 0.5267, 0.4133],
105 | [ 2200.0, 0.5056, 0.4152],
106 | [ 2400.0, 0.4862, 0.4147],
107 | [ 2600.0, 0.4682, 0.4123],
108 | [ 2800.0, 0.4519, 0.4086],
109 | [ 3000.0, 0.4369, 0.4041],
110 | [ 3200.0, 0.4234, 0.3990],
111 | [ 3400.0, 0.4110, 0.3935],
112 | [ 3600.0, 0.3999, 0.3879],
113 | [ 3800.0, 0.3897, 0.3823],
114 | [ 4200.0, 0.3720, 0.3714],
115 | [ 4500.0, 0.3608, 0.3636],
116 | [ 4800.0, 0.3510, 0.3562],
117 | [ 5200.0, 0.3397, 0.3472],
118 | [ 5800.0, 0.3260, 0.3354],
119 | [ 6500.0, 0.3135, 0.3237],
120 | [ 7500.0, 0.3004, 0.3103],
121 | [ 8500.0, 0.2908, 0.3000],
122 | [10000.0, 0.2807, 0.2884],
123 | [30000.0, 0.2501, 0.2489]])
124 |
125 |
126 | class TestBlackbody(unittest.TestCase):
127 | ''' Test cases for blackbody spectrum. '''
128 |
129 | def test_coverage_color(self, verbose=False):
130 | ''' Coverage test of blackbody color. '''
131 | # Calculate the color for a variety of temperatures.
132 | T_list = numpy.logspace(1.0, 6.0, 21, base=10).tolist()
133 | for T in T_list:
134 | xyz = blackbody.blackbody_color (T)
135 | msg = 'T: %g K xyz: %s' % (T, str(xyz))
136 | if verbose:
137 | print (msg)
138 |
139 | def test_coverage_total_intensity(self):
140 | ''' Coverage test of blackbody total intensity. '''
141 | # FIXME: This function is only used in a test that is not working now.
142 | blackbody_total_intensity (100.0, 0, 100)
143 | blackbody_total_intensity (0.0, 0, 100)
144 | blackbody_total_intensity (100000.0, 0, 100)
145 | blackbody_total_intensity (0.0, 0, 100000)
146 | blackbody_total_intensity (100000.0, 0, 100000)
147 |
148 | def test_gold_point(self, verbose=False):
149 | ''' Test the chromaticity at the 'gold point'. '''
150 | # From Wyszecki & Stiles, p. 28.
151 | T = 1336.0 # 'Gold' point
152 | x_expect = 0.607
153 | y_expect = 0.381
154 | xyz = blackbody.blackbody_color (T)
155 | colormodels.xyz_normalize (xyz)
156 | x_actual = xyz[0]
157 | y_actual = xyz[1]
158 | # Check result. The tolerance is high, there is a discrepancy
159 | # in the last printed digit in the table in the book.
160 | # A tolerance of 5.0e-4 would match the precision in the book.
161 | tolerance = 6.0e-4
162 | self.assertAlmostEqual(x_actual, x_expect, delta=tolerance)
163 | self.assertAlmostEqual(y_actual, y_expect, delta=tolerance)
164 | # This source is supposed to be 0.11 cd/cm^2 = 1100 cd/m^2,
165 | # whereas monitors are c. 80 cd/m^2 to 300 cd/m^2.
166 | msg = 'Blackbody color at gold point: %s' % (str (xyz))
167 | if verbose:
168 | print (msg)
169 |
170 | def test_judd_wyszecki(self, verbose=False):
171 | ''' Test computed chromaticities vs table in Judd and Wyszecki. '''
172 | if verbose:
173 | print ('Test vs. Judd and Wyszecki:')
174 | table = Judd_Wyszeki_blackbody_chromaticity_table
175 | num_rows = table.shape[0]
176 | for i in range (0, num_rows):
177 | # Read temperature and expected chromaticity.
178 | T = table [i][0]
179 | x_expect = table [i][1]
180 | y_expect = table [i][2]
181 | # Calculate chromaticity for the temperature.
182 | xyz = blackbody.blackbody_color (T)
183 | colormodels.xyz_normalize (xyz)
184 | x_actual = xyz[0]
185 | y_actual = xyz[1]
186 | # Check against the tabulated result.
187 | x_error = math.fabs(x_actual - x_expect)
188 | y_error = math.fabs(y_actual - y_expect)
189 | # The tolerance used is larger than desired.
190 | # A tolerance of 5.0e-5 would match the precision in the book.
191 | tolerance = 15.0e-5
192 | self.assertAlmostEqual(x_actual, x_expect, delta=tolerance)
193 | self.assertAlmostEqual(y_actual, y_expect, delta=tolerance)
194 | # Print results.
195 | msg = 'T: %8.1f K Calculated x,y: %.5f, %.5f Expected x,y: %.5f, %.5f Error: %.5e, %.5e' % (
196 | T, x_actual, y_actual, x_expect, y_expect, x_error, y_error)
197 | if verbose:
198 | print (msg)
199 |
200 |
201 | if __name__ == '__main__':
202 | if False:
203 | # This calculation is not working yet...
204 | test_stefan_boltzman()
205 | unittest.main()
206 |
--------------------------------------------------------------------------------
/colorpy/test_ciexyz.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_ciexyz.py - Test module for ciexyz.py.
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import random
28 | import unittest
29 |
30 | import ciexyz
31 |
32 |
33 | class TestCiexyz(unittest.TestCase):
34 | ''' Test cases for CIE XYZ conversions. '''
35 |
36 | def test_coverage_1(self, verbose=False):
37 | ''' A coverage test. '''
38 | for i in range (100):
39 | wl_nm = 1000.0 * random.random()
40 | xyz = ciexyz.xyz_from_wavelength (wl_nm)
41 | msg = 'wl_nm = %7.3f, xyz = %s' % (wl_nm, str (xyz))
42 | if verbose:
43 | print (msg)
44 |
45 | def test_coverage_2(self, verbose=False):
46 | ''' Another coverage test. '''
47 | empty = ciexyz.empty_spectrum ()
48 | xyz = ciexyz.xyz_from_spectrum (empty)
49 | if verbose:
50 | print ('black = %s' % (str (xyz)))
51 | xyz_555 = ciexyz.xyz_from_wavelength (555.0)
52 | if verbose:
53 | print ('555 nm = %s' % (str (xyz_555)))
54 |
55 |
56 | if __name__ == '__main__':
57 | unittest.main()
58 |
--------------------------------------------------------------------------------
/colorpy/test_colormodels.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_colormodels.py - Test routines for colormodels.py.
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import math, random, numpy
28 | import unittest
29 |
30 | import colormodels
31 | import ciexyz
32 |
33 | # Functions to calculate the cutoff point between various algorithms.
34 | # These do not really belong here...
35 |
36 | # Luminance function [of Y value of an XYZ color] used in Luv and Lab.
37 | # See [Kasson p.399] for details.
38 | # The linear range coefficient L_LUM_C has more digits than in the paper,
39 | # this makes the function more continuous over the boundary.
40 |
41 | def calc_L_LUM_C ():
42 | '''L_LUM_C should be ideally chosen so that the two models in L_luminance() agree exactly at the cutoff point.
43 | This is where the extra digits in L_LUM_C, over Kasson, come from.'''
44 | wanted = (colormodels.L_LUM_A * math.pow (colormodels.L_LUM_CUTOFF, 1.0/3.0) - colormodels.L_LUM_B) / colormodels.L_LUM_CUTOFF
45 | print ('optimal L_LUM_C = %.16e' % (wanted))
46 |
47 | # Utility function for Lab.
48 | # See [Kasson p.399] for details.
49 | # The linear range coefficient has more digits than in the paper,
50 | # this makes the function more continuous over the boundary.
51 |
52 | def calc_LAB_F_A ():
53 | '''LAB_F_A should be ideally chosen so that the two models in Lab_f() agree exactly at the cutoff point.
54 | This is where the extra digits in LAB_F_A, over Kasson, come from.'''
55 | wanted = (math.pow (colormodels.L_LUM_CUTOFF, 1.0/3.0) - colormodels.LAB_F_B) / colormodels.L_LUM_CUTOFF
56 | print ('optimal LAB_F_A = %.16e' % (wanted))
57 |
58 |
59 | class TestColormodels(unittest.TestCase):
60 | ''' Test cases for colormodel conversions. '''
61 |
62 | def test_rgb_xyz_matrices_inverses(self, verbose=False):
63 | ''' Test that the rgb<--->xyz conversion matrices are inverses of each other. '''
64 | test_eye0 = numpy.dot (colormodels.rgb_from_xyz_matrix, colormodels.xyz_from_rgb_matrix)
65 | test_eye1 = numpy.dot (colormodels.xyz_from_rgb_matrix, colormodels.rgb_from_xyz_matrix)
66 | msg0 = 'RGB_from_XYZ * XYZ_from_RGB =\n%s' % (str(test_eye0))
67 | msg1 = 'XYZ_from_RGB * RGB_from_XYZ =\n%s' % (str(test_eye1))
68 | if verbose:
69 | print (msg0)
70 | print (msg1)
71 | atol = 1.0e-8
72 | ok0 = numpy.allclose (test_eye0, numpy.eye (3), atol=atol)
73 | ok1 = numpy.allclose (test_eye1, numpy.eye (3), atol=atol)
74 | self.assertTrue(ok0)
75 | self.assertTrue(ok1)
76 |
77 | def check_xyz_rgb(self, xyz0, verbose):
78 | ''' Check that the xyz color, converted to rgb then back, remains the same. '''
79 | rgb0 = colormodels.rgb_from_xyz (xyz0)
80 | xyz1 = colormodels.xyz_from_rgb (rgb0)
81 | rgb1 = colormodels.rgb_from_xyz (xyz1)
82 | # Check errors.
83 | err_rgb = rgb1 - rgb0
84 | error_rgb = math.sqrt (numpy.dot (err_rgb, err_rgb))
85 | err_xyz = xyz1 - xyz0
86 | error_xyz = math.sqrt (numpy.dot (err_xyz, err_xyz))
87 | tolerance = 1.0e-10
88 | self.assertLess(error_xyz, tolerance)
89 | self.assertLess(error_rgb, tolerance)
90 | msg = 'xyz: %s rgb: %s xyz2: %s rgb2: %s' % (
91 | str(xyz0), str(rgb0), str(xyz1), str(rgb1))
92 | if verbose:
93 | print (msg)
94 |
95 | def test_xyz_rgb(self, verbose=False):
96 | ''' Test some color values via check_xyz_rgb(). '''
97 | for i in range (100):
98 | x0 = 10.0 * random.random()
99 | y0 = 10.0 * random.random()
100 | z0 = 10.0 * random.random()
101 | xyz0 = colormodels.xyz_color (x0, y0, z0)
102 | self.check_xyz_rgb (xyz0, verbose)
103 |
104 | def check_xyz_irgb(self, xyz0, verbose):
105 | ''' Check the direct conversions from xyz to irgb. '''
106 | irgb0 = colormodels.irgb_from_rgb (
107 | colormodels.rgb_from_xyz (xyz0))
108 | irgb1 = colormodels.irgb_from_xyz (xyz0)
109 | self.assertEqual(irgb0[0], irgb1[0])
110 | self.assertEqual(irgb0[1], irgb1[1])
111 | self.assertEqual(irgb0[2], irgb1[2])
112 | # The string should also match.
113 | irgbs0 = colormodels.irgb_string_from_rgb (
114 | colormodels.rgb_from_xyz (xyz0))
115 | irgbs1 = colormodels.irgb_string_from_xyz (xyz0)
116 | msg = 'irgb0: %s text0: %s irgb1: %s text1: %s' % (
117 | str(irgb0), irgbs0, str(irgb1), irgbs1)
118 | if verbose:
119 | print (msg)
120 | self.assertEqual(irgbs0, irgbs1)
121 |
122 | def test_xyz_irgb(self, verbose=False):
123 | ''' Test the direct conversions from xyz to irgb. '''
124 | for i in range (100):
125 | x0 = 10.0 * random.random()
126 | y0 = 10.0 * random.random()
127 | z0 = 10.0 * random.random()
128 | xyz0 = colormodels.xyz_color (x0,y0,z0)
129 | self.check_xyz_irgb(xyz0, verbose)
130 |
131 | def check_rgb_irgb(self, irgb0, verbose):
132 | ''' Check that conversions between rgb and irgb are invertible. '''
133 | rgb0 = colormodels.rgb_from_irgb (irgb0)
134 | irgb1 = colormodels.irgb_from_rgb (rgb0)
135 | rgb1 = colormodels.rgb_from_irgb (irgb1)
136 | # Integer conversion should match exactly.
137 | self.assertEqual(irgb0[0], irgb1[0])
138 | self.assertEqual(irgb0[1], irgb1[1])
139 | self.assertEqual(irgb0[2], irgb1[2])
140 | msg = 'irgb0: %s irgb1: %s' % (str(irgb0), str(irgb1))
141 | if verbose:
142 | print (msg)
143 | # Float conversion should match closely.
144 | # (It actually seems to match exactly for me.)
145 | tolerance = 1.0e-14
146 | err_rgb = rgb1 - rgb0
147 | err_r = math.fabs (err_rgb [0])
148 | err_g = math.fabs (err_rgb [1])
149 | err_b = math.fabs (err_rgb [2])
150 | self.assertLessEqual(err_r, tolerance)
151 | self.assertLessEqual(err_g, tolerance)
152 | self.assertLessEqual(err_b, tolerance)
153 | msg = 'rgb0: %s rgb1: %s' % (str(rgb0), str(rgb1))
154 | if verbose:
155 | print (msg)
156 |
157 | def test_rgb_irgb(self, verbose=False):
158 | ''' Test that conversions between rgb and irgb are invertible. '''
159 | for i in range (100):
160 | ir = random.randrange (0, 256)
161 | ig = random.randrange (0, 256)
162 | ib = random.randrange (0, 256)
163 | irgb0 = colormodels.irgb_color (ir, ig, ib)
164 | self.check_rgb_irgb(irgb0, verbose)
165 |
166 | def check_irgb_string(self, irgb, verbose):
167 | ''' Convert back and forth from irgb and irgb_string. '''
168 | irgb_string = colormodels.irgb_string_from_irgb (irgb)
169 | irgb2 = colormodels.irgb_from_irgb_string (irgb_string)
170 | irgb_string2 = colormodels.irgb_string_from_irgb (irgb2)
171 | # Values should match.
172 | self.assertEqual(irgb[0], irgb2[0])
173 | self.assertEqual(irgb[1], irgb2[1])
174 | self.assertEqual(irgb[2], irgb2[2])
175 | # String should match.
176 | self.assertEqual(irgb_string, irgb_string2)
177 | msg = 'irgb: %s irgb2: %s irgb_string: %s irgb_string2: %s' % (
178 | str(irgb), str(irgb2), irgb_string, irgb_string2)
179 | if verbose:
180 | print (msg)
181 |
182 | def test_irgb_string(self, verbose=False):
183 | ''' Convert back and forth from irgb and irgb_string. '''
184 | for i in range (100):
185 | ir = random.randrange (0, 256)
186 | ig = random.randrange (0, 256)
187 | ib = random.randrange (0, 256)
188 | irgb = colormodels.irgb_color (ir, ig, ib)
189 | self.check_irgb_string(irgb, verbose)
190 |
191 | # Clipping.
192 |
193 | def test_clipping(self, verbose=False):
194 | ''' Test the various color clipping methods. '''
195 | # This is just a coverage test.
196 | xyz_colors = ciexyz.get_normalized_spectral_line_colors ()
197 | num_wl = xyz_colors.shape[0]
198 | for i in range (num_wl):
199 | # Get rgb values for standard add white clipping.
200 | colormodels.init_clipping (colormodels.CLIP_ADD_WHITE)
201 | rgb_white_color = colormodels.irgb_string_from_rgb (
202 | colormodels.rgb_from_xyz (xyz_colors [i]))
203 |
204 | # Get rgb values for clamp-to-zero clipping.
205 | colormodels.init_clipping (colormodels.CLIP_CLAMP_TO_ZERO)
206 | rgb_clamp_color = colormodels.irgb_string_from_rgb (
207 | colormodels.rgb_from_xyz (xyz_colors [i]))
208 |
209 | msg = 'Wavelength: %s White: %s Clamp: %s' % (
210 | str(i), # FIXME: Put in Angstroms.
211 | rgb_white_color,
212 | rgb_clamp_color)
213 | if verbose:
214 | print (msg)
215 |
216 | # Gamma correction.
217 |
218 | def check_gamma_correction(self, verbose):
219 | ''' Check if the current gamma correction is consistent. '''
220 | for i in range (10):
221 | x = 10.0 * (2.0 * random.random() - 1.0)
222 | a = colormodels.linear_from_display_component (x)
223 | y = colormodels.display_from_linear_component (a)
224 | b = colormodels.linear_from_display_component (y)
225 | # Check errors.
226 | abs_err1 = math.fabs (y - x)
227 | rel_err1 = math.fabs (abs_err1 / (y + x))
228 | abs_err2 = math.fabs (b - a)
229 | rel_err2 = math.fabs (abs_err2 / (b + a))
230 | msg1 = 'x = %g, y = %g, err = %g, rel = %g' % (x, y, abs_err1, rel_err1)
231 | msg2 = 'a = %g, b = %g, err = %g, rel = %g' % (a, b, abs_err2, rel_err2)
232 | if verbose:
233 | print (msg1)
234 | print (msg2)
235 | tolerance = 1.0e-14
236 | self.assertLessEqual(rel_err1, tolerance)
237 | self.assertLessEqual(rel_err2, tolerance)
238 |
239 | def test_gamma_srgb(self, verbose=False):
240 | ''' Test default sRGB component (cannot supply exponent). '''
241 | msg = 'Testing sRGB gamma:'
242 | if verbose:
243 | print (msg)
244 | colormodels.init_gamma_correction (
245 | display_from_linear_function = colormodels.srgb_gamma_invert,
246 | linear_from_display_function = colormodels.srgb_gamma_correct)
247 | self.check_gamma_correction(verbose)
248 |
249 | def test_gamma_power(self, verbose=False):
250 | ''' Test simple power law gamma (can supply exponent). '''
251 | gamma_set = [0.1, 0.5, 1.0, 1.1, 1.5, 2.0, 2.2, 2.5, 10.0]
252 | for gamma in gamma_set:
253 | msg = 'Testing power-law gamma: %g' % (gamma)
254 | if verbose:
255 | print (msg)
256 | colormodels.init_gamma_correction (
257 | display_from_linear_function = colormodels.simple_gamma_invert,
258 | linear_from_display_function = colormodels.simple_gamma_correct,
259 | gamma = gamma)
260 | self.check_gamma_correction(verbose)
261 |
262 | # Conversions between standard device independent color space (CIE XYZ)
263 | # and the almost perceptually uniform space Luv.
264 |
265 | def check_xyz_luv(self, xyz0, verbose):
266 | ''' Check that luv_from_xyz() and xyz_from_luv() are inverses. '''
267 | tolerance = 1.0e-10
268 | luv0 = colormodels.luv_from_xyz (xyz0)
269 | xyz1 = colormodels.xyz_from_luv (luv0)
270 | luv1 = colormodels.luv_from_xyz (xyz1)
271 | # Check errors.
272 | dluv = luv1 - luv0
273 | error_luv = math.sqrt (numpy.dot (dluv, dluv))
274 | dxyz = xyz1 - xyz0
275 | error_xyz = math.sqrt (numpy.dot (dxyz, dxyz))
276 | self.assertLessEqual(error_luv, tolerance)
277 | self.assertLessEqual(error_xyz, tolerance)
278 | msg = 'xyz0: %s luv0: %s xyz1: %s luv1: %s' % (
279 | str(xyz0), str(luv0), str(xyz1), str(luv1))
280 | if verbose:
281 | print (msg)
282 |
283 | def test_xyz_luv_black(self, verbose=False):
284 | ''' Test Luv conversions on black. '''
285 | xyz0 = colormodels.xyz_color (0.0, 0.0, 0.0)
286 | self.check_xyz_luv(xyz0, verbose)
287 |
288 | def test_xyz_luv(self, verbose=False):
289 | ''' Test that luv_from_xyz() and xyz_from_luv() are inverses. '''
290 | for i in range (100):
291 | x0 = 10.0 * random.random()
292 | y0 = 10.0 * random.random()
293 | z0 = 10.0 * random.random()
294 | xyz0 = colormodels.xyz_color (x0, y0, z0)
295 | self.check_xyz_luv(xyz0, verbose)
296 |
297 | # Conversions between standard device independent color space (CIE XYZ)
298 | # and the almost perceptually uniform space Lab.
299 |
300 | def check_xyz_lab(self, xyz0, verbose):
301 | ''' Check that lab_from_xyz() and xyz_from_lab() are inverses. '''
302 | tolerance = 1.0e-10
303 | lab0 = colormodels.lab_from_xyz (xyz0)
304 | xyz1 = colormodels.xyz_from_lab (lab0)
305 | lab1 = colormodels.lab_from_xyz (xyz1)
306 | # Check errors.
307 | dlab = lab1 - lab0
308 | error_lab = math.sqrt (numpy.dot (dlab, dlab))
309 | dxyz = xyz1 - xyz0
310 | error_xyz = math.sqrt (numpy.dot (dxyz, dxyz))
311 | self.assertLessEqual(error_lab, tolerance)
312 | self.assertLessEqual(error_xyz, tolerance)
313 | msg = 'xyz0: %s lab0: %s xyz1: %s lab1: %s' % (
314 | str(xyz0), str(lab0), str(xyz1), str(lab1))
315 | if verbose:
316 | print (msg)
317 |
318 | def test_xyz_lab_black(self, verbose=False):
319 | ''' Test Lab conversions on black. '''
320 | xyz0 = colormodels.xyz_color (0.0, 0.0, 0.0)
321 | self.check_xyz_lab(xyz0, verbose)
322 |
323 | def test_xyz_lab(self, verbose=False):
324 | '''Test that lab_from_xyz() and xyz_from_lab() are inverses.'''
325 | for i in range (100):
326 | x0 = 10.0 * random.random()
327 | y0 = 10.0 * random.random()
328 | z0 = 10.0 * random.random()
329 | xyz0 = colormodels.xyz_color (x0, y0, z0)
330 | self.check_xyz_lab(xyz0, verbose)
331 |
332 | # Luminance function [of Y value of an XYZ color] used in Luv and Lab.
333 |
334 | def check_L_luminance_inverse_1(self, y0, verbose):
335 | ''' Check that L_luminance_inverse() is the inverse of L_luminance() for the given y0. '''
336 | L0 = colormodels.L_luminance (y0)
337 | y1 = colormodels.L_luminance_inverse (L0)
338 | # Check error.
339 | error = math.fabs (y1 - y0)
340 | tolerance = 1.0e-13
341 | self.assertLessEqual(error, tolerance)
342 | msg = 'y0: %g L(y0): %g y(L(y0)): %g Error: %g' % (
343 | y0, L0, y1, error)
344 | if verbose:
345 | print (msg)
346 |
347 | def check_L_luminance_inverse_2(self, L0, verbose):
348 | ''' Check that L_luminance() is the inverse of L_luminance_inverse() for the given L0. '''
349 | y0 = colormodels.L_luminance_inverse (L0)
350 | L1 = colormodels.L_luminance (y0)
351 | # Check error.
352 | error = math.fabs (L1 - L0)
353 | tolerance = 1.0e-10
354 | self.assertLessEqual(error, tolerance)
355 | msg = 'L0: %g y(L0): %g L(y(L0)): %g Error: %g' % (
356 | L0, y0, L1, error)
357 | if verbose:
358 | print (msg)
359 |
360 | def test_L_luminance_inverse_1(self, verbose=False):
361 | ''' Test that L_luminance_inverse(L_luminance(y)) = y. '''
362 | # Test with specific values on both sides of cutoff value.
363 | vals = [0.1, 0.5, 0.9, 1.1, 2.0, 10.0]
364 | for val in vals:
365 | y0 = val * colormodels.L_LUM_CUTOFF
366 | self.check_L_luminance_inverse_1(y0, verbose)
367 | # Test with random fairly small y values.
368 | for i in range (20):
369 | y0 = 0.1 * random.random()
370 | self.check_L_luminance_inverse_1(y0, verbose)
371 | # Test with random fairly large y values.
372 | for i in range (20):
373 | y0 = 10.0 * random.random()
374 | self.check_L_luminance_inverse_1(y0, verbose)
375 |
376 | def test_L_luminance_inverse_2(self, verbose=False):
377 | ''' Test that L_luminance(L_luminance_inverse(L)) = L. '''
378 | # Test with specific values on both sides of cutoff value.
379 | vals = [0.1, 0.5, 0.9, 1.1, 2.0, 10.0]
380 | for val in vals:
381 | L0 = val * colormodels.L_LUM_C * colormodels.L_LUM_CUTOFF
382 | self.check_L_luminance_inverse_2(L0, verbose)
383 | # Test with random fairly small L values.
384 | for i in range (20):
385 | L0 = 25.0 * random.random()
386 | self.check_L_luminance_inverse_2(L0, verbose)
387 | # Test with random fairly large L values.
388 | for i in range (20):
389 | L0 = 1000.0 * random.random()
390 | self.check_L_luminance_inverse_2(L0, verbose)
391 |
392 | # Utility function for Lab.
393 |
394 | def check_Lab_f_inverse_1(self, t0, verbose):
395 | ''' Check that Lab_f_inverse() is the inverse of Lab_f() for the given t0. '''
396 | f0 = colormodels.Lab_f (t0)
397 | t1 = colormodels.Lab_f_inverse (f0)
398 | # Check error.
399 | error = math.fabs (t1 - t0)
400 | tolerance = 1.0e-13
401 | self.assertLessEqual(error, tolerance)
402 | msg = 't0: %g f(t0): %g t(f(t0)): %g Error: %g' % (
403 | t0, f0, t1, error)
404 | if verbose:
405 | print (msg)
406 |
407 | def check_Lab_f_inverse_2(self, f0, verbose):
408 | ''' Check that Lab_f() is the inverse of Lab_f_inverse() for the given f0. '''
409 | t0 = colormodels.Lab_f_inverse (f0)
410 | f1 = colormodels.Lab_f (t0)
411 | # Check error.
412 | error = math.fabs (f1 - f0)
413 | tolerance = 1.0e-10
414 | self.assertLessEqual(error, tolerance)
415 | msg = 'f0: %g t(f0): %g f(t(f0)): %g Error: %g' % (
416 | f0, t0, f1, error)
417 | if verbose:
418 | print (msg)
419 |
420 | def test_Lab_f_inverse_1(self, verbose=False):
421 | ''' Test that Lab_f_inverse(Lab_f(t)) = t. '''
422 | # Test with specific values on both sides of cutoff value.
423 | vals = [0.1, 0.5, 0.9, 1.1, 2.0, 10.0]
424 | for val in vals:
425 | y0 = val * colormodels.L_LUM_CUTOFF
426 | self.check_Lab_f_inverse_1(y0, verbose)
427 | # Test with fairly small random values.
428 | for i in range (20):
429 | y0 = 0.02 * random.random()
430 | self.check_Lab_f_inverse_1(y0, verbose)
431 | # Test with fairly large random values.
432 | for i in range (20):
433 | y0 = 10.0 * random.random()
434 | self.check_Lab_f_inverse_1(y0, verbose)
435 |
436 | def test_Lab_f_inverse_2(self, verbose=False):
437 | ''' Test that Lab_f(Lab_f_inverse(L)) = L. '''
438 | # Test with specific values on both sides of cutoff value.
439 | vals = [0.1, 0.5, 0.9, 1.1, 2.0, 10.0]
440 | for val in vals:
441 | L0 = val * (colormodels.LAB_F_A * colormodels.L_LUM_CUTOFF + colormodels.LAB_F_B)
442 | self.check_Lab_f_inverse_2(L0, verbose)
443 | # Test with fairly small random values.
444 | for i in range (20):
445 | L0 = 0.25 * random.random()
446 | self.check_Lab_f_inverse_2(L0, verbose)
447 | # Test with fairly large random values.
448 | for i in range (20):
449 | L0 = 1000.0 * random.random()
450 | self.check_Lab_f_inverse_2(L0, verbose)
451 |
452 | # Utility function for Luv.
453 |
454 | def check_uv_primes_inverse_1(self, xyz0, verbose):
455 | ''' Check that uv_primes() and uv_primes_inverse() are inverses. '''
456 | up0, vp0 = colormodels.uv_primes (xyz0)
457 | xyz1 = colormodels.uv_primes_inverse (up0, vp0, xyz0[1])
458 | # Check error.
459 | dxyz = (xyz1 - xyz0)
460 | error = math.sqrt (numpy.dot (dxyz, dxyz))
461 | tolerance = 1.0e-13
462 | self.assertLessEqual(error, tolerance)
463 | msg = 'xyz0: %s up: %g vp: %g xyz(up,vp): %s Error: %g' % (
464 | str (xyz0), up0, vp0, str(xyz1), error)
465 | if verbose:
466 | print (msg)
467 |
468 | def check_uv_primes_inverse_2(self, up0, vp0, y0, verbose):
469 | ''' Check that uv_primes() and uv_primes_inverse() are inverses. '''
470 | xyz0 = colormodels.uv_primes_inverse (up0, vp0, y0)
471 | up1, vp1 = colormodels.uv_primes (xyz0)
472 | # Check error.
473 | error_up = up1 - up0
474 | error_vp = vp1 - vp0
475 | error = numpy.hypot (error_up, error_vp)
476 | tolerance = 1.0e-13
477 | self.assertLessEqual(error, tolerance)
478 | msg = 'up0, vp0, y0: %g, %g, %g xyz(up0,vp0,y0): %s (up,vp)(xyz): %g, %g Error: %g' % (
479 | up0, vp0, y0, str (xyz0), up1, vp1, error)
480 | if verbose:
481 | print (msg)
482 |
483 | def test_uv_primes_inverse_1(self, verbose=False):
484 | ''' Test that uv_primes() and uv_primes_inverse() are inverses. '''
485 | # Test some random values.
486 | for i in range (20):
487 | x0 = 10.0 * random.random()
488 | y0 = 10.0 * random.random()
489 | z0 = 10.0 * random.random()
490 | xyz0 = colormodels.xyz_color (x0, y0, z0)
491 | self.check_uv_primes_inverse_1(xyz0, verbose)
492 | # Test black explicitly.
493 | xyz0 = colormodels.xyz_color (0.0, 0.0, 0.0)
494 | self.check_uv_primes_inverse_1(xyz0, verbose)
495 |
496 | def test_uv_primes_inverse_2(self, verbose=False):
497 | ''' Test that uv_primes() and uv_primes_inverse() are inverses. '''
498 | # Test some random values.
499 | for i in range (20):
500 | up0 = 4.0 * (2.0 * random.random() - 1.0)
501 | vp0 = 9.0 * (2.0 * random.random() - 1.0)
502 | y0 = 10.0 * random.random()
503 | self.check_uv_primes_inverse_2(up0, vp0, y0, verbose)
504 | # Test black explicitly.
505 | self.check_uv_primes_inverse_2(0.0, 0.0, 0.0, verbose)
506 |
507 |
508 | if __name__ == '__main__':
509 | unittest.main()
510 |
--------------------------------------------------------------------------------
/colorpy/test_illuminants.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_illuminants.py - Test module for illuminants.py.
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import unittest
28 |
29 | import illuminants
30 |
31 |
32 | class TestIlluminants(unittest.TestCase):
33 | ''' Test cases for illuminants. '''
34 |
35 | def test_coverage_1(self, verbose=False):
36 | ''' A coverage test of illuminants. '''
37 | D65 = illuminants.get_illuminant_D65()
38 | if verbose:
39 | print ('Illuminant D65')
40 | print (str (D65))
41 | A = illuminants.get_illuminant_A()
42 | if verbose:
43 | print ('Illuminant A')
44 | print (str (A))
45 | const = illuminants.get_constant_illuminant()
46 | if verbose:
47 | print ('Constant Illuminant')
48 | print (str (const))
49 |
50 | def test_coverage_2(self, verbose=False):
51 | ''' Another coverage test of illuminants. '''
52 | T_list = [0.0, 1.0, 100.0, 1000.0, 5778.0, 10000.0, 100000.0]
53 | for T in T_list:
54 | bb = illuminants.get_blackbody_illuminant (T)
55 | if verbose:
56 | print ('Blackbody Illuminant : %g K' % (T))
57 | print (str (bb))
58 |
59 |
60 | if __name__ == '__main__':
61 | unittest.main()
62 |
--------------------------------------------------------------------------------
/colorpy/test_rayleigh.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_rayleigh.py - Test module for rayleigh.py.
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import math
28 | import numpy
29 | import random
30 | import unittest
31 |
32 | import ciexyz
33 | import rayleigh
34 | import illuminants
35 |
36 |
37 | class TestRayleigh(unittest.TestCase):
38 | ''' Test cases for Rayleigh scattering. '''
39 |
40 | def test_wavelength_4(self, verbose=False):
41 | ''' Test that scattering scales as 1/wl^4. '''
42 | for i in range(20):
43 | # Two random wavelengths, avoiding zero.
44 | wl_1 = 1.0 + 999.0 * random.random()
45 | wl_2 = 1.0 + 999.0 * random.random()
46 | # Scattering.
47 | sc_1 = rayleigh.rayleigh_scattering(wl_1)
48 | sc_2 = rayleigh.rayleigh_scattering(wl_2)
49 | # Ratios, avoiding pow() for more independence from implementation.
50 | r_sc = sc_1 / sc_2
51 | r_wl = wl_2 / wl_1
52 | r4_wl = r_wl * r_wl * r_wl * r_wl
53 | # Check.
54 | actual = r_sc / r4_wl
55 | expect = 1.0
56 | error = math.fabs(actual - expect)
57 | tolerance = 1.0e-12
58 | self.assertLessEqual(error, tolerance)
59 | msg = 'Wavelength: %g, %g Scattering: %g, %g Ratio of Powers: %.8f' % (
60 | wl_1, wl_2, sc_1, sc_2, actual)
61 | if verbose:
62 | print (msg)
63 |
64 | def test_scattering(self, verbose=False):
65 | ''' Test of scattering calculations. '''
66 | # Coverage test of rayleigh_scattering_spectrum().
67 | rayleigh.rayleigh_scattering_spectrum()
68 | illum = illuminants.get_illuminant_D65()
69 | spect = rayleigh.rayleigh_illuminated_spectrum (illum)
70 | # Both color calculations should give the same result.
71 | xyz1 = ciexyz.xyz_from_spectrum (spect)
72 | xyz2 = rayleigh.rayleigh_illuminated_color (illum)
73 | atol = 1.0e-16
74 | ok = numpy.allclose(xyz1, xyz2, atol=atol)
75 | self.assertTrue(ok)
76 | msg = 'D65 Rayleigh scattered xyz: %s, %s' % (str(xyz1), str(xyz2))
77 | if verbose:
78 | print (msg)
79 |
80 |
81 | if __name__ == '__main__':
82 | unittest.main()
83 |
--------------------------------------------------------------------------------
/colorpy/test_thinfilm.py:
--------------------------------------------------------------------------------
1 | '''
2 | test_thinfilm.py - Test module for thinfilm.py.
3 |
4 | License:
5 |
6 | Copyright (C) 2008 Mark Kness
7 |
8 | Author - Mark Kness - mkness@alumni.utexas.net
9 |
10 | This file is part of ColorPy.
11 |
12 | ColorPy is free software: you can redistribute it and/or modify
13 | it under the terms of the GNU Lesser General Public License as
14 | published by the Free Software Foundation, either version 3 of
15 | the License, or (at your option) any later version.
16 |
17 | ColorPy is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public License
23 | along with ColorPy. If not, see .
24 | '''
25 | from __future__ import print_function
26 |
27 | import random
28 | import unittest
29 |
30 | import illuminants
31 | import thinfilm
32 |
33 |
34 | class TestThinFilm(unittest.TestCase):
35 | ''' Test cases for thin film scattering. '''
36 |
37 | def test_coverage(self):
38 | ''' A coverage test of thin film scattering. '''
39 | illuminant = illuminants.get_illuminant_D65()
40 | for j in range (20):
41 | n1 = 5.0 * random.random()
42 | n2 = 5.0 * random.random()
43 | n3 = 5.0 * random.random()
44 | thickness_nm = 10000.0 * random.random()
45 | film = thinfilm.thin_film (n1, n2, n3, thickness_nm)
46 | for k in range (20):
47 | wl_nm = 1000.0 * random.random()
48 | film.get_interference_reflection_coefficient (wl_nm)
49 | film.reflection_spectrum ()
50 | film.illuminated_spectrum (illuminant)
51 | film.illuminated_color (illuminant)
52 |
53 |
54 | if __name__ == '__main__':
55 | unittest.main()
56 |
--------------------------------------------------------------------------------
/colorpy/thinfilm.py:
--------------------------------------------------------------------------------
1 | '''
2 | thinfilm.py - Thin film interference colors.
3 |
4 | Description:
5 |
6 | Reflection from a thin film, as a function of wavelength, thickness, and index of refraction of materials.
7 |
8 | Note that film thicknesses are given in nm instead of m, as this is a more convenient unit in this case.
9 |
10 | We consider incident light from a medium of index of refraction n1,
11 | striking a thin film of index n2, with a third medium of index n3 behind the film.
12 |
13 | The total reflection from the film, back towards the incident light, is calculated.
14 |
15 | Some sample values of the index of refraction:
16 | air : n = 1.003
17 | water: n = 1.33
18 | glass/plastic: n = 1.5
19 | oil: n = 1.44 (matches Minnaert's color observations)
20 |
21 | Functions:
22 |
23 | class thin_film (n1, n2, n3, thickness_nm) -
24 | Represents a thin film, with the indices of refraction n1,n2,n3 representing:
25 | n1 - index of refraction of infinite region the light comes from
26 | n2 - index of refraction of finite region of the film
27 | n3 - index of refraction of infinite region beyond the film
28 | and thickness_nm being the thickness of the film [nm].
29 |
30 | On these class objects, the following functions are available:
31 |
32 | get_interference_reflection_coefficient (wl_nm) -
33 | Get the reflection coefficient for the intensity for light
34 | of the given wavelength impinging on the film.
35 |
36 | reflection_spectrum () -
37 | Get the reflection spectrum (independent of illuminant) for the thin film.
38 |
39 | illuminated_spectrum (illuminant) -
40 | Get the spectrum when illuminated by the specified illuminant.
41 |
42 | illuminated_color (illuminant) -
43 | Get the xyz color when illuminated by the specified illuminant.
44 |
45 | Plots:
46 |
47 | thinfilm_patch_plot (n1, n2, n3, thickness_nm_list, illuminant, title, filename) -
48 | Make a patch plot of the color of the film for each thickness [nm].
49 |
50 | thinfilm_color_vs_thickness_plot (n1, n2, n3, thickness_nm_list, illuminant, title, filename) -
51 | Plot the color of the thin film for the specfied thicknesses [nm].
52 |
53 | thinfilm_spectrum_plot (n1, n2, n3, thickness_nm, illuminant, title, filename) -
54 | Plot the spectrum of the reflection from a thin film for the given thickness [nm].
55 |
56 | References:
57 |
58 | Frank S. Crawford, Jr., Waves: Berkeley Physics Course - Volume 3,
59 | McGraw-Hill Book Company, 1968. Library of Congress 64-66016.
60 |
61 | M. Minnaert, The nature of light and color in the open air,
62 | translation H.M. Kremer-Priest, Dover Publications, New York, 1954. ISBN 486-20196-1. p. 208-209.
63 |
64 | License:
65 |
66 | Copyright (C) 2008 Mark Kness
67 |
68 | Author - Mark Kness - mkness@alumni.utexas.net
69 |
70 | This file is part of ColorPy.
71 |
72 | ColorPy is free software: you can redistribute it and/or modify
73 | it under the terms of the GNU Lesser General Public License as
74 | published by the Free Software Foundation, either version 3 of
75 | the License, or (at your option) any later version.
76 |
77 | ColorPy is distributed in the hope that it will be useful,
78 | but WITHOUT ANY WARRANTY; without even the implied warranty of
79 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80 | GNU Lesser General Public License for more details.
81 |
82 | You should have received a copy of the GNU Lesser General Public License
83 | along with ColorPy. If not, see .
84 | '''
85 | import math, cmath, numpy
86 |
87 | import colormodels
88 | import ciexyz
89 | import illuminants
90 | import plots
91 |
92 | class thin_film:
93 | '''A thin film of dielectric material.'''
94 | def __init__ (self, n1, n2, n3, thickness_nm):
95 | self.n1 = n1
96 | self.n2 = n2
97 | self.n3 = n3
98 | self.thickness_nm = thickness_nm
99 | self.too_thick = False
100 |
101 | # pre-calculate
102 | def field_reflection_coefficient (n1, n2):
103 | ''' Calculate the reflection coefficient for a light wave traveling from
104 | a region with index of refraction n1 to one having an index of n2.
105 | This is the coefficient for the electric field, not the intensity.'''
106 | return ( (n1 - n2) / (n1 + n2) )
107 |
108 | # R12 = field reflection coefficient for light traveling from region 1 to 2
109 | # R23 = field reflection coefficient for light traveling from region 2 to 3
110 | self.R12 = field_reflection_coefficient (n1, n2)
111 | self.R23 = field_reflection_coefficient (n2, n3)
112 | self.R12sqd_plus_R23sqd = self.R12*self.R12 + self.R23*self.R23
113 | self.R12_times_R23_times_2 = 2.0 * self.R12 * self.R23
114 | self.phase_factor = -2.0 * self.thickness_nm * 2.0 * math.pi * n2
115 |
116 | # aliasing will occur if the layer is too thick - see if this is true
117 | sample_interval_nm = 1.0 # assuming 1 nm
118 | wavelength_0_nm = 380.0 # shortest wl results in minimum max_thickness
119 | max_thickness_nm = 0.25 * math.pow (wavelength_0_nm, 2) / (n2 * sample_interval_nm)
120 | if self.thickness_nm > max_thickness_nm:
121 | self.too_thick = True
122 |
123 | def get_interference_reflection_coefficient (self, wl_nm):
124 | '''Get the reflection coefficient for the intensity for light
125 | of the given wavelength impinging on the film.'''
126 | if self.too_thick:
127 | # would alias -
128 | # if the layer is too thick, the cos() factor is averaged over multiple periods
129 | # to zero, this is the best we can do
130 | return self.R12sqd_plus_R23sqd
131 |
132 | ## small-reflection approximation
133 | #R = self.R12sqd_plus_R23sqd + self.R12_times_R23_times_2 * math.cos (self.phase_factor / wl_nm)
134 | #return R
135 |
136 | # exact - accounts for multiple reflections, and does not assume a small
137 | # reflection coefficient. Should be correct for complex n1,n2,n3 as well.
138 | phase = cmath.exp (complex (0, 1.0) * (self.phase_factor / wl_nm))
139 | num = self.R12 + self.R23 * phase
140 | den = 1.0 + self.R12 * self.R23 * phase
141 | Re = num / den
142 | R = Re.real*Re.real + Re.imag*Re.imag
143 | return R
144 |
145 | def reflection_spectrum (self):
146 | '''Get the reflection spectrum (independent of illuminant) for the thin film.'''
147 | spectrum = ciexyz.empty_spectrum()
148 | num_wl = spectrum.shape[0]
149 | for i in range (0, num_wl):
150 | wl_nm = spectrum [i][0]
151 | spectrum [i][1] = self.get_interference_reflection_coefficient (wl_nm)
152 | return spectrum
153 |
154 | def illuminated_spectrum (self, illuminant):
155 | '''Get the spectrum when illuminated by the specified illuminant.'''
156 | spectrum = self.reflection_spectrum()
157 | num_wl = spectrum.shape[0]
158 | for i in range (0, num_wl):
159 | spectrum [i][1] *= illuminant [i][1]
160 | return spectrum
161 |
162 | def illuminated_color (self, illuminant):
163 | '''Get the xyz color when illuminated by the specified illuminant.'''
164 | spectrum = self.illuminated_spectrum (illuminant)
165 | xyz = ciexyz.xyz_from_spectrum (spectrum)
166 | return xyz
167 |
168 |
169 | def create_thin_films (n1, n2, n3, thickness_list):
170 | ''' Create a list of thin films from a list of thicknesses. '''
171 | films = []
172 | for thickness in thickness_list:
173 | film = thin_film (n1, n2, n3, thickness)
174 | films.append(film)
175 | return films
176 |
177 | #
178 | # Figures
179 | #
180 |
181 | def thinfilm_patch_plot (n1, n2, n3, thickness_nm_list, illuminant, title, filename):
182 | '''Make a patch plot of the color of the film for each thickness [nm].'''
183 | films = create_thin_films(n1, n2, n3, thickness_nm_list)
184 | xyz_colors = []
185 | labels = []
186 | for film in films:
187 | xyz = film.illuminated_color (illuminant)
188 | xyz_colors.append (xyz)
189 | label = '%.1f nm' % (film.thickness_nm)
190 | labels.append(label)
191 | plots.xyz_patch_plot (xyz_colors, labels, title, filename)
192 |
193 | def thinfilm_color_vs_thickness_plot (n1, n2, n3, thickness_nm_list, illuminant, title, filename):
194 | '''Plot the color of the thin film for the specfied thicknesses [nm].'''
195 | films = create_thin_films(n1, n2, n3, thickness_nm_list)
196 | num_films = len (films)
197 | rgb_list = numpy.empty ((num_films, 3))
198 | for i in range (0, num_films):
199 | film = films[i]
200 | xyz = film.illuminated_color (illuminant)
201 | rgb_list [i] = colormodels.rgb_from_xyz (xyz)
202 | plots.color_vs_param_plot (
203 | thickness_nm_list,
204 | rgb_list,
205 | title,
206 | filename,
207 | xlabel = r'Thickness (nm)',
208 | ylabel = r'RGB Color')
209 |
210 | def thinfilm_spectrum_plot (n1, n2, n3, thickness_nm, illuminant, title, filename):
211 | '''Plot the spectrum of the reflection from a thin film for the given thickness [nm].'''
212 | film = thin_film (n1, n2, n3, thickness_nm)
213 | illuminated_spectrum = film.illuminated_spectrum (illuminant)
214 | plots.spectrum_plot (
215 | illuminated_spectrum,
216 | title,
217 | filename,
218 | xlabel = 'Wavelength (nm)',
219 | ylabel = 'Refection Intensity')
220 |
221 | def figures ():
222 | '''Draw some thin film plots.'''
223 | # Simple patch plot. This is not all that interesting.
224 | thickness_nm_list = numpy.linspace(0.0, 750.0, 36)
225 | illuminant = illuminants.get_illuminant_D65()
226 | illuminants.scale_illuminant (illuminant, 9.50)
227 | thinfilm_patch_plot (1.500, 1.003, 1.500, thickness_nm_list,
228 | illuminant, 'ThinFilm Patch Plot', 'ThinFilm-Patch')
229 |
230 | # Plot the colors of films vs thickness.
231 | # Scale the illuminant to get a better range of color.
232 | thickness_nm_list = numpy.linspace(0.0, 1000.0, 800)
233 | # Gap in glass/plastic.
234 | illuminant = illuminants.get_illuminant_D65()
235 | illuminants.scale_illuminant (illuminant, 4.50)
236 | thinfilm_color_vs_thickness_plot (
237 | 1.500, 1.003, 1.500, thickness_nm_list, illuminant,
238 | 'Thin Film - Gap In Glass/Plastic (n = 1.50)\nIlluminant D65',
239 | 'ThinFilm-GlassGap')
240 | # Soap bubble.
241 | illuminant = illuminants.get_illuminant_D65()
242 | illuminants.scale_illuminant (illuminant, 9.50)
243 | thinfilm_color_vs_thickness_plot (
244 | 1.003, 1.33, 1.003, thickness_nm_list, illuminant,
245 | 'Thin Film - Soap Bubble (n = 1.33)\nIlluminant D65',
246 | 'ThinFilm-SoapBubble')
247 | # Oil slick on water.
248 | illuminant = illuminants.get_illuminant_D65()
249 | illuminants.scale_illuminant (illuminant, 15.00)
250 | thinfilm_color_vs_thickness_plot (
251 | 1.003, 1.44, 1.33, thickness_nm_list, illuminant,
252 | 'Thin Film - Oil Slick (n = 1.44) on Water (n = 1.33)\nIlluminant D65',
253 | 'ThinFilm-OilSlick')
254 | # Large index of refraction bubble.
255 | # This has the brightest colors, but is a bit of an artificial example.
256 | illuminant = illuminants.get_illuminant_D65()
257 | illuminants.scale_illuminant (illuminant, 3.33)
258 | thinfilm_color_vs_thickness_plot (
259 | 1.003, 1.60, 1.003, thickness_nm_list, illuminant,
260 | 'Thin Film - Large Index (n = 1.60) Bubble\nIlluminant D65',
261 | 'ThinFilm-LargeBubble')
262 |
263 | # A very thick film to test the aliasing limits.
264 | # You have to go to very large thicknesses to get much aliasing.
265 | thickness_nm_list = numpy.linspace(0.0, 200000.0, 800)
266 | illuminant = illuminants.get_illuminant_D65()
267 | illuminants.scale_illuminant (illuminant, 9.50)
268 | thinfilm_color_vs_thickness_plot (
269 | 1.003, 1.33, 1.003, thickness_nm_list, illuminant,
270 | 'Not-so-thin Film - Soap Bubble (n = 1.33)\nIlluminant D65',
271 | 'ThinFilm-Thick')
272 |
273 | # Plot the spectrum of the refection for a couple of thicknesses.
274 | # Use a constant illuminant for a cleaner plot.
275 | # FIXME: Should this really be using an illuminant?
276 | illuminant = illuminants.get_constant_illuminant()
277 | illuminants.scale_illuminant (illuminant, 9.50)
278 | thinfilm_spectrum_plot (1.003, 1.33, 1.003, 400.0, illuminant,
279 | 'Thin Film Interference Spectrum - 400 nm thick\nConstant Illuminant',
280 | 'ThinFilm-Spectrum-400nm')
281 | thinfilm_spectrum_plot (1.003, 1.33, 1.003, 500.0, illuminant,
282 | 'Thin Film Interference Spectrum - 500 nm thick\nConstant Illuminant',
283 | 'ThinFilm-Spectrum-500nm')
284 |
285 |
286 | if __name__ == '__main__':
287 | figures()
288 |
--------------------------------------------------------------------------------