join#

metatensor.join(tensors: List[TensorMap], axis: str, different_keys: str = 'error', sort_samples: bool = False, remove_tensor_name: bool = False) TensorMap[source]#

Join a sequence of TensorMap with the same blocks along an axis.

The axis parameter specifies the type of joining. For example, if axis='properties' the tensor maps in tensors will be joined along the properties dimension and for axis='samples' they will be the along the samples dimension.

Parameters:
  • tensors (List[TensorMap]) – sequence of TensorMap for join

  • axis (str) – A string indicating how the tensormaps are stacked. Allowed values are 'properties' or 'samples'.

  • different_keys (str) – Method to handle different keys between the tensors. For "error" keys in all tensors have to be the same. For "intersection" only blocks present in all tensors will be taken into account. For "union" missing keys will be treated like if they where associated with an empty block.

  • sort_samples (bool) – whether to sort the samples of the merged tensors or keep them in their original order.

  • remove_tensor_name (bool) – Remove the extra tensor dimension from labels if possible. See examples above for the case where this is applicable.

Return tensor_joined:

The stacked TensorMap with more properties or samples than the input TensorMap.

Return type:

TensorMap

Examples#

Possible clashes of the meta data like samples/properties will be resolved by one of the three following strategies:

  1. If Labels names are the same, the values are unique and remove_tensor_name=True we keep the names and join the values

    >>> import numpy as np
    >>> import metatensor
    >>> from metatensor import Labels, TensorBlock, TensorMap
    
    >>> values = np.array([[1.1, 2.1, 3.1]])
    >>> samples = Labels("sample", np.array([[0]]))
    

    Define two disjoint Labels.

    >>> properties_1 = Labels("n", np.array([[0], [2], [3]]))
    >>> properties_2 = Labels("n", np.array([[1], [4], [5]]))
    
    >>> block_1 = TensorBlock(
    ...     values=values,
    ...     samples=Labels.single(),
    ...     components=[],
    ...     properties=properties_1,
    ... )
    >>> block_2 = TensorBlock(
    ...     values=values,
    ...     samples=Labels.single(),
    ...     components=[],
    ...     properties=properties_2,
    ... )
    
    >>> tensor_1 = TensorMap(keys=Labels.single(), blocks=[block_1])
    >>> tensor_2 = TensorMap(keys=Labels.single(), blocks=[block_2])
    

    joining along the properties leads

    >>> joined_tensor = metatensor.join(
    ...     [tensor_1, tensor_2], axis="properties", remove_tensor_name=True
    ... )
    >>> joined_tensor[0].properties
    Labels(
        n
        0
        2
        3
        1
        4
        5
    )
    

    If remove_tensor_name=False There will be an extra dimension tensor added

    >>> joined_tensor = metatensor.join(
    ...     [tensor_1, tensor_2], axis="properties", remove_tensor_name=False
    ... )
    >>> joined_tensor[0].properties
    Labels(
        tensor  n
          0     0
          0     2
          0     3
          1     1
          1     4
          1     5
    )
    
  2. If Labels names are the same but the values are not unique, a new dimension "tensor" is added to the names.

    >>> properties_3 = Labels("n", np.array([[0], [2], [3]]))
    

    properties_3 has the same name and also shares values with properties_1 as defined above.

    >>> block_3 = TensorBlock(
    ...     values=values,
    ...     samples=Labels.single(),
    ...     components=[],
    ...     properties=properties_3,
    ... )
    >>> tensor_3 = TensorMap(keys=Labels.single(), blocks=[block_3])
    

    joining along properties leads to

    >>> joined_tensor = metatensor.join([tensor_1, tensor_3], axis="properties")
    >>> joined_tensor[0].properties
    Labels(
        tensor  n
          0     0
          0     2
          0     3
          1     0
          1     2
          1     3
    )
    
  3. If Labels names are different we change the names to (“tensor”, “property”). This case is only supposed to happen when joining in the property dimension, hence the choice of names:

    >>> properties_4 = Labels(["a", "b"], np.array([[0, 0], [1, 2], [1, 3]]))
    

    properties_4 has the different names compared to properties_1 defined above.

    >>> block_4 = TensorBlock(
    ...     values=values,
    ...     samples=Labels.single(),
    ...     components=[],
    ...     properties=properties_4,
    ... )
    >>> tensor_4 = TensorMap(keys=Labels.single(), blocks=[block_4])
    

    joining along properties leads to

    >>> joined_tensor = metatensor.join([tensor_1, tensor_4], axis="properties")
    >>> joined_tensor[0].properties
    Labels(
        tensor  property
          0        0
          0        1
          0        2
          1        0
          1        1
          1        2
    )