code: def align_bam(in_bam, ref_file, names, align_dir, data):
      
      config = data["config"]
      out_file = os.path.join(align_dir, "{0}-sort.bam".format(names["lane"]))
      novoalign = config_utils.get_program("novoalign", config)
      samtools = config_utils.get_program("samtools", config)
      resources = config_utils.get_resources("novoalign", config)
      num_cores = config["algorithm"].get("num_cores", 1)
      max_mem = resources.get("memory", "4G").upper()
      extra_novo_args = " ".join(_novoalign_args_from_config(config, False))
  
      if not file_exists(out_file):
          with tx_tmpdir(data, base_dir=align_dir) as work_dir:
              with postalign.tobam_cl(data, out_file, bam.is_paired(in_bam)) as (tobam_cl, tx_out_file):
                  rg_info = get_rg_info(names)
                  tx_out_prefix = os.path.splitext(tx_out_file)[0]
                  prefix1 = "%s-in1" % tx_out_prefix
                  cmd = ("unset JAVA_HOME && "
                         "{samtools} sort -n -o -l 1 -@ {num_cores} -m {max_mem} {in_bam} {prefix1} "
                         "| {novoalign} -o SAM '{rg_info}' -d {ref_file} -f /dev/stdin "
                         "  -F BAMPE -c {num_cores} {extra_novo_args} | ")
                  cmd = (cmd + tobam_cl).format(**locals())
                  do.run(cmd, "Novoalign: %s" % names["sample"], None,
                         [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, in_bam)])
      return out_file
docs: Perform realignment of input BAM file; uses unix pipes for avoid IO.