code: def sanitize_array(
      data, index, dtype=None, copy=False, raise_cast_failure=False
  ):
      """
      Sanitize input data to an ndarray, copy if specified, coerce to the
      dtype if specified.
      """
      if dtype is not None:
          dtype = pandas_dtype(dtype)
  
      if isinstance(data, ma.MaskedArray):
          mask = ma.getmaskarray(data)
          if mask.any():
              data, fill_value = maybe_upcast(data, copy=True)
              data.soften_mask()  # set hardmask False if it was True
              data[mask] = fill_value
          else:
              data = data.copy()
  
      data = extract_array(data, extract_numpy=True)
  
      # GH#846
      if isinstance(data, np.ndarray):
          if dtype is not None:
              subarr = np.array(data, copy=False)
  
              # possibility of nan -> garbage
              if is_float_dtype(data.dtype) and is_integer_dtype(dtype):
                  try:
                      subarr = _try_cast(data, True, dtype, copy, True)
                  except ValueError:
                      if copy:
                          subarr = data.copy()
              else:
                  subarr = _try_cast(
                      data, True, dtype, copy, raise_cast_failure
                  )
          elif isinstance(data, Index):
              # don't coerce Index types
              # e.g. indexes can have different conversions (so don't fast path
              # them)
              # GH#6140
              subarr = sanitize_index(data, index, copy=copy)
          else:
              # we will try to copy be-definition here
              subarr = _try_cast(
                  data, True, dtype, copy, raise_cast_failure
              )
  
      elif isinstance(data, ExtensionArray):
          if isinstance(data, ABCPandasArray):
              # We don't want to let people put our PandasArray wrapper
              # (the output of Series/Index.array), into a Series. So
              # we explicitly unwrap it here.
              subarr = data.to_numpy()
          else:
              subarr = data
  
          # everything else in this block must also handle ndarray's,
          # becuase we've unwrapped PandasArray into an ndarray.
  
          if dtype is not None:
              subarr = data.astype(dtype)
  
          if copy:
              subarr = data.copy()
          return subarr
  
      elif isinstance(data, (list, tuple)) and len(data) > 0:
          if dtype is not None:
              try:
                  subarr = _try_cast(
                      data, False, dtype, copy, raise_cast_failure
                  )
              except Exception:
                  if raise_cast_failure:  # pragma: no cover
                      raise
                  subarr = np.array(data, dtype=object, copy=copy)
                  subarr = lib.maybe_convert_objects(subarr)
  
          else:
              subarr = maybe_convert_platform(data)
  
          subarr = maybe_cast_to_datetime(subarr, dtype)
  
      elif isinstance(data, range):
          # GH#16804
          start, stop, step = get_range_parameters(data)
          arr = np.arange(start, stop, step, dtype="int64")
          subarr = _try_cast(
              arr, False, dtype, copy, raise_cast_failure
          )
      else:
          subarr = _try_cast(
              data, False, dtype, copy, raise_cast_failure
          )
  
      # scalar like, GH
      if getattr(subarr, "ndim", 0) == 0:
          if isinstance(data, list):  # pragma: no cover
              subarr = np.array(data, dtype=object)
          elif index is not None:
              value = data
  
              # figure out the dtype from the value (upcast if necessary)
              if dtype is None:
                  dtype, value = infer_dtype_from_scalar(value)
              else:
                  # need to possibly convert the value here
                  value = maybe_cast_to_datetime(value, dtype)
  
              subarr = construct_1d_arraylike_from_scalar(
                  value, len(index), dtype
              )
  
          else:
              return subarr.item()
  
      # the result that we want
      elif subarr.ndim == 1:
          if index is not None:
              # a 1-element ndarray
              if len(subarr) != len(index) and len(subarr) == 1:
                  subarr = construct_1d_arraylike_from_scalar(
                      subarr[0], len(index), subarr.dtype
                  )
  
      elif subarr.ndim > 1:
          if isinstance(data, np.ndarray):
              raise Exception("Data must be 1-dimensional")
          else:
              subarr = com.asarray_tuplesafe(data, dtype=dtype)
  
      # This is to prevent mixed-type Series getting all casted to
      # NumPy string type, e.g. NaN --> '-1#IND'.
      if issubclass(subarr.dtype.type, compat.string_types):
          # GH#16605
          # If not empty convert the data to dtype
          # GH#19853: If data is a scalar, subarr has already the result
          if not lib.is_scalar(data):
              if not np.all(isna(data)):
                  data = np.array(data, dtype=dtype, copy=False)
              subarr = np.array(data, dtype=object, copy=copy)
  
      if is_object_dtype(subarr.dtype) and dtype != "object":
          inferred = lib.infer_dtype(subarr, skipna=False)
          if inferred == "period":
              try:
                  subarr = period_array(subarr)
              except IncompatibleFrequency:
                  pass
  
      return subarr
  
imports: from collections import OrderedDict
  import numpy
  import numpy.ma
  from pandas._libs import lib
  from pandas._libs.tslibs import IncompatibleFrequency
  import pandas.compat
  from pandas.compat import get_range_parameters, lmap, lrange, raise_with_traceback, range
  from pandas.core.dtypes.cast import construct_1d_arraylike_from_scalar, construct_1d_ndarray_preserving_na, construct_1d_object_array_from_listlike, infer_dtype_from_scalar, maybe_cast_to_datetime, maybe_cast_to_integer_array, maybe_castable, maybe_convert_platform, maybe_infer_to_datetimelike, maybe_upcast
  from pandas.core.dtypes.common import is_categorical_dtype, is_datetime64tz_dtype, is_dtype_equal, is_extension_array_dtype, is_extension_type, is_float_dtype, is_integer_dtype, is_iterator, is_list_like, is_object_dtype, pandas_dtype
  from pandas.core.dtypes.generic import ABCDataFrame, ABCDatetimeIndex, ABCIndexClass, ABCPandasArray, ABCPeriodIndex, ABCSeries, ABCTimedeltaIndex
  from pandas.core.dtypes.missing import isna
  from pandas.core import algorithms, common
  from pandas.core.arrays import Categorical, ExtensionArray, period_array
  from pandas.core.index import Index, _get_objs_combined_axis, _union_indexes, ensure_index
  from pandas.core.indexes import base
  from pandas.core.internals import create_block_manager_from_arrays, create_block_manager_from_blocks
  from pandas.core.internals.arrays import extract_array
label_desc: Use image node_id 17 for calling a global function with example usage: sanitize_array(data, index, dtype, copy, raise_cast_failure) and returns: subarr, subarr, subarr