<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _sam_to_grouped_umi_cl(data, umi_consensus, tx_out_file):
 """Mark duplicates on aligner output and convert to grouped UMIs by position. Works with either a separate umi_file or UMI embedded in the read names. """

    tmp_file = "%s-sorttmp" % utils.splitext_plus(tx_out_file)[0]
    jvm_opts = _get_fgbio_jvm_opts(data, os.path.dirname(tmp_file), 1)
    cores, mem = _get_cores_memory(data)
    bamsormadup = config_utils.get_program("bamsormadup", data)
    cmd = ("{bamsormadup} tmpfile={tmp_file}-markdup inputformat=sam threads={cores} outputformat=bam "
           "level=0 SO=coordinate | ")
    # UMIs in a separate file
    if os.path.exists(umi_consensus) and os.path.isfile(umi_consensus):
        cmd += "fgbio {jvm_opts} AnnotateBamWithUmis -i /dev/stdin -f {umi_consensus} -o {tx_out_file}"
    # UMIs embedded in read name
    else:
        cmd += ("%s %s bamtag - | samtools view -b > {tx_out_file}" %
                (utils.get_program_python("umis"),
                 config_utils.get_program("umis", data["config"])))
    return cmd.format(**locals())