for(k=0; (k<4); k++,j++) anm[k]=line[j];
anm[k]=nc;
strcpy(anm_copy,anm);
+ rtrim(anm_copy);
atomnumber = NOTSET;
trim(anm);
altloc=line[j];
int type; /* PDB record name */
int atomnr; /* PDB atom number */
char altloc; /* Alternate location indicator */
- char atomnm[6]; /* True atom name including spaces */
+ char atomnm[6]; /* True atom name including leading spaces */
real occup; /* Occupancy */
real bfac; /* B-factor */
gmx_bool bAnisotropic; /* (an)isotropic switch */
"[TT]charge -1 to -0.7[tt][BR]",
"result in a syntax error. A workaround is to write[BR]",
"[TT]charge {-1 to -0.7}[tt][BR]",
- "instead.",
+ "instead.[PAR]",
+
+ "When [TT]name[tt] selection keyword is used together with PDB input",
+ "files, the behavior may be unintuitive. When Gromacs reads in a PDB",
+ "file, 4 character atom names that start with a digit are transformed",
+ "such that, e.g., 1HG2 becomes HG21, and the latter is what is matched",
+ "by the [TT]name[tt] keyword. Use [TT]pdbname[tt] to match the atom name",
+ "as it appears in the input PDB file.",
};
struct PositionsHelpText
{
public:
//! Initialize help topic for the given selection method.
- explicit KeywordDetailsHelpTopic(const gmx_ana_selmethod_t &method)
- : method_(method)
+ KeywordDetailsHelpTopic(const std::string &name,
+ const gmx_ana_selmethod_t &method)
+ : name_(name), method_(method)
{
}
virtual const char *name() const
{
- return method_.name;
+ return name_.c_str();
}
virtual const char *title() const
{
}
private:
+ std::string name_;
const gmx_ana_selmethod_t &method_;
GMX_DISALLOW_COPY_AND_ASSIGN(KeywordDetailsHelpTopic);
methods_.push_back(std::make_pair(std::string(symname), method));
if (method->help.nlhelp > 0 && method->help.help != NULL)
{
- addSubTopic(HelpTopicPointer(new KeywordDetailsHelpTopic(*method)));
+ addSubTopic(HelpTopicPointer(
+ new KeywordDetailsHelpTopic(symname, *method)));
}
++symbol;
}
extern gmx_ana_selmethod_t sm_resindex;
extern gmx_ana_selmethod_t sm_molindex;
extern gmx_ana_selmethod_t sm_atomname;
+extern gmx_ana_selmethod_t sm_pdbatomname;
extern gmx_ana_selmethod_t sm_atomtype;
extern gmx_ana_selmethod_t sm_resname;
extern gmx_ana_selmethod_t sm_insertcode;
{"molecule", &sm_molindex},
{NULL, &sm_atomname},
{"name", &sm_atomname},
+ {NULL, &sm_pdbatomname},
+ {"pdbname", &sm_pdbatomname},
{NULL, &sm_atomtype},
{"type", &sm_atomtype},
{NULL, &sm_resname},
#include <config.h>
#endif
+#include <cctype>
+
+#include "gromacs/legacyheaders/macros.h"
+
#include "gromacs/selection/position.h"
#include "gromacs/selection/selmethod.h"
#include "gromacs/utility/exceptions.h"
static void
evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p pdbatomname selection keyword. */
+static void
+evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
/** Checks whether atom types are present in the topology. */
static void
check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+/** Help text for atom name selection keywords. */
+static const char *help_atomname[] = {
+ "ATOM NAME SELECTION KEYWORDS[PAR]",
+
+ "[TT]name[tt] [TT]pdbname[tt] [TT]atomname[tt] [TT]pdbatomname[tt][PAR]",
+
+ "These keywords select atoms by name. [TT]name[tt] selects atoms using",
+ "the Gromacs atom naming convention.",
+ "For input formats other than PDB, the atom names are matched exactly",
+ "as they appear in the input file. For PDB files, 4 character atom names",
+ "that start with a digit are matched after moving the digit to the end",
+ "(e.g., to match 3HG2 from a PDB file, use [TT]name HG23[tt]).",
+ "[TT]pdbname[tt] can only be used with a PDB input file, and selects",
+ "atoms based on the exact name given in the input file, without the",
+ "transformation described above.[PAR]",
+
+ "[TT]atomname[tt] and [TT]pdbatomname[tt] are synonyms for the above two",
+ "keywords."
+};
+
/** \internal Selection method data for \p all selection keyword. */
gmx_ana_selmethod_t sm_all = {
"all", GROUP_VALUE, 0,
NULL,
&evaluate_atomname,
NULL,
+ {NULL, asize(help_atomname), help_atomname}
+};
+
+/** \internal Selection method data for \p pdbatomname selection keyword. */
+gmx_ana_selmethod_t sm_pdbatomname = {
+ "pdbatomname", STR_VALUE, SMETH_REQTOP,
+ 0, NULL,
+ NULL,
+ NULL,
+ &check_pdbinfo,
+ NULL,
+ NULL,
+ NULL,
+ &evaluate_pdbatomname,
+ NULL,
+ {NULL, asize(help_atomname), help_atomname}
};
/** \internal Selection method data for \p atomtype selection keyword. */
}
}
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the PDB atom name for each atom in \p out->u.s.
+ */
+static void
+evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+ gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+ int i;
+
+ out->nr = g->isize;
+ for (i = 0; i < g->isize; ++i)
+ {
+ char *s = top->atoms.pdbinfo[g->index[i]].atomnm;
+ while (std::isspace(*s))
+ {
+ ++s;
+ }
+ out->u.s[i] = s;
+ }
+}
+
/*!
* \param[in] top Topology structure.
* \param npar Not used.
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <ParsedSelections Name="Parsed">
+ <ParsedSelection Name="Selection1">
+ <String Name="Input">name HG21</String>
+ <String Name="Name">name HG21</String>
+ <String Name="Text">name HG21</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection2">
+ <String Name="Input">name 1HG2</String>
+ <String Name="Name">name 1HG2</String>
+ <String Name="Text">name 1HG2</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection3">
+ <String Name="Input">pdbname HG21 CB</String>
+ <String Name="Name">pdbname HG21 CB</String>
+ <String Name="Text">pdbname HG21 CB</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ <ParsedSelection Name="Selection4">
+ <String Name="Input">pdbatomname 1HG2</String>
+ <String Name="Name">pdbatomname 1HG2</String>
+ <String Name="Text">pdbatomname 1HG2</String>
+ <Bool Name="Dynamic">false</Bool>
+ </ParsedSelection>
+ </ParsedSelections>
+ <CompiledSelections Name="Compiled">
+ <Selection Name="Selection1">
+ <Sequence Name="Atoms">
+ <Int Name="Length">2</Int>
+ <Int>4</Int>
+ <Int>7</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection2">
+ <Sequence Name="Atoms">
+ <Int Name="Length">0</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection3">
+ <Sequence Name="Atoms">
+ <Int Name="Length">7</Int>
+ <Int>0</Int>
+ <Int>3</Int>
+ <Int>6</Int>
+ <Int>7</Int>
+ <Int>9</Int>
+ <Int>12</Int>
+ <Int>15</Int>
+ </Sequence>
+ </Selection>
+ <Selection Name="Selection4">
+ <Sequence Name="Atoms">
+ <Int Name="Length">1</Int>
+ <Int>4</Int>
+ </Sequence>
+ </Selection>
+ </CompiledSelections>
+</ReferenceData>
runTest("simple.gro", selections);
}
+TEST_F(SelectionCollectionDataTest, HandlesPdbAtomname)
+{
+ static const char * const selections[] = {
+ "name HG21",
+ "name 1HG2",
+ "pdbname HG21 CB",
+ "pdbatomname 1HG2",
+ NULL
+ };
+ runTest("simple.pdb", selections);
+}
+
// TODO: Add test for atomtype
TEST_F(SelectionCollectionDataTest, HandlesChain)
ATOM 2 S1 RA A 1 10.000 20.000 0.000 1.00 0.00
ATOM 3 S2 RA A 1 10.000 30.000 0.000 1.00 0.00
ATOM 4 CB RB A 2 10.000 40.000 0.000 1.00 0.50
-ATOM 5 S1 RB A 2 20.000 10.000 0.000 1.00 0.50
-ATOM 6 S2 RB A 2 20.000 20.000 0.000 1.00 0.50
+ATOM 5 1HG2 RB A 2 20.000 10.000 0.000 1.00 0.50
+ATOM 6 2HG2 RB A 2 20.000 20.000 0.000 1.00 0.50
ATOM 7 CB RA B 1 20.000 30.000 0.000 1.00 0.00
-ATOM 8 S1 RA B 1 20.000 40.000 0.000 1.00 0.30
-ATOM 9 S2 RA B 1 30.000 10.000 0.000 1.00 0.30
+ATOM 8 HG21 RA B 1 20.000 40.000 0.000 1.00 0.30
+ATOM 9 HG22 RA B 1 30.000 10.000 0.000 1.00 0.30
ATOM 10 CB RC B 1A 30.000 20.000 0.000 1.00 0.00
ATOM 11 S1 RC B 1A 30.000 30.000 0.000 1.00 0.00
ATOM 12 S2 RC B 1A 30.000 40.000 0.000 1.00 0.30