text: #!/usr/bin/python
  
  # Copyright (C) 2002, Thomas Hamelryck (thamelry@vub.ac.be)
  # This code is part of the Biopython distribution and governed by its
  # license.  Please see the LICENSE file that should have been included
  # as part of this package.
  
  """Calculates solvent exposure for a PDB file using one of 5 different methods.
  
      -DSSP (DSSP needs to be installed)
      -Residue depth (MSMS needs to be installed)
      -Coordination number (ie. number of CA atoms within a sphere)
      -HSEalpha half sphere exposure
      -HSEbeta half sphere exposure
  
  A PDB file can be written out with the exposure in the B factor field.
  See --help for all args.
  """
  
  
  import argparse
  import sys
  
  from Bio.PDB import (
      DSSP,
      ExposureCN,
      HSExposureCA,
      HSExposureCB,
      PDBParser,
      PDBIO,
      ResidueDepth,
      Selection,
  )
  
  ap = argparse.ArgumentParser(description=__doc__)
  ap.add_argument("pdbfile", help="Input structure in PDB format.")
  ap.add_argument(
      "-t",
      "--type",
      dest="exp",
      choices=["HSEAU", "HSEAD", "HSEBU", "HSEBD", "CN", "DSSPr", "DSSPa", "RD", "RDa"],
      help="Exposure Type",
      default="HSEb",
  )
  ap.add_argument(
      "-o", "--out", dest="outfile", help="output to PDB file (B factor=exposure)",
  )
  ap.add_argument(
      "-r",
      "--radius",
      dest="radius",
      type=float,
      help="sphere radius (default 13.0 A)",
      default=13.0,
  )
  ap.add_argument(
      "-m",
      "--model",
      dest="model",
      type=int,
      help="PDB model number (default 0)",
      default=0,
  )
  ap.add_argument("--dssp", help="Path to the DSSP executable", default="dssp")
  ap.add_argument("--msms", help="Path to the MSMS executable", default=None)
  args = ap.parse_args()
  
  # Get the structure
  p = PDBParser()
  s = p.get_structure("X", args.pdbfile)
  
  # First model by default
  m = s[args.model]
  
  RADIUS = args.radius
  
  # d=dictionary of exposures
  # k=position in ntuple containing the desired exposure
  
  format = "%4i"
  
  args.exp = args.exp.upper()
  
  if args.exp[0] == "H" and args.exp[3] == "A":
      hse = HSExposureCA(m, RADIUS)
      if args.exp[-1] == "D":
          k = "EXP_HSE_A_D"
      else:
          k = "EXP_HSE_A_U"
  elif args.exp[0] == "H" and args.exp[3] == "B":
      hse = HSExposureCB(m, RADIUS)
      # hse.write_pymol_script()
      if args.exp[-1] == "D":
          k = "EXP_HSE_B_U"
      else:
          k = "EXP_HSE_B_D"
  elif args.exp == "CN":
      hse = ExposureCN(m, RADIUS)
      k = "EXP_CN"
  elif args.exp == "ANGLE":
      hse = HSExposureCA(m, RADIUS)
      k = "EXP_CB_PCB_ANGLE"
      format = "%4.1f"
  elif args.exp == "DSSPR":
      d = DSSP(m, args.pdbfile, dssp=args.dssp)
      k = "EXP_DSSP_RASA"
      format = "%.4f"
  elif args.exp == "DSSPA":
      d = DSSP(m, args.pdbfile, dssp=args.dssp)
      k = "EXP_DSSP_ASA"
  elif args.exp == "RD":
      d = ResidueDepth(m, args.pdbfile, msms_exec=args.msms)
      k = "EXP_RD"
      format = "%4.1f"
  elif args.exp == "RDA":
      d = ResidueDepth(m, args.pdbfile, msms_exec=args.msms)
      k = "EXP_RD_CA"
      format = "%4.1f"
  else:
      print("ERROR: Unknown option.")
      sys.exit()
  
  residue_list = Selection.unfold_entities(m, "R")
  
  for r in residue_list:
  
      if k in r.xtra:
  
          exposure = r.xtra[k]
  
          if args.exp == "DSSPR":
              # to 0=exposed, 1=buried
              exposure = 1 - exposure
  
          # Print info
          hetflag, resseq, icode = r.get_id()
  
          if icode == " ":
              icode = "_"
  
          resname = r.get_resname()
  
          print(("%s %4i %c\t" + format) % (resname, resseq, icode, exposure))
      else:
          exposure = 0.0
  
      for atom in r.get_iterator():
          atom.set_bfactor(exposure)
  
  if args.outfile:
      io = PDBIO()
      io.set_structure(s)
      io.save(args.outfile)
  