code: def export_plink(
      dataset,
      output,
      call=None,
      fam_id=None,
      ind_id=None,
      pat_id=None,
      mat_id=None,
      is_female=None,
      pheno=None,
      varid=None,
      cm_position=None,
  ):
      """Export a :class:`.MatrixTable` as
      `PLINK2 <https://www.cog-genomics.org/plink2/formats>`__
      BED, BIM and FAM files.
  
      .. include:: ../_templates/req_tvariant_w_struct_locus.rst
      .. include:: ../_templates/req_tstring.rst
      .. include:: ../_templates/req_biallelic.rst
      .. include:: ../_templates/req_unphased_diploid_gt.rst
  
      Examples
      --------
      Import data from a VCF file, split multi-allelic variants, and export to
      PLINK files with the FAM file individual ID set to the sample ID:
  
      >>> ds = hl.split_multi_hts(dataset)
      >>> hl.export_plink(ds, 'output/example', ind_id = ds.s)
  
      Notes
      -----
      On an imported VCF, the example above will behave similarly to the PLINK
      conversion command
  
      .. code-block:: text
  
          plink --vcf /path/to/file.vcf --make-bed --out sample --const-fid --keep-allele-order
  
      except that:
  
      - Variants that result from splitting a multi-allelic variant may be
        re-ordered relative to the BIM and BED files.
  
      Parameters
      ----------
      dataset : :class:`.MatrixTable`
          Dataset.
      output : :class:`str`
          Filename root for output BED, BIM, and FAM files.
      call : :class:`.CallExpression`, optional
          Expression for the genotype call to output. If ``None``, the entry field
          `GT` is used if defined and is of type :py:data:`.tcall`.
      fam_id : :class:`.StringExpression`, optional
          Expression for the family ID. The default and missing values are
          ``'0'``.
      ind_id : :class:`.StringExpression`, optional
          Expression for the individual (proband) ID. If ``None``, the column key
          of the dataset is used and must be one field of type :py:data:`.tstr`.
      pat_id : :class:`.StringExpression`, optional
          Expression for the paternal ID. The default and missing values are
          ``'0'``.
      mat_id : :class:`.StringExpression`, optional
          Expression for the maternal ID. The default and missing values are
          ``'0'``.
      is_female : :class:`.BooleanExpression`, optional
          Expression for the proband sex. ``True`` is output as ``'2'`` and
          ``False`` is output as ``'1'``. The default and missing values are
          ``'0'``.
      pheno : :class:`.BooleanExpression` or :class:`.NumericExpression`, optional
          Expression for the phenotype. If `pheno` is a boolean expression,
          ``True`` is output as ``'2'`` and ``False`` is output as ``'1'``. The
          default and missing values are ``'NA'``.
      varid : :class:`.StringExpression`, optional
          Expression for the variant ID (2nd column of the BIM file). The default
          value is ``hl.delimit([dataset.locus.contig, hl.str(dataset.locus.position), dataset.alleles[0], dataset.alleles[1]], ':')``
      cm_position : :class:`.Float64Expression`, optional
          Expression for the 3rd column of the BIM file (position in centimorgans).
          The default value is ``0.0``. The missing value is ``0.0``.
      """
  
      require_biallelic(
          dataset, "export_plink", tolerate_generic_locus=True
      )
  
      hl.current_backend().validate_file(output)
  
      if ind_id is None:
          require_col_key_str(dataset, "export_plink")
          ind_id = dataset.col_key[0]
  
      if call is None:
          if "GT" in dataset.entry and dataset.GT.dtype == tcall:
              entry_exprs = {"GT": dataset.GT}
          else:
              entry_exprs = {}
      else:
          entry_exprs = {"GT": call}
  
      fam_exprs = {
          "fam_id": expr_or_else(fam_id, "0"),
          "ind_id": hl.or_else(ind_id, "0"),
          "pat_id": expr_or_else(pat_id, "0"),
          "mat_id": expr_or_else(mat_id, "0"),
          "is_female": expr_or_else(
              is_female, "0", lambda x: hl.if_else(x, "2", "1")
          ),
          "pheno": expr_or_else(
              pheno,
              "NA",
              lambda x: hl.if_else(x, "2", "1")
              if x.dtype == tbool
              else hl.str(x),
          ),
      }
  
      locus = dataset.locus
      a = dataset.alleles
  
      bim_exprs = {
          "varid": expr_or_else(
              varid,
              hl.delimit(
                  [locus.contig, hl.str(locus.position), a[0], a[1]],
                  ":",
              ),
          ),
          "cm_position": expr_or_else(cm_position, 0.0),
      }
  
      for exprs, axis in [
          (fam_exprs, dataset._col_indices),
          (bim_exprs, dataset._row_indices),
          (entry_exprs, dataset._entry_indices),
      ]:
          for name, expr in exprs.items():
              analyze("export_plink/{}".format(name), expr, axis)
  
      dataset = dataset._select_all(
          col_exprs=fam_exprs,
          col_key=[],
          row_exprs=bim_exprs,
          entry_exprs=entry_exprs,
      )
  
      # check FAM ids for white space
      t_cols = dataset.cols()
      errors = []
      for name in ["ind_id", "fam_id", "pat_id", "mat_id"]:
          ids = t_cols.filter(t_cols[name].matches(r"\s+"))[
              name
          ].collect()
  
          if ids:
              errors.append(
                  f"""expr '{name}' has spaces in the following values:\n"""
              )
              for row in ids:
                  errors.append(f"""  {row}\n""")
  
      if errors:
          raise TypeError("\n".join(errors))
  
      writer = ir.MatrixPLINKWriter(output)
      Env.backend().execute(ir.MatrixWrite(dataset._mir, writer))
  
imports: import os
  import re
  from collections import defaultdict
  import avro.schema
  from avro.datafile import DataFileReader
  from avro.io import DatumReader
  import hail
  from hail import ir
  from hail.expr import StructExpression, LocusExpression, expr_array, expr_float64, expr_str, expr_numeric, expr_call, expr_bool, expr_int32, to_expr, analyze
  from hail.expr.types import hail_type, tarray, tfloat64, tstr, tint32, tstruct, tcall, tbool, tint64, tfloat32
  from hail.genetics.reference_genome import reference_genome_type
  from hail.ir.utils import parse_type
  from hail.matrixtable import MatrixTable
  from hail.methods.misc import require_biallelic, require_row_key_variant, require_col_key_str
  from hail.table import Table
  from hail.typecheck import typecheck, nullable, oneof, dictof, anytype, sequenceof, enumeration, sized_tupleof, numeric, table_key_type, char
  from hail.utils import new_temp_file
  from hail.utils.deduplicate import deduplicate
  from hail.utils.java import Env, FatalError, jindexed_seq_args, warning
  from hail.utils.java import info
  from hail.utils.misc import wrap_to_list, plural
  from .import_lines_helpers import split_lines, should_remove_line
label_desc: Use image node_id 5 for calling a global function with example usage: export_plink(dataset, output, call, fam_id, ind_id, pat_id, mat_id, is_female, pheno, varid, cm_position) without return types