{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ASTM E2022" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "//anaconda/envs/colour-2.7/lib/python2.7/site-packages/matplotlib/__init__.py:872: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.\n", " warnings.warn(self.msg_depr % (key, alt_key))\n" ] } ], "source": [ "% matplotlib inline\n", "\n", "from __future__ import division\n", "\n", "import numpy as np\n", "import pandas as pd\n", "from scipy.interpolate import lagrange\n", "\n", "import colour\n", "from colour import (\n", " CaseInsensitiveMapping,\n", " SpectralShape,\n", " STANDARD_OBSERVERS_CMFS,\n", " ones_spd,\n", " tsplit,\n", " tstack,\n", " warning)\n", "from colour.plotting import *\n", "\n", "np.set_printoptions(suppress=True)\n", "\n", "CMFS = colour.STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1964 10 Degree Standard Observer')\n", "\n", "\n", "# TODO: Investigate if we shouldn't rename occurences of *steps*\n", "# to *interval*.\n", "# TODO: Implement in *colour.SpectralPowerDistribution*.\n", "def _trim(self, shape):\n", " wavelengths = sorted(\n", " list(set(self.shape.range()).intersection(shape.range())))\n", " values = self[wavelengths]\n", "\n", " self.data = dict(zip(wavelengths, values))\n", "\n", " return self\n", "\n", "\n", "colour.SpectralPowerDistribution.trim = _trim\n", "\n", "\n", "_A = colour.CIE_standard_illuminant_A\n", "\n", "A_0 = colour.SpectralPowerDistribution('A_0', dict(zip(CMFS.shape.range(),\n", " _A(CMFS.shape.range()))))\n", "A_1 = colour.ILLUMINANTS_RELATIVE_SPDS['A']\n", "A_1.name = 'A_1'\n", "A_2 = colour.SpectralPowerDistribution('A_2', dict(zip(A_0.wavelengths[::5],\n", " A_0.values[::5])))\n", "A_3 = colour.SpectralPowerDistribution('A_2', dict(zip(A_0.wavelengths[::10],\n", " A_0.values[::10])))\n", "A_4 = colour.SpectralPowerDistribution('A_3', dict(zip(A_1.wavelengths[::2],\n", " A_1.values[::2])))\n", "A_5 = A_4.clone().trim(SpectralShape(400, 700, 10))\n", "A_5.name = 'A_5'\n", "A_6 = colour.SpectralPowerDistribution('A_6', dict(zip(A_0.wavelengths[::20],\n", " A_0.values[::20])))\n", "\n", "spds = (A_0, A_1, A_2, A_3, A_4, A_5, A_6)\n", "\n", "_TRISTIMULUS_WEIGHTING_FACTORS_CACHE = None\n", "\n", "_LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE = None\n", "\n", "\n", "def lagrange_interpolating_coefficient(r, d=4):\n", " r_i = np.arange(d)\n", " L_n = []\n", " for j in range(len(r_i)):\n", " p = [(r - r_i[m]) / (r_i[j] - r_i[m])\n", " for m in range(len(r_i)) if m != j]\n", " L_n.append(reduce(lambda m, n: m * n, p))\n", "\n", " return L_n\n", "\n", "\n", "def lagrange_interpolating_coefficients_ASTME2022(interval=10,\n", " interval_type='intermediate'):\n", " global _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE\n", " if _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE is None:\n", " _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE = CaseInsensitiveMapping()\n", "\n", " name_lica = ', '.join((str(interval), interval_type))\n", " if name_lica in _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE:\n", " return _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE[name_lica]\n", "\n", " r_n = np.linspace(1 / interval, 1 - (1 / interval), interval - 1)\n", " d = 3\n", " if interval_type.lower() == 'intermediate':\n", " r_n += 1\n", " d = 4\n", "\n", " lica = _LAGRANGE_INTERPOLATING_COEFFICIENTS_CACHE[name_lica] = (\n", " np.asarray([lagrange_interpolating_coefficient(r, d) for r in r_n]))\n", "\n", " return lica\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nx44dfzy2cuVK9txzTz766CPq1Knzs/Hjx4/nhhtuIIRAXl4ehx9+OA888ABVqlTZ7Pun0r1KkiRJ\nksqHT95fyg1D32Vcvcqs2ff/b1dQ7ZM0Tv8mj7s7HMhv6u5S6HsUNpPCkqKcqkj3KkmSJEkqOevW\nbeDS63szfqf6fH5kDaic/2fNsDydg2Zv5NZmu3PaCQ2L/H4u95AkSZIkSVvlzRlz6XhrT96bORoW\nL4TzzoOMDtSalUbHmM7t5zUn85QdivVnWlKkmC5dujBt2jRCyC+VYow0aNCA0aNHJ5xMkiRJklTe\n5W3Mo2u3kTw0bjArZr8Aq1fnn6hVh32/rM6AyvU57Ip9Suznu9yjnKpI9ypJkiRJ2j5zP1jC2bf1\n5bXZo4kfvPnj8Uq/O4hTW7Yl+6Gr2Kl61WL5WS73kCRJkiRJPxPzIr0fmcxto5/iqzljYNmS/BM7\nVGG3xsdy39+70LHTiaWayZJCkiRJkqQK5JslKzn31iGMmzWaDW9PgvX5T+lIq7Mnh//pdAb/+yb2\n3HO3RLJZUkiSJEmSVAFMGPcul/Qdwrz3RsPH7+UfDIHM37fgms7nc8t1nUlLS0s0oyWFJEmSJEnl\n1Nq1G7nunnH0mzqS1TPGwP++zT9RtRr7N29F/x63cEjzxsmG/AlLioQtWrSIvfbai3vuuYfrrrtu\ni+Pmz5/Pfvvtx/7770+MkRACubm5ZGZmlmJaSZIkSVJZ8N57S+nU/SnefH80cfp/IC8PgMq770O7\nU9rz6AP/YKeddko45S/5dI+EdevWjcmTJ7N48WLmzJmzxXHz58+nZcuWLFiwoEjvm4r3KkmSJEkq\nWTk507h+5HCWzh4F8+bmH0xLZ48/tKTHjVdy5lmnEMJmH6xRany6RxHk5m7/v6SsrK0vBXJychg5\nciTt2rVjxowZNG/efItjLR0kSZIkSZta8/06Lrt9FANnjGTd9HHw/fcAhGq7kHXYqQzodTsN9m6Q\ncMqisaRI0NSpU6levTqNGjWiU6dODBgwoNCS4quvvqJZs2akp6dz9tlnc9lll5ViWkmSJElSKvnk\n3SWcdWc20z98FmZNg4K/2K665x+54uzz6Nr1UnbYYYeEU24dl3sk6IILLqBx48ZcfvnlfPnllzRp\n0oRFixZRqVKlX4xdv3493333HbVr12bJkiW0bt2aa6+9lr/+9a+bfe9Uu1dJkiRJUvEYMugNrho4\n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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "multi_spd_plot(spds)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "scrolled": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/anaconda/envs/colour-2.7/lib/python2.7/site-packages/ipykernel/__main__.py:21: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n", "/anaconda/envs/colour-2.7/lib/python2.7/site-packages/ipykernel/__main__.py:51: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n" ] }, { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
360-0.000-0.000-0.000
370-0.000-0.000-0.000
380-0.000-0.000-0.000
3900.0020.0000.008
4000.0250.0030.110
4100.1340.0140.615
4200.3770.0391.792
4300.6860.0843.386
4400.9640.1564.944
4501.0800.2595.806
4601.0060.4245.812
4700.7310.6964.919
4800.3431.0823.300
4900.0781.6161.973
5000.0222.4221.152
5100.2183.5290.658
5200.7504.8400.382
5301.6426.1000.211
5402.8427.2500.102
5504.3368.1140.032
5606.2008.7580.001
5708.2628.988-0.000
58010.2278.7600.000
59011.9458.3040.000
60012.7467.4680.000
61012.3376.3230.000
62010.8175.0330.000
6308.5603.7440.000
6406.0142.5060.000
6503.8871.5600.000
6602.3090.9110.000
6701.2760.4990.000
6800.6660.2590.000
6900.3360.1300.000
7000.1660.0650.000
7100.0820.0320.000
7200.0400.0160.000
7300.0200.0080.000
7400.0100.0040.000
7500.0050.0020.000
7600.0030.0010.000
7700.0010.0010.000
7800.0010.0000.000
7900.0000.0000.000
8000.0000.0000.000
8100.0000.0000.000
8200.0000.0000.000
8300.0000.0000.000
\n", "
" ], "text/plain": [ " 0 1 2\n", "360 -0.000 -0.000 -0.000\n", "370 -0.000 -0.000 -0.000\n", "380 -0.000 -0.000 -0.000\n", "390 0.002 0.000 0.008\n", "400 0.025 0.003 0.110\n", "410 0.134 0.014 0.615\n", "420 0.377 0.039 1.792\n", "430 0.686 0.084 3.386\n", "440 0.964 0.156 4.944\n", "450 1.080 0.259 5.806\n", "460 1.006 0.424 5.812\n", "470 0.731 0.696 4.919\n", "480 0.343 1.082 3.300\n", "490 0.078 1.616 1.973\n", "500 0.022 2.422 1.152\n", "510 0.218 3.529 0.658\n", "520 0.750 4.840 0.382\n", "530 1.642 6.100 0.211\n", "540 2.842 7.250 0.102\n", "550 4.336 8.114 0.032\n", "560 6.200 8.758 0.001\n", "570 8.262 8.988 -0.000\n", "580 10.227 8.760 0.000\n", "590 11.945 8.304 0.000\n", "600 12.746 7.468 0.000\n", "610 12.337 6.323 0.000\n", "620 10.817 5.033 0.000\n", "630 8.560 3.744 0.000\n", "640 6.014 2.506 0.000\n", "650 3.887 1.560 0.000\n", "660 2.309 0.911 0.000\n", "670 1.276 0.499 0.000\n", "680 0.666 0.259 0.000\n", "690 0.336 0.130 0.000\n", "700 0.166 0.065 0.000\n", "710 0.082 0.032 0.000\n", "720 0.040 0.016 0.000\n", "730 0.020 0.008 0.000\n", "740 0.010 0.004 0.000\n", "750 0.005 0.002 0.000\n", "760 0.003 0.001 0.000\n", "770 0.001 0.001 0.000\n", "780 0.001 0.000 0.000\n", "790 0.000 0.000 0.000\n", "800 0.000 0.000 0.000\n", "810 0.000 0.000 0.000\n", "820 0.000 0.000 0.000\n", "830 0.000 0.000 0.000" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def tristimulus_weighting_factors_ASTME2022(cmfs, illuminant, shape):\n", " # Assumes that the measurement interval is equal to the spectral bandwidth integral when applying correction\n", " # for bandwidth.\n", " if cmfs.shape.interval != 1:\n", " raise RuntimeError('\"{0}\" shape \"interval\" must be 1!'.format(cmfs))\n", "\n", " if illuminant.shape.interval != 1:\n", " raise RuntimeError('\"{0}\" shape \"interval\" must be 1!'.format(illuminant))\n", "\n", " global _TRISTIMULUS_WEIGHTING_FACTORS_CACHE\n", " if _TRISTIMULUS_WEIGHTING_FACTORS_CACHE is None:\n", " _TRISTIMULUS_WEIGHTING_FACTORS_CACHE = CaseInsensitiveMapping()\n", "\n", " name_twf = ', '.join((cmfs.name, illuminant.name, str(shape)))\n", " if name_twf in _TRISTIMULUS_WEIGHTING_FACTORS_CACHE:\n", " return _TRISTIMULUS_WEIGHTING_FACTORS_CACHE[name_twf]\n", "\n", " Y = cmfs.values\n", " S = illuminant.values\n", "\n", " W = S[::shape.interval, np.newaxis] * Y[::shape.interval, :]\n", "\n", " # First and last measurement intervals Lagrange interpolating coefficients.\n", " c_c = lagrange_interpolating_coefficients_ASTME2022(\n", " shape.interval, 'boundaries')\n", " # Intermediate measurement intervals Lagrange interpolating coefficients.\n", " c_b = lagrange_interpolating_coefficients_ASTME2022(\n", " shape.interval, 'intermediate')\n", "\n", " # Total wavelengths count.\n", " w_c = len(Y)\n", " # Measurement interval interpolated values count.\n", " r_c = c_b.shape[0]\n", " # Last interval first interpolated wavelength.\n", " w_lif = w_c - (w_c - 1) % shape.interval - 1 - r_c\n", "\n", " # Intervals count.\n", " i_c = W.shape[0]\n", " i_cm = i_c - 1\n", "\n", " for i in range(3):\n", " # First interval.\n", " for j in range(r_c):\n", " for k in range(3):\n", " W[k, i] = W[k, i] + c_c[j, k] * S[j + 1] * Y[j + 1, i]\n", "\n", " # Last interval.\n", " for j in range(r_c):\n", " for k in range(i_cm, i_cm - 3, -1):\n", " W[k, i] = (W[k, i] + c_c[r_c - j - 1, i_cm - k] *\n", " S[j + w_lif] * Y[j + w_lif, i])\n", "\n", " # Intermediate intervals.\n", " for j in range(i_c - 3):\n", " for k in range(r_c):\n", " w_i = (r_c + 1) * (j + 1) + 1 + k\n", " W[j, i] = W[j, i] + c_b[k, 0] * S[w_i] * Y[w_i, i]\n", " W[j + 1, i] = W[j + 1, i] + c_b[k, 1] * S[w_i] * Y[w_i, i]\n", " W[j + 2, i] = W[j + 2, i] + c_b[k, 2] * S[w_i] * Y[w_i, i]\n", " W[j + 3, i] = W[j + 3, i] + c_b[k, 3] * S[w_i] * Y[w_i, i]\n", "\n", " # Extrapolation of incomplete interval.\n", " for j in range(int(w_c - ((w_c - 1) % shape.interval)), w_c, 1):\n", " W[i_cm, i] = W[i_cm, i] + S[j] * Y[j, i]\n", "\n", " W *= 100 / np.sum(W, axis=0)[1]\n", " \n", " _TRISTIMULUS_WEIGHTING_FACTORS_CACHE[name_twf] = W\n", "\n", " return W\n", "\n", "\n", "interval = 10\n", "W = tristimulus_weighting_factors_ASTME2022(\n", " CMFS, A_0, SpectralShape(360, 830, interval))\n", "pd.DataFrame(np.round(W, 3), index=CMFS.wavelengths[::interval])" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[u'CIE 1964 10 Degree Standard Observer, A_0, (360.0, 830.0, 10.0)']\n", "[[ -0.00000107 -0.00000012 -0.00000472]\n", " [ -0.00001661 -0.00000178 -0.00007381]\n", " [ -0.00006265 -0.00000599 -0.00029594]\n", " [ 0.00173203 0.00019067 0.00750329]\n", " [ 0.02462197 0.00258221 0.11002471]\n", " [ 0.13380791 0.01362493 0.61486115]\n", " [ 0.37667958 0.03938975 1.79237892]\n", " [ 0.68597339 0.0841476 3.3861349 ]\n", " [ 0.96392708 0.15560923 4.9435215 ]\n", " [ 1.07974419 0.25937514 5.80554508]\n", " [ 1.00590861 0.42435443 5.81195103]\n", " [ 0.73080637 0.69621402 4.91946293]\n", " [ 0.34300924 1.0820871 3.29990629]\n", " [ 0.07831511 1.61594792 1.97254698]\n", " [ 0.02194756 2.42211921 1.15160362]\n", " [ 0.21833481 3.52935836 0.65817752]\n", " [ 0.74977436 4.83960641 0.38208014]\n", " [ 1.64205871 6.09952855 0.21088813]\n", " [ 2.84155576 7.24966561 0.1017075 ]\n", " [ 4.33599624 8.11420343 0.03166653]\n", " [ 6.19979323 8.75836777 0.00075805]\n", " [ 8.26209852 8.98754929 -0.00039173]\n", " [ 10.22702179 8.76043263 0. ]\n", " [ 11.94453493 8.30368873 0. ]\n", " [ 12.74568269 7.46780925 0. ]\n", " [ 12.33748425 6.32293455 0. ]\n", " [ 10.8174099 5.03327421 0. ]\n", " [ 8.56033345 3.74437296 0. ]\n", " [ 6.01359695 2.5057274 0. ]\n", " [ 3.88742931 1.56029743 0. ]\n", " [ 2.30930966 0.91132438 0. ]\n", " [ 1.27604009 0.49928962 0. ]\n", " [ 0.66559109 0.25908944 0. ]\n", " [ 0.33564033 0.13039083 0. ]\n", " [ 0.16631373 0.06456164 0. ]\n", " [ 0.08152211 0.03166502 0. ]\n", " [ 0.04003215 0.01557503 0. ]\n", " [ 0.0197651 0.00770767 0. ]\n", " [ 0.00985927 0.00385519 0. ]\n", " [ 0.00498819 0.00195642 0. ]\n", " [ 0.00256792 0.00101058 0. ]\n", " [ 0.00133954 0.00052911 0. ]\n", " [ 0.00070759 0.0002806 0. ]\n", " [ 0.00037977 0.00015123 0. ]\n", " [ 0.00020654 0.00008261 0. ]\n", " [ 0.00011164 0.00004484 0. ]\n", " [ 0.00007022 0.00002835 0. ]\n", " [ 0.00001614 0.00000654 0. ]]\n" ] } ], "source": [ "print(_TRISTIMULUS_WEIGHTING_FACTORS_CACHE.keys())\n", "print(_TRISTIMULUS_WEIGHTING_FACTORS_CACHE[\n", " 'CIE 1964 10 Degree Standard Observer, A_0, (360.0, 830.0, 10.0)'])" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ -0.00000107, -0.00000012, -0.00000472],\n", " [ -0.00001661, -0.00000178, -0.00007381],\n", " [ -0.00006265, -0.00000599, -0.00029594],\n", " [ 0.00173203, 0.00019067, 0.00750329],\n", " [ 0.02462197, 0.00258221, 0.11002471],\n", " [ 0.13380791, 0.01362493, 0.61486115],\n", " [ 0.37667958, 0.03938975, 1.79237892],\n", " [ 0.68597339, 0.0841476 , 3.3861349 ],\n", " [ 0.96392708, 0.15560923, 4.9435215 ],\n", " [ 1.07974419, 0.25937514, 5.80554508],\n", " [ 1.00590861, 0.42435443, 5.81195103],\n", " [ 0.73080637, 0.69621402, 4.91946293],\n", " [ 0.34300924, 1.0820871 , 3.29990629],\n", " [ 0.07831511, 1.61594792, 1.97254698],\n", " [ 0.02194756, 2.42211921, 1.15160362],\n", " [ 0.21833481, 3.52935836, 0.65817752],\n", " [ 0.74977436, 4.83960641, 0.38208014],\n", " [ 1.64205871, 6.09952855, 0.21088813],\n", " [ 2.84155576, 7.24966561, 0.1017075 ],\n", " [ 4.33599624, 8.11420343, 0.03166653],\n", " [ 6.19979323, 8.75836777, 0.00075805],\n", " [ 8.26209852, 8.98754929, -0.00039173],\n", " [ 10.22702179, 8.76043263, 0. ],\n", " [ 11.94453493, 8.30368873, 0. ],\n", " [ 12.74568269, 7.46780925, 0. ],\n", " [ 12.33748425, 6.32293455, 0. ],\n", " [ 10.8174099 , 5.03327421, 0. ],\n", " [ 8.56033345, 3.74437296, 0. ],\n", " [ 6.01359695, 2.5057274 , 0. ],\n", " [ 3.88742931, 1.56029743, 0. ],\n", " [ 2.30930966, 0.91132438, 0. ],\n", " [ 1.27604009, 0.49928962, 0. ],\n", " [ 0.66559109, 0.25908944, 0. ],\n", " [ 0.33564033, 0.13039083, 0. ],\n", " [ 0.16631373, 0.06456164, 0. ],\n", " [ 0.08152211, 0.03166502, 0. ],\n", " [ 0.04003215, 0.01557503, 0. ],\n", " [ 0.0197651 , 0.00770767, 0. ],\n", " [ 0.00985927, 0.00385519, 0. ],\n", " [ 0.00498819, 0.00195642, 0. ],\n", " [ 0.00256792, 0.00101058, 0. ],\n", " [ 0.00133954, 0.00052911, 0. ],\n", " [ 0.00070759, 0.0002806 , 0. ],\n", " [ 0.00037977, 0.00015123, 0. ],\n", " [ 0.00020654, 0.00008261, 0. ],\n", " [ 0.00011164, 0.00004484, 0. ],\n", " [ 0.00007022, 0.00002835, 0. ],\n", " [ 0.00001614, 0.00000654, 0. ]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def reshape_tristimulus_weighting_factors_ASTME2022(W, shape_W, shape_R):\n", " W = np.copy(W)\n", "\n", " start_index = int((shape_R.start - shape_W.start) / shape_W.interval)\n", " for i in range(start_index):\n", " W[start_index] += W[i]\n", "\n", " end_index = int((shape_W.end - shape_R.end) / shape_W.interval)\n", " for i in range(end_index):\n", " W[-end_index - 1] += W[-i - 1]\n", " \n", " return W[start_index:-end_index or None, ...]\n", "\n", "W = _TRISTIMULUS_WEIGHTING_FACTORS_CACHE[\n", " 'CIE 1964 10 Degree Standard Observer, A_0, (360.0, 830.0, 10.0)']\n", "\n", "reshape_tristimulus_weighting_factors_ASTME2022(\n", " W, SpectralShape(360, 830, 10), SpectralShape(360, 830, 10))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A_0\n", "\tName: (360.0, 830.0, 1.0)\n", "\tXYZ: [ 108.41037515 97.54050189 34.33420992]\n", "\tDelta E: 0.0\n", "\n", "\n", "A_1\n", "\tName: (300.0, 780.0, 5.0)\n", "\tXYZ: [ 108.41140563 97.54101491 34.33390573]\n", "\tDelta E: 0.000643086073379\n", "\n", "\n", "A_2\n", "\tName: (360.0, 830.0, 5.0)\n", "\tXYZ: [ 108.41148545 97.54104514 34.33390262]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/kelsolaar/Documents/Development/colour-science/colour/colour/utilities/verbose.py:128: UserWarning: Aligning \"\" illuminant shape to \"\" colour matching functions shape.\n", " warn(*args, **kwargs)\n", "/Users/kelsolaar/Documents/Development/colour-science/colour/colour/utilities/verbose.py:128: UserWarning: Aligning \"\" spectral power distribution shape to \"\" colour matching functions shape.\n", " warn(*args, **kwargs)\n", "/anaconda/envs/colour-2.7/lib/python2.7/site-packages/ipykernel/__main__.py:21: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "\tDelta E: 0.000720553331383\n", "\n", "\n", "A_2\n", "\tName: (360.0, 830.0, 10.0)\n", "\tXYZ: [ 108.41037377 97.54050302 34.33426204]\n", "\tDelta E: 4.86633069299e-05\n", "\n", "\n", "A_3\n", "\tName: (300.0, 780.0, 10.0)\n", "\tXYZ: [ 108.41030137 97.5404718 34.33426832]\n", "\tDelta E: 5.07225469815e-05\n", "\n", "\n", "A_5\n", "\tName: (400.0, 700.0, 10.0)\n", "\tXYZ: [ 108.40204834 97.5371289 34.33618511]\n", "\tDelta E: 0.00712222031386\n", "\n", "\n", "A_6\n", "\tName: (360.0, 820.0, 20.0)\n", "\tXYZ: [ 108.41035673 97.54051762 34.33490451]\n", "\tDelta E: 0.000646820939847\n", "\n", "\n", "\n", "\n", "[u'CIE 1964 10 Degree Standard Observer, A_0, (360.0, 830.0, 10.0)', u'CIE 1964 10 Degree Standard Observer, 1 Constant, (None, None, 10.0)']\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/anaconda/envs/colour-2.7/lib/python2.7/site-packages/ipykernel/__main__.py:51: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n", "/Users/kelsolaar/Documents/Development/colour-science/colour/colour/utilities/verbose.py:128: UserWarning: Trimming \"\" spectral power distribution shape to \"\" colour matching functions shape.\n", " warn(*args, **kwargs)\n" ] } ], "source": [ "def spectral_to_XYZ_integration(\n", " spd,\n", " cmfs=STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer'),\n", " illuminant=ones_spd(STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer').shape)):\n", " if illuminant.shape != cmfs.shape:\n", " warning('Aligning \"{0}\" illuminant shape to '\n", " '\"{1}\" colour matching functions shape.'.format(\n", " illuminant, cmfs))\n", " illuminant = illuminant.clone().align(cmfs.shape)\n", "\n", " if spd.shape != cmfs.shape:\n", " warning('Aligning \"{0}\" spectral power distribution shape to '\n", " '\"{1}\" colour matching functions shape.'.format(\n", " spd, cmfs))\n", " spd = spd.clone().align(cmfs.shape)\n", "\n", " S = illuminant.values\n", " x_bar, y_bar, z_bar = tsplit(cmfs.values)\n", " R = spd.values\n", " dw = cmfs.shape.interval\n", "\n", " k = 100 / (np.sum(y_bar * S) * dw)\n", "\n", " X_p = R * x_bar * S * dw\n", " Y_p = R * y_bar * S * dw\n", " Z_p = R * z_bar * S * dw\n", "\n", " XYZ = k * np.array([np.sum(X_p), np.sum(Y_p), np.sum(Z_p)])\n", "\n", " return XYZ\n", "\n", "\n", "def spectral_to_XYZ_tristimulus_weighting_factors(\n", " spd,\n", " cmfs=STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer'),\n", " illuminant=ones_spd(STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer').shape)):\n", " if illuminant.shape != cmfs.shape:\n", " warning('Aligning \"{0}\" illuminant shape to '\n", " '\"{1}\" colour matching functions shape.'.format(\n", " illuminant, cmfs))\n", " illuminant = illuminant.clone().align(cmfs.shape)\n", "\n", " if spd.shape.boundaries != cmfs.shape.boundaries:\n", " warning('Trimming \"{0}\" spectral power distribution shape to '\n", " '\"{1}\" colour matching functions shape.'.format(\n", " illuminant, cmfs))\n", " spd = spd.clone().trim(cmfs.shape)\n", "\n", " W = tristimulus_weighting_factors_ASTME2022(\n", " cmfs, illuminant, SpectralShape(interval=spd.shape.interval))\n", " start_w = cmfs.shape.start\n", " end_w = cmfs.shape.start + spd.shape.interval * (W.shape[0] - 1)\n", " W = reshape_tristimulus_weighting_factors_ASTME2022(\n", " W, SpectralShape(start_w, end_w, spd.shape.interval), spd.shape)\n", " R = spd.values\n", "\n", " XYZ = np.sum(W * R[..., np.newaxis], axis=0)\n", "\n", " return XYZ\n", "\n", "\n", "def spectral_to_XYZ_ASTM_E30815(\n", " spd,\n", " cmfs=STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer'),\n", " illuminant=ones_spd(\n", " STANDARD_OBSERVERS_CMFS.get(\n", " 'CIE 1931 2 Degree Standard Observer').shape),\n", " im_5nm_omission_method=True,\n", " im_20nm_abridge_method=True):\n", " if spd.shape.interval not in (1, 5, 10, 20):\n", " raise ValueError(\n", " 'Tristimulus values conversion from spectral data following '\n", " '*ASTM E308-15* designation should be performed on spectral '\n", " 'data with measurement interval of 1, 5, 10 or 20nm!')\n", "\n", " method = spectral_to_XYZ_tristimulus_weighting_factors\n", " if spd.shape.interval == 1:\n", " method = spectral_to_XYZ_integration\n", " elif spd.shape.interval == 5 and im_5nm_omission_method:\n", " if cmfs.shape.interval != 5:\n", " cmfs = cmfs.clone().interpolate(SpectralShape(interval=5))\n", " method = spectral_to_XYZ_integration\n", " elif spd.shape.interval == 20 and im_20nm_abridge_method:\n", " spd = spd.clone()\n", " if spd.shape.boundaries != cmfs.shape.boundaries:\n", " warning('Trimming \"{0}\" spectral power distribution shape to '\n", " '\"{1}\" colour matching functions shape.'.format(\n", " illuminant, cmfs))\n", " spd.trim(cmfs.shape)\n", "\n", " # Extrapolation of additional 20nm padding intervals.\n", " spd.align(SpectralShape(spd.shape.start - 20, spd.shape.end + 20, 10))\n", " for i in range(2):\n", " spd[spd.wavelengths[i]] = (3 * spd.values[i + 2] -\n", " 3 * spd.values[i + 4] +\n", " spd.values[i + 6])\n", " i_e = len(spd) - 1 - i\n", " spd[spd.wavelengths[i_e]] = (spd.values[i_e - 6] -\n", " 3 * spd.values[i_e - 4] +\n", " 3 * spd.values[i_e - 2])\n", "\n", " # Interpolating every odd numbered values. \n", " # TODO: Investigate code vectorisation. \n", " for i in range(3, len(spd) - 3, 2):\n", " spd[spd.wavelengths[i]] = (-0.0625 * spd.values[i - 3] +\n", " 0.5625 * spd.values[i - 1] +\n", " 0.5625 * spd.values[i + 1] -\n", " 0.0625 * spd.values[i + 3])\n", "\n", " # Discarding the additional 20nm padding intervals. \n", " spd.trim(SpectralShape(spd.shape.start + 20, spd.shape.end - 20, 10))\n", "\n", " XYZ = method(spd, cmfs, illuminant)\n", "\n", " return XYZ\n", "\n", "\n", "XYZ_A_0 = spectral_to_XYZ_ASTM_E30815(A_0, CMFS) / 100\n", "\n", "for spd in spds:\n", " print(spd.name)\n", " print('\\tName: {0}'.format(spd.shape))\n", " XYZ_A_n = spectral_to_XYZ_ASTM_E30815(spd, CMFS) / 100\n", " print('\\tXYZ: {0}'.format(XYZ_A_n))\n", " print('\\tDelta E: {0}'.format(\n", " colour.delta_E_CIE2000(colour.XYZ_to_Lab(XYZ_A_0),\n", " colour.XYZ_to_Lab(XYZ_A_n))))\n", " print('\\n')\n", "\n", "print('\\n')\n", "\n", "print(_TRISTIMULUS_WEIGHTING_FACTORS_CACHE.keys())" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.11" } }, "nbformat": 4, "nbformat_minor": 0 }