def test_extrapolate(self): """ Tests :func:`colour.colorimetry.spectrum.\ MultiSpectralDistribution.extrapolate` method. """ data = dict(zip(range(25, 35), tstack([[0] * 5 + [1] * 5] * 3))) multi_sd = MultiSpectralDistribution(data) multi_sd.extrapolate(SpectralShape(10, 50)) np.testing.assert_almost_equal(multi_sd[10], np.array([0.0, 0.0, 0.0]), decimal=7) np.testing.assert_almost_equal(multi_sd[50], np.array([1.0, 1.0, 1.0]), decimal=7) multi_sd = MultiSpectralDistribution( tstack([np.linspace(0, 1, 10)] * 3), np.linspace(25, 35, 10)) multi_sd.extrapolate(SpectralShape(10, 50), extrapolator_args={ 'method': 'Linear', 'left': None, 'right': None }) np.testing.assert_almost_equal(multi_sd[10], np.array([-1.5, -1.5, -1.5]), decimal=7) np.testing.assert_almost_equal(multi_sd[50], np.array([2.5, 2.5, 2.5]), decimal=7)
def make_srgb_2015_color_checker(): # get color checker spectrum cc_spectrum, cc_shape = load_colorchecker_spectrum() cc_shape = SpectralShape(390, 730, 1) cc_spectrum.trim(cc_shape) cc_spectrum = cc_spectrum.interpolate(SpectralShape(interval=1), interpolator=LinearInterpolator) # get d65 spd, cie1931 cmfs d65_spd = load_d65_spd_1nmdata().trim(cc_shape) cmfs_cie2015 =\ STANDARD_OBSERVERS_CMFS['CIE 2012 2 Degree Standard Observer'].copy() cmfs_cie2015.trim(cc_shape) d65_spd_1nm = d65_spd.values[:, 1] cmfs_cie2015_1nm = cmfs_cie2015.values # get large xyz data from spectrum large_xyz = colorchecker_spectrum_to_large_xyz_2015( d_light=d65_spd_1nm, cc_spectrum=cc_spectrum, cmfs=cmfs_cie2015_1nm, temperature=6500) # convert from XYZ to sRGB rgb = color_checker_large_xyz_to_rgb(large_xyz) rgb[rgb < 0] = 0 # rgb[rgb > 1] = 1 rgb = np.uint8(np.round(oetf_sRGB(rgb) * 255)) # plot tpg.plot_color_checker_image(rgb) return rgb
def test_extrapolate(self): """ Tests :func:`colour.colorimetry.spectrum.\ SpectralPowerDistribution.extrapolate` method. """ data = dict(zip(range(25, 35), [0] * 5 + [1] * 5)) spd = SpectralPowerDistribution(data) spd.extrapolate(SpectralShape(10, 50)) self.assertAlmostEqual(spd[10], 0, places=7) self.assertAlmostEqual(spd[50], 1, places=7) spd = SpectralPowerDistribution( np.linspace(0, 1, 10), np.linspace(25, 35, 10)) spd.extrapolate( SpectralShape(10, 50), extrapolator_args={ 'method': 'Linear', 'left': None, 'right': None }) self.assertAlmostEqual(spd[10], -1.5000000000000004, places=7) self.assertAlmostEqual(spd[50], 2.4999999999999964, places=7)
def test__eq__(self): """ Tests :func:`colour.colorimetry.spectrum.SpectralShape.__eq__` method. """ self.assertEqual(SpectralShape(0, 10, 0.1), SpectralShape(0, 10, 0.1))
def test_interpolate(self): """ Tests :func:`colour.colorimetry.spectrum.\ MultiSpectralDistribution.interpolate` method. """ multi_sd = self._sample_multi_sd.copy() multi_sd.interpolate(SpectralShape(interval=1)) for signal in multi_sd.signals.values(): np.testing.assert_almost_equal(signal.values, INTERPOLATED_SAMPLE_SD_DATA, decimal=7) # TODO: Remove statement whenever we make "Scipy" 0.19.0 the minimum # version. # Skipping tests because of "Scipy" 0.19.0 interpolation code changes. if LooseVersion(scipy.__version__) < LooseVersion('0.19.0'): return multi_sd = self._non_uniform_sample_multi_sd.copy() multi_sd.interpolate(SpectralShape(interval=1)) for signal in multi_sd.signals.values(): np.testing.assert_allclose(signal.values, INTERPOLATED_NON_UNIFORM_SAMPLE_SD_DATA, rtol=0.0000001, atol=0.0000001)
def test_end(self): """ Tests :attr:`colour.colorimetry.spectrum.SpectralShape.end` attribute. """ self.assertEqual(SpectralShape(360, 830, 1).end, 830) self.assertRaises(AssertionError, lambda: SpectralShape(830, 830, 1)) self.assertRaises(AssertionError, lambda: SpectralShape(830, 0, 1))
def test_trim(self): """ Tests :func:`colour.colorimetry.spectrum.\ SpectralDistribution.trim` method. """ shape = SpectralShape(400, 700, 20) self.assertEqual(self._sd.copy().trim(shape).shape, shape) shape = SpectralShape(200, 900, 1) self.assertEqual(self._sd.copy().trim(shape).shape, self._sd.shape)
def test_align(self): """ Tests :func:`colour.colorimetry.spectrum.\ SpectralDistribution.align` method. """ shape = SpectralShape(100, 900, 5) self.assertEqual(self._sd.copy().align(shape).shape, shape) shape = SpectralShape(600, 650, 1) self.assertEqual(self._sd.copy().align(shape).shape, shape)
def test_boundaries(self): """ Tests :attr:`colour.colorimetry.spectrum.SpectralShape.boundaries` attribute. """ shape = SpectralShape() shape.boundaries = (360, 830) self.assertEqual(shape.start, 360) self.assertEqual(shape.end, 830)
def test_boundaries(self): """ Tests :attr:`colour.colorimetry.spectrum.SpectralShape.boundaries` attribute. """ shape = SpectralShape() shape.boundaries = (360, 830) self.assertEqual(shape.start, 360) self.assertEqual(shape.end, 830)
def test_align(self): """ Tests :func:`colour.colorimetry.spectrum.\ MultiSpectralPowerDistribution.align` method. """ multi_spd = self._sample_multi_spd.copy() shape = SpectralShape(100, 900, 5) self.assertEqual(multi_spd.align(shape).shape, shape) shape = SpectralShape(600, 650, 1) self.assertEqual(multi_spd.align(shape).shape, shape)
def test__contains__(self): """ Tests :func:`colour.colorimetry.spectrum.SpectralShape.__contains__` method. """ self.assertIn(360.1, SpectralShape(360, 830, 0.1)) self.assertNotIn(360.11, SpectralShape(360, 830, 0.1)) self.assertIn(np.array([0.5, 0.6]), SpectralShape(0, 10, 0.1)) self.assertNotIn(np.array([0.5, 0.61]), SpectralShape(0, 10, 0.1))
def test_raise_exception_range(self): """ Tests :func:`colour.colorimetry.spectrum.SpectralShape.range` method raised exception. """ self.assertRaises(RuntimeError, SpectralShape().range)
def test_interval(self): """ Tests :attr:`colour.colorimetry.spectrum.SpectralShape.interval` attribute. """ self.assertEqual(SpectralShape(360, 830, 1).interval, 1)
def interpolate_5nm_cmfs_data(spd, interplation="linear"): interpolator = get_interpolater(interplation) temp = spd.copy() temp.interpolate(SpectralShape(interval=1), interpolator=interpolator) return temp
def get_normalize_large_y_param_cie1931_5nm(temperature=6500): """ XYZ算出用の正規化係数を算出する """ d_light = make_day_light_by_calculation(temperature=temperature, interpolater=LinearInterpolator, interval=5) # d_light.values = fit_significant_figures(d_light.values, 6) d_light.trim(SpectralShape(380, 780)) cmfs_cie1931 = load_cie1931_1nm_data().trim(SpectralShape(380, 780)) d_light_5nm = d_light.values cmfs_cie1931_5nm = cmfs_cie1931.values[::5] large_y = np.sum(d_light_5nm * cmfs_cie1931_5nm[:, 1]) normalize_coef = 100 / large_y return normalize_coef
def test_shape(self): """ Tests :attr:`colour.colorimetry.spectrum.\ SpectralDistribution.shape` attribute. """ self.assertEqual(self._sd.shape, SpectralShape(340, 820, 20))
def get_nomalize_large_y_cie2015(temperature=6500): """ XYZ算出用の正規化係数を算出する """ shape = SpectralShape(390, 830, 1) if temperature == 6500: d_light = load_d65_spd_1nmdata() else: d_light = make_day_light_by_calculation( temperature=temperature, interpolater=LinearInterpolator, interval=1) d_light.trim(shape) if temperature == 6500: d_light_1nm = d_light.values[:, 1] else: d_light_1nm = d_light.values cmfs =\ STANDARD_OBSERVERS_CMFS['CIE 2012 2 Degree Standard Observer'].copy() cmfs_cie2015_1nm = cmfs.values large_y = np.sum(d_light_1nm * cmfs_cie2015_1nm[:, 1]) normalize_coef = 100 / large_y return normalize_coef
def test_shape(self): """ Tests :attr:`colour.colorimetry.spectrum.\ MultiSpectralDistribution.shape` attribute. """ self.assertEqual(self._multi_sd.shape, SpectralShape(380, 780, 5))
def test_range(self): """ Tests :func:`colour.colorimetry.spectrum.SpectralShape.range` method. """ np.testing.assert_almost_equal( [wavelength for wavelength in SpectralShape(0, 10, 0.1)], np.arange(0, 10 + 0.1, 0.1))
def load_cie1931_1nm_data(): """ CIE S 014-1 に記載の2°視野の等色関数を得る """ cie_file = "./src_data/CMFs_CIE_S_014-1.csv" cms_1931_2 = np.loadtxt(cie_file, delimiter=',') m_data = make_multispectral_format_data(cms_1931_2[:, 0], cms_1931_2[:, 1:], "CIE1931_1nm_data") cmfs_1nm = MultiSpectralDistribution(m_data) cmfs_1nm.trim(SpectralShape(380, 780, 5)) # print(cmfs_1nm.wavelengths[::5]) return cmfs_1nm
def make_day_light_by_calculation(temperature=6500, interpolater=LinearInterpolator, interval=1): """ 計算でD光源を作る。 interpolater: SpragueInterpolator or LinearInterpolator """ xy = make_xy_value_from_temperature(temperature) spd = sd_CIE_illuminant_D_series(xy) spd = spd.interpolate(SpectralShape(interval=interval), interpolator=interpolater) spd.values = fit_significant_figures(spd.values, 6) return spd
def calc_d65_white_xy(): """ とりあえず D65 White の XYZ および xy を求めてみる。 """ # temperature = 6500 # d65_spd = make_day_light_by_calculation(temperature=temperature, # interpolater=LinearInterpolator, # interval=5) # d65_spd.values = fit_significant_figures(d65_spd.values, 6) d65_spd = load_d65_spd_1nmdata().trim(SpectralShape(380, 780)) cmfs_cie1931 = load_cie1931_1nm_data().trim(SpectralShape(380, 780)) d65_spd_5nm = d65_spd.values[::5] cmfs_cie1931_5nm = cmfs_cie1931.values[::5] large_x = np.sum(d65_spd_5nm[:, 1] * cmfs_cie1931_5nm[:, 0]) large_y = np.sum(d65_spd_5nm[:, 1] * cmfs_cie1931_5nm[:, 1]) large_z = np.sum(d65_spd_5nm[:, 1] * cmfs_cie1931_5nm[:, 2]) normalize_coef = 100 / large_y large_xyz = [ large_x * normalize_coef, large_y * normalize_coef, large_z * normalize_coef ] print(large_xyz) print(XYZ_to_xy(large_xyz))
def load_colorchecker_spectrum(): """ Babel Average 2012 のデータをロード。 """ csv = "./src_data/babel_spectrum_2012.csv" data = np.loadtxt(csv, delimiter=',', skiprows=0) wavelength = data[0, :] values = tstack([data[x, :] for x in range(1, 25)]) m_data = make_multispectral_format_data(wavelength, values, "Babel Average Spectrum") color_checker_spd = MultiSpectralDistribution(m_data) color_checker_spd.interpolate(SpectralShape(interval=5), interpolator=LinearInterpolator) return color_checker_spd, color_checker_spd.shape
def make_day_light_by_calculation(temperature=6500, interpolater=None, interval=1): """ 計算でD光源を作る。 interpolater: SpragueInterpolator or LinearInterpolator """ xy = make_xy_value_from_temperature(temperature) spd = sd_CIE_illuminant_D_series(xy) spd = spd.interpolate(SpectralShape(interval=interval), interpolator=interpolater) spd.values = fit_significant_figures(spd.values, 6) # ret_value = np.dstack([spd.wavelengths, spd.values]) # return ret_value.reshape((len(spd.values), 2)).T return spd
def get_normalize_large_y_param_cie1931_5nm_test(): temperature = 5000 shape = SpectralShape(380, 780) coef = get_normalize_large_y_param_cie1931_5nm(temperature) d_light = make_day_light_by_calculation(temperature=temperature, interpolater=LinearInterpolator, interval=5) d_light.trim(shape) cmfs_cie1931 = load_cie1931_1nm_data().trim(shape) cmfs_cie1931_5nm = cmfs_cie1931.values[::5] large_x = np.sum(d_light.values * cmfs_cie1931_5nm[:, 0]) large_y = np.sum(d_light.values * cmfs_cie1931_5nm[:, 1]) large_z = np.sum(d_light.values * cmfs_cie1931_5nm[:, 2]) large_xyz = [large_x * coef, large_y * coef, large_z * coef] print(large_xyz) print(XYZ_to_xy(large_xyz))
def calc_cie2015_d65_white_xy(): shape = SpectralShape(390, 830, 1) cmfs = STANDARD_OBSERVERS_CMFS['CIE 2012 2 Degree Standard Observer'] d65_spd = load_d65_spd_1nmdata().trim(shape) d65_1nm = d65_spd.values[:, 1] cmfs_1nm = cmfs.values large_x = np.sum(d65_1nm * cmfs_1nm[:, 0]) large_y = np.sum(d65_1nm * cmfs_1nm[:, 1]) large_z = np.sum(d65_1nm * cmfs_1nm[:, 2]) normalize_coef = 100 / large_y large_xyz = [ large_x * normalize_coef, large_y * normalize_coef, large_z * normalize_coef ] print(large_xyz) print(XYZ_to_xy(large_xyz))
def load_colorchecker_spectrum(interpolator=SpragueInterpolator): """ Babel Average 2012 のデータをロード。 """ base_dir = os.path.dirname(os.path.abspath(__file__)) csv = base_dir + "/data/babel_spectrum_2012.csv" data = np.loadtxt(csv, delimiter=',', skiprows=0) wavelength = data[0, :] values = tstack([data[x, :] for x in range(1, 25)]) m_data = _make_multispectral_format_data(wavelength, values) color_checker_spd = MultiSpectralDistribution(m_data) if interpolator is not None: color_checker_spd.interpolate(SpectralShape(interval=1), interpolator=interpolator) return color_checker_spd
def calc_appropriate_shape(spd1, spd2): """ 等色関数と測定対象の波長範囲が一致しない場合に 適切な Shape を設定する。 例: ``` a.shape = SpectralShape(390, 830, 1) b.shape = SpectralShape(360, 780, 5) calc_appropriate_shape(a, b) >>> SpectralShape(360, 780, 5) ``` """ start = np.max(np.array([spd1.shape.start, spd2.shape.start])) end = np.min(np.array([spd1.shape.end, spd2.shape.end])) interval = np.max(np.array([spd1.shape.interval, spd2.shape.interval])) return SpectralShape(start, end, interval)