code: def calculate_chunk(
      cutoff_time,
      chunk_size,
      feature_set,
      entityset,
      approximate,
      training_window,
      save_progress,
      no_unapproximated_aggs,
      cutoff_df_time_col,
      target_time,
      pass_columns,
      progress_bar=None,
      progress_callback=None,
      include_cutoff_time=True,
      schema=None,
  ):
      if not isinstance(feature_set, FeatureSet):
          feature_set = cloudpickle.loads(
              feature_set
          )  # pragma: no cover
  
      feature_matrix = []
      if no_unapproximated_aggs and approximate is not None:
          if entityset.time_type == "numeric":
              group_time = np.inf
          else:
              group_time = datetime.now()
  
      if isinstance(cutoff_time, tuple):
          update_progress_callback = None
          if progress_bar is not None:
  
              def update_progress_callback(done):
                  previous_progress = progress_bar.n
                  progress_bar.update(done * len(cutoff_time[1]))
                  if progress_callback is not None:
                      (
                          update,
                          progress_percent,
                          time_elapsed,
                      ) = update_progress_callback_parameters(
                          progress_bar,
                          previous_progress,
                      )
                      progress_callback(
                          update, progress_percent, time_elapsed
                      )
  
          time_last = cutoff_time[0]
          ids = cutoff_time[1]
          calculator = FeatureSetCalculator(
              entityset,
              feature_set,
              time_last,
              training_window=training_window,
          )
          _feature_matrix = calculator.run(
              ids,
              progress_callback=update_progress_callback,
              include_cutoff_time=include_cutoff_time,
          )
          if isinstance(_feature_matrix, pd.DataFrame):
              time_index = pd.Index([time_last] * len(ids), name="time")
              _feature_matrix = _feature_matrix.set_index(
                  time_index, append=True
              )
          feature_matrix.append(_feature_matrix)
  
      else:
          if schema:
              cutoff_time.ww.init_with_full_schema(
                  schema=schema
              )  # pragma: no cover
          for _, group in cutoff_time.groupby(cutoff_df_time_col):
              # if approximating, calculate the approximate features
              if approximate is not None:
                  group.ww.init(
                      schema=cutoff_time.ww.schema, validate=False
                  )
                  precalculated_features_trie = approximate_features(
                      feature_set,
                      group,
                      window=approximate,
                      entityset=entityset,
                      training_window=training_window,
                      include_cutoff_time=include_cutoff_time,
                  )
              else:
                  precalculated_features_trie = None
  
              @save_csv_decorator(save_progress)
              def calc_results(
                  time_last,
                  ids,
                  precalculated_features=None,
                  training_window=None,
                  include_cutoff_time=True,
              ):
                  update_progress_callback = None
  
                  if progress_bar is not None:
  
                      def update_progress_callback(done):
                          previous_progress = progress_bar.n
                          progress_bar.update(done * group.shape[0])
                          if progress_callback is not None:
                              (
                                  update,
                                  progress_percent,
                                  time_elapsed,
                              ) = update_progress_callback_parameters(
                                  progress_bar,
                                  previous_progress,
                              )
                              progress_callback(
                                  update, progress_percent, time_elapsed
                              )
  
                  calculator = FeatureSetCalculator(
                      entityset,
                      feature_set,
                      time_last,
                      training_window=training_window,
                      precalculated_features=precalculated_features,
                  )
                  matrix = calculator.run(
                      ids,
                      progress_callback=update_progress_callback,
                      include_cutoff_time=include_cutoff_time,
                  )
  
                  return matrix
  
              # if all aggregations have been approximated, can calculate all together
              if no_unapproximated_aggs and approximate is not None:
                  inner_grouped = [[group_time, group]]
              else:
                  # if approximated features, set cutoff_time to unbinned time
                  if precalculated_features_trie is not None:
                      group[cutoff_df_time_col] = group[target_time]
  
                  inner_grouped = group.groupby(
                      cutoff_df_time_col, sort=True
                  )
  
              if chunk_size is not None:
                  inner_grouped = _chunk_dataframe_groups(
                      inner_grouped, chunk_size
                  )
  
              for time_last, group in inner_grouped:
                  # sort group by instance id
                  ids = group["instance_id"].sort_values().values
                  if no_unapproximated_aggs and approximate is not None:
                      window = None
                  else:
                      window = training_window
  
                  # calculate values for those instances at time time_last
                  _feature_matrix = calc_results(
                      time_last,
                      ids,
                      precalculated_features=precalculated_features_trie,
                      training_window=window,
                      include_cutoff_time=include_cutoff_time,
                  )
  
                  if is_instance(
                      _feature_matrix, (dd, ps), "DataFrame"
                  ):
                      id_name = _feature_matrix.columns[-1]
                  else:
                      id_name = _feature_matrix.index.name
  
                  # if approximate, merge feature matrix with group frame to get original
                  # cutoff times and passed columns
                  if approximate:
                      cols = [
                          c
                          for c in _feature_matrix.columns
                          if c not in pass_columns
                      ]
                      indexer = group[
                          ["instance_id", target_time] + pass_columns
                      ]
                      _feature_matrix = _feature_matrix[cols].merge(
                          indexer,
                          right_on=["instance_id"],
                          left_index=True,
                          how="right",
                      )
                      _feature_matrix.set_index(
                          ["instance_id", target_time],
                          inplace=True,
                      )
                      _feature_matrix.index.set_names(
                          [id_name, "time"], inplace=True
                      )
                      _feature_matrix.sort_index(
                          level=1, kind="mergesort", inplace=True
                      )
                  else:
                      # all rows have same cutoff time. set time and add passed columns
                      num_rows = len(ids)
                      if len(pass_columns) > 0:
                          pass_through = group[
                              ["instance_id", cutoff_df_time_col]
                              + pass_columns
                          ]
                          pass_through.rename(
                              columns={
                                  "instance_id": id_name,
                                  cutoff_df_time_col: "time",
                              },
                              inplace=True,
                          )
                      if isinstance(_feature_matrix, pd.DataFrame):
                          time_index = pd.Index(
                              [time_last] * num_rows, name="time"
                          )
                          _feature_matrix = _feature_matrix.set_index(
                              time_index,
                              append=True,
                          )
                          if len(pass_columns) > 0:
                              pass_through.set_index(
                                  [id_name, "time"], inplace=True
                              )
                              for col in pass_columns:
                                  _feature_matrix[col] = pass_through[
                                      col
                                  ]
                      elif is_instance(
                          _feature_matrix, dd, "DataFrame"
                      ) and (len(pass_columns) > 0):
                          _feature_matrix["time"] = time_last
                          for col in pass_columns:
                              pass_df = dd.from_pandas(
                                  pass_through[[id_name, "time", col]],
                                  npartitions=_feature_matrix.npartitions,
                              )
                              _feature_matrix = _feature_matrix.merge(
                                  pass_df,
                                  how="outer",
                              )
                          _feature_matrix = _feature_matrix.drop(
                              columns=["time"]
                          )
                      elif is_instance(
                          _feature_matrix, ps, "DataFrame"
                      ) and (len(pass_columns) > 0):
                          _feature_matrix["time"] = time_last
                          for col in pass_columns:
                              pass_df = ps.from_pandas(
                                  pass_through[[id_name, "time", col]],
                              )
                              _feature_matrix = _feature_matrix.merge(
                                  pass_df,
                                  how="outer",
                              )
                          _feature_matrix = _feature_matrix.drop(
                              columns=["time"]
                          )
                  feature_matrix.append(_feature_matrix)
  
      ww_init_kwargs = get_ww_types_from_features(
          feature_set.target_features,
          entityset,
          pass_columns,
          cutoff_time,
      )
      feature_matrix = init_ww_and_concat_fm(
          feature_matrix, ww_init_kwargs
      )
      return feature_matrix
  
imports: import logging
  import math
  import os
  import shutil
  import time
  import warnings
  from datetime import datetime
  import cloudpickle
  import numpy
  import pandas
  from woodwork.logical_types import Age, AgeNullable, Boolean, BooleanNullable, Integer, IntegerNullable
  from featuretools.computational_backends.feature_set import FeatureSet
  from featuretools.computational_backends.feature_set_calculator import FeatureSetCalculator
  from featuretools.computational_backends.utils import _check_cutoff_time_type, _validate_cutoff_time, bin_cutoff_times, create_client_and_cluster, gather_approximate_features, gen_empty_approx_features_df, get_ww_types_from_features, save_csv_decorator
  from featuretools.entityset.relationship import RelationshipPath
  from featuretools.feature_base import AggregationFeature, FeatureBase
  from featuretools.utils import Trie
  from featuretools.utils.gen_utils import Library, import_or_none, import_or_raise, is_instance, make_tqdm_iterator
label_desc: Use image node_id 2 for calling a global function with example usage: calculate_chunk(cutoff_time, chunk_size, feature_set, entityset, approximate, training_window, save_progress, no_unapproximated_aggs, cutoff_df_time_col, target_time, pass_columns, progress_bar, progress_callback, include_cutoff_time, schema) and returns: feature_matrix, matrix