docs: def parser(input_args=None):
      """
      Command line parser for *sick*.
      """
  
      parser = argparse.ArgumentParser(
          description="sick, the spectroscopic inference crank", epilog="Use "
              "'sick-model COMMAND -h' for information on a specific command."
              " Documentation and examples available at "
              "https://github.com/andycasey/sick")
  
      # Create a parent subparser.
      parent_parser = argparse.ArgumentParser(add_help=False)
      parent_parser.add_argument(
          "-v", "--verbose", dest="verbose", action="store_true", default=False,
          help="Vebose logging mode.")
      parent_parser.add_argument(
          "--clobber", dest="clobber", action="store_true", default=False, 
          help="Overwrite existing files if they already exist.")
      parent_parser.add_argument(
          "--debug", dest="debug", action="store_true", default=False,
          help="Enable debug mode. Any suppressed exception will be re-raised.")
      parent_parser.add_argument(
          "-o", "--output_dir", dest="output_dir", nargs="?", type=str,
          help="Directory for the files that will be created. If not given, this"
          " defaults to the current working directory.", default=os.getcwd())
  
      # Create subparsers.
      subparsers = parser.add_subparsers(title="command", dest="command",
          description="Specify the action to perform.")
  
      # Create parser for the aggregate command
      aggregate_parser = subparsers.add_parser(
          "aggregate", parents=[parent_parser],
          help="Aggregate many result files into a single tabular FITS file.")
      aggregate_parser.add_argument("output_filename", type=str, nargs=1,
          help="Output filename to aggregate results into.")
      aggregate_parser.add_argument("result_filenames", nargs="+",
          help="The YAML result filenames to combine.")
      aggregate_parser.set_defaults(func=aggregate)
  
      # Create parser for the estimate command
      estimate_parser = subparsers.add_parser(
          "estimate", parents=[parent_parser],
          help="Compute a point estimate of the model parameters given the data.")
      estimate_parser.add_argument(
          "model", type=str,
          help="The model filename in YAML-style formatting.")
      estimate_parser.add_argument(
          "spectrum_filenames", nargs="+",
          help="Filenames of (observed) spectroscopic data.")
      estimate_parser.add_argument(
          "--filename-prefix", "-p", dest="filename_prefix",
          type=str, help="The filename prefix to use for the output files.")
      estimate_parser.add_argument(
          "--no-plots", dest="plotting", action="store_false", default=True,
          help="Disable plotting.")
      estimate_parser.add_argument(
          "--plot-format", "-pf", dest="plot_format", action="store", type=str, 
          default="png", help="Format for output plots (default: %(default)s)")
      estimate_parser.add_argument(
          "-r", dest="read_from_filename", action="store", type=bool,
          default=False, help="Read spectrum paths from a filename.")
      estimate_parser.set_defaults(func=estimate)
  
      # Create parser for the optimise command
      optimise_parser = subparsers.add_parser(
          "optimise", parents=[parent_parser],
          help="Optimise the model parameters, given the data.")
      optimise_parser.add_argument(
          "model", type=str,
          help="The model filename in YAML-style formatting.")
      optimise_parser.add_argument(
          "spectrum_filenames", nargs="+",
          help="Filenames of (observed) spectroscopic data.")
      optimise_parser.add_argument(
          "--filename-prefix", "-p", dest="filename_prefix", type=str,
          help="The filename prefix to use for the output files.")
      optimise_parser.add_argument(
          "--no-plots", dest="plotting", action="store_false", default=True,
          help="Disable plotting.")
      optimise_parser.add_argument(
          "--plot-format", "-pf", dest="plot_format", action="store", type=str,
          default="png", help="Format for output plots (default: %(default)s)")
      optimise_parser.add_argument(
          "-r", dest="read_from_filename", action="store", type=bool,
          default=False, help="Read spectrum paths from a filename.")
      optimise_parser.set_defaults(func=optimise)
  
      # Create parser for the infer command
      infer_parser = subparsers.add_parser(
          "infer", parents=[parent_parser],
          help="Infer the model parameters, given the data.")
      infer_parser.add_argument(
          "model", type=str,
          help="The model filename in YAML-style formatting.")
      infer_parser.add_argument(
          "spectrum_filenames", nargs="+",
          help="Filenames of (observed) spectroscopic data.")
      infer_parser.add_argument(
          "--filename-prefix", "-p", dest="filename_prefix", type=str,
          help="The filename prefix to use for the output files.")
      infer_parser.add_argument(
          "--no-chains", dest="save_chain_files", action="store_false",
          default=True, help="Do not save the chains to disk.", )
      infer_parser.add_argument(
          "--no-plots", dest="plotting", action="store_false", default=True,
          help="Disable plotting.")
      infer_parser.add_argument(
          "--plot-format", "-pf", dest="plot_format", action="store", type=str,
          default="png", help="Format for output plots (default: %(default)s)")
      infer_parser.add_argument(
          "-r", dest="read_from_filename", action="store", type=bool,
          default=False, help="Read spectrum paths from a filename.")
      infer_parser.set_defaults(func=infer)
  
      args = parser.parse_args(input_args)
      logger.setLevel(logging.DEBUG if args.verbose else logging.INFO)
  
      # Check plot formats.
      if args.command.lower() in ("estimate", "optimise", "infer") \
      and args.plotting:
  
          import matplotlib.pyplot as plt
          fig = plt.figure()
          available = fig.canvas.get_supported_filetypes().keys()
          plt.close(fig)
  
          if args.plot_format.lower() not in available:
              raise ValueError("plotting format {0} is unavailable: Options are:"\
                  " {1}".format(args.plot_format.lower(), ", ".join(available)))
  
      # Create a default filename prefix based on the input filename arguments
      if args.command.lower() in ("estimate", "optimise", "infer") \
      and args.filename_prefix is None \
      and not args.read_from_filename:
          args.filename_prefix = _default_output_prefix(args.spectrum_filenames)
  
          handler = logging.FileHandler("{}.log".format(
              os.path.join(args.output_dir, args.filename_prefix)))
          formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
          handler.setFormatter(formatter)
          logger.addHandler(handler)
  
      else:
          args.filename_prefix = ""
  
      return args