code: def _logistic_regression_inner(
      genotype_pdf: pd.DataFrame,
      log_reg_state: LogRegState,
      C: NDArray[(Any, Any), Float],
      Y: NDArray[(Any, Any), Float],
      Y_mask: NDArray[(Any, Any), bool],
      Q: Optional[NDArray[(Any, Any), Float]],
      correction: str,
      pvalue_threshold: float,
      phenotype_names: pd.Series,
      gt_indices_to_drop: Optional[NDArray[(Any,), Int32]],
  ) -> pd.DataFrame:
      """
      Tests a block of genotypes for association with binary traits. We first residualize
      the genotypes based on the null model fit, then perform a fast score test to check for
      possible significance.
  
      We use semantic indices for the einsum expressions:
      s, i: sample (or individual)
      g: genotype
      p: phenotype
      c, d: covariate
      """
      genotype_values = genotype_pdf[_VALUES_COLUMN_NAME].array
      X = np.column_stack(genotype_values)
      if gt_indices_to_drop is not None and gt_indices_to_drop.size:
          X = np.delete(X, gt_indices_to_drop, axis=0)
  
      # For approximate Firth correction, we perform a linear residualization
      if correction == correction_approx_firth:
          X = gwas_fx._residualize_in_place(X, Q)
  
      with oe.shared_intermediates():
          X_res = _logistic_residualize(
              X,
              C,
              Y_mask,
              log_reg_state.gamma,
              log_reg_state.inv_CtGammaC,
          )
          num = (
              gwas_fx._einsum("sgp,sp->pg", X_res, log_reg_state.Y_res)
              ** 2
          )
          denom = gwas_fx._einsum(
              "sgp,sgp,sp->pg", X_res, X_res, log_reg_state.gamma
          )
      chisq = np.ravel(num / denom)
      p_values = stats.chi2.sf(chisq, 1)
  
      genotype_pdf.drop(_VALUES_COLUMN_NAME, axis=1, inplace=True)
      out_df = pd.concat([genotype_pdf] * log_reg_state.Y_res.shape[1])
      out_df["chisq"] = list(np.ravel(chisq))
      out_df["pvalue"] = list(np.ravel(p_values))
      out_df["phenotype"] = phenotype_names.repeat(
          genotype_pdf.shape[0]
      ).tolist()
  
      if correction != correction_none:
          out_df["correctionSucceeded"] = None
          correction_indices = list(
              np.where(out_df["pvalue"] < pvalue_threshold)[0]
          )
          if correction == correction_approx_firth:
              out_df["effect"] = np.nan
              out_df["stderror"] = np.nan
              for correction_idx in correction_indices:
                  snp_idx = correction_idx % X.shape[1]
                  pheno_idx = int(correction_idx / X.shape[1])
                  approx_firth_snp_fit = af.correct_approx_firth(
                      X[:, snp_idx],
                      Y[:, pheno_idx],
                      log_reg_state.firth_offset[:, pheno_idx],
                      Y_mask[:, pheno_idx],
                  )
                  if approx_firth_snp_fit is None:
                      out_df.correctionSucceeded.iloc[
                          correction_idx
                      ] = False
                  else:
                      out_df.correctionSucceeded.iloc[
                          correction_idx
                      ] = True
                      out_df.effect.iloc[
                          correction_idx
                      ] = approx_firth_snp_fit.effect
                      out_df.stderror.iloc[
                          correction_idx
                      ] = approx_firth_snp_fit.stderror
                      out_df.chisq.iloc[
                          correction_idx
                      ] = approx_firth_snp_fit.chisq
                      out_df.pvalue.iloc[
                          correction_idx
                      ] = approx_firth_snp_fit.pvalue
  
      return out_df
  
imports: from pyspark.sql.types import ArrayType, BooleanType, StringType, StructField, DataType, StructType
  from typing import Any, List, Optional, Dict, Union
  import pandas
  import numpy
  from pyspark.sql import DataFrame, SparkSession
  import statsmodels.api
  from dataclasses import dataclass
  from typeguard import typechecked
  from nptyping import Float, NDArray, Int32
  from scipy import stats
  import opt_einsum
  from .None import functions
  from .None import approx_firth
  from .functions import _VALUES_COLUMN_NAME, _get_indices_to_drop
  from ..wgr.wgr_functions import reshape_for_gwas
label_desc: Use image node_id 7 for calling a global function with example usage: _logistic_regression_inner(genotype_pdf, log_reg_state, C, Y, Y_mask, Q, correction, pvalue_threshold, phenotype_names, gt_indices_to_drop) and returns: out_df