code: def get_draws(
      fit, variables=None, ignore=None, warmup=False, dtypes=None
  ):
      """Extract draws from PyStan fit."""
      if ignore is None:
          ignore = []
      if fit.mode == 1:
          msg = "Model in mode 'test_grad'. Sampling is not conducted."
          raise AttributeError(msg)
  
      if fit.mode == 2 or fit.sim.get("samples") is None:
          msg = "Fit doesn't contain samples."
          raise AttributeError(msg)
  
      if dtypes is None:
          dtypes = {}
  
      dtypes = {**infer_dtypes(fit), **dtypes}
  
      if variables is None:
          variables = fit.sim["pars_oi"]
      elif isinstance(variables, str):
          variables = [variables]
      variables = list(variables)
  
      for var, dim in zip(fit.sim["pars_oi"], fit.sim["dims_oi"]):
          if var in variables and np.prod(dim) == 0:
              del variables[variables.index(var)]
  
      ndraws_warmup = fit.sim["warmup2"]
      if max(ndraws_warmup) == 0:
          warmup = False
      ndraws = [s - w for s, w in zip(fit.sim["n_save"], ndraws_warmup)]
      nchain = len(fit.sim["samples"])
  
      # check if the values are in 0-based (<=2.17) or 1-based indexing (>=2.18)
      shift = 1
      if any(dim and np.prod(dim) != 0 for dim in fit.sim["dims_oi"]):
          # choose variable with lowest number of dims > 1
          par_idx = min(
              (dim, i)
              for i, dim in enumerate(fit.sim["dims_oi"])
              if (dim and np.prod(dim) != 0)
          )[1]
          offset = int(sum(map(np.prod, fit.sim["dims_oi"][:par_idx])))
          par_offset = int(np.prod(fit.sim["dims_oi"][par_idx]))
          par_keys = fit.sim["fnames_oi"][offset : offset + par_offset]
          shift = len(par_keys)
          for item in par_keys:
              _, shape = item.replace("]", "").split("[")
              shape_idx_min = min(
                  int(shape_value) for shape_value in shape.split(",")
              )
              if shape_idx_min < shift:
                  shift = shape_idx_min
          # If shift is higher than 1, this will probably mean that Stan
          # has implemented sparse structure (saves only non-zero parts),
          # but let's hope that dims are still corresponding to the full shape
          shift = int(min(shift, 1))
  
      var_keys = OrderedDict((var, []) for var in fit.sim["pars_oi"])
      for key in fit.sim["fnames_oi"]:
          var, *tails = key.split("[")
          loc = [Ellipsis]
          for tail in tails:
              loc = []
              for i in tail[:-1].split(","):
                  loc.append(int(i) - shift)
          var_keys[var].append((key, loc))
  
      shapes = dict(zip(fit.sim["pars_oi"], fit.sim["dims_oi"]))
  
      variables = [var for var in variables if var not in ignore]
  
      data = OrderedDict()
      data_warmup = OrderedDict()
  
      for var in variables:
          if var in data:
              continue
          keys_locs = var_keys.get(var, [(var, [Ellipsis])])
          shape = shapes.get(var, [])
          dtype = dtypes.get(var)
  
          ndraw = max(ndraws)
          ary_shape = [nchain, ndraw] + shape
          ary = np.empty(ary_shape, dtype=dtype, order="F")
  
          if warmup:
              nwarmup = max(ndraws_warmup)
              ary_warmup_shape = [nchain, nwarmup] + shape
              ary_warmup = np.empty(
                  ary_warmup_shape, dtype=dtype, order="F"
              )
  
          for chain, (pyholder, ndraw, ndraw_warmup) in enumerate(
              zip(fit.sim["samples"], ndraws, ndraws_warmup)
          ):
              axes = [chain, slice(None)]
              for key, loc in keys_locs:
                  ary_slice = tuple(axes + loc)
                  ary[ary_slice] = pyholder.chains[key][-ndraw:]
                  if warmup:
                      ary_warmup[ary_slice] = pyholder.chains[key][
                          :ndraw_warmup
                      ]
          data[var] = ary
          if warmup:
              data_warmup[var] = ary_warmup
      return data, data_warmup
  
imports: import re
  from collections import OrderedDict
  from copy import deepcopy
  from math import ceil
  import numpy
  import xarray
  from ..None import _log
  from ..rcparams import rcParams
  from .base import dict_to_dataset, generate_dims_coords, infer_stan_dtypes, make_attrs, requires
  from .inference_data import InferenceData
label_desc: Use image node_id 1 for calling a global function with example usage: get_draws(fit, variables, ignore, warmup, dtypes) and returns: data,  data_warmup