How FirstGlance in Jmol Defines Conformations.
New in FirstGlance version 4.3. (The version 4.3 release included all version 4.2 updates mentioned below.)


Background
Terminology
Rules for Conformations
Atoms in Common
Definitions of Conformations  
EXAMPLES
Technical & Jmol Code


Background. Before continuing below, you may want to review these introductions to alternate locations in PDB files: The Alternate Locations Server created by Jaime Prilusky has been indispensible to the development of FirstGlance.

Terminology. An atom is, for example, the beta carbon of an amino acid, such as Arg1098:A.CB in 1zir. One atom can have multiple alternate locations, each with distinct XYZ coordinates. Alternate locations for an atom are distinguished by alternate location (altloc) codes or symbols. In the case just mentioned, those are Q and R, or %Q and %R in Jmol syntax: Arg1098:A.CB%Q and Arg1098:A.CB%R.

Rules for Conformations. FirstGlance versions 4.2 and later use the following rules when defining conformations based upon alternate locations:
  1. The number of conformations that FirstGlance offers to display is the highest number of alternate locations (altlocs) specified for any atom. As explained in the Notes, this is far fewer than the number of conformations of which the molecule is actually capable. Each alternate location of a given atom is present in a distinct FirstGlance conformation.

  2. Each conformation includes one location for every atom in the model. Thus, all conformations have the same number of atoms.

  3. The number of conformations reported by FirstGlance is independent of the number of distinct altloc marking symbols utilized in the PDB file. An extreme example is 1zir, which uses 22 symbols to mark altlocs, A-V. However, no atom has more than two locations, so FirstGlance reports that there are 2 conformations.

  4. Conformations are defined independently of which altloc marking symbols are used on specific atoms. The first location of an atom is most often marked A, and the second B. But in 3eoj (asymmetric unit), the sidechain of Arg125 has two locations marked A and C. (These atoms have no locations marked B.) In 5pog, first locations are marked A or E, and second locations B or F. Eight atoms are marked C but have only one location. And in 3pga, first locations are marked C, and second locations O.

  5. Conformation 1 includes the first location given in the PDB file for each atom that has multiple locations. Omitting any of these first locations would leave an incomplete model. For example, in 1zir, the first locations for the sidechain atoms in Arg1098 are marked with altloc code Q (and the second locations with R). Omitting the Q locations from conformation 1 would leave Arg1098 without a sidechain. FirstGlance determines the first through Nth locations for all atoms with multiple locations.

  6. Quite often PDB files have atoms marked with an altloc symbol that nevertheless have only a single location (" Singletons"). These atoms are common to all conformations. FirstGlance gathers these in the Jmol variable locsPerAtomBitset[1].
Atoms in common are atoms common to all conformations. They include:
  1. Atoms without altloc marking symbols. These have a single location/atom, and are common to all conformations. (Jmol: {altloc=""} which is the same as {%})
  2. Atoms marked with altloc symbols that nevertheless have only a single location (a single set of XYZ coordinates). (FirstGlance gathers these in Jmol variable @{locsPerAtomBitset[1]}.)
In Jmol, the atoms in common are {% | @{locsPerAtomBitset[1]}}, the latter variable defined by FirstGlance.

Definitions of Conformations. The conformations used by FirstGlance are defined as follows. These definitions are independent of the number of altloc marking symbols used, and independent of which symbols mark particular atoms (see examples above). Examples

The following examples compare the tabular alternate location reports in FirstGlance versions 4.1 vs. 4.2. Version 4.1 had a number of bugs because it used Jmol's definitions of "config=N", rather than the ones later implemented in FirstGlance as described above. Version 4.2 tabulates additional details.
Links to PDB entries at the tops of each pair of snapshots are live. Links within the snapshots do NOT work here, but work in FirstGlance.

3eoj asymmetric unit
Version 4.1

In 4.1, some counts of atom locations were erroneously low. Altlocs E and F have 2 locations/atom but are not listed.
Version 4.2


1zir
Version 4.1

Counts in 4.1 were correct. 4.2 adds links to identify first and second locations regardless of the altloc symbol marks.
Version 4.2


5pog
Version 4.1

Counts in 4.1 were correct. 4.2 adds links to identify first and second locations regardless of the altloc symbol marks.
Version 4.2


5qye
Version 4.1

4.1 did not accommodate 6 locations/atom. Counts in 4.1 were correct. 4.2 adds links to identify first and second locations regardless of the altloc symbol marks.
Version 4.2


6ss1 asymmetric unit
Version 4.1

In 4.1, some counts of atom locations were erroneously zero. 4.2 adds links to identify first and second locations regardless of the altloc symbol marks.
Version 4.2


Technical & Jmol Code

The Jmol bitsets defined by FirstGlance that contain conformations 1-6 are conf[1] through conf[6]. In addition to the atoms in common (see above), they include the first (atomNthLocs[1]) through 6th (atomNthLocs[6]) locations/atom, plus the locations of atoms not represented at each level (atomsNotRepIn[N]). FirstGlance defines altlocMultBitset to include all locations of atoms with multiple locations, and locsPerAtomBitset[N] to include all locations of atoms with N locations (N being 1-6). All these variables are defined in Jmol function altloc1() defined by FirstGlance in util.js. That function goes through three stages:
  1. Finding the number of locations/atom, defining locsPerAtomBitset[N], and defining Javascript variable configCount (Jmol ~configCount) as the largest number of locations/atom. This is the total number of conformations as defined in FirstGlance.
  2. Gathering the Nth locations of atoms with 1, 2, 3 ... 6 locations each into the Jmol variables atomNthLocs[N].
  3. Finding the atoms not represented in conformations 3-6, atomsNotRepIn[N]. Once these are gathered, the conformations, Jmol bitsets conf[N] (N = 1 through ~configCount), are defined. To select the locations of atoms in conformation 1, the Jmol syntax is select @{conf[1]}.
The first implementation by Eric Martz was sluggish as shown in the "Eric" column. Bob Hanson made some improvements to Jmol and suggested a much more efficient code, with the results in the "Bob" column. Bob's code (below) is in version 4.2.

Times the code below requires on a 2015 MacBook Pro:
                                        Eric     Bob
PDB   Assy   MLALC     TotALC   TotLocs Seconds  Seconds
2f03  AU          0     4,912    4,912    2       2
3eoj  AU        769       927    4,115    3
5sop  BU1     2,755     2,826    4,266    7
1cm4          5,032     5,048    5,107   13       6
7Lb6            960    47,760   47,760   17       8
4nia  AU      2,931    10,174   28,403   28       5
4oq9  AU      2,671    10,293   29,296   33       6
6sry  AU     11,212    11,420   15,615   72      10
2v97         17,030    18,791   18,979  134      13
Assy: AU Asymmetric Unit; BU1 Biological Unit 1; Blank when AU = BU1.
MLALC Multiple Location AltLoc Codes
TotALC Total AltLoc Codes
TotLocs Total Locations
Simplification, when offered, must be declined in order to work with altlocs.


CODE IN VERSION 4.2 (COMPARE WITH THAT IN util.js FOR ANY LATE CHANGES): conf = []; altLocAtoms = {}; // associative array { "[SER]22:B.OG" : ({984 985}), ...} locsPerAtomBitset = []; atomNthLocs = []; // array of bitsets configCap = 6; // maximum number of configs function altLoc1() { ~configCount = 1; # BOB'S CODE # GET LOCATIONS/ATOM # Atoms with altloc codes but only a single location. locsPerAtomBitset[1] = {config=0 and altloc != ""}; # Locations for atoms with multiple locations/atom. altLocMultBitset = {%? and not config=0}; # All multiple locations. # Get associative array altLocAtoms[] { "[SER]22:B.OG" : ({984 985}), ...} for (var ata in altLocMultBitset) { var atname = ata.atom; if (altLocAtoms[atname] == null) { altLocAtoms[atname] = ({}); } altLocAtoms[atname] |= ata.atomIndex; } # Get locations for atoms with exactly 2, 3, 4, 5, 6 locations/atom. # and get ~configCount for (var key in altlocAtoms.keys) { var locs = altlocAtoms[key]; var len = locs.length; if (len > configCap) { javascript locsPerAtomExceedsCap = true; len = configCap; } if (locsPerAtomBitset[len] == null) {locsPerAtomBitset[len] = ({})}; locsPerAtomBitset[len] |= locs; if (len > ~configCount) ~configCount = len; } # Initialize array of bitsets for (var nth = 1; nth <= configCap; nth++) {atomNthLocs[nth] = ({});} # ERIC'S CODE USING BOB'S ADVICE # Get atomNthLocs[N]. N=1=1st locs of multiple loc atoms. N=2=2nd locs of multiloc atoms. for (var atname in altLocAtoms) // { "[SER]22:B.OG" : ({984 985}), ...} { // atname is an atom var locs = altLocAtoms[atname]; // bitset of altlocs for this atom var lpa = locs.length; // lpa = locs/atom. # if (lpa == 1) {continue} // we have already eliminated singletons in altLocAtoms[]. if (lpa > configCap) { javascript locsPerAtomExceedsCap = true; lpa = configCap; // Put 7th+ locations in 6th locations. No known cases. } for (var bsn = 1; bsn <= lpa; bsn++) { atomNthLocs[bsn] |= altLocAtoms[atname][bsn]; } } # ERIC'S CODE // DEFINE CONFORMATIONS AND ATOMS-NOT-REPRESENTED-IN[N] conf[1] = {%} or locsPerAtomBitset[1] or atomNthLocs[1]; conf[2] = {%} or locsPerAtomBitset[1] or atomNthLocs[2]; for (i=3; i <=~configCount; i++) { # For each configuration >2, get fill-in atoms atomsNotRepIn[N] getNotRep(i); # populates atomsNotRepIn[N] } if (~configCount >= 4) {atomsNotRepIn[4] |= atomsNotRepIn[3];} if (~configCount >= 5) {atomsNotRepIn[5] |= atomsNotRepIn[4];} if (~configCount >= 6) {atomsNotRepIn[6] |= atomsNotRepIn[5];} for (i=3; i <=~configCount; i++) { conf[i] = {%} or locsPerAtomBitset[1] or atomNthLocs[i] or atomsNotRepIn[i]; // syntax: select {@{conf[1]}} } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - atomsNotRepIn = []; # ERIC'S CODE function getNotRep(lvl) { byseq = []; # Load byseq with (lvl)th locs of multloc atom labels at each sequence number. # For 3eoj AU this is 17 locations. for (var i in atomNthLocs[lvl]) { atseq = i.label("%r"); if (byseq[atseq].type == "string") byseq[atseq] = []; byseq[atseq].push(i.label("[%n]%r:%c.%a")); } # 2. GATHER BITSET OF lvl-1 LOCS (376 MULTLOC IN 3EOJ) NOT REPRESENTED at lvl (359 3EOJ). atomsNotRepIn[lvl] = {none}; for (var i in atomNthLocs[lvl-1]) { atseq = i.label("%r"); # resno==sequence number. if (atseq > byseq.length || byseq[atseq].type != "array") # no atseq element in byseq. { # print "Skipping " + atseq; # atomsNotRepIn[lvl].push(i) PUSH DOES NOT WORK FOR BITSETS atomsNotRepIn[lvl] |= i; continue; } # print "------------ Doing " + atseq; addme = i.label("[%n]%r:%c.%a"); for (var j in byseq[atseq]) # i=atomindex, j=atomlabel. { #print "" + addme + " / " + j if (addme == j) {#print "Rep " + addme; addme = ""; break;} } if (addme) {#print "NotRep " + addme; atomsNotRepIn[lvl] |= i;} } }

Suggestions for clarification or improvements are always welcome.
Feedback to