item_change_ix

mdtools.numpy_helper_functions.item_change_ix(a, **kwargs)[source]

Get the indices of item changes in an array.

Parameters:
  • a (array_like) – Array for which to get all indices where its elements change.

  • kwargs (tuple, optional) – Additional keyword arguments to parse to mdtools.numpy_helper_functions.locate_item_change(). See there for possible choices. By default axis is set to -1, pin is set to "after" and change_type is set to None.

Returns:

  • ix_before (tuple of numpy.ndarray) – Tuple of arrays, one for each dimension of a, containing the indices where the elements of a will change. Can be used to index a and get its values right before the item change. Is not returned if pin is "after".

  • ix_after (tuple of numpy.ndarray) – Tuple of arrays, one for each dimension of a, containing the indices where the elements of a have changed. Can be used to index a and get its values right after the item change. Is not returned if pin is "before".

See also

mdtools.numpy_helper_functions.locate_item_change()

Locate the positions of item changes in an array

mdtools.dtrj.trans_ix()

Same function but specifically for discrete trajectories

Notes

This function only applies numpy.nonzero() to the output of mdtools.numpy_helper_functions.locate_item_change().

Examples

>>> a = np.array([1, 2, 2, 3, 3, 3])
>>> before, after = mdt.nph.item_change_ix(a, pin="both")
>>> before
(array([0, 2]),)
>>> after
(array([1, 3]),)
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, pin="both", change_type="both"
... )
>>> before_type[0]  # Changes to higher values
(array([0, 2]),)
>>> before_type[1]  # Changes to lower values
(array([], dtype=int64),)
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
>>> after_type[0]  # Changes to higher values
(array([1, 3]),)
>>> after_type[1]  # Changes to lower values
(array([], dtype=int64),)
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
>>> mdt.nph.item_change_ix(a, pin="before", change_type=1)
(array([0, 2]),)
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, pin="both", change_type=(1, -1)
... )
>>> before_type_float[0]  # Changes where final-initial=1
(array([0, 2]),)
>>> before_type_float[1]  # Changes where final-initial=-1
(array([], dtype=int64),)
>>> after_type_float[0]  # Changes where final-initial=1
(array([1, 3]),)
>>> after_type_float[1]  # Changes where final-initial=-1
(array([], dtype=int64),)
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 2, 5]),)
>>> after_wrap
(array([0, 1, 3]),)
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 2]),)
>>> before_type_wrap[1]
(array([5]),)
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
>>> after_type_wrap[0]
(array([1, 3]),)
>>> after_type_wrap[1]
(array([0]),)
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, pin="both", change_type=(1, -1), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 2]),)
>>> before_type_float_wrap[1]
(array([], dtype=int64),)
>>> after_type_float_wrap[0]
(array([1, 3]),)
>>> after_type_float_wrap[1]
(array([], dtype=int64),)
>>> before_tfic, after_tfic = mdt.nph.item_change_ix(
...     a, pin="both", tfic=True
... )
>>> before_tfic
(array([0, 2]),)
>>> after_tfic
(array([0, 1, 3]),)
>>> before_tlic, after_tlic = mdt.nph.item_change_ix(
...     a, pin="both", tlic=True
... )
>>> before_tlic
(array([0, 2, 5]),)
>>> after_tlic
(array([1, 3]),)
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 2, 5]),)
>>> after_tfic_tlic
(array([0, 1, 3]),)
>>> a = np.array([1, 2, 2, 3, 3, 3, 1])
>>> before, after = mdt.nph.item_change_ix(a, pin="both")
>>> before
(array([0, 2, 5]),)
>>> after
(array([1, 3, 6]),)
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 2]),)
>>> before_type[1]
(array([5]),)
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
>>> after_type[0]
(array([1, 3]),)
>>> after_type[1]
(array([6]),)
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, pin="both", change_type=(1, -1)
... )
>>> before_type_float[0]
(array([0, 2]),)
>>> before_type_float[1]
(array([], dtype=int64),)
>>> after_type_float[0]
(array([1, 3]),)
>>> after_type_float[1]
(array([], dtype=int64),)
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 2, 5]),)
>>> after_wrap
(array([1, 3, 6]),)
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 2]),)
>>> before_type_wrap[1]
(array([5]),)
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
>>> after_type_wrap[0]
(array([1, 3]),)
>>> after_type_wrap[1]
(array([6]),)
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, pin="both", change_type=(1, -1)
... )
>>> before_type_float_wrap[0]
(array([0, 2]),)
>>> before_type_float_wrap[1]
(array([], dtype=int64),)
>>> after_type_float_wrap[0]
(array([1, 3]),)
>>> after_type_float_wrap[1]
(array([], dtype=int64),)
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 2, 5, 6]),)
>>> after_tfic_tlic
(array([0, 1, 3, 6]),)

2-dimensional example:

>>> a = np.array([[1, 3, 3, 3],
...               [3, 1, 3, 3],
...               [3, 3, 1, 3]])
>>> ax = 0
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0, 0, 1, 1]), array([0, 1, 1, 2]))
>>> after
(array([1, 1, 2, 2]), array([0, 1, 1, 2]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 1]), array([0, 1]))
>>> before_type[1]
(array([0, 1]), array([1, 2]))
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
True
>>> after_type[0]
(array([1, 2]), array([0, 1]))
>>> after_type[1]
(array([1, 2]), array([1, 2]))
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(2, -2)
... )
>>> before_type_float[0]
(array([0, 1]), array([0, 1]))
>>> before_type_float[1]
(array([0, 1]), array([1, 2]))
>>> after_type_float[0]
(array([1, 2]), array([0, 1]))
>>> after_type_float[1]
(array([1, 2]), array([1, 2]))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))
>>> after_wrap
(array([0, 0, 1, 1, 2, 2]), array([0, 2, 0, 1, 1, 2]))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type_wrap[1]
(array([0, 1, 2]), array([1, 2, 0]))
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
True
>>> after_type_wrap[0]
(array([0, 1, 2]), array([2, 0, 1]))
>>> after_type_wrap[1]
(array([0, 1, 2]), array([0, 1, 2]))
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(2, -2), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type_float_wrap[1]
(array([0, 1, 2]), array([1, 2, 0]))
>>> after_type_float_wrap[0]
(array([0, 1, 2]), array([2, 0, 1]))
>>> after_type_float_wrap[1]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_tfic_tlic
(array([0, 0, 1, 1, 2, 2, 2, 2]), array([0, 1, 1, 2, 0, 1, 2, 3]))
>>> after_tfic_tlic
(array([0, 0, 0, 0, 1, 1, 2, 2]), array([0, 1, 2, 3, 0, 1, 1, 2]))
>>> ax = 1
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0, 1, 1, 2, 2]), array([0, 0, 1, 1, 2]))
>>> after
(array([0, 1, 1, 2, 2]), array([1, 1, 2, 2, 3]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type[1]
(array([1, 2]), array([0, 1]))
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
True
>>> after_type[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_type[1]
(array([1, 2]), array([1, 2]))
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(2, -2)
... )
>>> before_type_float[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type_float[1]
(array([1, 2]), array([0, 1]))
>>> after_type_float[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_type_float[1]
(array([1, 2]), array([1, 2]))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 0, 1, 1, 2, 2]), array([0, 3, 0, 1, 1, 2]))
>>> after_wrap
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 2, 3]))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type_wrap[1]
(array([0, 1, 2]), array([3, 0, 1]))
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
True
>>> after_type_wrap[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_type_wrap[1]
(array([0, 1, 2]), array([0, 1, 2]))
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(2, -2), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_type_float_wrap[1]
(array([0, 1, 2]), array([3, 0, 1]))
>>> after_type_float_wrap[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_type_float_wrap[1]
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0, 1, 1, 1, 2, 2, 2]), array([0, 3, 0, 1, 3, 1, 2, 3]))
>>> after_tfic_tlic
(array([0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 0, 1, 2, 0, 2, 3]))

3-dimensional example:

>>> a = np.array([[[1, 2, 2],
...                [2, 2, 1]],
...
...               [[2, 2, 1],
...                [1, 2, 2]]])
>>> ax = 0
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0, 0, 0, 0]), array([0, 0, 1, 1]), array([0, 2, 0, 2]))
>>> after
(array([1, 1, 1, 1]), array([0, 0, 1, 1]), array([0, 2, 0, 2]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 0]), array([0, 1]), array([0, 2]))
>>> before_type[1]
(array([0, 0]), array([0, 1]), array([2, 0]))
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
True
True
>>> after_type[0]
(array([1, 1]), array([0, 1]), array([0, 2]))
>>> after_type[1]
(array([1, 1]), array([0, 1]), array([2, 0]))
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
True
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1)
... )
>>> before_type_float[0]
(array([0, 0]), array([0, 1]), array([0, 2]))
>>> before_type_float[1]
(array([0, 0]), array([0, 1]), array([2, 0]))
>>> after_type_float[0]
(array([1, 1]), array([0, 1]), array([0, 2]))
>>> after_type_float[1]
(array([1, 1]), array([0, 1]), array([2, 0]))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> after_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
True
True
>>> after_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
True
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 0, 1, 1, 1]), array([0, 2, 0, 2, 0, 1, 2, 0, 1, 2]))
>>> after_tfic_tlic
(array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 0, 1, 1, 1, 0, 0, 1, 1]), array([0, 1, 2, 0, 1, 2, 0, 2, 0, 2]))
>>> ax = 1
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0, 0, 1, 1]), array([0, 0, 0, 0]), array([0, 2, 0, 2]))
>>> after
(array([0, 0, 1, 1]), array([1, 1, 1, 1]), array([0, 2, 0, 2]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 1]), array([0, 0]), array([0, 2]))
>>> before_type[1]
(array([0, 1]), array([0, 0]), array([2, 0]))
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
True
True
>>> after_type[0]
(array([0, 1]), array([1, 1]), array([0, 2]))
>>> after_type[1]
(array([0, 1]), array([1, 1]), array([2, 0]))
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
True
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1)
... )
>>> before_type_float[0]
(array([0, 1]), array([0, 0]), array([0, 2]))
>>> before_type_float[1]
(array([0, 1]), array([0, 0]), array([2, 0]))
>>> after_type_float[0]
(array([0, 1]), array([1, 1]), array([0, 2]))
>>> after_type_float[1]
(array([0, 1]), array([1, 1]), array([2, 0]))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> after_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
True
True
>>> after_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
True
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]), array([0, 0, 1, 1, 1, 0, 0, 1, 1, 1]), array([0, 2, 0, 1, 2, 0, 2, 0, 1, 2]))
>>> after_tfic_tlic
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]), array([0, 0, 0, 1, 1, 0, 0, 0, 1, 1]), array([0, 1, 2, 0, 2, 0, 1, 2, 0, 2]))
>>> ax = 2
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 1, 1, 0]))
>>> after
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([1, 2, 2, 1]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type[0]
(array([0, 1]), array([0, 1]), array([0, 0]))
>>> before_type[1]
(array([0, 1]), array([1, 0]), array([1, 1]))
>>> for i, bt in enumerate(zip(*before_type)):
...     np.array_equal(
...         np.sort(np.concatenate(bt)), np.sort(before[i])
...     )
True
True
True
>>> after_type[0]
(array([0, 1]), array([0, 1]), array([1, 1]))
>>> after_type[1]
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> for i, at in enumerate(zip(*after_type)):
...     np.array_equal(
...         np.sort(np.concatenate(at)), np.sort(after[i])
...     )
True
True
True
>>> before_type_float, after_type_float = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1)
... )
>>> before_type_float[0]
(array([0, 1]), array([0, 1]), array([0, 0]))
>>> before_type_float[1]
(array([0, 1]), array([1, 0]), array([1, 1]))
>>> after_type_float[0]
(array([0, 1]), array([0, 1]), array([1, 1]))
>>> after_type_float[1]
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 1, 2, 1, 2, 0, 2]))
>>> after_wrap
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 1, 0, 2, 0, 2, 0, 1]))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 1, 1, 2]))
>>> for i, btw in enumerate(zip(*before_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(btw)), np.sort(before_wrap[i])
...     )
True
True
True
>>> after_type_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([1, 0, 0, 1]))
>>> after_type_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> for i, atw in enumerate(zip(*after_type_wrap)):
...     np.array_equal(
...         np.sort(np.concatenate(atw)), np.sort(after_wrap[i])
...     )
True
True
True
>>> before_type_float_wrap, after_type_float_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type=(1, -1), wrap=True
... )
>>> before_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 1, 1, 2]))
>>> after_type_float_wrap[0]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([1, 0, 0, 1]))
>>> after_type_float_wrap[1]
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 1, 2, 1, 2, 0, 2]))
>>> after_tfic_tlic
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 1, 0, 2, 0, 2, 0, 1]))

Examples for using discard_neg:

>>> a = np.array([ 1, -2, -2,  3,  3,  3])
>>> before_start, after_start = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="start"
... )
>>> before_start
(array([0]),)
>>> after_start
(array([1]),)
>>> before_end, after_end = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="end"
... )
>>> before_end
(array([2]),)
>>> after_end
(array([3]),)
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64),)
>>> after_both
(array([], dtype=int64),)
>>> before_start = mdt.nph.item_change_ix(
...     a, pin="before", discard_neg="start"
... )
>>> before_start
(array([0]),)
>>> after_end = mdt.nph.item_change_ix(
...     a, pin="after", discard_neg="end"
... )
>>> after_end
(array([3]),)
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="end", change_type="both"
... )
>>> before_end_type[0]  # Changes to higher values
(array([2]),)
>>> before_end_type[1]  # Changes to lower values
(array([], dtype=int64),)
>>> after_end_type[0]  # Changes to higher values
(array([3]),)
>>> after_end_type[1]  # Changes to lower values
(array([], dtype=int64),)
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 5]),)
>>> after_start_wrap
(array([0, 1]),)
>>> before_end_type_w, after_end_type_w = mdt.nph.item_change_ix(
...     a,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_type_w[0]  # Changes to higher values
(array([2]),)
>>> before_end_type_w[1]  # Changes to lower values
(array([5]),)
>>> after_end_type_w[0]  # Changes to higher values
(array([3]),)
>>> after_end_type_w[1]  # Changes to lower values
(array([0]),)
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([5]),)
>>> after_both_wrap
(array([0]),)
>>> a = np.array([ 1, -2, -2,  3,  3,  3,  1])
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="both"
... )
>>> before_both
(array([5]),)
>>> after_both
(array([6]),)
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="end", change_type="both"
... )
>>> before_end_type[0]  # Changes to higher values
(array([2]),)
>>> before_end_type[1]  # Changes to lower values
(array([5]),)
>>> after_end_type[0]
(array([3]),)
>>> after_end_type[1]
(array([6]),)
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 5]),)
>>> after_start_wrap
(array([1, 6]),)
>>> before_end_type_w, after_end_type_w = mdt.nph.item_change_ix(
...     a,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_type_w[0]  # Changes to higher values
(array([2]),)
>>> before_end_type_w[1]  # Changes to lower values
(array([5]),)
>>> after_end_type_w[0]
(array([3]),)
>>> after_end_type_w[1]
(array([6]),)
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([5]),)
>>> after_both_wrap
(array([6]),)

2-dimensional example for using discard_neg:

>>> a = np.array([[-1,  3,  3,  3],
...               [ 3, -1,  3,  3],
...               [ 3,  3, -1,  3]])
>>> ax = 0
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64), array([], dtype=int64))
>>> after_both
(array([], dtype=int64), array([], dtype=int64))
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
... )
>>> before_end_type[0]  # Changes to higher values
(array([0, 1]), array([0, 1]))
>>> before_end_type[1]  # Changes to lower values
(array([], dtype=int64), array([], dtype=int64))
>>> after_end_type[0]
(array([1, 2]), array([0, 1]))
>>> after_end_type[1]
(array([], dtype=int64), array([], dtype=int64))
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 1, 2]), array([1, 2, 0]))
>>> after_start_wrap
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_end_type_w, after_end_type_w = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_type_w[0]  # Changes to higher values
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_end_type_w[1]  # Changes to lower values
(array([], dtype=int64), array([], dtype=int64))
>>> after_end_type_w[0]
(array([0, 1, 2]), array([2, 0, 1]))
>>> after_end_type_w[1]
(array([], dtype=int64), array([], dtype=int64))
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> after_both_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> ax = 1
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64), array([], dtype=int64))
>>> after_both
(array([], dtype=int64), array([], dtype=int64))
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
... )
>>> before_end_type[0]  # Changes to higher values
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_end_type[1]  # Changes to lower values
(array([], dtype=int64), array([], dtype=int64))
>>> after_end_type[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_end_type[1]
(array([], dtype=int64), array([], dtype=int64))
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 1, 2]), array([3, 0, 1]))
>>> after_start_wrap
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_end_type_w, after_end_type_w = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_type_w[0]  # Changes to higher values
(array([0, 1, 2]), array([0, 1, 2]))
>>> before_end_type_w[1]  # Changes to lower values
(array([], dtype=int64), array([], dtype=int64))
>>> after_end_type_w[0]
(array([0, 1, 2]), array([1, 2, 3]))
>>> after_end_type_w[1]
(array([], dtype=int64), array([], dtype=int64))
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> after_both_wrap
(array([], dtype=int64), array([], dtype=int64))

3-dimensional example for using discard_neg:

>>> a = np.array([[[-1,  2,  2],
...                [ 2,  2,  1]],
...
...               [[ 2,  2,  1],
...                [-1,  2,  2]]])
>>> ax = 0
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([0, 0]), array([0, 1]), array([2, 2]))
>>> after_both
(array([1, 1]), array([0, 1]), array([2, 2]))
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
... )
>>> before_end_type[0]  # Changes to higher values
(array([0, 0]), array([0, 1]), array([0, 2]))
>>> before_end_type[1]  # Changes to lower values
(array([0]), array([0]), array([2]))
>>> after_end_type[0]
(array([1, 1]), array([0, 1]), array([0, 2]))
>>> after_end_type[1]
(array([1]), array([0]), array([2]))
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 1, 1, 0, 0, 1]), array([2, 0, 2, 0, 2, 2]))
>>> after_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 0, 1, 0, 1, 1]), array([0, 2, 2, 2, 0, 2]))
>>> before_end_typ_w, after_end_typ_w = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([0, 1]), array([2, 2]))
>>> after_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 2, 2, 2]))
>>> after_both_wrap
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 2, 2, 2]))
>>> ax = 1
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([0, 1]), array([0, 0]), array([2, 2]))
>>> after_both
(array([0, 1]), array([1, 1]), array([2, 2]))
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
... )
>>> before_end_type[0]  # Changes to higher values
(array([0, 1]), array([0, 0]), array([0, 2]))
>>> before_end_type[1]  # Changes to lower values
(array([0]), array([0]), array([2]))
>>> after_end_type[0]
(array([0, 1]), array([1, 1]), array([0, 2]))
>>> after_end_type[1]
(array([0]), array([1]), array([2]))
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 1, 1, 0, 0, 1]), array([2, 0, 2, 0, 2, 2]))
>>> after_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 0, 1, 0, 1, 1]), array([0, 2, 2, 2, 0, 2]))
>>> before_end_typ_w, after_end_typ_w = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([0, 1]), array([2, 2]))
>>> after_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 0, 2]))
>>> after_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 2, 2, 2]))
>>> after_both_wrap
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 2, 2, 2]))
>>> ax = 2
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([0, 1]), array([1, 0]), array([1, 1]))
>>> after_both
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_end_type, after_end_type = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
... )
>>> before_end_type[0]  # Changes to higher values
(array([0, 1]), array([0, 1]), array([0, 0]))
>>> before_end_type[1]  # Changes to lower values
(array([0, 1]), array([1, 0]), array([1, 1]))
>>> after_end_type[0]
(array([0, 1]), array([0, 1]), array([1, 1]))
>>> after_end_type[1]
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_start_wrap, after_start_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="start", wrap=True
... )
>>> before_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 1, 1, 0, 0, 1]), array([2, 1, 2, 1, 2, 2]))
>>> after_start_wrap
(array([0, 0, 0, 1, 1, 1]), array([0, 1, 1, 0, 0, 1]), array([0, 0, 2, 0, 2, 0]))
>>> before_end_typ_w, after_end_typ_w = mdt.nph.item_change_ix(
...     a,
...     axis=ax,
...     pin="both",
...     discard_neg="end",
...     change_type="both",
...     wrap=True,
... )
>>> before_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([0, 2, 2, 0]))
>>> before_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([1, 0]), array([1, 1]))
>>> after_end_typ_w[0]  # Changes to higher values
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([1, 0, 0, 1]))
>>> after_end_typ_w[1]  # Changes to lower values
(array([0, 1]), array([1, 0]), array([2, 2]))
>>> before_both_wrap, after_both_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both", wrap=True
... )
>>> before_both_wrap
(array([0, 0, 1, 1]), array([1, 1, 0, 0]), array([1, 2, 1, 2]))
>>> after_both_wrap
(array([0, 0, 1, 1]), array([1, 1, 0, 0]), array([0, 2, 0, 2]))

Edge cases:

>>> a = np.array([[1, 2, 2]])
>>> ax = 0
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([], dtype=int64), array([], dtype=int64))
>>> after
(array([], dtype=int64), array([], dtype=int64))
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64), array([], dtype=int64))
>>> after_both
(array([], dtype=int64), array([], dtype=int64))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type_wrap
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0, 0]), array([0, 1, 2]))
>>> after_tfic_tlic
(array([0, 0, 0]), array([0, 1, 2]))
>>> ax = 1
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([0]), array([0]))
>>> after
(array([0]), array([1]))
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([0]), array([0]))
>>> after_both
(array([0]), array([1]))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type
((array([0]), array([0])), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([0]), array([1])), (array([], dtype=int64), array([], dtype=int64)))
>>> before_type_wrap, after_type_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap
((array([0]), array([0])), (array([0]), array([2])))
>>> after_type_wrap
((array([0]), array([1])), (array([0]), array([0])))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([0, 0]), array([0, 2]))
>>> after_tfic_tlic
(array([0, 0]), array([0, 1]))
>>> a = np.array([]).reshape(2,0)
>>> ax = 0
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([], dtype=int64), array([], dtype=int64))
>>> after
(array([], dtype=int64), array([], dtype=int64))
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64), array([], dtype=int64))
>>> after_both
(array([], dtype=int64), array([], dtype=int64))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> after_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> before_type_wrap, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([], dtype=int64), array([], dtype=int64))
>>> after_tfic_tlic
(array([], dtype=int64), array([], dtype=int64))
>>> ax = 1
>>> before, after = mdt.nph.item_change_ix(a, axis=ax, pin="both")
>>> before
(array([], dtype=int64), array([], dtype=int64))
>>> after
(array([], dtype=int64), array([], dtype=int64))
>>> before_both, after_both = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", discard_neg="both"
... )
>>> before_both
(array([], dtype=int64), array([], dtype=int64))
>>> after_both
(array([], dtype=int64), array([], dtype=int64))
>>> before_type, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both"
... )
>>> before_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_wrap, after_wrap = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", wrap=True
... )
>>> before_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> after_wrap
(array([], dtype=int64), array([], dtype=int64))
>>> before_type_wrap, after_type = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", change_type="both", wrap=True
... )
>>> before_type_wrap
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> after_type
((array([], dtype=int64), array([], dtype=int64)), (array([], dtype=int64), array([], dtype=int64)))
>>> before_tfic_tlic, after_tfic_tlic = mdt.nph.item_change_ix(
...     a, axis=ax, pin="both", tfic=True, tlic=True
... )
>>> before_tfic_tlic
(array([], dtype=int64), array([], dtype=int64))
>>> after_tfic_tlic
(array([], dtype=int64), array([], dtype=int64))
>>> a = np.array(0)
>>> mdt.nph.item_change_ix(a, pin="both")
Traceback (most recent call last):
...
ValueError: The input array must be at least one dimensional
>>> mdt.nph.item_change_ix(a, pin="both", wrap=True, tfic=True)
Traceback (most recent call last):
...
ValueError: 'wrap' must not be used together with 'tfic' of 'tlic'

Examples from mdtools.numpy_helper_functions.ix_of_item_change() mapped to mdtools.numpy_helper_functions.item_change_ix():

>>> a = np.arange(3)
>>> a
array([0, 1, 2])
>>> mdt.nph.item_change_ix(a, pin="after")
(array([1, 2]),)
>>> mdt.nph.item_change_ix(a, pin="after", wrap=True)
(array([0, 1, 2]),)
>>> ix = mdt.nph.item_change_ix(a, pin="after", tfic=True)
>>> ix
(array([0, 1, 2]),)
>>> a[ix]
array([0, 1, 2])
>>> b = np.array([1, 2, 2, 3, 3, 3, 1])
>>> mdt.nph.item_change_ix(b, pin="after")
(array([1, 3, 6]),)
>>> mdt.nph.item_change_ix(b, pin="after", wrap=True)
(array([1, 3, 6]),)
>>> ix = mdt.nph.item_change_ix(b, pin="after", tfic=True)
>>> ix
(array([0, 1, 3, 6]),)
>>> b[ix]
array([1, 2, 3, 1])
>>> c = np.ones(3)
>>> ix = mdt.nph.item_change_ix(c, pin="after")
>>> ix
(array([], dtype=int64),)
>>> c[ix]
array([], dtype=float64)
>>> mdt.nph.item_change_ix(c, pin="after", wrap=True)
(array([], dtype=int64),)
>>> mdt.nph.item_change_ix(c, pin="after", tfic=True)
(array([0]),)

2-dimensional example:

>>> d = np.array([[1, 3, 3, 3],
...               [3, 1, 3, 3],
...               [3, 3, 1, 3]])
>>> ax = 0
>>> mdt.nph.item_change_ix(d, axis=ax, pin="after")
(array([1, 1, 2, 2]), array([0, 1, 1, 2]))
>>> mdt.nph.item_change_ix(d, axis=ax, pin="after", wrap=True)
(array([0, 0, 1, 1, 2, 2]), array([0, 2, 0, 1, 1, 2]))
>>> ix = mdt.nph.item_change_ix(d, axis=ax, pin="after", tfic=True)
>>> ix
(array([0, 0, 0, 0, 1, 1, 2, 2]), array([0, 1, 2, 3, 0, 1, 1, 2]))
>>> d[ix]
array([1, 3, 3, 3, 3, 1, 3, 1])
>>> ax = 1
>>> mdt.nph.item_change_ix(d, axis=ax, pin="after")
(array([0, 1, 1, 2, 2]), array([1, 1, 2, 2, 3]))
>>> mdt.nph.item_change_ix(d, axis=ax, pin="after", wrap=True)
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 2, 3]))
>>> mdt.nph.item_change_ix(d, axis=ax, pin="after", tfic=True)
(array([0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 0, 1, 2, 0, 2, 3]))

3-dimensional example:

>>> e = np.array([[[1, 2, 2],
...                [2, 2, 1]],
...
...               [[2, 2, 1],
...                [1, 2, 2]]])
>>> ax = 0
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after")
(array([1, 1, 1, 1]), array([0, 0, 1, 1]), array([0, 2, 0, 2]))
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after", wrap=True)
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> ix = mdt.nph.item_change_ix(e, axis=ax, pin="after", tfic=True)
>>> ix
(array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 0, 1, 1, 1, 0, 0, 1, 1]), array([0, 1, 2, 0, 1, 2, 0, 2, 0, 2]))
>>> e[ix]
array([1, 2, 2, 2, 2, 1, 2, 1, 1, 2])
>>> ax = 1
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after")
(array([0, 0, 1, 1]), array([1, 1, 1, 1]), array([0, 2, 0, 2]))
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after", wrap=True)
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 2, 0, 2, 0, 2, 0, 2]))
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after", tfic=True)
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]), array([0, 0, 0, 1, 1, 0, 0, 0, 1, 1]), array([0, 1, 2, 0, 2, 0, 1, 2, 0, 2]))
>>> ax = 2
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after")
(array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([1, 2, 2, 1]))
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after", wrap=True)
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 1, 0, 2, 0, 2, 0, 1]))
>>> mdt.nph.item_change_ix(e, axis=ax, pin="after", tfic=True)
(array([0, 0, 0, 0, 1, 1, 1, 1]), array([0, 0, 1, 1, 0, 0, 1, 1]), array([0, 1, 0, 2, 0, 2, 0, 1]))

Edge cases:

>>> x = np.array([1])
>>> mdt.nph.item_change_ix(x, pin="after")
(array([], dtype=int64),)
>>> mdt.nph.item_change_ix(x, pin="after", wrap=True)
(array([], dtype=int64),)
>>> mdt.nph.item_change_ix(x, pin="after", tfic=True)
(array([0]),)
>>> x = np.array([])
>>> mdt.nph.item_change_ix(x, pin="after")
(array([], dtype=int64),)
>>> mdt.nph.item_change_ix(x, pin="after", wrap=True)
(array([], dtype=int64),)
>>> ix = mdt.nph.item_change_ix(x, pin="after", tfic=True)
>>> ix
(array([], dtype=int64),)
>>> x[ix]
array([], dtype=float64)
>>> x = np.array(0)
>>> mdt.nph.item_change_ix(x, pin="after")
Traceback (most recent call last):
...
ValueError: The dimension of a must be greater than zero