def test_signal_unpack_data(self): """ Tests :func:`colour.continuous.signal.Signal.signal_unpack_data` method. """ domain, range_ = Signal.signal_unpack_data(self._range) np.testing.assert_array_equal(range_, self._range) np.testing.assert_array_equal(domain, np.arange(0, 10, 1)) domain, range_ = Signal.signal_unpack_data(self._range, self._domain) np.testing.assert_array_equal(range_, self._range) np.testing.assert_array_equal(domain, self._domain) domain, range_ = Signal.signal_unpack_data( dict(zip(self._domain, self._range))) np.testing.assert_array_equal(range_, self._range) np.testing.assert_array_equal(domain, self._domain) domain, range_ = Signal.signal_unpack_data( Signal(self._range, self._domain)) np.testing.assert_array_equal(range_, self._range) np.testing.assert_array_equal(domain, self._domain) if is_pandas_installed(): from pandas import Series domain, range_ = Signal.signal_unpack_data( Series(dict(zip(self._domain, self._range)))) np.testing.assert_array_equal(range_, self._range) np.testing.assert_array_equal(domain, self._domain)
def to_series(self): """ Converts the continuous signal to a *Pandas* :class:`Series` class instance. Returns ------- Series Continuous signal as a *Pandas* :class:`Series` class instance. Examples -------- >>> if is_pandas_installed(): ... range_ = np.linspace(10, 100, 10) ... signal = Signal(range_) ... print(signal.to_series()) # doctest: +SKIP 0.0 10.0 1.0 20.0 2.0 30.0 3.0 40.0 4.0 50.0 5.0 60.0 6.0 70.0 7.0 80.0 8.0 90.0 9.0 100.0 Name: Signal (...), dtype: float64 """ if is_pandas_installed(): from pandas import Series return Series(data=self._range, index=self._domain, name=self.name)
def test__init__(self): """ Tests :func:`colour.continuous.signal.Signal.__init__` method. """ signal = Signal(self._range) np.testing.assert_array_equal(signal.domain, np.arange(0, 10, 1)) np.testing.assert_array_equal(signal.range, self._range) signal = Signal(self._range, self._domain) np.testing.assert_array_equal(signal.domain, self._domain) np.testing.assert_array_equal(signal.range, self._range) signal = Signal(dict(zip(self._domain, self._range))) np.testing.assert_array_equal(signal.domain, self._domain) np.testing.assert_array_equal(signal.range, self._range) signal = Signal(signal) np.testing.assert_array_equal(signal.domain, self._domain) np.testing.assert_array_equal(signal.range, self._range) if is_pandas_installed(): from pandas import Series signal = Signal(Series(dict(zip(self._domain, self._range)))) np.testing.assert_array_equal(signal.domain, self._domain) np.testing.assert_array_equal(signal.range, self._range)
def test_multi_signal_unpack_data(self): """ Tests :func:`colour.continuous.multi_signal.MultiSignal.\ multi_signal_unpack_data` method. """ signals = MultiSignal.multi_signal_unpack_data(self._range_1) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_1) np.testing.assert_array_equal(signals[0].range, self._range_1) signals = MultiSignal.multi_signal_unpack_data(self._range_1, self._domain_2) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_2) np.testing.assert_array_equal(signals[0].range, self._range_1) signals = MultiSignal.multi_signal_unpack_data(self._range_2, self._domain_2) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) signals = MultiSignal.multi_signal_unpack_data( dict(zip(self._domain_2, self._range_2))) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) signals = MultiSignal.multi_signal_unpack_data( MultiSignal.multi_signal_unpack_data( dict(zip(self._domain_2, self._range_2)))) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) if is_pandas_installed(): from pandas import DataFrame, Series signals = MultiSignal.multi_signal_unpack_data( Series(dict(zip(self._domain_1, self._range_1)))) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_1) np.testing.assert_array_equal(signals[0].range, self._range_1) data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) signals = MultiSignal.multi_signal_unpack_data( DataFrame(data, self._domain_1)) self.assertListEqual(list(signals.keys()), ['a', 'b', 'c']) np.testing.assert_array_equal(signals['a'].range, self._range_1) np.testing.assert_array_equal(signals['b'].range, self._range_1 + 10) np.testing.assert_array_equal(signals['c'].range, self._range_1 + 20)
def test_multi_signals_unpack_data(self): """ Tests :func:`colour.continuous.multi_signals.MultiSignals.\ multi_signals_unpack_data` method. """ signals = MultiSignals.multi_signals_unpack_data(self._range_1) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_1) np.testing.assert_array_equal(signals[0].range, self._range_1) signals = MultiSignals.multi_signals_unpack_data( self._range_1, self._domain_2) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_2) np.testing.assert_array_equal(signals[0].range, self._range_1) signals = MultiSignals.multi_signals_unpack_data( self._range_2, self._domain_2) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) signals = MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2))) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) signals = MultiSignals.multi_signals_unpack_data( MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2)))) self.assertListEqual(list(signals.keys()), [0, 1, 2]) np.testing.assert_array_equal(signals[0].range, self._range_1) np.testing.assert_array_equal(signals[1].range, self._range_1 + 10) np.testing.assert_array_equal(signals[2].range, self._range_1 + 20) if is_pandas_installed(): from pandas import DataFrame, Series signals = MultiSignals.multi_signals_unpack_data( Series(dict(zip(self._domain_1, self._range_1)))) self.assertListEqual(list(signals.keys()), [0]) np.testing.assert_array_equal(signals[0].domain, self._domain_1) np.testing.assert_array_equal(signals[0].range, self._range_1) data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) signals = MultiSignals.multi_signals_unpack_data( DataFrame(data, self._domain_1)) self.assertListEqual(list(signals.keys()), ['a', 'b', 'c']) np.testing.assert_array_equal(signals['a'].range, self._range_1) np.testing.assert_array_equal(signals['b'].range, self._range_1 + 10) np.testing.assert_array_equal(signals['c'].range, self._range_1 + 20)
def test_to_series(self): """Test :func:`colour.continuous.signal.Signal.to_series` method.""" if is_pandas_installed(): from pandas import Series self.assertEqual( Signal(self._range, self._domain).to_series().all(), Series(dict(zip(self._domain, self._range))).all(), )
def test__init__(self): """ Tests :func:`colour.continuous.multi_signal.MultiSignal.__init__` method. """ multi_signal = MultiSignal(self._range_1) np.testing.assert_array_equal(multi_signal.domain, self._domain_1) np.testing.assert_array_equal(multi_signal.range, self._range_1[:, np.newaxis]) multi_signal = MultiSignal(self._range_1, self._domain_2) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_1[:, np.newaxis]) multi_signal = MultiSignal(self._range_2, self._domain_2) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_2) multi_signal = MultiSignal(dict(zip(self._domain_2, self._range_2))) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_2) multi_signal = MultiSignal(multi_signal) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_2) class NotSignal(Signal): """ Not :class:`Signal` class. """ pass multi_signal = MultiSignal(self._range_1, signal_type=NotSignal) self.assertIsInstance(multi_signal.signals[0], NotSignal) np.testing.assert_array_equal(multi_signal.domain, self._domain_1) np.testing.assert_array_equal(multi_signal.range, self._range_1[:, np.newaxis]) if is_pandas_installed(): from pandas import DataFrame, Series multi_signal = MultiSignal( Series(dict(zip(self._domain_2, self._range_1)))) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_1[:, np.newaxis]) data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) multi_signal = MultiSignal(DataFrame(data, self._domain_2)) np.testing.assert_array_equal(multi_signal.domain, self._domain_2) np.testing.assert_array_equal(multi_signal.range, self._range_2)
def test_to_series(self): """ Tests :func:`colour.continuous.signal.Signal.to_series` method. """ if is_pandas_installed(): from pandas import Series self.assertEqual( Signal(self._range, self._domain).to_series().all(), Series(dict(zip(self._domain, self._range))).all())
def test__init__(self): """ Tests :func:`colour.continuous.multi_signals.MultiSignals.__init__` method. """ multi_signals = MultiSignals(self._range_1) np.testing.assert_array_equal(multi_signals.domain, self._domain_1) np.testing.assert_array_equal(multi_signals.range, self._range_1[:, np.newaxis]) multi_signals = MultiSignals(self._range_1, self._domain_2) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_1[:, np.newaxis]) multi_signals = MultiSignals(self._range_2, self._domain_2) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_2) multi_signals = MultiSignals(dict(zip(self._domain_2, self._range_2))) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_2) multi_signals = MultiSignals(multi_signals) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_2) class NotSignal(Signal): """ Not :class:`Signal` class. """ pass multi_signals = MultiSignals(self._range_1, signal_type=NotSignal) self.assertIsInstance(multi_signals.signals[0], NotSignal) np.testing.assert_array_equal(multi_signals.domain, self._domain_1) np.testing.assert_array_equal(multi_signals.range, self._range_1[:, np.newaxis]) if is_pandas_installed(): from pandas import DataFrame, Series multi_signals = MultiSignals( Series(dict(zip(self._domain_2, self._range_1)))) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_1[:, np.newaxis]) data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) multi_signals = MultiSignals(DataFrame(data, self._domain_2)) np.testing.assert_array_equal(multi_signals.domain, self._domain_2) np.testing.assert_array_equal(multi_signals.range, self._range_2)
def test_to_dataframe(self): """ Tests :func:`colour.continuous.multi_signals.MultiSignals.to_dataframe` method. """ if is_pandas_installed(): from pandas import DataFrame data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) assert MultiSignals(self._range_2, self._domain_2, labels=['a', 'b', 'c']).to_dataframe().equals( DataFrame(data, self._domain_2))
def test_to_dataframe(self): """ Tests :func:`colour.continuous.multi_signal.MultiSignal.to_dataframe` method. """ if is_pandas_installed(): from pandas import DataFrame data = dict(zip(['a', 'b', 'c'], tsplit(self._range_2))) assert MultiSignal( self._range_2, self._domain_2, labels=['a', 'b', 'c']).to_dataframe().equals( DataFrame(data, self._domain_2))
def test_to_dataframe(self): """ Test :meth:`colour.continuous.multi_signals.MultiSignals.to_dataframe` method. """ if is_pandas_installed(): from pandas import DataFrame data = dict(zip(["a", "b", "c"], tsplit(self._range_2))) attest( MultiSignals(self._range_2, self._domain_2, labels=["a", "b", "c"]).to_dataframe().equals( DataFrame(data, self._domain_2)))
def to_dataframe(self): """ Converts the continuous signal to a *Pandas* :class:`DataFrame` class instance. Returns ------- DataFrame Continuous signal as a *Pandas* :class:`DataFrame` class instance. Examples -------- >>> if is_pandas_installed(): ... domain = np.arange(0, 10, 1) ... range_ = tstack([np.linspace(10, 100, 10)] * 3) ... range_ += np.array([0, 10, 20]) ... multi_signal = MultiSignal(range_) ... print(multi_signal.to_dataframe()) # doctest: +SKIP 0 1 2 0.0 10.0 20.0 30.0 1.0 20.0 30.0 40.0 2.0 30.0 40.0 50.0 3.0 40.0 50.0 60.0 4.0 50.0 60.0 70.0 5.0 60.0 70.0 80.0 6.0 70.0 80.0 90.0 7.0 80.0 90.0 100.0 8.0 90.0 100.0 110.0 9.0 100.0 110.0 120.0 """ if is_pandas_installed(): from pandas import DataFrame return DataFrame(data=self.range, index=self.domain, columns=self.labels)
def to_dataframe(self): """ Converts the continuous signal to a *Pandas* :class:`DataFrame` class instance. Returns ------- DataFrame Continuous signal as a *Pandas* :class:`DataFrame` class instance. Examples -------- >>> if is_pandas_installed(): ... domain = np.arange(0, 10, 1) ... range_ = tstack([np.linspace(10, 100, 10)] * 3) ... range_ += np.array([0, 10, 20]) ... multi_signal = MultiSignal(range_) ... print(multi_signal.to_dataframe()) # doctest: +SKIP 0 1 2 0.0 10.0 20.0 30.0 1.0 20.0 30.0 40.0 2.0 30.0 40.0 50.0 3.0 40.0 50.0 60.0 4.0 50.0 60.0 70.0 5.0 60.0 70.0 80.0 6.0 70.0 80.0 90.0 7.0 80.0 90.0 100.0 8.0 90.0 100.0 110.0 9.0 100.0 110.0 120.0 """ if is_pandas_installed(): from pandas import DataFrame return DataFrame( data=self.range, index=self.domain, columns=self.labels)
def signal_unpack_data(data=None, domain=None, dtype=DEFAULT_FLOAT_DTYPE): """ Unpack given data for continuous signal instantiation. Parameters ---------- data : Series or Signal or array_like or dict_like, optional Data to unpack for continuous signal instantiation. domain : array_like, optional Values to initialise the :attr:`colour.continuous.Signal.domain` attribute with. If both ``data`` and ``domain`` arguments are defined, the latter will be used to initialise the :attr:`colour.continuous.Signal.domain` attribute. dtype : type, optional **{np.float16, np.float32, np.float64, np.float128}**, Floating point data type. Returns ------- tuple Independent domain :math:`x` variable and corresponding range :math:`y` variable unpacked for continuous signal instantiation. Examples -------- Unpacking using implicit *domain*: >>> range_ = np.linspace(10, 100, 10) >>> domain, range_ = Signal.signal_unpack_data(range_) >>> print(domain) [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using explicit *domain*: >>> domain = np.arange(100, 1100, 100) >>> domain, range = Signal.signal_unpack_data(range_, domain) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *dict*: >>> domain, range_ = Signal.signal_unpack_data( ... dict(zip(domain, range_))) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *Pandas* *Series*: >>> if is_pandas_installed(): ... from pandas import Series ... domain, range = Signal.signal_unpack_data( ... Series(dict(zip(domain, range_)))) ... # doctest: +ELLIPSIS >>> print(domain) # doctest: +SKIP [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) # doctest: +SKIP [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a :class:`colour.continuous.Signal` class: >>> domain, range_ = Signal.signal_unpack_data( ... Signal(range_, domain)) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] """ assert dtype in np.sctypes['float'], ( '"dtype" must be one of the following types: {0}'.format( np.sctypes['float'])) domain_u, range_u = None, None if isinstance(data, Signal): domain_u = data.domain range_u = data.range elif (issubclass(type(data), Sequence) or isinstance(data, (tuple, list, np.ndarray, Iterator))): data = tsplit(list(data) if isinstance(data, Iterator) else data) assert data.ndim == 1, 'User "data" must be 1-dimensional!' domain_u, range_u = np.arange(0, data.size, dtype=dtype), data elif (issubclass(type(data), Mapping) or isinstance(data, (dict, OrderedDict))): domain_u, range_u = tsplit(sorted(data.items())) elif is_pandas_installed(): from pandas import Series if isinstance(data, Series): domain_u = data.index.values range_u = data.values if domain is not None and range_u is not None: assert len(domain) == len(range_u), ( 'User "domain" is not compatible with unpacked range!') domain_u = as_array(domain, dtype) if range_u is not None: range_u = as_array(range_u, dtype) return domain_u, range_u
def multi_signal_unpack_data(data=None, domain=None, labels=None, dtype=DEFAULT_FLOAT_DTYPE, signal_type=Signal, **kwargs): """ Unpack given data for multi-continuous signal instantiation. Parameters ---------- data : Series or Dataframe or Signal or MultiSignal or array_like or \ dict_like, optional Data to unpack for multi-continuous signal instantiation. domain : array_like, optional Values to initialise the multiple :class:`colour.continuous.Signal` sub-class instances :attr:`colour.continuous.Signal.domain` attribute with. If both ``data`` and ``domain`` arguments are defined, the latter will be used to initialise the :attr:`colour.continuous.Signal.domain` attribute. dtype : type, optional **{np.float16, np.float32, np.float64, np.float128}**, Floating point data type. signal_type : type, optional A :class:`colour.continuous.Signal` sub-class type. Other Parameters ---------------- name : unicode, optional Multi-continuous signal name. interpolator : object, optional Interpolator class type to use as interpolating function for the :class:`colour.continuous.Signal` sub-class instances. interpolator_args : dict_like, optional Arguments to use when instantiating the interpolating function of the :class:`colour.continuous.Signal` sub-class instances. extrapolator : object, optional Extrapolator class type to use as extrapolating function for the :class:`colour.continuous.Signal` sub-class instances. extrapolator_args : dict_like, optional Arguments to use when instantiating the extrapolating function of the :class:`colour.continuous.Signal` sub-class instances. Returns ------- dict Mapping of labeled :class:`colour.continuous.Signal` sub-class instances. Examples -------- Unpacking using implicit *domain* and a single signal: >>> range_ = np.linspace(10, 100, 10) >>> signals = MultiSignal.multi_signal_unpack_data(range_) >>> list(signals.keys()) [0] >>> print(signals[0]) [[ 0. 10.] [ 1. 20.] [ 2. 30.] [ 3. 40.] [ 4. 50.] [ 5. 60.] [ 6. 70.] [ 7. 80.] [ 8. 90.] [ 9. 100.]] Unpacking using explicit *domain* and a single signal: >>> domain = np.arange(100, 1100, 100) >>> signals = MultiSignal.multi_signal_unpack_data(range_, domain) >>> list(signals.keys()) [0] >>> print(signals[0]) [[ 100. 10.] [ 200. 20.] [ 300. 30.] [ 400. 40.] [ 500. 50.] [ 600. 60.] [ 700. 70.] [ 800. 80.] [ 900. 90.] [ 1000. 100.]] Unpacking using multiple signals: >>> range_ = tstack([np.linspace(10, 100, 10)] * 3) >>> range_ += np.array([0, 10, 20]) >>> signals = MultiSignal.multi_signal_unpack_data(range_, domain) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using a *dict*: >>> signals = MultiSignal.multi_signal_unpack_data( ... dict(zip(domain, range_))) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using *MultiSignal.multi_signal_unpack_data* method output: >>> signals = MultiSignal.multi_signal_unpack_data( ... dict(zip(domain, range_))) >>> signals = MultiSignal.multi_signal_unpack_data(signals) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using a *Pandas* *Series*: >>> if is_pandas_installed(): ... from pandas import Series ... signals = MultiSignal.multi_signal_unpack_data( ... Series(dict(zip(domain, np.linspace(10, 100, 10))))) ... print(signals[0]) # doctest: +SKIP [[ 100. 10.] [ 200. 20.] [ 300. 30.] [ 400. 40.] [ 500. 50.] [ 600. 60.] [ 700. 70.] [ 800. 80.] [ 900. 90.] [ 1000. 100.]] Unpacking using a *Pandas* *Dataframe*: >>> if is_pandas_installed(): ... from pandas import DataFrame ... data = dict(zip(['a', 'b', 'c'], tsplit(range_))) ... signals = MultiSignal.multi_signal_unpack_data( ... DataFrame(data, domain)) ... print(signals['c']) # doctest: +SKIP [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] """ assert dtype in np.sctypes['float'], ( '"dtype" must be one of the following types: {0}'.format( np.sctypes['float'])) domain_u, range_u, signals = None, None, None signals = OrderedDict() # TODO: Implement support for Signal class passing. if isinstance(data, MultiSignal): signals = data.signals elif (issubclass(type(data), Sequence) or isinstance(data, (tuple, list, np.ndarray, Iterator))): data = tsplit(list(data) if isinstance(data, Iterator) else data) assert data.ndim in (1, 2), ( 'User "data" must be 1-dimensional or 2-dimensional!') if data.ndim == 1: data = data[np.newaxis, :] for i, range_u in enumerate(data): signals[i] = signal_type(range_u, domain, **kwargs) elif (issubclass(type(data), Mapping) or isinstance(data, (dict, OrderedDict))): # Handling `MultiSignal.multi_signal_unpack_data` method output # used as argument to `MultiSignal.multi_signal_unpack_data` # method. is_signal = all([ True if isinstance(i, Signal) else False for i in data.values() ]) if is_signal: for label, signal in data.items(): signals[label] = signal_type(signal.range, signal.domain, **kwargs) else: domain_u, range_u = zip(*sorted(data.items())) for i, range_u in enumerate(tsplit(range_u)): signals[i] = signal_type(range_u, domain_u, **kwargs) elif is_pandas_installed(): from pandas import DataFrame, Series if isinstance(data, Series): signals[0] = signal_type(data, **kwargs) elif isinstance(data, DataFrame): domain_u = data.index.values signals = OrderedDict(((label, signal_type( data[label], domain_u, name=label, **kwargs)) for label in data)) if domain is not None and signals is not None: for signal in signals.values(): assert len(domain) == len(signal.domain), ( 'User "domain" is not compatible with unpacked signals!') signal.domain = domain if labels is not None and signals is not None: assert len(labels) == len(signals), ( 'User "labels" is not compatible with unpacked signals!') signals = OrderedDict( [(labels[i], signal) for i, (_key, signal) in enumerate(signals.items())]) return signals
def signal_unpack_data(data=None, domain=None, dtype=None): """ Unpack given data for continuous signal instantiation. Parameters ---------- data : Series or Signal or array_like or dict_like, optional Data to unpack for continuous signal instantiation. domain : array_like, optional Values to initialise the :attr:`colour.continuous.Signal.domain` attribute with. If both ``data`` and ``domain`` arguments are defined, the latter will be used to initialise the :attr:`colour.continuous.Signal.domain` attribute. dtype : type, optional **{np.float16, np.float32, np.float64, np.float128}**, Floating point data type. Returns ------- tuple Independent domain :math:`x` variable and corresponding range :math:`y` variable unpacked for continuous signal instantiation. Examples -------- Unpacking using implicit *domain*: >>> range_ = np.linspace(10, 100, 10) >>> domain, range_ = Signal.signal_unpack_data(range_) >>> print(domain) [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using explicit *domain*: >>> domain = np.arange(100, 1100, 100) >>> domain, range = Signal.signal_unpack_data(range_, domain) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *dict*: >>> domain, range_ = Signal.signal_unpack_data( ... dict(zip(domain, range_))) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *Pandas* `Series`: >>> if is_pandas_installed(): ... from pandas import Series ... domain, range = Signal.signal_unpack_data( ... Series(dict(zip(domain, range_)))) ... # doctest: +ELLIPSIS >>> print(domain) # doctest: +SKIP [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) # doctest: +SKIP [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a :class:`colour.continuous.Signal` class: >>> domain, range_ = Signal.signal_unpack_data( ... Signal(range_, domain)) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] """ if dtype is None: dtype = DEFAULT_FLOAT_DTYPE domain_u, range_u = None, None if isinstance(data, Signal): domain_u = data.domain range_u = data.range elif (issubclass(type(data), Sequence) or isinstance(data, (tuple, list, np.ndarray, Iterator))): data = tsplit(list(data) if isinstance(data, Iterator) else data) assert data.ndim == 1, 'User "data" must be 1-dimensional!' domain_u, range_u = np.arange(0, data.size, dtype=dtype), data elif (issubclass(type(data), Mapping) or isinstance(data, (dict, OrderedDict))): domain_u, range_u = tsplit(sorted(data.items())) elif is_pandas_installed(): from pandas import Series if isinstance(data, Series): domain_u = data.index.values range_u = data.values if domain is not None and range_u is not None: assert len(domain) == len(range_u), ( 'User "domain" is not compatible with unpacked range!') domain_u = as_array(domain, dtype) if range_u is not None: range_u = as_array(range_u, dtype) return domain_u, range_u
def multi_signal_unpack_data(data=None, domain=None, labels=None, dtype=DEFAULT_FLOAT_DTYPE, signal_type=Signal, **kwargs): """ Unpack given data for multi-continuous signal instantiation. Parameters ---------- data : Series or Dataframe or Signal or MultiSignal or array_like or \ dict_like, optional Data to unpack for multi-continuous signal instantiation. domain : array_like, optional Values to initialise the multiple :class:`colour.continuous.Signal` sub-class instances :attr:`colour.continuous.Signal.domain` attribute with. If both ``data`` and ``domain`` arguments are defined, the latter will be used to initialise the :attr:`colour.continuous.Signal.domain` attribute. dtype : type, optional **{np.float16, np.float32, np.float64, np.float128}**, Floating point data type. signal_type : type, optional A :class:`colour.continuous.Signal` sub-class type. Other Parameters ---------------- name : unicode, optional Multi-continuous signal name. interpolator : object, optional Interpolator class type to use as interpolating function for the :class:`colour.continuous.Signal` sub-class instances. interpolator_args : dict_like, optional Arguments to use when instantiating the interpolating function of the :class:`colour.continuous.Signal` sub-class instances. extrapolator : object, optional Extrapolator class type to use as extrapolating function for the :class:`colour.continuous.Signal` sub-class instances. extrapolator_args : dict_like, optional Arguments to use when instantiating the extrapolating function of the :class:`colour.continuous.Signal` sub-class instances. Returns ------- dict Mapping of labeled :class:`colour.continuous.Signal` sub-class instances. Examples -------- Unpacking using implicit *domain* and a single signal: >>> range_ = np.linspace(10, 100, 10) >>> signals = MultiSignal.multi_signal_unpack_data(range_) >>> list(signals.keys()) [0] >>> print(signals[0]) [[ 0. 10.] [ 1. 20.] [ 2. 30.] [ 3. 40.] [ 4. 50.] [ 5. 60.] [ 6. 70.] [ 7. 80.] [ 8. 90.] [ 9. 100.]] Unpacking using explicit *domain* and a single signal: >>> domain = np.arange(100, 1100, 100) >>> signals = MultiSignal.multi_signal_unpack_data(range_, domain) >>> list(signals.keys()) [0] >>> print(signals[0]) [[ 100. 10.] [ 200. 20.] [ 300. 30.] [ 400. 40.] [ 500. 50.] [ 600. 60.] [ 700. 70.] [ 800. 80.] [ 900. 90.] [ 1000. 100.]] Unpacking using multiple signals: >>> range_ = tstack([np.linspace(10, 100, 10)] * 3) >>> range_ += np.array([0, 10, 20]) >>> signals = MultiSignal.multi_signal_unpack_data(range_, domain) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using a *dict*: >>> signals = MultiSignal.multi_signal_unpack_data( ... dict(zip(domain, range_))) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using *MultiSignal.multi_signal_unpack_data* method output: >>> signals = MultiSignal.multi_signal_unpack_data( ... dict(zip(domain, range_))) >>> signals = MultiSignal.multi_signal_unpack_data(signals) >>> list(signals.keys()) [0, 1, 2] >>> print(signals[2]) [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] Unpacking using a *Pandas* *Series*: >>> if is_pandas_installed(): ... from pandas import Series ... signals = MultiSignal.multi_signal_unpack_data( ... Series(dict(zip(domain, np.linspace(10, 100, 10))))) ... print(signals[0]) # doctest: +SKIP [[ 100. 10.] [ 200. 20.] [ 300. 30.] [ 400. 40.] [ 500. 50.] [ 600. 60.] [ 700. 70.] [ 800. 80.] [ 900. 90.] [ 1000. 100.]] Unpacking using a *Pandas* *Dataframe*: >>> if is_pandas_installed(): ... from pandas import DataFrame ... data = dict(zip(['a', 'b', 'c'], tsplit(range_))) ... signals = MultiSignal.multi_signal_unpack_data( ... DataFrame(data, domain)) ... print(signals['c']) # doctest: +SKIP [[ 100. 30.] [ 200. 40.] [ 300. 50.] [ 400. 60.] [ 500. 70.] [ 600. 80.] [ 700. 90.] [ 800. 100.] [ 900. 110.] [ 1000. 120.]] """ assert dtype in np.sctypes['float'], ( '"dtype" must be one of the following types: {0}'.format( np.sctypes['float'])) domain_u, range_u, signals = None, None, None signals = OrderedDict() # TODO: Implement support for Signal class passing. if isinstance(data, MultiSignal): signals = data.signals elif (issubclass(type(data), Sequence) or isinstance(data, (tuple, list, np.ndarray, Iterator))): data = tsplit(list(data) if isinstance(data, Iterator) else data) assert data.ndim in (1, 2), ( 'User "data" must be 1-dimensional or 2-dimensional!') if data.ndim == 1: data = data[np.newaxis, :] for i, range_u in enumerate(data): signals[i] = signal_type(range_u, domain, **kwargs) elif (issubclass(type(data), Mapping) or isinstance(data, (dict, OrderedDict))): # Handling `MultiSignal.multi_signal_unpack_data` method output # used as argument to `MultiSignal.multi_signal_unpack_data` # method. is_signal = all([ True if isinstance(i, Signal) else False for i in data.values() ]) if is_signal: for label, signal in data.items(): signals[label] = signal_type(signal.range, signal.domain, **kwargs) else: domain_u, range_u = zip(*sorted(data.items())) for i, range_u in enumerate(tsplit(range_u)): signals[i] = signal_type(range_u, domain_u, **kwargs) elif is_pandas_installed(): from pandas import DataFrame, Series if isinstance(data, Series): signals[0] = signal_type(data, **kwargs) elif isinstance(data, DataFrame): domain_u = data.index.values signals = OrderedDict(((label, signal_type(data[label], domain_u, name=label, **kwargs)) for label in data)) if domain is not None and signals is not None: for signal in signals.values(): assert len(domain) == len(signal.domain), ( 'User "domain" is not compatible with unpacked signals!') signal.domain = domain if labels is not None and signals is not None: assert len(labels) == len(signals), ( 'User "labels" is not compatible with unpacked signals!') signals = OrderedDict([ (labels[i], signal) for i, (_key, signal) in enumerate(signals.items()) ]) return signals
def signal_unpack_data( data=Optional[Union[ArrayLike, dict, Series, "Signal"]], domain: Optional[ArrayLike] = None, dtype: Optional[Type[DTypeFloating]] = None, ) -> Tuple: """ Unpack given data for continuous signal instantiation. Parameters ---------- data Data to unpack for continuous signal instantiation. domain Values to initialise the :attr:`colour.continuous.Signal.domain` attribute with. If both ``data`` and ``domain`` arguments are defined, the latter will be used to initialise the :attr:`colour.continuous.Signal.domain` property. dtype Floating point data type. Returns ------- :class:`tuple` Independent domain variable :math:`x` and corresponding range variable :math:`y` unpacked for continuous signal instantiation. Examples -------- Unpacking using implicit *domain*: >>> range_ = np.linspace(10, 100, 10) >>> domain, range_ = Signal.signal_unpack_data(range_) >>> print(domain) [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using explicit *domain*: >>> domain = np.arange(100, 1100, 100) >>> domain, range = Signal.signal_unpack_data(range_, domain) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *dict*: >>> domain, range_ = Signal.signal_unpack_data( ... dict(zip(domain, range_))) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a *Pandas* :class:`pandas.Series`: >>> if is_pandas_installed(): ... from pandas import Series ... domain, range = Signal.signal_unpack_data( ... Series(dict(zip(domain, range_)))) ... # doctest: +ELLIPSIS >>> print(domain) # doctest: +SKIP [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) # doctest: +SKIP [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] Unpacking using a :class:`colour.continuous.Signal` class: >>> domain, range_ = Signal.signal_unpack_data( ... Signal(range_, domain)) >>> print(domain) [ 100. 200. 300. 400. 500. 600. 700. 800. 900. 1000.] >>> print(range_) [ 10. 20. 30. 40. 50. 60. 70. 80. 90. 100.] """ dtype = cast(Type[DTypeFloating], optional(dtype, DEFAULT_FLOAT_DTYPE)) domain_unpacked: NDArray = np.array([]) range_unpacked: NDArray = np.array([]) if isinstance(data, Signal): domain_unpacked = data.domain range_unpacked = data.range elif issubclass(type(data), Sequence) or isinstance( data, (tuple, list, np.ndarray, Iterator, ValuesView) ): data_array = tsplit(list(data)) attest(data_array.ndim == 1, 'User "data" must be 1-dimensional!') domain_unpacked, range_unpacked = ( np.arange(0, data_array.size, dtype=dtype), data_array, ) elif issubclass(type(data), Mapping) or isinstance(data, dict): domain_unpacked, range_unpacked = tsplit(sorted(data.items())) elif is_pandas_installed(): if isinstance(data, Series): domain_unpacked = data.index.values range_unpacked = data.values if domain is not None: domain_array = as_float_array(list(domain), dtype) # type: ignore[arg-type] attest( len(domain_array) == len(range_unpacked), 'User "domain" length is not compatible with unpacked "range"!', ) domain_unpacked = domain_array if range_unpacked is not None: range_unpacked = as_float_array(range_unpacked, dtype) return domain_unpacked, range_unpacked
from colour.utilities import ( as_float_array, attest, fill_nan, full, is_pandas_installed, optional, required, runtime_warning, tsplit, tstack, validate_method, ) from colour.utilities.documentation import is_documentation_building if is_pandas_installed(): from pandas import Series else: # pragma: no cover from unittest import mock Series = mock.MagicMock() __author__ = "Colour Developers" __copyright__ = "Copyright 2013 Colour Developers" __license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" __maintainer__ = "Colour Developers" __email__ = "*****@*****.**" __status__ = "Production" __all__ = [ "Signal",
def test_multi_signals_unpack_data(self): """ Test :func:`colour.continuous.multi_signals.MultiSignals.\ multi_signals_unpack_data` method. """ signals = MultiSignals.multi_signals_unpack_data(self._range_1) self.assertListEqual(list(signals.keys()), ["0"]) np.testing.assert_array_equal(signals["0"].domain, self._domain_1) np.testing.assert_array_equal(signals["0"].range, self._range_1) signals = MultiSignals.multi_signals_unpack_data( self._range_1, self._domain_2) self.assertListEqual(list(signals.keys()), ["0"]) np.testing.assert_array_equal(signals["0"].domain, self._domain_2) np.testing.assert_array_equal(signals["0"].range, self._range_1) signals = MultiSignals.multi_signals_unpack_data( self._range_1, dict(zip(self._domain_2, self._range_1)).keys()) np.testing.assert_array_equal(signals["0"].domain, self._domain_2) signals = MultiSignals.multi_signals_unpack_data( self._range_2, self._domain_2) self.assertListEqual(list(signals.keys()), ["0", "1", "2"]) np.testing.assert_array_equal(signals["0"].range, self._range_1) np.testing.assert_array_equal(signals["1"].range, self._range_1 + 10) np.testing.assert_array_equal(signals["2"].range, self._range_1 + 20) signals = MultiSignals.multi_signals_unpack_data( list( MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2))).values())[0]) np.testing.assert_array_equal(signals["0"].range, self._range_1) signals = MultiSignals.multi_signals_unpack_data( MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2))).values()) np.testing.assert_array_equal(signals["0"].range, self._range_1) np.testing.assert_array_equal(signals["1"].range, self._range_1 + 10) np.testing.assert_array_equal(signals["2"].range, self._range_1 + 20) signals = MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2))) self.assertListEqual(list(signals.keys()), ["0", "1", "2"]) np.testing.assert_array_equal(signals["0"].range, self._range_1) np.testing.assert_array_equal(signals["1"].range, self._range_1 + 10) np.testing.assert_array_equal(signals["2"].range, self._range_1 + 20) signals = MultiSignals.multi_signals_unpack_data( MultiSignals.multi_signals_unpack_data( dict(zip(self._domain_2, self._range_2)))) self.assertListEqual(list(signals.keys()), ["0", "1", "2"]) np.testing.assert_array_equal(signals["0"].range, self._range_1) np.testing.assert_array_equal(signals["1"].range, self._range_1 + 10) np.testing.assert_array_equal(signals["2"].range, self._range_1 + 20) if is_pandas_installed(): from pandas import DataFrame, Series signals = MultiSignals.multi_signals_unpack_data( Series(dict(zip(self._domain_1, self._range_1)))) self.assertListEqual(list(signals.keys()), ["0"]) np.testing.assert_array_equal(signals["0"].domain, self._domain_1) np.testing.assert_array_equal(signals["0"].range, self._range_1) data = dict(zip(["a", "b", "c"], tsplit(self._range_2))) signals = MultiSignals.multi_signals_unpack_data( DataFrame(data, self._domain_1)) self.assertListEqual(list(signals.keys()), ["a", "b", "c"]) np.testing.assert_array_equal(signals["a"].range, self._range_1) np.testing.assert_array_equal(signals["b"].range, self._range_1 + 10) np.testing.assert_array_equal(signals["c"].range, self._range_1 + 20)