icn3d 3.54.6 → 3.54.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/icn3d.js +480 -297
  2. package/icn3d.min.js +12 -6
  3. package/icn3d.module.js +480 -297
  4. package/package.json +1 -1
package/icn3d.js CHANGED
@@ -179,7 +179,8 @@ $NGL_shaderTextHash['SphereImpostor.frag'] = ["#define STANDARD",
179
179
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
180
180
  " #endif",
181
181
  " #ifdef FOG_EXP2",
182
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
182
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
183
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
183
184
  " #else",
184
185
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
185
186
  " #endif",
@@ -643,7 +644,8 @@ $NGL_shaderTextHash['CylinderImpostor.frag'] = ["#define STANDARD",
643
644
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
644
645
  " #endif",
645
646
  " #ifdef FOG_EXP2",
646
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
647
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
648
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
647
649
  " #else",
648
650
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
649
651
  " #endif",
@@ -2613,13 +2615,33 @@ var CIFTools;
2613
2615
  /**
2614
2616
  * Options for filling the unit cell of a core CIF by lattice translation
2615
2617
  * (applied after the symmetry operators have generated the contents of one cell).
2616
- * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2617
- * boundary : also emit the periodic image of every atom lying on a cell face/edge/corner
2618
- * (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl); default true.
2619
- * Set to false to get the original behavior (atoms wrapped into [0,1) only).
2620
- * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, boundary: true};
2618
+ * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2619
+ * wholeMolecules : keep every molecule / discrete chemical species intact. Atoms are grouped into
2620
+ * bonded fragments (covalent radii + bondTolerance, periodic), each fragment is
2621
+ * "unwrapped" so that it is contiguous (it may stick out of the unit cell), and the
2622
+ * fragment is placed in the cell that contains its centre. Fragments that are
2623
+ * infinite (chains, layers, frameworks, ionic lattices such as NaCl) cannot be made
2624
+ * whole and are handled as before (wrapped into the cell, see 'boundary'). default true
2625
+ * bondTolerance : extra distance (Angstrom) added to the sum of covalent radii when detecting bonds; default 0.4
2626
+ * boundary : for atoms that are NOT part of a whole molecule, also emit the periodic image of every
2627
+ * atom lying on a cell face/edge/corner (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl);
2628
+ * default true.
2629
+ * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, wholeMolecules: true};
2621
2630
  */
2622
- Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true };
2631
+ Text.coreCifOptions = {
2632
+ nx: 1, ny: 1, nz: 1,
2633
+ wholeMolecules: true, // new; set false for the old wrapped behaviour
2634
+ bondTolerance: 0.4, // new; raise it if bonds are missed, lower it if unrelated atoms get joined, default 0.4
2635
+ boundary: true
2636
+ };
2637
+ // covalent radii (Angstrom, Cordero et al. 2008) used for bond detection
2638
+ var coreCovRadii = { H: 0.31, D: 0.31, He: 0.28, Li: 1.28, Be: 0.96, B: 0.84, C: 0.76, N: 0.71, O: 0.66, F: 0.57, Ne: 0.58,
2639
+ Na: 1.66, Mg: 1.41, Al: 1.21, Si: 1.11, P: 1.07, S: 1.05, Cl: 1.02, Ar: 1.06, K: 2.03, Ca: 1.76, Sc: 1.70, Ti: 1.60, V: 1.53,
2640
+ Cr: 1.39, Mn: 1.39, Fe: 1.32, Co: 1.26, Ni: 1.24, Cu: 1.32, Zn: 1.22, Ga: 1.22, Ge: 1.20, As: 1.19, Se: 1.20, Br: 1.20, Kr: 1.16,
2641
+ Rb: 2.20, Sr: 1.95, Y: 1.90, Zr: 1.75, Nb: 1.64, Mo: 1.54, Tc: 1.47, Ru: 1.46, Rh: 1.42, Pd: 1.39, Ag: 1.45, Cd: 1.44, In: 1.42,
2642
+ Sn: 1.39, Sb: 1.39, Te: 1.38, I: 1.39, Xe: 1.40, Cs: 2.44, Ba: 2.15, La: 2.07, Ce: 2.04, Pr: 2.03, Nd: 2.01, Sm: 1.98, Eu: 1.98,
2643
+ Gd: 1.96, Tb: 1.94, Dy: 1.92, Ho: 1.92, Er: 1.89, Tm: 1.90, Yb: 1.87, Lu: 1.87, Hf: 1.75, Ta: 1.70, W: 1.62, Re: 1.51, Os: 1.44,
2644
+ Ir: 1.41, Pt: 1.36, Au: 1.36, Hg: 1.32, Tl: 1.45, Pb: 1.46, Bi: 1.48 };
2623
2645
  // g: fractional coordinates wrapped into [0,1). Returns all translated copies of g.
2624
2646
  function coreLatticeImages(g, nx, ny, nz, bBoundary) {
2625
2647
  var eps = 1e-3, n = [nx, ny, nz], ranges = [], out = [], k, i, r, x, y, z;
@@ -2635,6 +2657,60 @@ var CIFTools;
2635
2657
  out.push([ranges[0][x], ranges[1][y], ranges[2][z]]);
2636
2658
  return out;
2637
2659
  }
2660
+ /**
2661
+ * Group atoms (fractional coordinates wrapped into the cell) into bonded fragments, taking periodic
2662
+ * images into account. Every atom of a fragment gets an integer lattice translation T so that
2663
+ * (g + T) forms a contiguous molecule. A fragment that reaches its own periodic image
2664
+ * (chain / layer / framework) is flagged as infinite.
2665
+ * atoms : [{el, g:[fx,fy,fz]}] toCart : fractional -> Cartesian (linear part only)
2666
+ * h : interplanar spacings of the cell along a, b, c tol : bond tolerance (Angstrom)
2667
+ */
2668
+ function coreFindMolecules(atoms, toCart, h, tol) {
2669
+ var N = atoms.length, nb = [], rad = [], i, j, k, e, m, q;
2670
+ for (i = 0; i < N; i++) { nb.push([]); rad.push(coreCovRadii[atoms[i].el] || 1.5); }
2671
+ for (i = 0; i < N; i++) {
2672
+ for (j = i; j < N; j++) {
2673
+ var d = [atoms[j].g[0] - atoms[i].g[0], atoms[j].g[1] - atoms[i].g[1], atoms[j].g[2] - atoms[i].g[2]];
2674
+ var rc = rad[i] + rad[j] + tol, cand = [[], [], []], dt, t;
2675
+ for (k = 0; k < 3; k++) {
2676
+ var base = -Math.round(d[k]);
2677
+ for (dt = -1; dt <= 1; dt++) {
2678
+ t = base + dt;
2679
+ if (Math.abs(d[k] + t) * h[k] <= rc) cand[k].push(t);
2680
+ }
2681
+ }
2682
+ for (var a = 0; a < cand[0].length; a++) for (var b = 0; b < cand[1].length; b++) for (var c = 0; c < cand[2].length; c++) {
2683
+ var tv = [cand[0][a], cand[1][b], cand[2][c]];
2684
+ if (i === j) { // bond to own image: record each translation pair only once
2685
+ if (tv[0] === 0 && tv[1] === 0 && tv[2] === 0) continue;
2686
+ if (tv[0] < 0 || (tv[0] === 0 && (tv[1] < 0 || (tv[1] === 0 && tv[2] < 0)))) continue;
2687
+ }
2688
+ var cc = toCart([d[0] + tv[0], d[1] + tv[1], d[2] + tv[2]]);
2689
+ var d2 = cc[0] * cc[0] + cc[1] * cc[1] + cc[2] * cc[2];
2690
+ if (d2 < rc * rc && d2 > 0.25) { // > 0.5 A: closer atoms are disorder alternatives, not bonds
2691
+ nb[i].push({ j: j, t: tv });
2692
+ nb[j].push({ j: i, t: [-tv[0], -tv[1], -tv[2]] });
2693
+ }
2694
+ }
2695
+ }
2696
+ }
2697
+ var T = new Array(N), comps = [], s, queue, members, infinite, cur, tj, o;
2698
+ for (s = 0; s < N; s++) {
2699
+ if (T[s]) continue;
2700
+ T[s] = [0, 0, 0]; queue = [s]; members = [s]; infinite = false;
2701
+ for (q = 0; q < queue.length; q++) {
2702
+ cur = queue[q];
2703
+ for (e = 0; e < nb[cur].length; e++) {
2704
+ o = nb[cur][e];
2705
+ tj = [T[cur][0] + o.t[0], T[cur][1] + o.t[1], T[cur][2] + o.t[2]];
2706
+ if (!T[o.j]) { T[o.j] = tj; queue.push(o.j); members.push(o.j); }
2707
+ else if (T[o.j][0] !== tj[0] || T[o.j][1] !== tj[1] || T[o.j][2] !== tj[2]) infinite = true;
2708
+ }
2709
+ }
2710
+ comps.push({ members: members, infinite: infinite });
2711
+ }
2712
+ return { T: T, comps: comps };
2713
+ }
2638
2714
  function convertCoreCif(data) {
2639
2715
  var tk = coreTokens(data), i = 0, n = tk.length, single = {}, loops = [], name = 'data_core', t, cols, rows, cur;
2640
2716
  function isTag(x) { return x && !x.t && x.v.charAt(0) === '_'; }
@@ -2688,12 +2764,21 @@ var CIFTools;
2688
2764
  '_atom_site.label_comp_id', '_atom_site.label_asym_id', '_atom_site.label_entity_id', '_atom_site.label_seq_id',
2689
2765
  '_atom_site.Cartn_x', '_atom_site.Cartn_y', '_atom_site.Cartn_z', '_atom_site.occupancy', '_atom_site.B_iso_or_equiv',
2690
2766
  '_atom_site.auth_seq_id', '_atom_site.auth_asym_id', '_atom_site.pdbx_PDB_model_num');
2691
- var serial = 0, seen = [], r, s, f, g, k, dup, j, sym, el, lab, cart;
2767
+ var serial = 0, r, s, f, g, k, dup, j, sym, el, lab, cart;
2692
2768
  var o = Text.coreCifOptions || {}, images, im;
2693
2769
  var opt = {
2694
2770
  nx: Math.max(1, parseInt(o.nx) || 1), ny: Math.max(1, parseInt(o.ny) || 1), nz: Math.max(1, parseInt(o.nz) || 1),
2695
- boundary: (o.boundary === undefined) ? true : !!o.boundary
2771
+ boundary: (o.boundary === undefined) ? true : !!o.boundary,
2772
+ wholeMolecules: (o.wholeMolecules === undefined) ? true : !!o.wholeMolecules,
2773
+ bondTolerance: (o.bondTolerance === undefined || isNaN(parseFloat(o.bondTolerance))) ? 0.4 : parseFloat(o.bondTolerance)
2696
2774
  };
2775
+ function emit(at, frac) {
2776
+ var cart = toCart(frac);
2777
+ out.push(['HETATM', ++serial, at.el, at.lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2778
+ at.occ, '0.00', 1, 'A', 1].join(' '));
2779
+ }
2780
+ // 1) all symmetry-generated atoms of one cell, wrapped into [0,1)
2781
+ var list = [];
2697
2782
  for (r = 0; r < atoms.rows.length; r++) {
2698
2783
  var row = atoms.rows[r];
2699
2784
  if (get(row, '_atom_site_calc_flag') === 'dum') continue; // dummy atoms
@@ -2702,6 +2787,7 @@ var CIFTools;
2702
2787
  sym = get(row, '_atom_site_type_symbol'); if (sym === '?') sym = lab;
2703
2788
  el = (sym.match(/^[A-Za-z]{1,2}/) || ['X'])[0];
2704
2789
  el = el.charAt(0).toUpperCase() + el.substr(1).toLowerCase();
2790
+ var occ = coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy'));
2705
2791
  var mySeen = [];
2706
2792
  for (s = 0; s < symops.length; s++) {
2707
2793
  g = symops[s](f).map(function (v) { return v - Math.floor(v + 1e-6); });
@@ -2711,15 +2797,51 @@ var CIFTools;
2711
2797
  }
2712
2798
  if (dup) continue;
2713
2799
  mySeen.push(g);
2714
- // fill the cell (and optional supercell) by lattice translation of the symmetry-generated site
2715
- images = coreLatticeImages(g, opt.nx, opt.ny, opt.nz, opt.boundary);
2716
- for (im = 0; im < images.length; im++) {
2717
- cart = toCart(images[im]);
2718
- out.push(['HETATM', ++serial, el, lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2719
- coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy')), '0.00', 1, 'A', 1].join(' '));
2800
+ list.push({ el: el, lab: lab, occ: occ, g: g });
2801
+ }
2802
+ }
2803
+ // 2) emit them, either as whole molecules or simply wrapped into the cell
2804
+ var mol = null;
2805
+ if (opt.wholeMolecules && list.length) {
2806
+ var Vc = a * b * cc * vol, sinal = Math.sqrt(1 - cosa * cosa), sinbe = Math.sqrt(1 - cosb * cosb);
2807
+ var hh = [Vc / (b * cc * sinal), Vc / (a * cc * sinbe), Vc / (a * b * sing)];
2808
+ if (isFinite(hh[0] + hh[1] + hh[2]) && hh[0] > 0 && hh[1] > 0 && hh[2] > 0) mol = coreFindMolecules(list, toCart, hh, opt.bondTolerance);
2809
+ }
2810
+ var ci, m, at, ix, iy, iz, mean, shift;
2811
+ if (mol) {
2812
+ for (ci = 0; ci < mol.comps.length; ci++) {
2813
+ var comp = mol.comps[ci];
2814
+ if (comp.infinite) { // cannot be made whole: wrap into the cell as before
2815
+ for (m = 0; m < comp.members.length; m++) {
2816
+ at = list[comp.members[m]];
2817
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2818
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2819
+ }
2820
+ continue;
2821
+ }
2822
+ // contiguous molecule: place it in the cell that holds its centre, keep all atoms together
2823
+ mean = [0, 0, 0];
2824
+ for (m = 0; m < comp.members.length; m++) {
2825
+ at = list[comp.members[m]];
2826
+ for (k = 0; k < 3; k++) mean[k] += (at.g[k] + mol.T[comp.members[m]][k]) / comp.members.length;
2827
+ }
2828
+ shift = [-Math.floor(mean[0] + 1e-6), -Math.floor(mean[1] + 1e-6), -Math.floor(mean[2] + 1e-6)];
2829
+ for (ix = 0; ix < opt.nx; ix++) for (iy = 0; iy < opt.ny; iy++) for (iz = 0; iz < opt.nz; iz++) {
2830
+ for (m = 0; m < comp.members.length; m++) {
2831
+ at = list[comp.members[m]];
2832
+ var tt = mol.T[comp.members[m]];
2833
+ emit(at, [at.g[0] + tt[0] + shift[0] + ix, at.g[1] + tt[1] + shift[1] + iy, at.g[2] + tt[2] + shift[2] + iz]);
2834
+ }
2720
2835
  }
2721
2836
  }
2722
2837
  }
2838
+ else {
2839
+ for (m = 0; m < list.length; m++) {
2840
+ at = list[m];
2841
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2842
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2843
+ }
2844
+ }
2723
2845
  out.push('#');
2724
2846
  return out.join('\n') + '\n';
2725
2847
  }
@@ -3018,7 +3140,7 @@ var CIFTools;
3018
3140
  // This approach to binary parsing wastes a bit of memory to trade for speed compared to:
3019
3141
  //
3020
3142
  // let value = buffer.subarray(offset, offset + length); //new Uint8Array(buffer.buffer, offset, length);
3021
- //
3143
+ //
3022
3144
  // It turns out that using the view created by subarray probably uses DataView
3023
3145
  // in the background, which causes the element access to be several times slower
3024
3146
  // than creating the new byte array.
@@ -4342,7 +4464,7 @@ var CIFTools;
4342
4464
  if (index === void 0) {
4343
4465
  // increment the length
4344
4466
  accLength += s.length;
4345
- // store the string and index
4467
+ // store the string and index
4346
4468
  index = strings.length;
4347
4469
  strings[index] = s;
4348
4470
  map[s] = index;
@@ -55403,7 +55525,7 @@ class UtilsCls {
55403
55525
  }
55404
55526
 
55405
55527
  //Convert a three-letter residue name to a one-letter residue abbreviation, e.g., 'LYS' to 'K', or ' A' to 'A' for nucleotides.
55406
- residueName2Abbr(residueName) { this.icn3dui;
55528
+ residueName2Abbr(residueName, bOneLetter) { this.icn3dui;
55407
55529
  let pos = residueName.indexOf(' ');
55408
55530
  if(pos > 0) {
55409
55531
  residueName = residueName.substr(0, pos);
@@ -55498,7 +55620,12 @@ class UtilsCls {
55498
55620
  return 'O';
55499
55621
 
55500
55622
  default:
55501
- return residueName.trim();
55623
+ if(bOneLetter) {
55624
+ return 'X';
55625
+ }
55626
+ else {
55627
+ return residueName.trim();
55628
+ }
55502
55629
  }
55503
55630
  }
55504
55631
 
@@ -55574,15 +55701,20 @@ class UtilsCls {
55574
55701
  }
55575
55702
 
55576
55703
  getIdArray(resid) { this.icn3dui;
55577
- //var idArray = resid.split('_');
55578
55704
  let idArray = [];
55579
55705
 
55580
55706
  if(resid) {
55581
- let pos1 = resid.indexOf('_');
55582
- let pos2 = resid.lastIndexOf('_');
55583
- idArray.push(resid.substr(0, pos1));
55584
- idArray.push(resid.substr(pos1 + 1, pos2 - pos1 - 1));
55585
- idArray.push(resid.substr(pos2 + 1));
55707
+ let itemArray = resid.split('_');
55708
+
55709
+ if(resid.indexOf('pdb_') == 0 ) { // e.g., pdb_00001GPK_A_15
55710
+ idArray.push(itemArray[0] + '_' + itemArray[1]);
55711
+ for(let i = 2, il = itemArray.length; i < il; ++i) {
55712
+ idArray.push(itemArray[i]);
55713
+ }
55714
+ }
55715
+ else {
55716
+ idArray = itemArray;
55717
+ }
55586
55718
  }
55587
55719
 
55588
55720
  return idArray;
@@ -55593,12 +55725,12 @@ class UtilsCls {
55593
55725
  let bArray = b.split(',');
55594
55726
  let aIdArray, bIdArray;
55595
55727
  if(type == 'save1') {
55596
- aIdArray = me.utilsCls.getIdArray(aArray[0]); //aArray[0].split('_');
55597
- bIdArray = me.utilsCls.getIdArray(bArray[0]); //bArray[0].split('_');
55728
+ aIdArray = me.utilsCls.getIdArray(aArray[0]);
55729
+ bIdArray = me.utilsCls.getIdArray(bArray[0]);
55598
55730
  }
55599
55731
  else if(type == 'save2') {
55600
- aIdArray = me.utilsCls.getIdArray(aArray[1]); //aArray[1].split('_');
55601
- bIdArray = me.utilsCls.getIdArray(bArray[1]); //bArray[1].split('_');
55732
+ aIdArray = me.utilsCls.getIdArray(aArray[1]);
55733
+ bIdArray = me.utilsCls.getIdArray(bArray[1]);
55602
55734
  }
55603
55735
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
55604
55736
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
@@ -57513,6 +57645,9 @@ class ClickMenu {
57513
57645
  me.myEventCls.onIds("#" + me.pre + "mn1_mmcifid", "click", function(e) { me.icn3d; //e.preventDefault();
57514
57646
  me.htmlCls.dialogCls.openDlg('dl_mmcifid', 'Please input mmCIF ID');
57515
57647
  });
57648
+ me.myEventCls.onIds("#" + me.pre + "mn1_codid", "click", function(e) { me.icn3d; //e.preventDefault();
57649
+ me.htmlCls.dialogCls.openDlg('dl_codid', 'Please input COD ID');
57650
+ });
57516
57651
 
57517
57652
  me.myEventCls.onIds("#" + me.pre + "mn1_mmdbid", "click", function(e) { me.icn3d; //e.preventDefault();
57518
57653
  me.htmlCls.dialogCls.openDlg('dl_mmdbid', 'Please input MMDB or PDB ID');
@@ -58052,7 +58187,7 @@ class ClickMenu {
58052
58187
  thisClass.setLogCmd("link to compounds with structure similar to CID " + ic.inputid + ": " + url, false);
58053
58188
  }
58054
58189
  else {
58055
- let idArray = ic.inputid.split('_');
58190
+ let idArray = me.utilsCls.getIdArray(ic.inputid);
58056
58191
 
58057
58192
  if(idArray.length === 1) {
58058
58193
  url = me.htmlCls.baseUrl + "vastplus/vastplus.cgi?uid=" + ic.inputid;
@@ -59114,17 +59249,14 @@ class ClickMenu {
59114
59249
 
59115
59250
  }
59116
59251
 
59117
- async setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
59118
- ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
59119
-
59120
- if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
59121
- ic.pk = 1;
59122
- ic.opts['pk'] = 'atom';
59252
+ setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
59253
+ if(ic.cifData) {
59254
+ ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
59255
+
59256
+ ic.setStyleCls.setAtomStyleByOptions(ic.opts);
59257
+ ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
59258
+ ic.drawCls.draw();
59123
59259
  }
59124
-
59125
- ic.setStyleCls.setAtomStyleByOptions(ic.opts);
59126
- ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
59127
- await ic.ParserUtilsCls.renderStructure();
59128
59260
  }
59129
59261
 
59130
59262
  clickMenu6() { let me = this.icn3dui, ic = me.icn3d;
@@ -59144,20 +59276,20 @@ class ClickMenu {
59144
59276
  ic.drawCls.draw();
59145
59277
  });
59146
59278
 
59147
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", async function(e) { me.icn3d; //e.preventDefault();
59148
- await thisClass.setSupercell(0);
59279
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", function(e) { me.icn3d; //e.preventDefault();
59280
+ thisClass.setSupercell(0);
59149
59281
  thisClass.setLogCmd('set supercell 0', true);
59150
59282
  });
59151
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", async function(e) { me.icn3d; //e.preventDefault();
59152
- await thisClass.setSupercell(1);
59283
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", function(e) { me.icn3d; //e.preventDefault();
59284
+ thisClass.setSupercell(1);
59153
59285
  thisClass.setLogCmd('set supercell 1', true);
59154
59286
  });
59155
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", async function(e) { me.icn3d; //e.preventDefault();
59156
- await thisClass.setSupercell(2);
59287
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", function(e) { me.icn3d; //e.preventDefault();
59288
+ thisClass.setSupercell(2);
59157
59289
  thisClass.setLogCmd('set supercell 2', true);
59158
59290
  });
59159
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", async function(e) { me.icn3d; //e.preventDefault();
59160
- await thisClass.setSupercell(3);
59291
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", function(e) { me.icn3d; //e.preventDefault();
59292
+ thisClass.setSupercell(3);
59161
59293
  thisClass.setLogCmd('set supercell 3', true);
59162
59294
  });
59163
59295
 
@@ -60515,6 +60647,7 @@ class SetMenu {
60515
60647
  html += this.getLink('mn1_opmid', 'OPM PDB ID ' + me.htmlCls.wifiStr, undefined, 2);
60516
60648
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
60517
60649
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
60650
+ // html += this.getLink('mn1_codid', 'COD ID ' + me.htmlCls.wifiStr, 1, 2);
60518
60651
 
60519
60652
  html += this.getLink('mn1_cid', 'PubChem CID/Name/InChI ' + me.htmlCls.wifiStr, 1, 2);
60520
60653
  html += this.getLink('mn1_smiles', 'Chemical SMILES ', undefined, 2);
@@ -61755,16 +61888,17 @@ class SetMenu {
61755
61888
 
61756
61889
  html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
61757
61890
 
61758
- let bInputid = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
61891
+ let bInputid = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
61759
61892
 
61760
61893
  //if(bInputid) {
61761
61894
  html += this.getMenuText('assemblyWrapper', 'Assembly', undefined, 1, 1);
61762
61895
  html += "<ul>";
61763
61896
 
61764
- if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined) { // e.g., cif file input
61765
- html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Original Assembly', undefined, 1, 2);
61897
+ if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined) { // e.g., cif file input
61898
+ html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Biological Assembly', undefined, 1, 2);
61899
+ html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', undefined, 1, 2);
61766
61900
  html += this.getRadio('mn6_assembly', 'mn6_assembly1', '1 x 1 x 1', true, 1, 2);
61767
- html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, 1, 2);
61901
+ html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, undefined, 2);
61768
61902
  html += this.getRadio('mn6_assembly', 'mn6_assembly3', '3 x 3 x 3', undefined, 1, 2);
61769
61903
  }
61770
61904
  else if(!me.cfg.bu) {
@@ -63020,6 +63154,12 @@ class SetDialog {
63020
63154
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
63021
63155
  html += "</div>";
63022
63156
 
63157
+ html += me.htmlCls.divStr + "dl_codid' class='" + dialogClass + "'>";
63158
+ html += this.addNotebookTitle('dl_codid', 'Please input a COD ID');
63159
+ html += "COD ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "codid' value='1000041' size=8> ";
63160
+ html += me.htmlCls.buttonStr + "reload_cod'>Load</button>";
63161
+ html += "</div>";
63162
+
63023
63163
  html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
63024
63164
  html += this.addNotebookTitle('dl_mmdbid', 'Please input an MMDB ID');
63025
63165
  html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
@@ -64682,7 +64822,7 @@ class Events {
64682
64822
  let idArray = ids.split(',');
64683
64823
 
64684
64824
  if(!bAppend) {
64685
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64825
+ if(idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64686
64826
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64687
64827
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64688
64828
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -64694,8 +64834,8 @@ class Events {
64694
64834
  }
64695
64835
  }
64696
64836
  else {
64697
- // single MMDB ID could show memebranes
64698
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64837
+ // single MMDB ID could show membranes
64838
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64699
64839
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64700
64840
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64701
64841
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65183,7 +65323,7 @@ class Events {
65183
65323
  if(!me.cfg.notebook) dialog.dialog( "close" );
65184
65324
  thisClass.setLogCmd("load mmtf " + $("#" + me.pre + "mmtfid").val(), false);
65185
65325
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65186
- window.open(hostUrl + '?mmtfid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65326
+ window.open(hostUrl + '?bcifid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65187
65327
  }
65188
65328
  });
65189
65329
 
@@ -65527,7 +65667,7 @@ class Events {
65527
65667
  await ic.scapCls.retrieveScap(snp, bInteraction);
65528
65668
  thisClass.setLogCmd('scap interaction ' + snp, true);
65529
65669
 
65530
- let idArray = snp.split('_'); //stru_chain_resi_snp
65670
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
65531
65671
  let select = '.' + idArray[1] + ':' + idArray[2];
65532
65672
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
65533
65673
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -65566,7 +65706,6 @@ class Events {
65566
65706
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65567
65707
  window.open(hostUrl + '?mmcifid=' + $("#" + me.pre + "mmcifid").val(), urlTarget);
65568
65708
  });
65569
-
65570
65709
  me.myEventCls.onIds("#" + me.pre + "mmcifid", "keyup", function(e) { let ic = me.icn3d;
65571
65710
  if (e.keyCode === 13) {
65572
65711
  e.preventDefault();
@@ -65577,6 +65716,23 @@ class Events {
65577
65716
  }
65578
65717
  });
65579
65718
 
65719
+ me.myEventCls.onIds("#" + me.pre + "reload_cod", "click", function(e) { let ic = me.icn3d;
65720
+ e.preventDefault();
65721
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65722
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65723
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65724
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65725
+ });
65726
+ me.myEventCls.onIds("#" + me.pre + "codid", "keyup", function(e) { let ic = me.icn3d;
65727
+ if (e.keyCode === 13) {
65728
+ e.preventDefault();
65729
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65730
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65731
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65732
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65733
+ }
65734
+ });
65735
+
65580
65736
 
65581
65737
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { let ic = me.icn3d;
65582
65738
  e.preventDefault();
@@ -68162,7 +68318,7 @@ class Events {
68162
68318
  await ic.scapCls.retrieveScap(snp, bInteraction);
68163
68319
  thisClass.setLogCmd('scap interaction ' + snp, true);
68164
68320
 
68165
- let idArray = snp.split('_'); //stru_chain_resi_snp
68321
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
68166
68322
  let select = '.' + idArray[1] + ':' + idArray[2];
68167
68323
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
68168
68324
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -78186,6 +78342,43 @@ class Camera {
78186
78342
  // }
78187
78343
  }
78188
78344
 
78345
+ // Keep the slab plane at the same position relative to the molecule when zooming.
78346
+ // In perspective mode zooming moves the camera along the view direction, so the near plane
78347
+ // (distance from the camera) has to move with it. In orthographic mode zooming only changes
78348
+ // the frustum size and the camera does not move, so the slab plane already stays fixed.
78349
+ updateSlabByZoom() { let ic = this.icn3d, me = ic.icn3dui;
78350
+ if(ic.opts['slab'] !== 'yes' || me.bNode) return;
78351
+ if(ic.opts.camera.toLowerCase() !== 'perspective') return;
78352
+
78353
+ let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
78354
+ if(bInstance) return; // near plane is fixed at 0.1 for instancing
78355
+
78356
+ let cam = (ic.bControlGl) ? window.cam : ic.cam;
78357
+ let controls = (ic.bControlGl) ? window.controls : ic.controls;
78358
+
78359
+ // at zoom = 1 the slab plane is ic.maxD * camMaxDFactor from the camera, i.e. the plane through
78360
+ // the center (or 10 angstroms in front of it when fog is on to keep some surrounding residues)
78361
+ let offset = (ic.camMaxDFactorFog !== undefined) ? 10 : 0;
78362
+
78363
+ // current distance from the camera to the center of rotation, which changes with zooming
78364
+ let dist = cam.position.distanceTo(controls.target);
78365
+
78366
+ // keep the plane at the same position relative to the molecule
78367
+ let nearClip = Math.max(0.1, dist - offset);
78368
+
78369
+ if(Math.abs(cam.near - nearClip) > 1e-6) {
78370
+ cam.near = nearClip;
78371
+ cam.updateProjectionMatrix();
78372
+ if(ic.cam && ic.cam !== cam) {
78373
+ ic.cam.near = nearClip;
78374
+ ic.cam.updateProjectionMatrix();
78375
+ }
78376
+ }
78377
+
78378
+ // the impostor shaders (spheres, cylinders) clip with the nearClip uniform
78379
+ if(ic.uniforms && ic.uniforms.nearClip) ic.uniforms.nearClip.value = nearClip;
78380
+ }
78381
+
78189
78382
  setSlab() { let ic = this.icn3d, me = ic.icn3dui;
78190
78383
  if(ic.bControlGl && !me.bNode) {
78191
78384
  let maxD = ic.maxD;
@@ -78301,7 +78494,8 @@ class Fog {
78301
78494
  else {
78302
78495
  // adjust
78303
78496
  let zoomFactor = (ic._zoomFactor > 1) ? ic._zoomFactor * 1.0 : ic._zoomFactor;
78304
- ic.scene.fog = new Fog$1(background, 2.5 * ic.maxD * zoomFactor, 4 * ic.maxD * zoomFactor);
78497
+ let fogStrength = 2; // 1 = current, >1 = stronger
78498
+ ic.scene.fog = new Fog$1(background, (3 - 0.5 / fogStrength) * ic.maxD * zoomFactor, (3 + 1.0 / fogStrength) * ic.maxD * zoomFactor);
78305
78499
  ic.bSetFog = true;
78306
78500
  ic.camMaxDFactorFog = 3;
78307
78501
  }
@@ -80526,6 +80720,8 @@ class Tube {
80526
80720
 
80527
80721
  let prevAxis1 = new Vector3$1(), prevAxis2;
80528
80722
  for (let i = 0, lim = pnts.length; i < lim; ++i) {
80723
+ if(!pnts[i]) continue;
80724
+
80529
80725
  let r, idx = (i - 1) * axisDivInv;
80530
80726
 
80531
80727
  if (i === 0) {
@@ -80558,7 +80754,7 @@ class Tube {
80558
80754
  }
80559
80755
 
80560
80756
  let delta, axis1, axis2;
80561
- if (i < lim - 1) {
80757
+ if (i < lim - 1 && pnts[i + 1]) {
80562
80758
  delta = pnts[i].clone().sub(pnts[i + 1]);
80563
80759
  axis1 = new Vector3$1(0, -delta.z, delta.y).normalize().multiplyScalar(r);
80564
80760
  axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
@@ -84544,7 +84740,6 @@ class Surface {
84544
84740
  let chainStr = (Object.keys(chainHash).length > 1) ? '<th>Chain</th>' : '';
84545
84741
  html += '<tr>' + structureStr + chainStr + '<th>Residue</th><th>Number</th><th>SASA (&#8491;<sup>2</sup>)</th><th>Percent Out</th><th>In/Out</th></tr>';
84546
84742
  for(let resid in ic.resid2area) {
84547
- //var idArray = resid.split('_');
84548
84743
  let pos = resid.lastIndexOf('_');
84549
84744
  let resn = resid.substr(pos + 1);
84550
84745
 
@@ -85198,6 +85393,8 @@ class ApplyClbonds {
85198
85393
  // only apply to displayed atoms
85199
85394
  // if(!ic.dAtoms.hasOwnProperty(line.serial1) || !ic.dAtoms.hasOwnProperty(line.serial2)) continue;
85200
85395
 
85396
+ if(!ic.atoms[line.serial1] || !ic.atoms[line.serial2]) continue;
85397
+
85201
85398
  line.position1 = ic.atoms[line.serial1].coord;
85202
85399
  line.position2 = ic.atoms[line.serial2].coord;
85203
85400
 
@@ -85328,6 +85525,7 @@ class ApplyClbonds {
85328
85525
  if(type == 'chemical') continue; // just connect checmicals together
85329
85526
 
85330
85527
  if(ic.clbondpnts[atom0.structure] === undefined) ic.clbondpnts[atom0.structure] = [];
85528
+ if(ic.clbondpnts[atom1.structure] === undefined) ic.clbondpnts[atom1.structure] = [];
85331
85529
  ic.clbondpnts[atom0.structure].push(resid0);
85332
85530
  ic.clbondpnts[atom1.structure].push(resid1);
85333
85531
 
@@ -85873,9 +86071,9 @@ class ApplyOther {
85873
86071
  }
85874
86072
  }
85875
86073
 
85876
- ic.lineCls.createLines(ic.lines);
85877
- if(!ic.planes) ic.planes = [];
85878
- ic.cylinderCls.createPlanes(ic.planes);
86074
+ // ic.lineCls.createLines(ic.lines);
86075
+ // if(!ic.planes) ic.planes = [];
86076
+ // ic.cylinderCls.createPlanes(ic.planes);
85879
86077
  // }
85880
86078
 
85881
86079
  // distance sets
@@ -85998,6 +86196,10 @@ class ApplyOther {
85998
86196
  ic.pk = 3;
85999
86197
  break;
86000
86198
  }
86199
+
86200
+ ic.lineCls.createLines(ic.lines);
86201
+ if(!ic.planes) ic.planes = [];
86202
+ ic.cylinderCls.createPlanes(ic.planes);
86001
86203
  }
86002
86204
 
86003
86205
  applyChemicalbindingOptions(options) { let ic = this.icn3d, me = ic.icn3dui;
@@ -87144,6 +87346,8 @@ class Impostor {
87144
87346
 
87145
87347
  let shiness = ic.shininess / 100.0 * 0.5;
87146
87348
 
87349
+ let fogRGB = background.clone().convertLinearToSRGB();
87350
+
87147
87351
  ic.uniforms = UniformsUtils.merge([
87148
87352
  UniformsLib.common,
87149
87353
  {
@@ -87164,7 +87368,8 @@ class Impostor {
87164
87368
  nearClip: { type: "f", value: nearClip },
87165
87369
  ortho: { type: "f", value: 0.0 },
87166
87370
  shrink: { type: "f", value: 0.13 },
87167
- fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87371
+ //fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87372
+ fogColor: { type: "v3", value: [fogRGB.r, fogRGB.g, fogRGB.b] },
87168
87373
  fogNear: { type: "f", value: near },
87169
87374
  fogFar: { type: "f", value: far },
87170
87375
  fogDensity: { type: "f", value: 2.0 }
@@ -105397,6 +105602,9 @@ class WebGLPathTracer {
105397
105602
 
105398
105603
  cam = this.setDirectLight(cam);
105399
105604
 
105605
+ // move the slab plane according to the zoom
105606
+ if(ic.opts['slab'] === 'yes') ic.cameraCls.updateSlabByZoom();
105607
+
105400
105608
  if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
105401
105609
 
105402
105610
  if(ic.bVr) {
@@ -108960,7 +109168,7 @@ class AnnoCddSite {
108960
109168
  ic.bAjaxCddSite = true;
108961
109169
  }
108962
109170
 
108963
- getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d; ic.icn3dui;
109171
+ getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d, me = ic.icn3dui;
108964
109172
  let resiArrayStr = '';
108965
109173
  for(let i = 0, il = resiNCBIArray.length; i < il; ++i) {
108966
109174
  let resiNCBI = resiNCBIArray[i] + 1; // zero-based
@@ -108968,7 +109176,8 @@ class AnnoCddSite {
108968
109176
  let resid = ic.ncbi2resid[residNCBI];
108969
109177
  if(!resid) resid = residNCBI; // this happens sometimes, e.g., Q9Y4K1
108970
109178
 
108971
- let resi = resid.split('_')[2];
109179
+ let idArray = me.utilsCls.getIdArray(resid);
109180
+ let resi = idArray[2];
108972
109181
  if(i > 0) resiArrayStr += ',';
108973
109182
  resiArrayStr += resi;
108974
109183
  }
@@ -110064,7 +110273,8 @@ class AnnoIg {
110064
110273
  let residArray = Object.keys(residHash);
110065
110274
 
110066
110275
  // delete the following loops
110067
- let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, residArray[residArray.length - 1].split('_')[2]);
110276
+ let idArray = me.utilsCls.getIdArray(residArray[residArray.length - 1]);
110277
+ let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110068
110278
 
110069
110279
  for(let j = lastPos + 1, jl = ic.chainsSeq[chnid].length; j < jl; ++j) {
110070
110280
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -110080,7 +110290,8 @@ class AnnoIg {
110080
110290
  }
110081
110291
 
110082
110292
  // delete the previous loops
110083
- ic.setSeqAlignCls.getPosFromResi(chnid, residArray[0].split('_')[2]);
110293
+ idArray = me.utilsCls.getIdArray(residArray[0]);
110294
+ ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110084
110295
 
110085
110296
  for(let j = lastPos - 1; j >= 0; --j) {
110086
110297
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -111083,8 +111294,9 @@ class AnnoSnpClinVar {
111083
111294
  let residHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chnid]);
111084
111295
  // for(let i = 1, il = ic.giSeq[chnid].length; i <= il; ++i) {
111085
111296
  for(let resid in residHash) {
111086
- let i = resid.split('_')[2];
111087
-
111297
+ let idArray = me.utilsCls.getIdArray(resid);
111298
+ let i = idArray[2];
111299
+
111088
111300
  if(resi2index[i] !== undefined) {
111089
111301
  ++snpCnt;
111090
111302
  let allDiseaseTitle = '';
@@ -113277,7 +113489,6 @@ class Domain3d {
113277
113489
  // if(fromPos >= start && toPos <= end) {
113278
113490
  if(ssCnt > 0) jsonStr += ', ';
113279
113491
  jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
113280
- // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
113281
113492
  jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
113282
113493
  ++ssCnt;
113283
113494
  // }
@@ -113294,7 +113505,6 @@ class Domain3d {
113294
113505
  for(let j = startAll; j <= endAll; ++j) {
113295
113506
  let ncbiResid = chnid + '_' + j;
113296
113507
  let resid = ic.ncbi2resid[ncbiResid];
113297
- resid.split('_')[2];
113298
113508
 
113299
113509
  let pos = j;
113300
113510
 
@@ -113302,7 +113512,6 @@ class Domain3d {
113302
113512
 
113303
113513
  if(!residueHash.hasOwnProperty(resid)) {
113304
113514
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113305
- // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113306
113515
  }
113307
113516
  else {
113308
113517
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -113311,7 +113520,6 @@ class Domain3d {
113311
113520
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
113312
113521
 
113313
113522
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
113314
- // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
113315
113523
  }
113316
113524
 
113317
113525
  ++domainCnt;
@@ -119149,7 +119357,6 @@ class GetGraph {
119149
119357
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
119150
119358
  let node = graphJson.nodes[i];
119151
119359
  //node.r: 1_1_1KQ2_A_1
119152
- //var idArray = node.r.split('_');
119153
119360
  let idArray = [];
119154
119361
  idArray.push('');
119155
119362
  idArray.push('');
@@ -119328,8 +119535,8 @@ class GetGraph {
119328
119535
  compNode(a, b, bReverseChain) { let ic = this.icn3d, me = ic.icn3dui;
119329
119536
  let resid1 = a.r.substr(4); // 1_1_1KQ2_A_1
119330
119537
  let resid2 = b.r.substr(4); // 1_1_1KQ2_A_1
119331
- let aIdArray = me.utilsCls.getIdArray(resid1); //resid1.split('_');
119332
- let bIdArray = me.utilsCls.getIdArray(resid2); //resid2.split('_');
119538
+ let aIdArray = me.utilsCls.getIdArray(resid1);
119539
+ let bIdArray = me.utilsCls.getIdArray(resid2);
119333
119540
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
119334
119541
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
119335
119542
  let aResi = parseInt(aIdArray[2]);
@@ -120382,7 +120589,7 @@ class ViewInterPairs {
120382
120589
  residname2 =(type == 'save1') ? residname1_residname2[1] : residname1_residname2[0];
120383
120590
 
120384
120591
  // stru_chain_resi_resn
120385
- let ids = residname1.split('_');
120592
+ let ids = me.utilsCls.getIdArray(residname1);
120386
120593
  if(i > 0 && residname1 != prevResidname1) {
120387
120594
  bondCnt.push({res1: prevResidname1, res2: residname2List, cntHbond: cntHbond, cntIonic: cntIonic, cntContact: cntContact, cntHalegen: cntHalegen, cntPication: cntPication, cntPistacking: cntPistacking});
120388
120595
 
@@ -121783,8 +121990,8 @@ class AlignParser {
121783
121990
  //var scale = data2.transform.scale / factor;
121784
121991
  let tMaster = data2.transform.translate.master;
121785
121992
  let tMVector = new Vector3$1(tMaster[0] / factor, tMaster[1] / factor, tMaster[2] / factor);
121786
- let tSlave = data2.transform.translate.slave;
121787
- let tSVector = new Vector3$1(tSlave[0] / factor, tSlave[1] / factor, tSlave[2] / factor);
121993
+ let tQuery = data2.transform.translate.slave; // actually means query protein
121994
+ let tSVector = new Vector3$1(tQuery[0] / factor, tQuery[1] / factor, tQuery[2] / factor);
121788
121995
  let rotation = data2.transform.rotate;
121789
121996
  let rMatrix = [];
121790
121997
  for(let i = 0, il = rotation.length; i < il; ++i) { // 9 elements
@@ -122028,44 +122235,6 @@ class ChainalignParser {
122028
122235
  // calculate secondary structures with applyCommandDssp
122029
122236
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
122030
122237
  await ic.pdbParserCls.applyCommandDssp(true);
122031
- //!!!
122032
- /*
122033
- // original version =============
122034
- // align PDB chains
122035
- for(let index in ic.pdbChainIndexHash) {
122036
- //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
122037
- let idArray = ic.pdbChainIndexHash[index].split('_');
122038
- mmdbid_q = idArray[0];
122039
- let chain_q = idArray[1];
122040
- mmdbid_t = idArray[2];
122041
- let chain_t = idArray[3];
122042
-
122043
- thisClass.transformStructure(mmdbid_q, index-1, 'query');
122044
- }
122045
-
122046
- // dynamically align pairs in ic.afChainIndexHash
122047
- let ajaxArray = [], indexArray = [], struArray = [];
122048
- let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
122049
- let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
122050
-
122051
- let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
122052
-
122053
- for(let index in ic.afChainIndexHash) {
122054
- let idArray = ic.afChainIndexHash[index].split('_');
122055
- mmdbid_q = idArray[0];
122056
- let chain_q = idArray[1];
122057
- let chainid_q = mmdbid_q + '_' + chain_q;
122058
-
122059
- mmdbid_t = idArray[2];
122060
- let chain_t = idArray[3];
122061
- let chainid_t = mmdbid_t + '_' + chain_t;
122062
-
122063
- // let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t, true).hAtoms : ic.chains[chainid_t];
122064
- // let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q, true).hAtoms : ic.chains[chainid_q];
122065
- let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainid_t, true).hAtoms : ic.chains[chainid_t];
122066
- let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainid_q, true).hAtoms : ic.chains[chainid_q];
122067
- // end of original version =============
122068
- */
122069
122238
 
122070
122239
  // new version to be done for VASTsrv ==============
122071
122240
  // dynamically align pairs in all chainids
@@ -122534,10 +122703,10 @@ class ChainalignParser {
122534
122703
  return chainidArray;
122535
122704
  }
122536
122705
 
122537
- addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
122706
+ addPostfixForStructureids(structArray) { let ic = this.icn3d, me = ic.icn3dui;
122538
122707
  let struct2cnt = {};
122539
122708
  for(let i = 0, il = structArray.length; i < il; ++i) {
122540
- if(structArray[i].toLowerCase().toLowerCase().substr(0,8) == 'pdb_0000') structArray[i] = structArray[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122709
+ if((me.cfg.mmdbid != undefined || me.cfg.pdbid != undefined) && structArray[i].toLowerCase().toLowerCase().substr(0,8) == 'pdb_0000') structArray[i] = structArray[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122541
122710
 
122542
122711
  let struct = structArray[i].toUpperCase();
122543
122712
 
@@ -122561,6 +122730,8 @@ class ChainalignParser {
122561
122730
 
122562
122731
  ic.opts['proteins'] = 'c alpha trace';
122563
122732
 
122733
+ if(!chainalign) return;
122734
+
122564
122735
  let alignArray = chainalign.split(',');
122565
122736
  let domainArray = (me.cfg.domainids) ? me.cfg.domainids.split(',') : [];
122566
122737
  if(domainArray.length < alignArray.length) domainArray = [];
@@ -122633,7 +122804,7 @@ class ChainalignParser {
122633
122804
  let domainalign = (domainArray.length > 0) ? domainArray[index] + "," + domainArray[0] : undefined;
122634
122805
 
122635
122806
  // TM-align (me.cfg.aligntool == 'tmalign') needs to input PDB
122636
- if(me.cfg.aligntool != 'tmalign' && ic.mmdbid_t.length == 4 && ic.mmdbid_q.length == 4) {
122807
+ if(me.cfg.aligntool != 'tmalign' && (ic.mmdbid_t.length == 4 || ic.mmdbid_t.indexOf('pdb_') == 0) && (ic.mmdbid_q.length == 4 || ic.mmdbid_q.indexOf('pdb_') == 0)) {
122637
122808
  let urlalign;
122638
122809
 
122639
122810
  if(domainArray.length > 0) {
@@ -122922,7 +123093,7 @@ class ChainalignParser {
122922
123093
  }
122923
123094
  else {
122924
123095
  for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
122925
- if(structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
123096
+ if((me.cfg.mmdbid != undefined || me.cfg.pdbid != undefined) && structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122926
123097
 
122927
123098
  let id = structArrayTmp[i].toUpperCase();
122928
123099
  if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
@@ -124453,6 +124624,19 @@ class MmcifParser {
124453
124624
  await ic.opmParserCls.loadOpmData(data, mmcifid, undefined, 'mmcif', undefined, bText);
124454
124625
  }
124455
124626
 
124627
+ async downloadCod(codid) { let ic = this.icn3d, me = ic.icn3dui;
124628
+ //ic.bCid = undefined;
124629
+
124630
+ ic.ParserUtilsCls.setYourNote(codid.toUpperCase() + '(COD) in iCn3D');
124631
+
124632
+ let url = "https://www.crystallography.net/cod/" + codid + ".cif";
124633
+ // let url = "https://www.crystallography.net/cif/1/00/00/1000041.cif";
124634
+ let data = await me.getAjaxPromise(url, 'text', true);
124635
+
124636
+ let bText = true;
124637
+ ic.loadCIFCls.loadCIF(data, codid, bText);
124638
+ }
124639
+
124456
124640
  async downloadMmcifSymmetry(mmcifid, type) { let ic = this.icn3d, me = ic.icn3dui;
124457
124641
  try {
124458
124642
  // let url = "https://files.rcsb.org/download/" + mmcifid + ".cif";
@@ -124566,6 +124750,11 @@ class MmcifParser {
124566
124750
  ic.opts['color'] = 'structure';
124567
124751
  }
124568
124752
 
124753
+ if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
124754
+ ic.pk = 1;
124755
+ ic.opts['pk'] = 'atom';
124756
+ }
124757
+
124569
124758
  ic.opmParserCls.modifyUIMapAssembly();
124570
124759
 
124571
124760
  await ic.pdbParserCls.addSecondary(bAppend);
@@ -124659,9 +124848,10 @@ class MmdbParser {
124659
124848
  me.cfg.query_id = idArray[0];
124660
124849
  me.cfg.blast_rep_id = idArray[1];
124661
124850
 
124662
- let mmdbid = me.cfg.blast_rep_id.split('_')[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124851
+ let textArray = me.utilsCls.getIdArray(me.cfg.blast_rep_id);
124852
+ let mmdbid = textArray[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124663
124853
 
124664
- if(mmdbid.length == 4) { // pdb
124854
+ if(mmdbid.length == 4 || mmdbid.indexOf('pdb_') == 0) { // pdb
124665
124855
  await this.downloadMmdb(mmdbid);
124666
124856
  }
124667
124857
  else {
@@ -124813,7 +125003,7 @@ class MmdbParser {
124813
125003
  if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
124814
125004
  // save a set named me.cfg.ligand
124815
125005
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
124816
- let idArray = Object.keys(residueHash)[0].split('_');
125006
+ let idArray = me.utilsCls.getIdArray(Object.keys(residueHash)[0]);
124817
125007
  let select = '.' + idArray[1] + ':' + idArray[2];
124818
125008
 
124819
125009
  await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
@@ -125190,7 +125380,7 @@ class BcifParser {
125190
125380
 
125191
125381
  if (parsed.isError) {
125192
125382
  // report error:
125193
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
125383
+ var aaa = 1; //alert("1 The Binary CIF data can NOT be parsed: " + parsed.toString());
125194
125384
  return;
125195
125385
  }
125196
125386
 
@@ -126155,7 +126345,8 @@ class OpmParser {
126155
126345
  if(!pdbid) pdbid = ic.defaultPdbId;
126156
126346
 
126157
126347
  //if(me.cfg.mmtfid === undefined && me.cfg.bcifid === undefined) { // skip opm for bcif files
126158
- let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + pdbid.toLowerCase();
126348
+ let shortPdbid = pdbid.indexOf('pdb_0000') == 0 ? pdbid.substr(8) : pdbid;
126349
+ let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + shortPdbid.toLowerCase();
126159
126350
 
126160
126351
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
126161
126352
 
@@ -127231,7 +127422,7 @@ class DcdParser {
127231
127422
  }
127232
127423
 
127233
127424
  for(let j in residuesOri) {
127234
- let idArray = j.split('_');
127425
+ let idArray = me.utilsCls.getIdArray(j);
127235
127426
  let structure2 = idArray[0] + molNum;
127236
127427
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127237
127428
  ic.residues[residid2] = {};
@@ -127242,7 +127433,7 @@ class DcdParser {
127242
127433
  }
127243
127434
 
127244
127435
  for(let j in chainsOri) {
127245
- let idArray = j.split('_');
127436
+ let idArray = me.utilsCls.getIdArray(j);
127246
127437
  let structure2 = idArray[0] + molNum;
127247
127438
  let chainid2 = structure2 + '_' + idArray[1];
127248
127439
 
@@ -127273,7 +127464,7 @@ class DcdParser {
127273
127464
 
127274
127465
  // set ic.ncbi2resid and ic.resid2ncbi
127275
127466
  for(let chainid in chainsOri) {
127276
- let idArray = chainid.split('_');
127467
+ let idArray = me.utilsCls.getIdArray(chainid);
127277
127468
  let structure2 = idArray[0] + molNum;
127278
127469
  let chainid2 = structure2 + '_' + idArray[1];
127279
127470
 
@@ -127837,7 +128028,7 @@ class XtcParser {
127837
128028
  }
127838
128029
 
127839
128030
  for(let j in residuesOri) {
127840
- let idArray = j.split('_');
128031
+ let idArray = me.utilsCls.getIdArray(j);
127841
128032
  let structure2 = idArray[0] + molNum;
127842
128033
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127843
128034
  ic.residues[residid2] = {};
@@ -127848,7 +128039,7 @@ class XtcParser {
127848
128039
  }
127849
128040
 
127850
128041
  for(let j in chainsOri) {
127851
- let idArray = j.split('_');
128042
+ let idArray = me.utilsCls.getIdArray(j);
127852
128043
  let structure2 = idArray[0] + molNum;
127853
128044
  let chainid2 = structure2 + '_' + idArray[1];
127854
128045
 
@@ -127879,7 +128070,7 @@ class XtcParser {
127879
128070
 
127880
128071
  // set ic.ncbi2resid and ic.resid2ncbi
127881
128072
  for(let chainid in chainsOri) {
127882
- let idArray = chainid.split('_');
128073
+ let idArray = me.utilsCls.getIdArray(chainid);
127883
128074
  let structure2 = idArray[0] + molNum;
127884
128075
  let chainid2 = structure2 + '_' + idArray[1];
127885
128076
 
@@ -128105,9 +128296,8 @@ class MsaParser {
128105
128296
 
128106
128297
  // realign based on residue by residue
128107
128298
  let alignment_final = ic.inputChainidArray.join(',');
128108
-
128109
128299
  if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
128110
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
128300
+ var aaa = 1; //alert("Please make sure the number of chains " + (alignment_final.split(',').length - 1) + " and the lines of predefined residues " + predefinedres.split(': ').length + " are the same...");
128111
128301
  return;
128112
128302
  }
128113
128303
 
@@ -128165,7 +128355,7 @@ class MsaParser {
128165
128355
  }
128166
128356
 
128167
128357
  if(type == 'clustalw') {
128168
- if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
128358
+ if(line.substr(0, 1) != '.' && line.substr(0, 1) != '*') {
128169
128359
  let chainid_seq = line.split(/\s+/);
128170
128360
  let idArray = chainid_seq[0].split('|');
128171
128361
  let result = this.getChainid(idArray, bStart && !bSecBlock);
@@ -128190,9 +128380,11 @@ class MsaParser {
128190
128380
  seq = '';
128191
128381
 
128192
128382
  let pos = line.indexOf(' ');
128383
+ if(pos == -1) pos = line.length;
128193
128384
  let idArray = line.substr(1, pos).split('|');
128194
-
128385
+
128195
128386
  if(idArray.length == 1) {
128387
+ bFound = true;
128196
128388
  chainid = idArray[0];
128197
128389
  }
128198
128390
  else {
@@ -128256,8 +128448,9 @@ class MsaParser {
128256
128448
  ic.inputChainidArray.push(chainid + '_A');
128257
128449
  }
128258
128450
  }
128259
- else if(chainid.indexOf('_') != -1) { // PDB ID
128260
- let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
128451
+ else if(chainid.indexOf('_') != -1 || chainid.indexOf('pdb_') != -1) { // PDB ID
128452
+ let idArray = me.utilsCls.getIdArray(chainid);
128453
+ let stru = idArray[0];
128261
128454
  ic.struArray.push(stru);
128262
128455
  ic.inputChainidArray.push(chainid);
128263
128456
  }
@@ -128339,7 +128532,7 @@ class RealignParser {
128339
128532
  }
128340
128533
 
128341
128534
  // ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn.substr(0, 3)).substr(0, 1)});
128342
- ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn).substr(0, 1)});
128535
+ ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn, true)});
128343
128536
 
128344
128537
  struct2chain[atom.structure] = atom.structure + '_' + atom.chain;
128345
128538
 
@@ -128382,7 +128575,8 @@ class RealignParser {
128382
128575
 
128383
128576
  async parseChainRealignPredefined(chainidArray, struct2SeqHash, struct2CoorHash, struct2resid) { let ic = this.icn3d, me = ic.icn3dui;
128384
128577
 
128385
- let toStruct = chainidArray[0].substr(0, chainidArray[0].indexOf('_')); //.toUpperCase();
128578
+ let itemArray1 = me.utilsCls.getIdArray(chainidArray[0]);
128579
+ let toStruct = itemArray1[0];
128386
128580
 
128387
128581
  let hAtoms = {}, rmsd;
128388
128582
 
@@ -128395,13 +128589,14 @@ class RealignParser {
128395
128589
  ic.qt_start_end = [];
128396
128590
 
128397
128591
  let chainidHash = {};
128398
- for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
128399
- let fromStruct = chainidArray[index + 1].substr(0, chainidArray[index + 1].indexOf('_')); //.toUpperCase();
128592
+ for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
128593
+ let itemArray2 = me.utilsCls.getIdArray(chainidArray[index + 1]);
128594
+ let fromStruct = itemArray2[0];
128400
128595
 
128401
128596
  //if(toStruct == fromStruct) fromStruct += me.htmlCls.postfix;
128402
128597
 
128403
- let chainTo = toStruct + chainidArray[0].substr(chainidArray[0].indexOf('_'));
128404
- let chainFrom = fromStruct + chainidArray[index + 1].substr(chainidArray[index + 1].indexOf('_'));
128598
+ let chainTo = toStruct + '_' + itemArray1[1];
128599
+ let chainFrom = fromStruct + '_' + itemArray2[1];
128405
128600
  chainidHash[chainTo] = 1;
128406
128601
  chainidHash[chainFrom] = 1;
128407
128602
 
@@ -128436,7 +128631,7 @@ class RealignParser {
128436
128631
 
128437
128632
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, result.hAtoms);
128438
128633
  rmsd = parseFloat(result.rmsd);
128439
- }
128634
+ }
128440
128635
 
128441
128636
  // If rmsd from vastsrv is too large, realign the chains
128442
128637
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
@@ -128658,15 +128853,6 @@ class RealignParser {
128658
128853
  prevChainid = chainidArrayTmp[i];
128659
128854
  }
128660
128855
 
128661
- // use the model from Membranome as template
128662
- // if(ic.bAfMem && chainidArray.length == 2) {
128663
- // if(chainidArray[1].split('_')[0] == pdbidTemplate) {
128664
- // let tmp = chainidArray[0];
128665
- // chainidArray[0] = chainidArray[1];
128666
- // chainidArray[1] = tmp;
128667
- // }
128668
- // }
128669
-
128670
128856
  let bRealign = true;
128671
128857
  ic.qt_start_end = []; // reset the alignment
128672
128858
 
@@ -128911,12 +129097,12 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128911
129097
  let predefinedResArray, predefinedResPair;
128912
129098
 
128913
129099
  if(bPredefined) {
128914
- me.cfg.resdef.replace(/; /gi, ': ');
128915
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
128916
- // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
128917
-
129100
+ let tmpStr = me.cfg.resdef.replace(/; /gi, ': ');
129101
+ // predefinedResArray = decodeURIComponent(tmpStr).trim().replace(/\+/gi, ' ').split(': ');
129102
+ predefinedResArray = tmpStr.replace(/\+/gi, ' ').split(': ');
129103
+
128918
129104
  if(predefinedResArray.length != chainidArray.length - 1) {
128919
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
129105
+ var aaa = 1; //alert("Please make sure the number of chains " + (chainidArray.length - 1) + " and the lines of predefined residues " + predefinedResArray.length + " are the same...");
128920
129106
  return;
128921
129107
  }
128922
129108
  }
@@ -128925,8 +129111,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128925
129111
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
128926
129112
  //if(bPredefined) predefinedRes = predefinedResArray[i].trim();
128927
129113
 
128928
- let pos = chainidArray[i].indexOf('_');
128929
- let mmdbid = chainidArray[i].substr(0, pos); //.toUpperCase();
129114
+ let itemArray = me.utilsCls.getIdArray(chainidArray[i]);
129115
+ let mmdbid = itemArray[0]; //.toUpperCase();
128930
129116
 
128931
129117
  // if(!bRealign) mmdbid = mmdbid.toUpperCase();
128932
129118
 
@@ -128934,7 +129120,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128934
129120
  mmdbid_t = mmdbid;
128935
129121
  }
128936
129122
 
128937
- let chainid = mmdbid + chainidArray[i].substr(pos);
129123
+ let chainid = mmdbid + '_' + itemArray[1];
128938
129124
  if(i == 0) chainid_t = chainid;
128939
129125
 
128940
129126
  if(!ic.chainsSeq || !ic.chainsSeq[chainid]) {
@@ -128963,7 +129149,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128963
129149
  if(!struct2CoorHash[chainidpair]) struct2CoorHash[chainidpair] = {};
128964
129150
  if(!struct2resid[chainidpair]) struct2resid[chainidpair] = {};
128965
129151
 
128966
- // master
129152
+ // template
128967
129153
  resiArray = predefinedResPair[0].split(",");
128968
129154
 
128969
129155
  result = thisClass.getSeqCoorResid(resiArray, chainid_t);
@@ -128978,7 +129164,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128978
129164
  struct2CoorHash[chainidpair][mmdbid_t] = struct2CoorHash[chainidpair][mmdbid_t].concat(result.coor);
128979
129165
  struct2resid[chainidpair][mmdbid_t] = struct2resid[chainidpair][mmdbid_t].concat(result.resid);
128980
129166
 
128981
- // slave
129167
+ // query
128982
129168
  resiArray = predefinedResPair[1].split(",");
128983
129169
 
128984
129170
  result = thisClass.getSeqCoorResid(resiArray, chainid);
@@ -129006,7 +129192,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129006
129192
  }
129007
129193
  }
129008
129194
  else {
129009
- if(i == 0) { // master
129195
+ if(i == 0) { // template
129010
129196
  //base = parseInt(ic.chainsSeq[chainid][0].resi);
129011
129197
 
129012
129198
  resiArray = [];
@@ -129046,7 +129232,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129046
129232
  bSelectedBoth = true;
129047
129233
 
129048
129234
  let resn = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]).resn;
129049
- struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn);
129235
+ struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn, true);
129050
129236
 
129051
129237
  struct2CoorHash[chainid] = struct2CoorHash[chainid].concat(this.getResCoorArray(resid));
129052
129238
 
@@ -131361,9 +131547,6 @@ class LoadAtomData {
131361
131547
  atm.coord = new Vector3$1(atm.coord.x, atm.coord.y, atm.coord.z);
131362
131548
  }
131363
131549
 
131364
- // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131365
- let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn);
131366
-
131367
131550
  if((type === 'mmdbid' || type === 'align') && ic.bFullUi ) {
131368
131551
  // set ic.mmdbMolidResid2mmdbChainResi
131369
131552
  if(ic.mmdbMolidResid2mmdbChainResi === undefined) ic.mmdbMolidResid2mmdbChainResi = {};
@@ -131505,6 +131688,8 @@ class LoadAtomData {
131505
131688
  }
131506
131689
  }
131507
131690
 
131691
+ // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131692
+ let oneLetterRes = (atm.het) ? me.utilsCls.residueName2Abbr(atm.resn) : me.utilsCls.residueName2Abbr(atm.resn, true);
131508
131693
  ic.residueId2Name[residueid] = oneLetterRes;
131509
131694
 
131510
131695
  let secondaries = '-';
@@ -131852,11 +132037,11 @@ class SetSeqAlign {
131852
132037
  ic.nconsHash2 = {};
131853
132038
  ic.nalignHash2 = {};
131854
132039
 
131855
- let msaSameColor = [];
131856
- // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
131857
- for(let i = 0, il = seqalign[0].length; i < il; ++i) {
131858
- msaSameColor.push(1);
131859
- }
132040
+ // let msaSameColor = [];
132041
+ // // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132042
+ // for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132043
+ // msaSameColor.push(1);
132044
+ // }
131860
132045
 
131861
132046
  for(let i = 0, il = seqalign.length; i < il; ++i) {
131862
132047
  // first sequence
@@ -131865,44 +132050,30 @@ class SetSeqAlign {
131865
132050
 
131866
132051
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
131867
132052
  chainid1 = mmdbid1 + '_' + chain1;
131868
-
131869
- let id2aligninfo = {};
131870
- let start = alignData.sequence.length, end = -1;
131871
- let bStart = false;
132053
+ alignData.sequence.length;
131872
132054
  for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
131873
132055
  // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131874
- let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
131875
- let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131876
- resn =(resn === ' ' || resn === '') ? 'X' : resn;
131877
-
131878
- let aligned =(alignData.sequence[j][3]) ? 1 : 0;
131879
-
131880
- if(aligned == 1) {
131881
- if(j < start && !bStart) {
131882
- start = j;
131883
- bStart = true; // set start just once
131884
- }
131885
- if(j > end) end = j;
131886
- }
132056
+ (ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132057
+ (alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131887
132058
 
131888
- id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132059
+ (alignData.sequence[j][3]) ? 1 : 0;
131889
132060
  }
131890
132061
 
131891
132062
  // second sequence
131892
132063
  alignData = seqalign[i][1];
131893
132064
 
131894
- for(let j = start; j <= end; ++j) {
131895
- // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131896
- let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132065
+ // for(let j = start; j <= end; ++j) {
132066
+ // // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132067
+ // let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
131897
132068
 
131898
- let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132069
+ // let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
131899
132070
 
131900
- if(aligned === 2) { // aligned
131901
- if(id2aligninfo[j].resn != resn) {
131902
- msaSameColor[j] = 0;
131903
- }
131904
- }
131905
- }
132071
+ // if(aligned === 2) { // aligned
132072
+ // if(id2aligninfo[j].resn != resn) {
132073
+ // msaSameColor[j] = 0;
132074
+ // }
132075
+ // }
132076
+ // }
131906
132077
  }
131907
132078
 
131908
132079
  for(let i = 0, il = seqalign.length; i < il; ++i) {
@@ -132001,7 +132172,7 @@ class SetSeqAlign {
132001
132172
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132002
132173
  }
132003
132174
 
132004
- color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132175
+ // color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132005
132176
 
132006
132177
  // mapping, use the firstsequence as the reference structure
132007
132178
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132020,7 +132191,7 @@ class SetSeqAlign {
132020
132191
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132021
132192
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132022
132193
 
132023
- msaSameColor[j] = 2; // not aligned
132194
+ // msaSameColor[j] = 2; // not aligned
132024
132195
  }
132025
132196
 
132026
132197
  // chain1
@@ -132145,8 +132316,7 @@ class SetSeqAlign {
132145
132316
  return pos;
132146
132317
  }
132147
132318
 
132148
- getResnFromResi(chainid, resi) { let ic = this.icn3d; ic.icn3dui;
132149
- /*
132319
+ getResnFromResi(chainid, resi) { let ic = this.icn3d, me = ic.icn3dui;
132150
132320
  let pos = this.getPosFromResi(chainid, resi);
132151
132321
  if(!pos) return '?';
132152
132322
 
@@ -132161,8 +132331,8 @@ class SetSeqAlign {
132161
132331
  }
132162
132332
 
132163
132333
  return resn;
132164
- */
132165
132334
 
132335
+ /*
132166
132336
  let resid = chainid + '_' + resi;
132167
132337
  let resn = ic.residueId2Name[resid];
132168
132338
  if(!resn) {
@@ -132170,6 +132340,7 @@ class SetSeqAlign {
132170
132340
  }
132171
132341
 
132172
132342
  return resn;
132343
+ */
132173
132344
  }
132174
132345
 
132175
132346
  getResiAferAlign(chainid, bRealign, pos) { let ic = this.icn3d, me = ic.icn3dui;
@@ -132514,7 +132685,7 @@ class SetSeqAlign {
132514
132685
  let start1, end1;
132515
132686
 
132516
132687
  //ic.qt_start_end is zero-based
132517
- if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
132688
+ if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment or seqalign
132518
132689
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
132519
132690
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
132520
132691
  }
@@ -132549,15 +132720,18 @@ class SetSeqAlign {
132549
132720
 
132550
132721
  let resid2rangeArray = Object.keys(resid2range_t);
132551
132722
  resid2rangeArray.sort(function(a, b) {
132552
- return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
132723
+ let idArray1 = me.utilsCls.getIdArray(a);
132724
+ let idArray2 = me.utilsCls.getIdArray(b);
132725
+ return parseInt(idArray1[2]) - parseInt(idArray2[2]);
132553
132726
  });
132554
132727
 
132555
132728
  // assign range to each resi
132556
132729
  let prevResi = -999, start = 0, end = 0, residArray = [], prevEnd = 0;
132557
132730
  for(let i = 0, il = resid2rangeArray.length; i < il; ++i) {
132558
132731
  let resid = resid2rangeArray[i];
132559
- let resi = resid.split('_')[2];
132560
-
132732
+ let idArray = me.utilsCls.getIdArray(resid);
132733
+ let resi = idArray[2];
132734
+
132561
132735
  if(i == 0) {
132562
132736
  start = resi;
132563
132737
  }
@@ -132596,7 +132770,9 @@ class SetSeqAlign {
132596
132770
  let resid = chainid1 + '_' + resi;
132597
132771
 
132598
132772
  // let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : j + baseResi;
132599
- let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132773
+ //let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132774
+ //!!!
132775
+ let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132600
132776
 
132601
132777
  //if(j + baseResi < start_t || j + baseResi > end_t) {
132602
132778
  if(jAdjusted < start_t || jAdjusted > end_t) {
@@ -132797,21 +132973,23 @@ class SetSeqAlign {
132797
132973
  }
132798
132974
  }
132799
132975
 
132800
- getTemplatePosFromOriResi(chainid1, start, end, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
132801
- // let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
132802
- // let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
132803
- if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
132804
- let startResi = start;
132805
- let endResi = end;
132976
+ getTemplatePosFromOriPos(chainid1, start, end, bRealign) { let ic = this.icn3d; ic.icn3dui;
132977
+ //!!!
132978
+ let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
132979
+ let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
132980
+
132981
+ // if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
132982
+ // let startResi = start;
132983
+ // let endResi = end;
132806
132984
 
132807
132985
  let result1 = this.getResiPosInTemplate(chainid1, startResi);
132808
132986
  let result2 = this.getResiPosInTemplate(chainid1, endResi);
132809
132987
 
132810
132988
  return {"pos1": result1.pos, "pos2": result2.pos};
132811
- }
132812
- else {
132813
- return {"pos1": start, "pos2": end};
132814
- }
132989
+ // }
132990
+ // else {
132991
+ // return {"pos1": start, "pos2": end};
132992
+ // }
132815
132993
  }
132816
132994
 
132817
132995
  mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
@@ -132883,11 +133061,11 @@ class SetSeqAlign {
132883
133061
  start_t = ic.ParserUtilsCls.getResi(chainid1, start_t);
132884
133062
  end_t = ic.ParserUtilsCls.getResi(chainid1, end_t);
132885
133063
  }
132886
-
133064
+ console.log("### me.cfg.aligntool " + me.cfg.aligntool + " bRealign " + bRealign );
132887
133065
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
132888
- let start1, start2, end1, end2, resiStart1, start1Pos;
133066
+ let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
132889
133067
 
132890
- if(bRealign && me.cfg.aligntool == 'tmalign') { // real residue numbers are stored
133068
+ if(bRealign && (me.cfg.aligntool == 'tmalign')) { // real residue numbers are stored
132891
133069
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start);
132892
133070
  start2 = parseInt(ic.qt_start_end[chainIndex][i].q_start);
132893
133071
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end);
@@ -132901,7 +133079,7 @@ class SetSeqAlign {
132901
133079
  // 1. before the mapped residues
132902
133080
  resiStart1 = start1;
132903
133081
  start1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_start);
132904
- this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133082
+ end1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
132905
133083
  }
132906
133084
  else {
132907
133085
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start - 1);
@@ -132912,6 +133090,7 @@ class SetSeqAlign {
132912
133090
  // 1. before the mapped residues
132913
133091
  resiStart1 = ic.ParserUtilsCls.getResi(chainid1, start1);
132914
133092
  start1Pos = start1;
133093
+ end1Pos = end1;
132915
133094
  }
132916
133095
  //let range = resid2range_t[chainid1 + '_' + resiStart1];
132917
133096
 
@@ -132919,13 +133098,15 @@ class SetSeqAlign {
132919
133098
  if(i == 0) {
132920
133099
  startPosInTemplate = start1Pos;
132921
133100
 
132922
- result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
132923
- //result = this.getTemplatePosFromOriResi(chainid1, start_t, start1Pos, bRealign);
133101
+ //!!!
133102
+ // result = this.getTemplatePosFromOriPos(chainid1, start_t, start1, bRealign);
133103
+ result = this.getTemplatePosFromOriPos(chainid1, start_t, start1Pos, bRealign);
132924
133104
  pos1 = result.pos1;
132925
133105
  pos2 = result.pos2;
132926
133106
 
132927
- if(start1 > start_t) {
132928
- //if(start1Pos > start_t) {
133107
+ //!!!
133108
+ // if(start1 > start_t) {
133109
+ if(start1Pos > start_t) {
132929
133110
  for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
132930
133111
  ic.alnChainsSeq[chainid2].push(gapResObject2);
132931
133112
  }
@@ -132933,7 +133114,7 @@ class SetSeqAlign {
132933
133114
  }
132934
133115
  else {
132935
133116
  //let notAlnLen1 = start1 - (prevIndex1 + 1);
132936
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
133117
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, start1, bRealign);
132937
133118
  pos1 = result.pos1;
132938
133119
  pos2 = result.pos2;
132939
133120
  let notAlnLen1 = pos2 - (pos1 + 1);
@@ -132958,15 +133139,16 @@ class SetSeqAlign {
132958
133139
  }
132959
133140
 
132960
133141
  // 2. In the mapped residues
132961
- result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
132962
- //result = this.getTemplatePosFromOriResi(chainid1, start1Pos, end1Pos, bRealign);
133142
+ // result = this.getTemplatePosFromOriPos(chainid1, start1, end1, bRealign);
133143
+ result = this.getTemplatePosFromOriPos(chainid1, start1Pos, end1Pos, bRealign);
132963
133144
  pos1 = result.pos1;
132964
133145
  pos2 = result.pos2;
132965
133146
 
132966
133147
  let k = 0;
132967
133148
  if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
132968
133149
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
132969
- let resiAdjust = (bRealign && me.cfg.aligntool == 'tmalign') ? 0 : - startPosInTemplate + nGapInTemplate;
133150
+ //!!!!!!
133151
+ let resiAdjust = ((bRealign && me.cfg.aligntool == 'tmalign') || me.cfg.aligntool == 'seqalign') ? 0 : - startPosInTemplate + nGapInTemplate;
132970
133152
  for(let j = pos1; j <= pos2; ++j) {
132971
133153
  // inherit the gaps from the template
132972
133154
  if(ic.alnChainsSeq[chainid1][j + resiAdjust].resn == '-') {
@@ -133001,7 +133183,7 @@ class SetSeqAlign {
133001
133183
  }
133002
133184
 
133003
133185
  // add gaps at the end
133004
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
133186
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, end_t, bRealign);
133005
133187
  pos1 = result.pos1;
133006
133188
  pos2 = result.pos2;
133007
133189
  for(let i = pos1; i < pos2; ++i) {
@@ -133337,7 +133519,7 @@ class SetSeqAlign {
133337
133519
  }
133338
133520
  }
133339
133521
 
133340
- setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
133522
+ setMsaFormat(chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
133341
133523
  //set MSA
133342
133524
  let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
133343
133525
  let chainArrayClustal = [];
@@ -133349,7 +133531,9 @@ class SetSeqAlign {
133349
133531
  fastaFormat += '>' + chainid + '\n';
133350
133532
 
133351
133533
  let clustalwArray = [];
133352
- let clustalwLine = chainid.padEnd(20, ' ');
133534
+ let itemArray = me.utilsCls.getIdArray(chainid);
133535
+ let chainidStr = 'pdb|' + itemArray[0] + '|' + itemArray[1];
133536
+ let clustalwLine = chainidStr.padEnd(20, ' ');
133353
133537
  let consLine = ''.padEnd(20, ' ');
133354
133538
 
133355
133539
  let resiArrayTarget = [], resiArrayQuery = [];
@@ -133889,7 +134073,7 @@ class LoadPDB {
133889
134073
  //if(residueNum !== prevResidueNum) {
133890
134074
 
133891
134075
  if(oriResidueNum !== prevOriResidueNum) {
133892
- let residue = me.utilsCls.residueName2Abbr(resn);
134076
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
133893
134077
  ic.residueId2Name[residueNum] = residue;
133894
134078
 
133895
134079
  if(serial !== 1 && prevResidueNum !== '') ic.residues[prevResidueNum] = residuesTmp;
@@ -134336,7 +134520,7 @@ class LoadPDB {
134336
134520
 
134337
134521
  for(let chainid in chains) {
134338
134522
  if(pdbid !== undefined) {
134339
- let textArray = chainid.split('_');
134523
+ let textArray = me.utilsCls.getIdArray(chainid);
134340
134524
  if(textArray[0] !== pdbid) continue; // skip different chain
134341
134525
  }
134342
134526
 
@@ -134444,15 +134628,15 @@ class LoadCIF {
134444
134628
  loadCIF(bcifData, bcifid, bText, bAppend, supercell) { let ic = this.icn3d, me = ic.icn3dui;
134445
134629
  ic.cifText = bText;
134446
134630
  ic.cifData = bcifData;
134447
-
134631
+
134448
134632
  if(supercell === undefined) {
134449
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true };
134633
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134450
134634
  }
134451
134635
  else if(supercell === 0) {
134452
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: false };
134636
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134453
134637
  }
134454
134638
  else {
134455
- CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true };
134639
+ CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134456
134640
  }
134457
134641
 
134458
134642
  let hAtoms = {};
@@ -134468,7 +134652,7 @@ class LoadCIF {
134468
134652
  let serial, moleculeNum;
134469
134653
  // if(!bMutation && !bAppend) {
134470
134654
  if(!bAppend) {
134471
- ic.init();
134655
+ ic.init(undefined, true); // keep original configurations, such as color, style, etc. when loading multiple structures
134472
134656
  moleculeNum = 0; //1;
134473
134657
  serial = 0;
134474
134658
  }
@@ -134512,11 +134696,13 @@ class LoadCIF {
134512
134696
 
134513
134697
  if (parsed.isError) {
134514
134698
  // report error:
134515
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
134699
+ var aaa = 1; //alert("2 The Binary CIF data can NOT be parsed: " + parsed.toString());
134516
134700
  return;
134517
134701
  }
134518
134702
 
134519
134703
  let block = parsed.result.dataBlocks[0];
134704
+
134705
+ if(!block) continue;
134520
134706
 
134521
134707
  if(block.getCategory("_entry")) {
134522
134708
  id = block.getCategory("_entry").getColumn("id").getString(0);
@@ -134755,6 +134941,8 @@ class LoadCIF {
134755
134941
  ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
134756
134942
  ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
134757
134943
  ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
134944
+
134945
+ me.htmlCls.clickMenuCls.setLogCmd("define unitcell | " + ic.cell.length_a + " | " + ic.cell.length_b + " | " + ic.cell.length_c + " | " + ic.cell.angle_alpha + " | " + ic.cell.angle_beta + " | " + ic.cell.angle_gamma, true);
134758
134946
  }
134759
134947
 
134760
134948
  // if (record === 'ENDMDL') {
@@ -135099,7 +135287,7 @@ class LoadCIF {
135099
135287
 
135100
135288
  // if(oriResidueNum !== prevOriResidueNum) {
135101
135289
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
135102
- let residue = me.utilsCls.residueName2Abbr(resn);
135290
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
135103
135291
 
135104
135292
  ic.residueId2Name[residueNum] = residue;
135105
135293
 
@@ -136398,6 +136586,16 @@ class ApplyCommand {
136398
136586
  ic.opts['unitcell'] = 'no';
136399
136587
  ic.drawCls.draw();
136400
136588
  }
136589
+ else if(command.indexOf('define unitcell') !== -1) {
136590
+ let itemArray = command.split(' | ');
136591
+ ic.cell = {};
136592
+ ic.cell.length_a = parseFloat(itemArray[1]);
136593
+ ic.cell.length_b = parseFloat(itemArray[2]);
136594
+ ic.cell.length_c = parseFloat(itemArray[3]);
136595
+ ic.cell.angle_alpha = parseFloat(itemArray[4]);
136596
+ ic.cell.angle_beta = parseFloat(itemArray[5]);
136597
+ ic.cell.angle_gamma = parseFloat(itemArray[6]);
136598
+ }
136401
136599
  else if(command == 'set fog on') {
136402
136600
  ic.opts['fog'] = 'yes';
136403
136601
  ic.fogCls.setFog(true);
@@ -136428,7 +136626,7 @@ class ApplyCommand {
136428
136626
  let pos = command.lastIndexOf(' ');
136429
136627
  let supercell = parseInt(command.substr(pos + 1));
136430
136628
 
136431
- await me.htmlCls.clickMenuCls.setSupercell(supercell);
136629
+ me.htmlCls.clickMenuCls.setSupercell(supercell);
136432
136630
  }
136433
136631
  else if(command == 'set chemicalbinding show') {
136434
136632
  ic.setOptionCls.setOption('chemicalbinding', 'show');
@@ -136863,7 +137061,8 @@ class ApplyCommand {
136863
137061
  else if(commandOri.indexOf('select interaction') == 0) {
136864
137062
  let idArray = commandOri.substr(commandOri.lastIndexOf(' ') + 1).split(',');
136865
137063
  if(idArray !== null) {
136866
- let mmdbid = idArray[0].split('_')[0];
137064
+ let itemArray = me.utilsCls.getIdArray(idArray[0]);
137065
+ let mmdbid = itemArray[0];
136867
137066
  if(!ic.b2DShown) ic.ParserUtilsCls.download2Ddgm(mmdbid.toUpperCase());
136868
137067
 
136869
137068
  ic.diagram2dCls.selectInteraction(idArray[0], idArray[1]);
@@ -138709,7 +138908,7 @@ class DefinedSets {
138709
138908
 
138710
138909
  }
138711
138910
 
138712
- selectCombinedSets(strSets, commandname) { let ic = this.icn3d; ic.icn3dui;
138911
+ selectCombinedSets(strSets, commandname) { let ic = this.icn3d, me = ic.icn3dui;
138713
138912
  let idArray = strSets.split(' ');
138714
138913
 
138715
138914
  let orArray = [], andArray = [], notArray = [];
@@ -138717,7 +138916,7 @@ class DefinedSets {
138717
138916
 
138718
138917
  for(let i = 0, il = idArray.length; i < il; ++i) {
138719
138918
  // replace 1CD8_A_1 with 1CD8_A1
138720
- let tmpArray = idArray[i].split('_');
138919
+ let tmpArray = me.utilsCls.getIdArray(idArray[i]);
138721
138920
  if(tmpArray.length == 3 && !isNaN(tmpArray[2])) {
138722
138921
  idArray[i] = tmpArray[0] + '_' + tmpArray[1] + tmpArray[2];
138723
138922
  }
@@ -139719,7 +139918,7 @@ class LoadScript {
139719
139918
 
139720
139919
  // load pdb, mmcif, mmdb, cid
139721
139920
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
139722
- if(id.length == 4) id = id.toUpperCase();
139921
+ if(id.length == 4 || id.indexOf('pdb_') == 0) id = id.toUpperCase();
139723
139922
 
139724
139923
  // skip loading the structure if
139725
139924
  // 1. PDB was in the iCn3D PNG Image file
@@ -139766,6 +139965,10 @@ class LoadScript {
139766
139965
  me.cfg.mmcifid = id;
139767
139966
  await ic.mmcifParserCls.downloadMmcif(id);
139768
139967
  }
139968
+ else if(command.indexOf('load cod') !== -1) {
139969
+ me.cfg.codid = id;
139970
+ await ic.mmcifParserCls.downloadCod(id);
139971
+ }
139769
139972
  else if(command.indexOf('load mmdb ') !== -1 || command.indexOf('load mmdb1 ') !== -1) {
139770
139973
  me.cfg.mmdbid = id;
139771
139974
  me.cfg.bu = 1;
@@ -140280,7 +140483,7 @@ class SelectByCommand {
140280
140483
 
140281
140484
  // convert 1TOP_A:20 to $1TOP.A:20
140282
140485
  if(commandArray[i].indexOf('_') !== -1) {
140283
- let itemArray = commandArray[i].split('_');
140486
+ let itemArray = me.utilsCls.getIdArray(commandArray[i]);
140284
140487
  if(itemArray.length ==2 ) {
140285
140488
  commandArray[i] = '$' + itemArray[0] + '.' + itemArray[1];
140286
140489
  }
@@ -143161,24 +143364,6 @@ class Dssp {
143161
143364
  if(!me.bNode) console.log("domainid: " + domainid);
143162
143365
  }
143163
143366
 
143164
- // count the number of matched strands
143165
- // let strandHash = {};
143166
- // for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
143167
- // let seg = queryData[0].segs[j];
143168
- // let q_start = parseInt(seg.q_start)
143169
-
143170
- // let strand = this.getStrandFromRefnum(q_start);
143171
- // strandHash[strand] = 1;
143172
- // }
143173
-
143174
- // let tmAdjust = 0.1;
143175
-
143176
- // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
143177
- // if(!domainid2segs.hasOwnProperty(domainid) ||
143178
- // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
143179
- // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
143180
- // ) {
143181
-
143182
143367
  // use TM-score alone
143183
143368
  if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
143184
143369
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res + '_' + queryData[0].score2;
@@ -144510,7 +144695,7 @@ class Scap {
144510
144695
  let snpArray = snp.split(','); //stru_chain_resi_snp
144511
144696
  let atomHash = {}, snpResidArray = [], chainResi2pdb = {};
144512
144697
  for(let i = 0, il = snpArray.length; i < il; ++i) {
144513
- let idArray = snpArray[i].split('_'); //stru_chain_resi_snp
144698
+ let idArray = me.utilsCls.getIdArray(snpArray[i]); //stru_chain_resi_snp
144514
144699
 
144515
144700
  let resid = idArray[0] + '_' + idArray[1] + '_' + idArray[2];
144516
144701
  atomHash = me.hashUtilsCls.unionHash(atomHash, ic.residues[resid]);
@@ -147662,7 +147847,8 @@ class Diagram2d {
147662
147847
  if(refnumLabel) {
147663
147848
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
147664
147849
  if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
147665
- ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
147850
+ let idArray = me.utilsCls.getIdArray(resid);
147851
+ ic.refnum2resn[domainid][refnumStr] = resn + idArray[2];
147666
147852
  }
147667
147853
  }
147668
147854
 
@@ -149162,7 +149348,8 @@ class ResizeCanvas {
149162
149348
  let width = me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
149163
149349
  let height = me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
149164
149350
 
149165
- if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
149351
+ // if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
149352
+ if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height, true, true);
149166
149353
  });
149167
149354
  }
149168
149355
  }
@@ -153912,8 +154099,8 @@ class iCn3D {
153912
154099
  }
153913
154100
  }
153914
154101
  //When users first load a structure, call this function to empty previous settings.
153915
- iCn3D.prototype.init = function (bKeepCmd) {
153916
- this.init_base();
154102
+ iCn3D.prototype.init = function (bKeepCmd, bKeepConfig) {
154103
+ this.init_base(bKeepCmd, bKeepConfig);
153917
154104
 
153918
154105
  this.molTitle = "";
153919
154106
 
@@ -153933,8 +154120,8 @@ iCn3D.prototype.init = function (bKeepCmd) {
153933
154120
  this.axes = [];
153934
154121
  };
153935
154122
 
153936
- iCn3D.prototype.init_base = function (bKeepCmd) {
153937
- this.resetConfig();
154123
+ iCn3D.prototype.init_base = function (bKeepCmd, bKeepConfig) {
154124
+ if(!bKeepConfig) this.resetConfig();
153938
154125
 
153939
154126
  this.structures = {}; // structure name -> array of chains
153940
154127
  this.chains = {}; // structure_chain name -> atom hash
@@ -154124,7 +154311,7 @@ class iCn3DUI {
154124
154311
  //even when multiple iCn3D viewers are shown together.
154125
154312
  this.pre = this.cfg.divid + "_";
154126
154313
 
154127
- this.REVISION = '3.54.3';
154314
+ this.REVISION = '3.54.4';
154128
154315
 
154129
154316
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154130
154317
  this.bNode = (Object.keys(window).length < 3) ? true : false;
@@ -154326,7 +154513,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154326
154513
  let domainidArray = me.cfg.matchedchains.split(',');
154327
154514
  let chainidArray = [];
154328
154515
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
154329
- let idArray = domainidArray[i].split('_');
154516
+ let idArray = me.utilsCls.getIdArray(domainidArray[i]);
154330
154517
  chainidArray.push(idArray[0] + '_' + idArray[1]);
154331
154518
  }
154332
154519
 
@@ -154369,14 +154556,14 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154369
154556
  await ic.pdbParserCls.downloadUrl(url, type, me.cfg.command);
154370
154557
  }
154371
154558
  else if(me.cfg.mmtfid !== undefined) {
154372
- if(me.cfg.mmtfid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.mmtfid = me.cfg.mmtfid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154559
+ // if(me.cfg.mmtfid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.mmtfid = me.cfg.mmtfid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154373
154560
  ic.inputid = me.cfg.mmtfid;
154374
154561
  ic.loadCmd = 'load mmtf ' + me.cfg.mmtfid;
154375
154562
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154376
154563
  await ic.bcifParserCls.downloadBcif(me.cfg.mmtfid);
154377
154564
  }
154378
154565
  else if(me.cfg.bcifid !== undefined) {
154379
- if(me.cfg.bcifid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.bcifid = me.cfg.bcifid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154566
+ // if(me.cfg.bcifid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.bcifid = me.cfg.bcifid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154380
154567
  ic.inputid = me.cfg.bcifid;
154381
154568
  ic.loadCmd = 'load bcif ' + me.cfg.bcifid;
154382
154569
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -154551,6 +154738,12 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154551
154738
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154552
154739
  await ic.mmcifParserCls.downloadMmcif(me.cfg.mmcifid);
154553
154740
  }
154741
+ else if(me.cfg.codid !== undefined) {
154742
+ ic.inputid = me.cfg.codid;
154743
+ ic.loadCmd = 'load cod ' + me.cfg.codid;
154744
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154745
+ await ic.mmcifParserCls.downloadCod(me.cfg.codid);
154746
+ }
154554
154747
  else if(me.cfg.align !== undefined) {
154555
154748
  // ic.bNCBI = true;
154556
154749
  if(me.cfg.align.indexOf('185055,') != -1) {
@@ -154711,6 +154904,8 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
154711
154904
 
154712
154905
  reject('error');
154713
154906
  }
154907
+
154908
+ me.icn3d.ParserUtilsCls.hideLoading();
154714
154909
  }
154715
154910
  else {
154716
154911
  me.icn3d.ParserUtilsCls.showLoading();
@@ -154863,18 +155058,6 @@ iCn3DUI.prototype.setDialogAjax = function() { let me = this;
154863
155058
  });
154864
155059
  };
154865
155060
 
154866
- /*
154867
- iCn3DUI.prototype.setIcn3dui = function(id) { let me = this;
154868
- let idArray = id.split('_'); // id: div0_reload_pdbfile
154869
- ic.pre = idArray[0] + "_";
154870
- if(window.icn3duiHash !== undefined && window.icn3duiHash.hasOwnProperty(idArray[0])) { // for multiple 3D display
154871
- me = window.icn3duiHash[idArray[0]];
154872
- }
154873
- return me;
154874
- };
154875
- */
154876
-
154877
-
154878
155061
  // required by npm
154879
155062
  class printMsg {
154880
155063
  constructor() {