code: def block_variants_and_samples(
      variant_df: DataFrame,
      sample_ids: List[str],
      variants_per_block: int,
      sample_block_count: int,
  ) -> (DataFrame, Dict[str, List[str]]):
      """
      Creates a blocked GT matrix and index mapping from sample blocks to a list of corresponding sample IDs. Uses the
      same sample-blocking logic as the blocked GT matrix transformer.
  
      Requires that:
  
      - Each variant row has the same number of values
      - The number of values per row matches the number of sample IDs
  
      Args:
          variant_df : The variant DataFrame
          sample_ids : The list of sample ID strings
          variants_per_block : The number of variants per block
          sample_block_count : The number of sample blocks
  
      Returns:
          tuple of (blocked GT matrix, index mapping)
      """
      assert check_argument_types()
      first_row = variant_df.selectExpr(
          "size(values) as numValues"
      ).take(1)
      if not first_row:
          raise Exception("DataFrame has no values.")
      num_values = first_row[0].numValues
      if num_values != len(sample_ids):
          raise Exception(
              f"Number of values does not match between DataFrame ({num_values}) and sample ID list ({len(sample_ids)})."
          )
      __validate_sample_ids(sample_ids)
  
      blocked_gt = glow.transform(
          "block_variants_and_samples",
          variant_df,
          variants_per_block=variants_per_block,
          sample_block_count=sample_block_count,
      )
      index_map = __get_index_map(
          sample_ids, sample_block_count, variant_df.sql_ctx
      )
  
      output = blocked_gt, index_map
      assert check_return_type(output)
      return output
  
file_path: glow/python/glow/wgr/wgr_functions.py
imports: from glow import glow
  import pandas
  import numpy
  from pyspark import SparkContext
  from pyspark.sql import DataFrame, Row, SparkSession, SQLContext
  from typeguard import check_argument_types, check_return_type
  from typing import Any, Dict, List
  from nptyping import Float, NDArray
  from .ridge_reduction import RidgeReduction
  from .ridge_regression import RidgeRegression
  from .logistic_ridge_regression import LogisticRidgeRegression
label_desc: Use image node_id 5 for calling a global function with example usage: block_variants_and_samples(variant_df, sample_ids, variants_per_block, sample_block_count) and returns: output