code: def hash_from_ndarray(data):
      """
      Return a hash from an ndarray.
  
      It takes care of the data, shapes, strides and dtype.
  
      """
      # We need to hash the shapes and strides as hash_from_code only hashes
      # the data buffer. Otherwise, this will cause problem with shapes like:
      # (1, 0) and (2, 0) and problem with inplace transpose.
      # We also need to add the dtype to make the distinction between
      # uint32 and int32 of zeros with the same shape and strides.
  
      # python hash are not strong, so use sha256 (md5 is not
      # FIPS compatible). To not have too long of hash, I call it again on
      # the concatenation of all parts.
      if not data.flags["C_CONTIGUOUS"]:
          # hash_from_code needs a C-contiguous array.
          data = np.ascontiguousarray(data)
      return hash_from_code(
          hash_from_code(data)
          + hash_from_code(str(data.shape))
          + hash_from_code(str(data.strides))
          + hash_from_code(str(data.dtype))
      )
  
file_path: pytensor/pytensor/tensor/utils.py
imports: import re
  from collections.abc import Sequence
  from typing import Union
  import numpy
  import pytensor
  from pytensor.utils import hash_from_code
label_desc: Use image node_id 1 for calling a global function with example usage: hash_from_ndarray(data) and returns: hash_from_code