# Interface to NumPy

Code author: Daniel G. A. Smith

Section author: Daniel G. A. Smith

Module: Keywords, psi4/psi4/driver/p4util/numpy_helper.py

## Basics

Converting between the PSI4 Data classes and a NumPy array is easy through various helper functions as detailed in this section. A quick overview NumPy functionality can be found here. In addition, numerous example of hybrid NumPy and Psi4 can be found at the Psi4Numpy project. Currently only the Matrix and Vector objects support NumPy interfacing. Let us begin with a simple conversion from these objects to a NumPy array:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    >>> import psi4
    >>> import numpy as np

    # Build the Psi4 data objects
    >>> mat = psi4.Matrix(3, 3)
    >>> vec = psi4.Vector(3)

    # Convert to a NumPy array
    >>> numpy_mat = np.array(mat)
    >>> numpy_vec = np.array(vec)

Here the data is copied into new NumPy arrays. NumPy arrays can be converted back to PSI4 objects using the `from_array` interface:

    1
    2
    >>> new_mat = psi4.Matrix.from_array(mat)
    >>> new_vec = psi4.Vector.from_array(vec)

## NumPy Views

Copying the data between NumPy and Psi4 objects can lead to excessive data movement and convoluted code. Here we introduce the idea of “Views” where the same data can be viewed by multiple objects. However, this can lead to very subtle errors if used incorrectly and care needs to be taken when using these views. Views can be created in two ways:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> numpy_mat_view = np.asarray(mat)

    # Access the NumPy object and set all values to 1 through broadcasting
    >>> numpy_mat_view[:] = 1

    >>> print(np.array(mat))
    [[ 1.  1.  1.]
     [ 1.  1.  1.]
     [ 1.  1.  1.]]

Secondly, these objects have a `.np` attribute for easy access to the underlying data:

    1
    >>> mat.np[:] = 1

this operation is identical to the above.

## PSI4 Data Objects with Irreps

PSI4 data objects natively support multiple irreducible representations which is quite useful for Quantum Chemistry. However, this is not fundamental to NumPy and some work around are required to natively support these operations. Take the following irreped Matrix:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> dim = psi4.Dimension.from_list([1, 2, 3])
    >>> irreped_mat = psi4.Matrix("New Matrix", dim, dim)

    # Create a list of Psi4 arrays
    >>> list_of_arrays = irreped_mat.to_array()

    # Or, use the .nph irreped accessor
    >>> irreped_mat.nph[0][:] = 1

Where `.nph` is the irreped accessor form. If `.np` or `np.array` are called on irreped Matrices or Vectors an error will be thrown; however, the irreped form is always valid for non-irreped matrices.

## Array to Matrix

A general function that converts PSI4 data objects to NumPy arrays.

`psi4.driver.p4util.numpy_helper.``array_to_matrix`(self, arr, name='New Matrix', dim1=None, dim2=None)

  Converts a numpy array or list of numpy arrays into a Psi4 Matrix (irreped if list).

  Parameters: | arr (array or list of arrays) – Numpy array or list of arrays to use as the data for a new core.Matrix name (str) – Name to give the new core.Matrix dim1 (list, tuple, or core.Dimension (optional)) – If a single dense numpy array is given, a dimension can be supplied to apply irreps to this array. Note that this discards all extra information given in the matrix besides the diagonal blocks determined by the passed dimension. dim2 – Same as dim1 only if using a psi4.core.Dimension object.
  Returns: | matrix – Returns the given Psi4 object
  Return type: | `Matrix` or `Vector`

  Notes

  This is a generalized function to convert a NumPy array to a Psi4 object

  Examples

      >>> data = np.random.rand(20)
      >>> vector = array_to_matrix(data)

      >>> irrep_data = [np.random.rand(2, 2), np.empty(shape=(0,3)), np.random.rand(4, 4)]
      >>> matrix = array_to_matrix(irrep_data)
      >>> print matrix.rowspi().to_tuple()
      (2, 0, 4)

## Matrix to Array

A general function that converts NumPy arrays to PSI4 data objects.

`psi4.driver.p4util.numpy_helper.``_to_array`(matrix, copy=True, dense=False)

  Converts a Psi4 Matrix or Vector to a numpy array. Either copies the data or simply constructs a view.

  Parameters: | matrix (`Matrix` or `Vector`) – Pointers to which Psi4 core class should be used in the construction. copy (bool, optional) – Copy the data if True, return a view otherwise dense (bool, optional) – Converts irreped Psi4 objects to diagonally blocked dense arrays if True. Returns a list of arrays otherwise.
  Returns: | array – Returns either a list of np.array’s or the base array depending on options.
  Return type: | ndarray or list of ndarray

  Notes

  This is a generalized function to convert a Psi4 object to a NumPy array

  Examples

      >>> data = psi4.Matrix(3, 3)
      >>> data.to_array()
      [[ 0.  0.  0.]
       [ 0.  0.  0.]
       [ 0.  0.  0.]]