code: def stack(band_paths, out_path="", nodata=None):
      """Convert a list of raster paths into a raster stack numpy darray.
  
      Parameters
      ----------
      band_paths : list of file paths
          A list with paths to the bands to be stacked. Bands
          will be stacked in the order given in this list.
      out_path : string (optional)
          A path with a file name for the output stacked raster
          tif file.
      nodata : numeric (optional)
          A value (int or float) that represents invalid or missing values to
          mask in the output.
  
      Returns
      ----------
      tuple :
  
          numpy array
              N-dimensional array created by stacking the raster files provided.
          rasterio profile object
              A rasterio profile object containing the updated spatial metadata
              for the stacked numpy array.
  
      Example
      -------
          >>> import os
          >>> import earthpy.spatial as es
          >>> from earthpy.io import path_to_example
          >>> band_fnames = ["red.tif", "green.tif", "blue.tif"]
          >>> band_paths = [path_to_example(fname) for fname in band_fnames]
          >>> destfile = "./stack_result.tif"
          >>> arr, arr_meta = es.stack(band_paths, destfile)
          >>> arr.shape
          (3, 373, 485)
          >>> os.path.isfile(destfile)
          True
          >>> # optionally, clean up example output
          >>> os.remove(destfile)
      """
  
      # Set default import to read
      kwds = {"mode": "r"}
  
      out_dir = os.path.dirname(out_path)
      writing_to_cwd = out_dir == ""
      if not os.path.exists(out_dir) and not writing_to_cwd:
          raise ValueError(
              "The output directory path that you provided does not exist"
          )
  
      if len(band_paths) < 2:
          raise ValueError(
              "The list of file paths is empty. You need at least 2 files to "
              "create a stack."
          )
  
      # Invalid filename specified and write_raster == True.
      # Tell user to specify valid filename
      if (len(out_path) > 0) and (
          len(os.path.basename(out_path).split(".")) < 2
      ):
          raise ValueError(
              "Please specify a valid file name for output."
          )
  
      # Set write_raster flag if valid filename provided
      write_raster = False
      if len(os.path.basename(out_path).split(".")) == 2:
          write_raster = True
  
      with contextlib.ExitStack() as context:
          sources = [
              context.enter_context(rio.open(path, **kwds))
              for path in band_paths
          ]
  
          # Check that the CRS and TRANSFORM are the same
          dest_crs = [src.meta["crs"].to_string() for src in sources]
          dest_aff = [src.meta["transform"] for src in sources]
          dest_shps = [
              (src.meta["height"], src.meta["width"]) for src in sources
          ]
  
          if not len(set(dest_crs)) == 1:
              raise ValueError(
                  "Please ensure all source rasters have the same CRS."
              )
  
          if not len(set(dest_aff)) == 1:
              raise ValueError(
                  "Please ensure all source rasters have same affine transform."
              )
  
          if not len(set(dest_shps)) == 1:
              raise ValueError(
                  "Please ensure all source rasters have same dimensions "
                  "(nrows, ncols)."
              )
  
          # Update band count
          dest_kwargs = sources[0].meta
          dest_count = sum(src.count for src in sources)
          dest_kwargs["count"] = dest_count
  
          if nodata is not None:
              dest_kwargs["nodata"] = nodata
  
          # Stack the bands and return an array, but don't write to disk
          if not write_raster:
              arr, meta = _stack_bands(sources)
  
              # If user specified nodata, mask the array
              if nodata is not None:
                  # Mask and input data types must be identical for mask_equal()
                  nodata = np.array([nodata]).astype(arr.dtype)[0]
                  arr = np.ma.masked_equal(arr, nodata)
  
              return arr, meta
  
          # Write out the stacked array and return a numpy array
          else:
              # Valid output path checked above
              file_fmt = os.path.basename(out_path).split(".")[-1]
  
              # Check that file format for output is the same as source driver
              rio_driver = sources[0].profile["driver"]
              if file_fmt not in rio_driver.lower():
                  raise ValueError(
                      "Source data is {}. Please specify corresponding output "
                      "extension.".format(rio_driver)
                  )
  
              # Write stacked gtif file
              with rio.open(out_path, "w", **dest_kwargs) as dest:
                  _stack_bands(sources, write_raster, dest)
  
              # Read and return array
              with rio.open(out_path, "r") as src:
                  arr = src.read()
                  meta = src.profile
  
                  # If user specified nodata, mask the array
                  if nodata is not None:
                      # Make sure value is same data type
                      nodata = np.array([nodata]).astype(arr.dtype)[0]
  
                      # Mask the array
                      arr = np.ma.masked_equal(arr, nodata)
  
                  return arr, meta
  
file_path: earthpy/earthpy/spatial.py
imports: import os
  import sys
  import contextlib
  import warnings
  import numpy
  from shapely.geometry import mapping, box
  import geopandas
  import rasterio
  from rasterio.mask import mask
label_desc: Use image node_id 3 for calling a global function with example usage: stack(band_paths, out_path, nodata) and returns: arr,  meta, arr,  meta