gmx make_ndx Tutorial: Index Groups for Protein-Ligand MD

Run gmx make_ndx -f em.gro -o index.ndx, find the numbers of the Protein group and your ligand group in the printed list, type 1 | 13 (using your own numbers) to merge them into Protein_LIG, then type q to save. Pass the file to grompp with -n index.ndx whenever your .mdp names a custom group.
Most students meet gmx make_ndx at the worst possible moment. Energy minimisation finished, the NVT .mdp from a tutorial says tc-grps = Protein_LIG Water_and_ions, and grompp stops with a fatal error about a group that does not exist. The fix takes thirty seconds once you understand what an index file is, and the same tool then builds every analysis group you will need later: ligand heavy atoms for restraints, pocket residues for binding-site RMSD, and clean groups for MM-PBSA. This guide is written by the StemSkills Lab team, drawing on 10+ years in sequence and structural bioinformatics, drug discovery and design, and multiscale molecular modeling. It sits inside our pillar guide to learning molecular dynamics with GROMACS, and the computational biology skills roadmap shows where it fits in the wider skill path.
What is an index file in GROMACS, and when do you actually need one?
An index file (.ndx) is a plain-text list of named groups, each followed by the atom numbers that belong to it. Nothing about the physics lives there. It is simply a way to tell a GROMACS program which atoms you mean when you say “the protein” or “the ligand”.
You often do not need one at all. The official gmx make_ndx documentation states that GROMACS programs generate default groups on their own, and puts it bluntly: “You ONLY have to use gmx make_ndx when you need SPECIAL index groups.” According to the same page, the defaults are one group for the whole system, 9 groups for proteins (Protein, Protein-H, C-alpha, Backbone, MainChain, MainChain+Cb, MainChain+H, SideChain and SideChain-H), and one group for every other residue name. In a solvated system with counter-ions you also get groups such as non-Protein, Water, SOL, non-Water, Ion and Water_and_ions.
So the rule is simple. If a group you want is already in the default list, use it directly. If you need a combination that the defaults do not provide, such as protein plus ligand as one group, you build it with make_ndx and pass the resulting file to every program that has to see it.
| Group you need | Default or custom? | Typical use |
|---|---|---|
| Protein, Backbone, C-alpha | Default | RMSD fitting, RMSF, visual centring |
| LIG (your ligand residue name) | Default | Ligand RMSD, distances |
| Water_and_ions | Default (when water and ions exist) | Second thermostat group |
| Protein_LIG | Custom | tc-grps, centring the complex with trjconv, MM-PBSA |
| Ligand heavy atoms | Custom | Ligand position restraints with genrestr |
| Binding-pocket residues | Custom | Pocket RMSD, contact analysis |
How do you start gmx make_ndx and read the group list?
Run it on a coordinate file that contains your whole system. After energy minimisation that is usually em.gro:
gmx make_ndx -f em.gro -o index.ndxThe program prints the default groups with an index number and an atom count for each, followed by a command summary and a > prompt. The numbers depend on what is in your system, so always read them from your own screen rather than copying them from a tutorial. In a typical protein-ligand system the start of the list looks like this (atom counts removed, because yours will differ):
0 System
1 Protein
2 Protein-H
3 C-alpha
4 Backbone
...
13 LIG
...
Water_and_ionsYour ligand group carries whatever residue name the ligand has in the coordinate file: LIG, UNL, JZ4 or something else. If you are not sure, press Enter at the prompt to reprint the groups, or type l to list residues. Two facts from the built-in help (type h) prevent most beginner confusion: atom numbering starts at 1, and name matching is case-insensitive by default, which you can toggle with case.
How do you merge the protein and ligand into Protein_LIG?
At the prompt, combine the two groups with the OR operator and save:
> 1 | 13
> qGROMACS names the result after both inputs, joined by the _ character, so Protein OR LIG becomes a new group named Protein_LIG at the end of the list. That name is exactly what your .mdp expects if your ligand residue is called LIG. If your ligand is called UNL, the group will be Protein_UNL, and your .mdp must say that instead.
Then pass the index file to grompp for every step whose .mdp mentions the custom group:
gmx grompp -f nvt.mdp -c em.gro -r em.gro -p topol.top -n index.ndx -o nvt.tprThe matching .mdp lines couple the complex and the solvent to separate heat baths, with one tau-t and one ref-t value per group:
tcoupl = V-rescale
tc-grps = Protein_LIG Water_and_ions
tau-t = 0.1 0.1
ref-t = 300 300This two-group layout is common in course material, including our own protein-ligand MD simulation tutorial. It is not the only valid choice. The current .mdp files for Justin Lemkul’s widely used GROMACS protein-ligand complex tutorial set tc-grps = System, which needs no custom group at all. Whichever you choose, the groups must cover every atom exactly once. For what each temperature-coupling option does, see our guide to the GROMACS .mdp file.
What do the |, & and ! operators do in make_ndx?
The editor has three boolean operators, and they cover almost everything a protein-ligand workflow needs:
|(OR) takes atoms in either group.1 | 13gives protein plus ligand.&(AND) keeps only atoms present in both.4 & r 45-60gives backbone atoms of residues 45 to 60.!(NOT) takes the complement with respect to every atom in the input file.! 1gives everything that is not protein.
One detail catches people out. The built-in help says the input “is processed from left to right”, so there is no operator precedence and no brackets. The help’s own example, 2 | 4 & r 3-5, first merges groups 2 and 4 and then keeps residues 3 to 5 from the result. If you need a different order, build an intermediate group first, then combine it on the next line.
Besides group numbers, you can select atoms directly:
| Command | Selects | Example |
|---|---|---|
a | Atoms by number, range or name (a * wildcard is allowed at the end of a name) | a CA, a 1-250, a H* |
r | Residues by number, range or name | r 45-60, r LIG |
ri | Residue index, counted from 1 regardless of the numbering in the file | ri 1-10 |
chain | Chain identifier (not available when the input is a .gro file) | chain A |
t | Atom type (needs a .tpr as input) | t OW |
"name" | An existing group by quoted name instead of number | "Protein" | "LIG" |
The housekeeping commands are name nr newname to rename a group, del nr to delete one, keep nr to delete all others, and splitch, splitres and splitat to split a group into chains, residues or single atoms.
Want the guided, hands-on version?
Our live Molecular Modeling & MD Simulations cohort bootcamp takes you from zero to running real docking and MD workflows, with a portfolio project for your grad-school applications.
How do you make a ligand heavy-atom group for position restraints?
During NVT and NPT equilibration you usually restrain the ligand alongside the protein. The restraint file comes from gmx genrestr, and it needs a group containing only the ligand’s non-hydrogen atoms. Lemkul’s tutorial does this on the ligand’s own coordinate file, not on the full system:
gmx make_ndx -f jz4.gro -o index_jz4.ndx
> 0 & ! a H*
> q
gmx genrestr -f jz4.gro -n index_jz4.ndx -o posre_jz4.itp -fc 1000 1000 10000 & ! a H* reads as “the whole system, excluding atoms whose names start with H”. When genrestr asks for a group, pick the new one (the tutorial notes it is group 3 in that file). The force constant is 1000 kJ mol-1 nm-2 in x, y and z.
Running this on the ligand file matters. Position restraints in an .itp are numbered relative to the start of that molecule. If you build the heavy-atom group on em.gro instead, the atom numbers are offset by every protein atom in front of the ligand, and grompp rejects the file (see the troubleshooting section below). If hydrogen names in your ligand do not start with H, check them in the .gro file and adjust the pattern.
The ligand topology itself, and why its atom names must match the coordinates, is covered in how to parameterize a ligand for GROMACS.
How do you build a binding-pocket group for pocket or ligand RMSD?
Whole-protein RMSD can look stable while the binding site is rearranging. A pocket group lets you measure what actually matters for a docking-derived complex. There are two ways to build it.
By residue numbers in make_ndx
If you already know the pocket residues, for example from your docking interaction diagram, select them and intersect with the backbone:
gmx make_ndx -f em.gro -o index.ndx
> 1 | 13
> r 45-60 | r 88 | r 112
> name 25 Pocket
> 4 & "Pocket"
> qReplace 25 with the number make_ndx actually gives the new group. Two cautions apply. First, r uses the residue numbers stored in the file, so check that your numbering still matches the PDB after pdb2gmx. Second, the ligand also has a residue number; if it happens to fall inside your range, it will be pulled into the pocket group. Intersecting with Backbone (group 4 here) removes it, and 1 & r 45-60 would do the same while keeping side chains.
By distance with gmx select
If you would rather define the pocket geometrically, gmx select writes index groups too, and the make_ndx documentation notes it “covers nearly all of gmx make_ndx functionality”. The GROMACS selection syntax page gives this exact example for protein residues with at least one atom within 0.5 nm of a residue LIG:
gmx select -s em.gro -on pocket.ndx -select 'group "Protein" and same residue as within 0.5 of resname LIG'Run it on a single structure so the pocket is fixed. Given a trajectory, a distance-based selection is re-evaluated every frame, which is useful for contact analysis but not for a fixed reference group. Then combine the files: gmx make_ndx -f em.gro -n index.ndx pocket.ndx -o index_all.ndx, because -n accepts more than one index file.
With the groups in place, ligand RMSD after fitting on the protein backbone is one command. gmx rms asks first for the fitting group, then for the group to measure:
printf "Backbone\nLIG\n" | gmx rms -s md.tpr -f md_center.xtc -n index.ndx -tu ns -o ligand_rmsd.xvgGroup prompts accept a name as well as a number. Prepare md_center.xtc first, as described in our trjconv tutorial, and see how to analyze RMSD and RMSF for reading the curve.
How do you run make_ndx non-interactively in a script?
make_ndx reads its commands from standard input, so you can pipe them in. This is what you want on an HPC cluster, in a Colab notebook, or in any pipeline that runs more than one system:
printf '1 | 13\nq\n' | gmx make_ndx -f em.gro -o index.ndxHard-coded numbers break the moment a system has a different composition, for example an extra ion type that shifts every later group. Quoted names are sturdier, because the help says a quoted string is matched against the whole group name first, then the start of a name, then any substring:
printf '"Protein" | "LIG"\n"LIG" & ! a H*\nq\n' | gmx make_ndx -f em.gro -o index.ndxThe second line builds a ligand heavy-atom group in full-system numbering, which suits analysis. It is not the group for genrestr, which needs the ligand-only file shown earlier. The help also warns that “a multiple match is an error”, so if your list contains the same name twice, fall back to a number. After any scripted run, check the result instead of trusting it:
grep '^\[' index.ndxThat prints every group header in the file, so you can confirm that [ Protein_LIG ] exists before grompp needs it.
Why does grompp say my index group was not found, and how do you fix the other index errors?
These are the messages students send us most often at this step, with the cause and the fix for each. Wording can differ slightly between GROMACS versions.
“Group Protein_LIG referenced in the .mdp file was not found in the list of index groups”
Older versions say “not found in the index file”. The message itself explains that group names must match either moleculetype names or custom index groups, “in which case you must supply an index file to the ‘-n’ option of grompp”. There are three usual causes: you did not pass -n index.ndx, you never saved the group (quitting with Ctrl+C instead of q writes nothing), or the name differs, such as Protein_UNL in the file and Protein_LIG in the .mdp. Run grep '^\[' index.ndx and make the two names identical.
“Invalid T coupling input: 2 groups, 1 ref-t values and 1 tau-t values”
You added a second group to tc-grps but left one value in ref-t and tau-t. Give each group its own value, for example tau-t = 0.1 0.1 and ref-t = 300 300.
“N atoms are not part of any of the T-Coupling groups”
Your thermostat groups leave atoms out. The classic case is tc-grps = Protein_LIG SOL in a system that also contains NA or CL ions. Use Water_and_ions for the second group so that every atom is covered. If the system also holds cofactors or lipids, merge them into one of the two groups with |.
“Atom N in multiple T-Coupling groups”
The opposite problem: an atom sits in two thermostat groups. Pairing Protein_LIG with non-Protein does this, because the ligand is non-protein. Pair it with Water_and_ions instead.
“Atom index (N) in position_restraints out of bounds”
The ligand restraint file was generated from a group built on the full system, so its atom numbers point past the end of the ligand molecule. Rebuild the heavy-atom group on the ligand’s own .gro file and rerun genrestr, as shown above. Our common GROMACS errors guide covers the rest of the fatal errors you may meet in the same run.
Analysis tools pick the wrong atoms or refuse the index file
An index file is only valid for the exact atom ordering it was built from. If you rebuilt the system, added ions again, or wrote a trajectory containing only the protein and ligand, the old index.ndx no longer lines up. Build a fresh index file from a structure that matches the trajectory you are analysing, for example the first frame written by trjconv with the same output group.
Frequently asked questions
Do I have to run gmx make_ndx for every GROMACS simulation?
No. GROMACS creates default groups such as System, Protein, Backbone, Water_and_ions and one group per residue name automatically. You only need make_ndx when an .mdp or analysis needs a combined or custom group, such as Protein_LIG, ligand heavy atoms, or a binding-pocket selection.
Which file should I use as input for make_ndx?
Use a coordinate file with exactly the atoms and order of the simulation that will use the index, usually em.gro or npt.gro for setup and a matching structure for analysis. For ligand restraints, use the ligand’s own .gro file so atom numbers start at 1.
What is the difference between gmx make_ndx and gmx select?
make_ndx is an interactive editor using group numbers, atom or residue names, and the | & ! operators. gmx select uses a text selection language with distance and geometry keywords and can be scripted more cleanly. The GROMACS documentation describes gmx select as covering nearly all make_ndx functionality.
Why is my new group called Protein_UNL instead of Protein_LIG?
make_ndx names an OR group after both inputs, joined by the _ character, and your ligand residue is named UNL in the coordinate file. Either use Protein_UNL in the .mdp, or rename the group at the prompt with name nr Protein_LIG before saving.
Can I edit an existing index file instead of starting again?
Yes. Pass it with -n, for example gmx make_ndx -f em.gro -n index.ndx -o index_new.ndx. The existing groups load first and you add, rename or delete from there. Writing to a new output name keeps the original as a backup.
Where does this fit in your MD workflow?
Index groups sit between system building and equilibration, and they come back at every analysis step, including NVT and NPT equilibration and MM-PBSA binding free energy, which asks for separate receptor and ligand groups. For the reasoning behind these tools, the canonical references are the GROMACS paper by Abraham et al. (2015, SoftwareX) and Lemkul’s peer-reviewed tutorial collection, “From Proteins to Perturbed Hamiltonians” (Living Journal of Computational Molecular Science, 2019). When you are ready to put the full sequence together, return to the GROMACS learning pillar.
Want the guided, hands-on version?
Our live Molecular Modeling & MD Simulations cohort bootcamp takes you from zero to running real docking and MD workflows, with a portfolio project for your grad-school applications.
