> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/clara/parabricks/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/clara/parabricks/_mcp/server.

# minimap2

Run a GPU-accelerated minimap2.

This tool aligns long read sequences against a large reference database
using an accelerated KSW2 to convert FASTQ to BAM/CRAM.

Refer to the [minimap2 Reference](#options) section for a detailed listing of all available options.

## Quick Start

```sh
# This command assumes all the inputs are in the current working directory and all the outputs go to the same place.
docker run --rm --gpus all --volume $(pwd):/workdir --volume $(pwd):/outputdir \
    --workdir /workdir \
    nvcr.io/nvidia/clara/clara-parabricks:4.7.1-1 \
    pbrun minimap2 \
    --ref /workdir/${REFERENCE_FILE} \
    --in-fq /workdir/${INPUT_FASTQ} \
    --out-bam /outputdir/${OUTPUT_BAM}
```

## Compatible CPU-based minimap2, GATK4 Commands

The commands below are the minimap2-v2.30 and GATK4 counterpart of the Clara Parabricks command
above. The output from these commands will be identical to the output
from the above command.  Refer to the [Output Comparison](/about-parabricks/comparison-with-baseline-tools) page for
comparing the results. You may need to increase the Java heap size based on your dataset, or
decrease the number of --MAX\_RECORDS\_IN\_RAM.

```sh
# Run minimap2 and pipe the output to create a sorted BAM.
$ minimap2 -ax map-pbmm2 \
    <INPUT_DIR>/${REFERENCE_FILE} \
    <INPUT_DIR>/${INPUT_FASTQ} | \
  gatk SortSam \
    --java-options -Xmx30g \
    --MAX_RECORDS_IN_RAM 5000000 \
    -I /dev/stdin \
    -O cpu.bam \
    --SORT_ORDER coordinate
```

**Note that two changes must be made to the baseline minimap2 code in order to match
the results exactly:**

*Firstly*, a new preset must be made in `options.c` in the `mm_set_opt` function that
tries to replicate the preset of pbmm2 by setting these parameters as a new preset named "map-pbmm2":

```sh
io->k = 19;
io->w = 19;
io->batch_size = 0x7fffffffffffffffL; // always build a uni-part index
mo->flag |= MM_F_CIGAR;
mo->flag |= MM_F_SOFTCLIP;
mo->flag |= MM_F_LONG_CIGAR;
mo->flag |= MM_F_EQX;
mo->flag |= MM_F_NO_PRINT_2ND; // Allow secondaries with enforced mapping, but disable per default!
mo->zdrop = 400;
mo->zdrop_inv = 50;
mo->a = 1;
mo->b = 4;
mo->q = 6;
mo->q2 = 26;
mo->e = 2;
mo->e2 = 1;
mo->bw = 2000;
mo->max_gap = 10000;
mo->occ_dist = 500;
mo->min_mid_occ = 50;
mo->max_mid_occ = 500;
mo->min_dp_max = 500;
```

*Secondly*, a fix must be made to the baseline KSW2 code to round the loop fission start and end
points by changing them to `st` and `en` respectively. If the start point (`st0`)
is a number below 16, but greater than 0, its scoring values will not be initialized correctly, but
will still be used later when computing the actual alignment. This can be fixed by rounding the
start and end points to multiples of 16.

To make this fix, change the following code in `ksw2_extd2_sse.c`:

```sh
// loop fission: set scores first
if (!(flag & KSW_EZ_GENERIC_SC)) {
    for (t = st0; t <= en0; t += 16) {
        __m128i sq, st, tmp, mask;
        sq = _mm_loadu_si128((__m128i*)&sf[t]);
        st = _mm_loadu_si128((__m128i*)&qrr[t]);
        mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
        tmp = _mm_cmpeq_epi8(sq, st);
    #ifdef __SSE4_1__
                    tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
                    tmp = _mm_blendv_epi8(tmp,     sc_N_,   mask);
    #else
                    tmp = _mm_or_si128(_mm_andnot_si128(tmp,  sc_mis_), _mm_and_si128(tmp,  sc_mch_));
                    tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp),     _mm_and_si128(mask, sc_N_));
    #endif
                    _mm_storeu_si128((__m128i*)((int8_t*)s + t), tmp);
                }
            } else {
                for (t = st0; t <= en0; ++t)
                    ((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
            }
```

Fixed version that uses `lf_start` and `lf_en`:

```sh
// loop fission: set scores first
int lf_start = st, lf_en = en;
if (!(flag & KSW_EZ_GENERIC_SC)) {
    for (t = lf_start; t <= lf_en; t += 16) {
        __m128i sq, st, tmp, mask;
        sq = _mm_loadu_si128((__m128i*)&sf[t]);
        st = _mm_loadu_si128((__m128i*)&qrr[t]);
        mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
        tmp = _mm_cmpeq_epi8(sq, st);
    #ifdef __SSE4_1__
                    tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
                    tmp = _mm_blendv_epi8(tmp,     sc_N_,   mask);
    #else
                    tmp = _mm_or_si128(_mm_andnot_si128(tmp,  sc_mis_), _mm_and_si128(tmp,  sc_mch_));
                    tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp),     _mm_and_si128(mask, sc_N_));
    #endif
                    _mm_storeu_si128((__m128i*)((int8_t*)s + t), tmp);
                }
            } else {
                for (t = lf_start; t <= lf_en; ++t)
                    ((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
            }
```

## Options