icn3d 3.54.6 → 3.54.8

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.
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);
@@ -60569,7 +60702,7 @@ class SetMenu {
60569
60702
  //html += this.getMenuText('mn1_fold', 'AlphaFold/ESM', undefined, undefined, 1);
60570
60703
  html += this.getMenuText('mn1_fold', 'Predict by Seq.', undefined, undefined, 1);
60571
60704
  html += "<ul>";
60572
- html += this.getLink('mn1_esmfold', 'ESMFold', undefined, 2);
60705
+ //html += this.getLink('mn1_esmfold', 'ESMFold', undefined, 2);
60573
60706
  //html += this.getMenuUrl('mn1_esmfold_link', "https://colab.research.google.com/github/sokrypton/ColabFold/blob/main/ESMFold.ipynb", "ESMFold via ColabFold" + me.htmlCls.wifiStr, undefined, 2);
60574
60707
  html += this.getLink('mn1_alphafold', 'AlphaFold2 via ColabFold' + me.htmlCls.wifiStr, undefined, 2);
60575
60708
  html += "</ul>";
@@ -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) {
@@ -62173,7 +62307,6 @@ class Dialog {
62173
62307
  if(status.bSetsInit2) thisClass.openDlg2Ddgm(me.pre + 'dl_definedsets');
62174
62308
  }
62175
62309
  else {
62176
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
62177
62310
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
62178
62311
  }
62179
62312
  }
@@ -62262,7 +62395,6 @@ class Dialog {
62262
62395
  let status = thisClass.getDialogStatus().status;
62263
62396
 
62264
62397
  if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bHbondplot2) &&(!status.bLigplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
62265
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
62266
62398
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
62267
62399
  }
62268
62400
  },
@@ -62307,8 +62439,7 @@ class Dialog {
62307
62439
  }
62308
62440
  }
62309
62441
  else {
62310
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH,(me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) * 0.5, true);
62311
- ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH,(me.htmlCls.HEIGHT) * 0.5, true);
62442
+ //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH,(me.htmlCls.HEIGHT) * 0.5, true);
62312
62443
 
62313
62444
  //height =(me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) * 0.5;
62314
62445
  height =(me.htmlCls.HEIGHT) * 0.5;
@@ -62348,7 +62479,6 @@ class Dialog {
62348
62479
  if(status.bSetsInit2) thisClass.openDlg2Ddgm(me.pre + 'dl_definedsets');
62349
62480
  }
62350
62481
  else {
62351
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
62352
62482
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
62353
62483
  }
62354
62484
  }
@@ -63020,6 +63150,12 @@ class SetDialog {
63020
63150
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
63021
63151
  html += "</div>";
63022
63152
 
63153
+ html += me.htmlCls.divStr + "dl_codid' class='" + dialogClass + "'>";
63154
+ html += this.addNotebookTitle('dl_codid', 'Please input a COD ID');
63155
+ html += "COD ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "codid' value='1000041' size=8> ";
63156
+ html += me.htmlCls.buttonStr + "reload_cod'>Load</button>";
63157
+ html += "</div>";
63158
+
63023
63159
  html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
63024
63160
  html += this.addNotebookTitle('dl_mmdbid', 'Please input an MMDB ID');
63025
63161
  html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
@@ -64475,7 +64611,20 @@ class Events {
64475
64611
  let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
64476
64612
 
64477
64613
  if(nameArray.length == 0) {
64478
- nameArray = $("#" + me.pre + "atomsCustom").val();
64614
+ // nameArray = $("#" + me.pre + "atomsCustom").val();
64615
+
64616
+ // choose the first chain for each structure
64617
+ nameArray = [];
64618
+ let structureHash = {};
64619
+ let chains = ic.resid2specCls.atoms2chains(ic.hAtoms);
64620
+
64621
+ for(let chainid in chains) {
64622
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
64623
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
64624
+ nameArray.push(chainid);
64625
+ structureHash[atom.structure] = 1;
64626
+ }
64627
+ }
64479
64628
  }
64480
64629
 
64481
64630
  if(nameArray.length > 0) {
@@ -64495,20 +64644,6 @@ class Events {
64495
64644
  }
64496
64645
 
64497
64646
  if(bMsa) {
64498
- // choose the first chain for each structure
64499
- if(nameArray.length == 0) {
64500
- nameArray = [];
64501
- let structureHash = {};
64502
-
64503
- for(let chainid in ic.chains) {
64504
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
64505
- if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
64506
- nameArray.push(chainid);
64507
- structureHash[atom.structure] = 1;
64508
- }
64509
- }
64510
- }
64511
-
64512
64647
  await ic.realignParserCls.realignOnStructAlignMsa(nameArray);
64513
64648
  }
64514
64649
  else {
@@ -64682,7 +64817,7 @@ class Events {
64682
64817
  let idArray = ids.split(',');
64683
64818
 
64684
64819
  if(!bAppend) {
64685
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64820
+ if(idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64686
64821
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64687
64822
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64688
64823
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -64694,8 +64829,8 @@ class Events {
64694
64829
  }
64695
64830
  }
64696
64831
  else {
64697
- // single MMDB ID could show memebranes
64698
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64832
+ // single MMDB ID could show membranes
64833
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64699
64834
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64700
64835
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64701
64836
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65183,7 +65318,7 @@ class Events {
65183
65318
  if(!me.cfg.notebook) dialog.dialog( "close" );
65184
65319
  thisClass.setLogCmd("load mmtf " + $("#" + me.pre + "mmtfid").val(), false);
65185
65320
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65186
- window.open(hostUrl + '?mmtfid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65321
+ window.open(hostUrl + '?bcifid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65187
65322
  }
65188
65323
  });
65189
65324
 
@@ -65527,7 +65662,7 @@ class Events {
65527
65662
  await ic.scapCls.retrieveScap(snp, bInteraction);
65528
65663
  thisClass.setLogCmd('scap interaction ' + snp, true);
65529
65664
 
65530
- let idArray = snp.split('_'); //stru_chain_resi_snp
65665
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
65531
65666
  let select = '.' + idArray[1] + ':' + idArray[2];
65532
65667
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
65533
65668
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -65566,7 +65701,6 @@ class Events {
65566
65701
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65567
65702
  window.open(hostUrl + '?mmcifid=' + $("#" + me.pre + "mmcifid").val(), urlTarget);
65568
65703
  });
65569
-
65570
65704
  me.myEventCls.onIds("#" + me.pre + "mmcifid", "keyup", function(e) { let ic = me.icn3d;
65571
65705
  if (e.keyCode === 13) {
65572
65706
  e.preventDefault();
@@ -65577,6 +65711,23 @@ class Events {
65577
65711
  }
65578
65712
  });
65579
65713
 
65714
+ me.myEventCls.onIds("#" + me.pre + "reload_cod", "click", function(e) { let ic = me.icn3d;
65715
+ e.preventDefault();
65716
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65717
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65718
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65719
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65720
+ });
65721
+ me.myEventCls.onIds("#" + me.pre + "codid", "keyup", function(e) { let ic = me.icn3d;
65722
+ if (e.keyCode === 13) {
65723
+ e.preventDefault();
65724
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65725
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65726
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65727
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65728
+ }
65729
+ });
65730
+
65580
65731
 
65581
65732
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { let ic = me.icn3d;
65582
65733
  e.preventDefault();
@@ -68162,7 +68313,7 @@ class Events {
68162
68313
  await ic.scapCls.retrieveScap(snp, bInteraction);
68163
68314
  thisClass.setLogCmd('scap interaction ' + snp, true);
68164
68315
 
68165
- let idArray = snp.split('_'); //stru_chain_resi_snp
68316
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
68166
68317
  let select = '.' + idArray[1] + ':' + idArray[2];
68167
68318
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
68168
68319
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -78186,6 +78337,43 @@ class Camera {
78186
78337
  // }
78187
78338
  }
78188
78339
 
78340
+ // Keep the slab plane at the same position relative to the molecule when zooming.
78341
+ // In perspective mode zooming moves the camera along the view direction, so the near plane
78342
+ // (distance from the camera) has to move with it. In orthographic mode zooming only changes
78343
+ // the frustum size and the camera does not move, so the slab plane already stays fixed.
78344
+ updateSlabByZoom() { let ic = this.icn3d, me = ic.icn3dui;
78345
+ if(ic.opts['slab'] !== 'yes' || me.bNode) return;
78346
+ if(ic.opts.camera.toLowerCase() !== 'perspective') return;
78347
+
78348
+ let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
78349
+ if(bInstance) return; // near plane is fixed at 0.1 for instancing
78350
+
78351
+ let cam = (ic.bControlGl) ? window.cam : ic.cam;
78352
+ let controls = (ic.bControlGl) ? window.controls : ic.controls;
78353
+
78354
+ // at zoom = 1 the slab plane is ic.maxD * camMaxDFactor from the camera, i.e. the plane through
78355
+ // the center (or 10 angstroms in front of it when fog is on to keep some surrounding residues)
78356
+ let offset = (ic.camMaxDFactorFog !== undefined) ? 10 : 0;
78357
+
78358
+ // current distance from the camera to the center of rotation, which changes with zooming
78359
+ let dist = cam.position.distanceTo(controls.target);
78360
+
78361
+ // keep the plane at the same position relative to the molecule
78362
+ let nearClip = Math.max(0.1, dist - offset);
78363
+
78364
+ if(Math.abs(cam.near - nearClip) > 1e-6) {
78365
+ cam.near = nearClip;
78366
+ cam.updateProjectionMatrix();
78367
+ if(ic.cam && ic.cam !== cam) {
78368
+ ic.cam.near = nearClip;
78369
+ ic.cam.updateProjectionMatrix();
78370
+ }
78371
+ }
78372
+
78373
+ // the impostor shaders (spheres, cylinders) clip with the nearClip uniform
78374
+ if(ic.uniforms && ic.uniforms.nearClip) ic.uniforms.nearClip.value = nearClip;
78375
+ }
78376
+
78189
78377
  setSlab() { let ic = this.icn3d, me = ic.icn3dui;
78190
78378
  if(ic.bControlGl && !me.bNode) {
78191
78379
  let maxD = ic.maxD;
@@ -78301,7 +78489,8 @@ class Fog {
78301
78489
  else {
78302
78490
  // adjust
78303
78491
  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);
78492
+ let fogStrength = 2; // 1 = current, >1 = stronger
78493
+ ic.scene.fog = new Fog$1(background, (3 - 0.5 / fogStrength) * ic.maxD * zoomFactor, (3 + 1.0 / fogStrength) * ic.maxD * zoomFactor);
78305
78494
  ic.bSetFog = true;
78306
78495
  ic.camMaxDFactorFog = 3;
78307
78496
  }
@@ -80526,6 +80715,8 @@ class Tube {
80526
80715
 
80527
80716
  let prevAxis1 = new Vector3$1(), prevAxis2;
80528
80717
  for (let i = 0, lim = pnts.length; i < lim; ++i) {
80718
+ if(!pnts[i]) continue;
80719
+
80529
80720
  let r, idx = (i - 1) * axisDivInv;
80530
80721
 
80531
80722
  if (i === 0) {
@@ -80558,7 +80749,7 @@ class Tube {
80558
80749
  }
80559
80750
 
80560
80751
  let delta, axis1, axis2;
80561
- if (i < lim - 1) {
80752
+ if (i < lim - 1 && pnts[i + 1]) {
80562
80753
  delta = pnts[i].clone().sub(pnts[i + 1]);
80563
80754
  axis1 = new Vector3$1(0, -delta.z, delta.y).normalize().multiplyScalar(r);
80564
80755
  axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
@@ -84544,7 +84735,6 @@ class Surface {
84544
84735
  let chainStr = (Object.keys(chainHash).length > 1) ? '<th>Chain</th>' : '';
84545
84736
  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
84737
  for(let resid in ic.resid2area) {
84547
- //var idArray = resid.split('_');
84548
84738
  let pos = resid.lastIndexOf('_');
84549
84739
  let resn = resid.substr(pos + 1);
84550
84740
 
@@ -85198,6 +85388,8 @@ class ApplyClbonds {
85198
85388
  // only apply to displayed atoms
85199
85389
  // if(!ic.dAtoms.hasOwnProperty(line.serial1) || !ic.dAtoms.hasOwnProperty(line.serial2)) continue;
85200
85390
 
85391
+ if(!ic.atoms[line.serial1] || !ic.atoms[line.serial2]) continue;
85392
+
85201
85393
  line.position1 = ic.atoms[line.serial1].coord;
85202
85394
  line.position2 = ic.atoms[line.serial2].coord;
85203
85395
 
@@ -85328,6 +85520,7 @@ class ApplyClbonds {
85328
85520
  if(type == 'chemical') continue; // just connect checmicals together
85329
85521
 
85330
85522
  if(ic.clbondpnts[atom0.structure] === undefined) ic.clbondpnts[atom0.structure] = [];
85523
+ if(ic.clbondpnts[atom1.structure] === undefined) ic.clbondpnts[atom1.structure] = [];
85331
85524
  ic.clbondpnts[atom0.structure].push(resid0);
85332
85525
  ic.clbondpnts[atom1.structure].push(resid1);
85333
85526
 
@@ -85873,9 +86066,9 @@ class ApplyOther {
85873
86066
  }
85874
86067
  }
85875
86068
 
85876
- ic.lineCls.createLines(ic.lines);
85877
- if(!ic.planes) ic.planes = [];
85878
- ic.cylinderCls.createPlanes(ic.planes);
86069
+ // ic.lineCls.createLines(ic.lines);
86070
+ // if(!ic.planes) ic.planes = [];
86071
+ // ic.cylinderCls.createPlanes(ic.planes);
85879
86072
  // }
85880
86073
 
85881
86074
  // distance sets
@@ -85998,6 +86191,10 @@ class ApplyOther {
85998
86191
  ic.pk = 3;
85999
86192
  break;
86000
86193
  }
86194
+
86195
+ ic.lineCls.createLines(ic.lines);
86196
+ if(!ic.planes) ic.planes = [];
86197
+ ic.cylinderCls.createPlanes(ic.planes);
86001
86198
  }
86002
86199
 
86003
86200
  applyChemicalbindingOptions(options) { let ic = this.icn3d, me = ic.icn3dui;
@@ -87144,6 +87341,8 @@ class Impostor {
87144
87341
 
87145
87342
  let shiness = ic.shininess / 100.0 * 0.5;
87146
87343
 
87344
+ let fogRGB = background.clone().convertLinearToSRGB();
87345
+
87147
87346
  ic.uniforms = UniformsUtils.merge([
87148
87347
  UniformsLib.common,
87149
87348
  {
@@ -87164,7 +87363,8 @@ class Impostor {
87164
87363
  nearClip: { type: "f", value: nearClip },
87165
87364
  ortho: { type: "f", value: 0.0 },
87166
87365
  shrink: { type: "f", value: 0.13 },
87167
- fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87366
+ //fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87367
+ fogColor: { type: "v3", value: [fogRGB.r, fogRGB.g, fogRGB.b] },
87168
87368
  fogNear: { type: "f", value: near },
87169
87369
  fogFar: { type: "f", value: far },
87170
87370
  fogDensity: { type: "f", value: 2.0 }
@@ -105397,6 +105597,9 @@ class WebGLPathTracer {
105397
105597
 
105398
105598
  cam = this.setDirectLight(cam);
105399
105599
 
105600
+ // move the slab plane according to the zoom
105601
+ if(ic.opts['slab'] === 'yes') ic.cameraCls.updateSlabByZoom();
105602
+
105400
105603
  if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
105401
105604
 
105402
105605
  if(ic.bVr) {
@@ -108960,7 +109163,7 @@ class AnnoCddSite {
108960
109163
  ic.bAjaxCddSite = true;
108961
109164
  }
108962
109165
 
108963
- getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d; ic.icn3dui;
109166
+ getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d, me = ic.icn3dui;
108964
109167
  let resiArrayStr = '';
108965
109168
  for(let i = 0, il = resiNCBIArray.length; i < il; ++i) {
108966
109169
  let resiNCBI = resiNCBIArray[i] + 1; // zero-based
@@ -108968,7 +109171,8 @@ class AnnoCddSite {
108968
109171
  let resid = ic.ncbi2resid[residNCBI];
108969
109172
  if(!resid) resid = residNCBI; // this happens sometimes, e.g., Q9Y4K1
108970
109173
 
108971
- let resi = resid.split('_')[2];
109174
+ let idArray = me.utilsCls.getIdArray(resid);
109175
+ let resi = idArray[2];
108972
109176
  if(i > 0) resiArrayStr += ',';
108973
109177
  resiArrayStr += resi;
108974
109178
  }
@@ -110064,7 +110268,8 @@ class AnnoIg {
110064
110268
  let residArray = Object.keys(residHash);
110065
110269
 
110066
110270
  // delete the following loops
110067
- let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, residArray[residArray.length - 1].split('_')[2]);
110271
+ let idArray = me.utilsCls.getIdArray(residArray[residArray.length - 1]);
110272
+ let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110068
110273
 
110069
110274
  for(let j = lastPos + 1, jl = ic.chainsSeq[chnid].length; j < jl; ++j) {
110070
110275
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -110080,7 +110285,8 @@ class AnnoIg {
110080
110285
  }
110081
110286
 
110082
110287
  // delete the previous loops
110083
- ic.setSeqAlignCls.getPosFromResi(chnid, residArray[0].split('_')[2]);
110288
+ idArray = me.utilsCls.getIdArray(residArray[0]);
110289
+ ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110084
110290
 
110085
110291
  for(let j = lastPos - 1; j >= 0; --j) {
110086
110292
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -111083,8 +111289,9 @@ class AnnoSnpClinVar {
111083
111289
  let residHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chnid]);
111084
111290
  // for(let i = 1, il = ic.giSeq[chnid].length; i <= il; ++i) {
111085
111291
  for(let resid in residHash) {
111086
- let i = resid.split('_')[2];
111087
-
111292
+ let idArray = me.utilsCls.getIdArray(resid);
111293
+ let i = idArray[2];
111294
+
111088
111295
  if(resi2index[i] !== undefined) {
111089
111296
  ++snpCnt;
111090
111297
  let allDiseaseTitle = '';
@@ -113277,7 +113484,6 @@ class Domain3d {
113277
113484
  // if(fromPos >= start && toPos <= end) {
113278
113485
  if(ssCnt > 0) jsonStr += ', ';
113279
113486
  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
113487
  jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
113282
113488
  ++ssCnt;
113283
113489
  // }
@@ -113294,7 +113500,6 @@ class Domain3d {
113294
113500
  for(let j = startAll; j <= endAll; ++j) {
113295
113501
  let ncbiResid = chnid + '_' + j;
113296
113502
  let resid = ic.ncbi2resid[ncbiResid];
113297
- resid.split('_')[2];
113298
113503
 
113299
113504
  let pos = j;
113300
113505
 
@@ -113302,7 +113507,6 @@ class Domain3d {
113302
113507
 
113303
113508
  if(!residueHash.hasOwnProperty(resid)) {
113304
113509
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113305
- // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113306
113510
  }
113307
113511
  else {
113308
113512
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -113311,7 +113515,6 @@ class Domain3d {
113311
113515
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
113312
113516
 
113313
113517
  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
113518
  }
113316
113519
 
113317
113520
  ++domainCnt;
@@ -119149,7 +119352,6 @@ class GetGraph {
119149
119352
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
119150
119353
  let node = graphJson.nodes[i];
119151
119354
  //node.r: 1_1_1KQ2_A_1
119152
- //var idArray = node.r.split('_');
119153
119355
  let idArray = [];
119154
119356
  idArray.push('');
119155
119357
  idArray.push('');
@@ -119328,8 +119530,8 @@ class GetGraph {
119328
119530
  compNode(a, b, bReverseChain) { let ic = this.icn3d, me = ic.icn3dui;
119329
119531
  let resid1 = a.r.substr(4); // 1_1_1KQ2_A_1
119330
119532
  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('_');
119533
+ let aIdArray = me.utilsCls.getIdArray(resid1);
119534
+ let bIdArray = me.utilsCls.getIdArray(resid2);
119333
119535
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
119334
119536
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
119335
119537
  let aResi = parseInt(aIdArray[2]);
@@ -120382,7 +120584,7 @@ class ViewInterPairs {
120382
120584
  residname2 =(type == 'save1') ? residname1_residname2[1] : residname1_residname2[0];
120383
120585
 
120384
120586
  // stru_chain_resi_resn
120385
- let ids = residname1.split('_');
120587
+ let ids = me.utilsCls.getIdArray(residname1);
120386
120588
  if(i > 0 && residname1 != prevResidname1) {
120387
120589
  bondCnt.push({res1: prevResidname1, res2: residname2List, cntHbond: cntHbond, cntIonic: cntIonic, cntContact: cntContact, cntHalegen: cntHalegen, cntPication: cntPication, cntPistacking: cntPistacking});
120388
120590
 
@@ -121783,8 +121985,8 @@ class AlignParser {
121783
121985
  //var scale = data2.transform.scale / factor;
121784
121986
  let tMaster = data2.transform.translate.master;
121785
121987
  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);
121988
+ let tQuery = data2.transform.translate.slave; // actually means query protein
121989
+ let tSVector = new Vector3$1(tQuery[0] / factor, tQuery[1] / factor, tQuery[2] / factor);
121788
121990
  let rotation = data2.transform.rotate;
121789
121991
  let rMatrix = [];
121790
121992
  for(let i = 0, il = rotation.length; i < il; ++i) { // 9 elements
@@ -122028,44 +122230,6 @@ class ChainalignParser {
122028
122230
  // calculate secondary structures with applyCommandDssp
122029
122231
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
122030
122232
  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
122233
 
122070
122234
  // new version to be done for VASTsrv ==============
122071
122235
  // dynamically align pairs in all chainids
@@ -122534,10 +122698,10 @@ class ChainalignParser {
122534
122698
  return chainidArray;
122535
122699
  }
122536
122700
 
122537
- addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
122701
+ addPostfixForStructureids(structArray) { let ic = this.icn3d, me = ic.icn3dui;
122538
122702
  let struct2cnt = {};
122539
122703
  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
122704
+ 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
122705
 
122542
122706
  let struct = structArray[i].toUpperCase();
122543
122707
 
@@ -122561,6 +122725,8 @@ class ChainalignParser {
122561
122725
 
122562
122726
  ic.opts['proteins'] = 'c alpha trace';
122563
122727
 
122728
+ if(!chainalign) return;
122729
+
122564
122730
  let alignArray = chainalign.split(',');
122565
122731
  let domainArray = (me.cfg.domainids) ? me.cfg.domainids.split(',') : [];
122566
122732
  if(domainArray.length < alignArray.length) domainArray = [];
@@ -122633,7 +122799,7 @@ class ChainalignParser {
122633
122799
  let domainalign = (domainArray.length > 0) ? domainArray[index] + "," + domainArray[0] : undefined;
122634
122800
 
122635
122801
  // 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) {
122802
+ 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
122803
  let urlalign;
122638
122804
 
122639
122805
  if(domainArray.length > 0) {
@@ -122922,7 +123088,7 @@ class ChainalignParser {
122922
123088
  }
122923
123089
  else {
122924
123090
  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
123091
+ 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
123092
 
122927
123093
  let id = structArrayTmp[i].toUpperCase();
122928
123094
  if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
@@ -124453,6 +124619,19 @@ class MmcifParser {
124453
124619
  await ic.opmParserCls.loadOpmData(data, mmcifid, undefined, 'mmcif', undefined, bText);
124454
124620
  }
124455
124621
 
124622
+ async downloadCod(codid) { let ic = this.icn3d, me = ic.icn3dui;
124623
+ //ic.bCid = undefined;
124624
+
124625
+ ic.ParserUtilsCls.setYourNote(codid.toUpperCase() + '(COD) in iCn3D');
124626
+
124627
+ let url = "https://www.crystallography.net/cod/" + codid + ".cif";
124628
+ // let url = "https://www.crystallography.net/cif/1/00/00/1000041.cif";
124629
+ let data = await me.getAjaxPromise(url, 'text', true);
124630
+
124631
+ let bText = true;
124632
+ ic.loadCIFCls.loadCIF(data, codid, bText);
124633
+ }
124634
+
124456
124635
  async downloadMmcifSymmetry(mmcifid, type) { let ic = this.icn3d, me = ic.icn3dui;
124457
124636
  try {
124458
124637
  // let url = "https://files.rcsb.org/download/" + mmcifid + ".cif";
@@ -124566,6 +124745,11 @@ class MmcifParser {
124566
124745
  ic.opts['color'] = 'structure';
124567
124746
  }
124568
124747
 
124748
+ if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
124749
+ ic.pk = 1;
124750
+ ic.opts['pk'] = 'atom';
124751
+ }
124752
+
124569
124753
  ic.opmParserCls.modifyUIMapAssembly();
124570
124754
 
124571
124755
  await ic.pdbParserCls.addSecondary(bAppend);
@@ -124659,9 +124843,10 @@ class MmdbParser {
124659
124843
  me.cfg.query_id = idArray[0];
124660
124844
  me.cfg.blast_rep_id = idArray[1];
124661
124845
 
124662
- let mmdbid = me.cfg.blast_rep_id.split('_')[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124846
+ let textArray = me.utilsCls.getIdArray(me.cfg.blast_rep_id);
124847
+ let mmdbid = textArray[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124663
124848
 
124664
- if(mmdbid.length == 4) { // pdb
124849
+ if(mmdbid.length == 4 || mmdbid.indexOf('pdb_') == 0) { // pdb
124665
124850
  await this.downloadMmdb(mmdbid);
124666
124851
  }
124667
124852
  else {
@@ -124813,7 +124998,7 @@ class MmdbParser {
124813
124998
  if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
124814
124999
  // save a set named me.cfg.ligand
124815
125000
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
124816
- let idArray = Object.keys(residueHash)[0].split('_');
125001
+ let idArray = me.utilsCls.getIdArray(Object.keys(residueHash)[0]);
124817
125002
  let select = '.' + idArray[1] + ':' + idArray[2];
124818
125003
 
124819
125004
  await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
@@ -124949,8 +125134,8 @@ class MmdbParser {
124949
125134
 
124950
125135
  if(type === undefined || type === 'target') {
124951
125136
  // if a command contains "load...", the commands should not be cleared with init()
124952
- let bKeepCmd = (ic.bCommandLoad) ? true : false;
124953
- if(!ic.bStatefile) ic.init(bKeepCmd);
125137
+ let bClearCmd = (ic.bCommandLoad) ? false : true;
125138
+ if(!ic.bStatefile) ic.init(bClearCmd);
124954
125139
 
124955
125140
  ic.chainsColor = {};
124956
125141
  ic.chainsGene = {};
@@ -125190,7 +125375,7 @@ class BcifParser {
125190
125375
 
125191
125376
  if (parsed.isError) {
125192
125377
  // report error:
125193
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
125378
+ var aaa = 1; //alert("1 The Binary CIF data can NOT be parsed: " + parsed.toString());
125194
125379
  return;
125195
125380
  }
125196
125381
 
@@ -126155,7 +126340,8 @@ class OpmParser {
126155
126340
  if(!pdbid) pdbid = ic.defaultPdbId;
126156
126341
 
126157
126342
  //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();
126343
+ let shortPdbid = pdbid.indexOf('pdb_0000') == 0 ? pdbid.substr(8) : pdbid;
126344
+ let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + shortPdbid.toLowerCase();
126159
126345
 
126160
126346
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
126161
126347
 
@@ -126417,8 +126603,8 @@ class PdbParser {
126417
126603
  async loadPdbData(data, pdbid, bOpm, bAppend, type, bLastQuery, bNoDssp, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
126418
126604
  if(!bAppend && (type === undefined || type === 'target')) {
126419
126605
  // if a command contains "load...", the commands should not be cleared with init()
126420
- let bKeepCmd = (ic.bCommandLoad) ? true : false;
126421
- if(!ic.bStatefile) ic.init(bKeepCmd);
126606
+ let bClearCmd = (ic.bCommandLoad) ? false : true;
126607
+ if(!ic.bStatefile) ic.init(bClearCmd);
126422
126608
  }
126423
126609
 
126424
126610
  let hAtoms = await ic.loadPDBCls.loadPDB(data, pdbid, bOpm, undefined, undefined, bAppend, type, bEsmfold); // defined in the core library
@@ -127231,7 +127417,7 @@ class DcdParser {
127231
127417
  }
127232
127418
 
127233
127419
  for(let j in residuesOri) {
127234
- let idArray = j.split('_');
127420
+ let idArray = me.utilsCls.getIdArray(j);
127235
127421
  let structure2 = idArray[0] + molNum;
127236
127422
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127237
127423
  ic.residues[residid2] = {};
@@ -127242,7 +127428,7 @@ class DcdParser {
127242
127428
  }
127243
127429
 
127244
127430
  for(let j in chainsOri) {
127245
- let idArray = j.split('_');
127431
+ let idArray = me.utilsCls.getIdArray(j);
127246
127432
  let structure2 = idArray[0] + molNum;
127247
127433
  let chainid2 = structure2 + '_' + idArray[1];
127248
127434
 
@@ -127273,7 +127459,7 @@ class DcdParser {
127273
127459
 
127274
127460
  // set ic.ncbi2resid and ic.resid2ncbi
127275
127461
  for(let chainid in chainsOri) {
127276
- let idArray = chainid.split('_');
127462
+ let idArray = me.utilsCls.getIdArray(chainid);
127277
127463
  let structure2 = idArray[0] + molNum;
127278
127464
  let chainid2 = structure2 + '_' + idArray[1];
127279
127465
 
@@ -127837,7 +128023,7 @@ class XtcParser {
127837
128023
  }
127838
128024
 
127839
128025
  for(let j in residuesOri) {
127840
- let idArray = j.split('_');
128026
+ let idArray = me.utilsCls.getIdArray(j);
127841
128027
  let structure2 = idArray[0] + molNum;
127842
128028
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127843
128029
  ic.residues[residid2] = {};
@@ -127848,7 +128034,7 @@ class XtcParser {
127848
128034
  }
127849
128035
 
127850
128036
  for(let j in chainsOri) {
127851
- let idArray = j.split('_');
128037
+ let idArray = me.utilsCls.getIdArray(j);
127852
128038
  let structure2 = idArray[0] + molNum;
127853
128039
  let chainid2 = structure2 + '_' + idArray[1];
127854
128040
 
@@ -127879,7 +128065,7 @@ class XtcParser {
127879
128065
 
127880
128066
  // set ic.ncbi2resid and ic.resid2ncbi
127881
128067
  for(let chainid in chainsOri) {
127882
- let idArray = chainid.split('_');
128068
+ let idArray = me.utilsCls.getIdArray(chainid);
127883
128069
  let structure2 = idArray[0] + molNum;
127884
128070
  let chainid2 = structure2 + '_' + idArray[1];
127885
128071
 
@@ -128105,9 +128291,8 @@ class MsaParser {
128105
128291
 
128106
128292
  // realign based on residue by residue
128107
128293
  let alignment_final = ic.inputChainidArray.join(',');
128108
-
128109
128294
  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...");
128295
+ 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
128296
  return;
128112
128297
  }
128113
128298
 
@@ -128165,7 +128350,7 @@ class MsaParser {
128165
128350
  }
128166
128351
 
128167
128352
  if(type == 'clustalw') {
128168
- if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
128353
+ if(line.substr(0, 1) != '.' && line.substr(0, 1) != '*') {
128169
128354
  let chainid_seq = line.split(/\s+/);
128170
128355
  let idArray = chainid_seq[0].split('|');
128171
128356
  let result = this.getChainid(idArray, bStart && !bSecBlock);
@@ -128190,9 +128375,11 @@ class MsaParser {
128190
128375
  seq = '';
128191
128376
 
128192
128377
  let pos = line.indexOf(' ');
128378
+ if(pos == -1) pos = line.length;
128193
128379
  let idArray = line.substr(1, pos).split('|');
128194
-
128380
+
128195
128381
  if(idArray.length == 1) {
128382
+ bFound = true;
128196
128383
  chainid = idArray[0];
128197
128384
  }
128198
128385
  else {
@@ -128256,8 +128443,9 @@ class MsaParser {
128256
128443
  ic.inputChainidArray.push(chainid + '_A');
128257
128444
  }
128258
128445
  }
128259
- else if(chainid.indexOf('_') != -1) { // PDB ID
128260
- let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
128446
+ else if(chainid.indexOf('_') != -1 || chainid.indexOf('pdb_') != -1) { // PDB ID
128447
+ let idArray = me.utilsCls.getIdArray(chainid);
128448
+ let stru = idArray[0];
128261
128449
  ic.struArray.push(stru);
128262
128450
  ic.inputChainidArray.push(chainid);
128263
128451
  }
@@ -128339,7 +128527,7 @@ class RealignParser {
128339
128527
  }
128340
128528
 
128341
128529
  // 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)});
128530
+ ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn, true)});
128343
128531
 
128344
128532
  struct2chain[atom.structure] = atom.structure + '_' + atom.chain;
128345
128533
 
@@ -128382,7 +128570,8 @@ class RealignParser {
128382
128570
 
128383
128571
  async parseChainRealignPredefined(chainidArray, struct2SeqHash, struct2CoorHash, struct2resid) { let ic = this.icn3d, me = ic.icn3dui;
128384
128572
 
128385
- let toStruct = chainidArray[0].substr(0, chainidArray[0].indexOf('_')); //.toUpperCase();
128573
+ let itemArray1 = me.utilsCls.getIdArray(chainidArray[0]);
128574
+ let toStruct = itemArray1[0];
128386
128575
 
128387
128576
  let hAtoms = {}, rmsd;
128388
128577
 
@@ -128395,13 +128584,14 @@ class RealignParser {
128395
128584
  ic.qt_start_end = [];
128396
128585
 
128397
128586
  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();
128587
+ for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
128588
+ let itemArray2 = me.utilsCls.getIdArray(chainidArray[index + 1]);
128589
+ let fromStruct = itemArray2[0];
128400
128590
 
128401
128591
  //if(toStruct == fromStruct) fromStruct += me.htmlCls.postfix;
128402
128592
 
128403
- let chainTo = toStruct + chainidArray[0].substr(chainidArray[0].indexOf('_'));
128404
- let chainFrom = fromStruct + chainidArray[index + 1].substr(chainidArray[index + 1].indexOf('_'));
128593
+ let chainTo = toStruct + '_' + itemArray1[1];
128594
+ let chainFrom = fromStruct + '_' + itemArray2[1];
128405
128595
  chainidHash[chainTo] = 1;
128406
128596
  chainidHash[chainFrom] = 1;
128407
128597
 
@@ -128436,7 +128626,7 @@ class RealignParser {
128436
128626
 
128437
128627
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, result.hAtoms);
128438
128628
  rmsd = parseFloat(result.rmsd);
128439
- }
128629
+ }
128440
128630
 
128441
128631
  // If rmsd from vastsrv is too large, realign the chains
128442
128632
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
@@ -128658,15 +128848,6 @@ class RealignParser {
128658
128848
  prevChainid = chainidArrayTmp[i];
128659
128849
  }
128660
128850
 
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
128851
  let bRealign = true;
128671
128852
  ic.qt_start_end = []; // reset the alignment
128672
128853
 
@@ -128911,12 +129092,13 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128911
129092
  let predefinedResArray, predefinedResPair;
128912
129093
 
128913
129094
  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
-
129095
+ me.cfg.resdef = decodeURIComponent(me.cfg.resdef).trim();
129096
+ let tmpStr = me.cfg.resdef.replace(/; /gi, ': ');
129097
+ // predefinedResArray = decodeURIComponent(tmpStr).trim().replace(/\+/gi, ' ').split(': ');
129098
+ predefinedResArray = tmpStr.replace(/\+/gi, ' ').split(': ');
129099
+
128918
129100
  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...");
129101
+ 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
129102
  return;
128921
129103
  }
128922
129104
  }
@@ -128925,8 +129107,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128925
129107
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
128926
129108
  //if(bPredefined) predefinedRes = predefinedResArray[i].trim();
128927
129109
 
128928
- let pos = chainidArray[i].indexOf('_');
128929
- let mmdbid = chainidArray[i].substr(0, pos); //.toUpperCase();
129110
+ let itemArray = me.utilsCls.getIdArray(chainidArray[i]);
129111
+ let mmdbid = itemArray[0]; //.toUpperCase();
128930
129112
 
128931
129113
  // if(!bRealign) mmdbid = mmdbid.toUpperCase();
128932
129114
 
@@ -128934,7 +129116,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128934
129116
  mmdbid_t = mmdbid;
128935
129117
  }
128936
129118
 
128937
- let chainid = mmdbid + chainidArray[i].substr(pos);
129119
+ let chainid = mmdbid + '_' + itemArray[1];
128938
129120
  if(i == 0) chainid_t = chainid;
128939
129121
 
128940
129122
  if(!ic.chainsSeq || !ic.chainsSeq[chainid]) {
@@ -128963,7 +129145,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128963
129145
  if(!struct2CoorHash[chainidpair]) struct2CoorHash[chainidpair] = {};
128964
129146
  if(!struct2resid[chainidpair]) struct2resid[chainidpair] = {};
128965
129147
 
128966
- // master
129148
+ // template
128967
129149
  resiArray = predefinedResPair[0].split(",");
128968
129150
 
128969
129151
  result = thisClass.getSeqCoorResid(resiArray, chainid_t);
@@ -128978,7 +129160,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128978
129160
  struct2CoorHash[chainidpair][mmdbid_t] = struct2CoorHash[chainidpair][mmdbid_t].concat(result.coor);
128979
129161
  struct2resid[chainidpair][mmdbid_t] = struct2resid[chainidpair][mmdbid_t].concat(result.resid);
128980
129162
 
128981
- // slave
129163
+ // query
128982
129164
  resiArray = predefinedResPair[1].split(",");
128983
129165
 
128984
129166
  result = thisClass.getSeqCoorResid(resiArray, chainid);
@@ -129006,7 +129188,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129006
129188
  }
129007
129189
  }
129008
129190
  else {
129009
- if(i == 0) { // master
129191
+ if(i == 0) { // template
129010
129192
  //base = parseInt(ic.chainsSeq[chainid][0].resi);
129011
129193
 
129012
129194
  resiArray = [];
@@ -129046,7 +129228,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129046
129228
  bSelectedBoth = true;
129047
129229
 
129048
129230
  let resn = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]).resn;
129049
- struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn);
129231
+ struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn, true);
129050
129232
 
129051
129233
  struct2CoorHash[chainid] = struct2CoorHash[chainid].concat(this.getResCoorArray(resid));
129052
129234
 
@@ -131361,9 +131543,6 @@ class LoadAtomData {
131361
131543
  atm.coord = new Vector3$1(atm.coord.x, atm.coord.y, atm.coord.z);
131362
131544
  }
131363
131545
 
131364
- // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131365
- let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn);
131366
-
131367
131546
  if((type === 'mmdbid' || type === 'align') && ic.bFullUi ) {
131368
131547
  // set ic.mmdbMolidResid2mmdbChainResi
131369
131548
  if(ic.mmdbMolidResid2mmdbChainResi === undefined) ic.mmdbMolidResid2mmdbChainResi = {};
@@ -131505,6 +131684,8 @@ class LoadAtomData {
131505
131684
  }
131506
131685
  }
131507
131686
 
131687
+ // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131688
+ let oneLetterRes = (atm.het) ? me.utilsCls.residueName2Abbr(atm.resn) : me.utilsCls.residueName2Abbr(atm.resn, true);
131508
131689
  ic.residueId2Name[residueid] = oneLetterRes;
131509
131690
 
131510
131691
  let secondaries = '-';
@@ -131852,59 +132033,6 @@ class SetSeqAlign {
131852
132033
  ic.nconsHash2 = {};
131853
132034
  ic.nalignHash2 = {};
131854
132035
 
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
- }
131860
-
131861
- for(let i = 0, il = seqalign.length; i < il; ++i) {
131862
- // first sequence
131863
- let alignData = seqalign[i][0];
131864
- let molid1 = alignData.moleculeId;
131865
-
131866
- let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
131867
- chainid1 = mmdbid1 + '_' + chain1;
131868
-
131869
- let id2aligninfo = {};
131870
- let start = alignData.sequence.length, end = -1;
131871
- let bStart = false;
131872
- for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
131873
- // 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
- }
131887
-
131888
- id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
131889
- }
131890
-
131891
- // second sequence
131892
- alignData = seqalign[i][1];
131893
-
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;
131897
-
131898
- let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
131899
-
131900
- if(aligned === 2) { // aligned
131901
- if(id2aligninfo[j].resn != resn) {
131902
- msaSameColor[j] = 0;
131903
- }
131904
- }
131905
- }
131906
- }
131907
-
131908
132036
  for(let i = 0, il = seqalign.length; i < il; ++i) {
131909
132037
  // first sequence
131910
132038
  let alignData = seqalign[i][0];
@@ -132001,8 +132129,6 @@ class SetSeqAlign {
132001
132129
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132002
132130
  }
132003
132131
 
132004
- color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132005
-
132006
132132
  // mapping, use the firstsequence as the reference structure
132007
132133
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
132008
132134
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132019,8 +132145,6 @@ class SetSeqAlign {
132019
132145
 
132020
132146
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132021
132147
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132022
-
132023
- msaSameColor[j] = 2; // not aligned
132024
132148
  }
132025
132149
 
132026
132150
  // chain1
@@ -132400,7 +132524,7 @@ class SetSeqAlign {
132400
132524
  }
132401
132525
  }
132402
132526
  }
132403
-
132527
+
132404
132528
  for(let j = 0; j <= end1 - start1; ++j) {
132405
132529
  ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
132406
132530
 
@@ -132513,29 +132637,43 @@ class SetSeqAlign {
132513
132637
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
132514
132638
  let start1, end1;
132515
132639
 
132516
- //ic.qt_start_end is zero-based
132517
- if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
132518
- start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
132519
- end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
132520
- }
132521
- else {
132522
- start1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_start) - 1;
132523
- end1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_end) - 1;
132524
- }
132525
-
132640
+ // if(bRealign) { // real residue numbers are stored
132641
+ // start1 = ic.qt_start_end[chainIndex][i].t_start;
132642
+ // end1 = ic.qt_start_end[chainIndex][i].t_end;
132643
+ // }
132644
+ // else {
132645
+ //ic.qt_start_end is zero-based
132646
+ if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
132647
+ start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
132648
+ end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
132649
+ }
132650
+ else {
132651
+ start1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_start) - 1;
132652
+ end1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_end) - 1;
132653
+ }
132654
+ // }
132526
132655
  for(let j = start1; j <= end1; ++j) {
132527
132656
  let resi, resid;
132528
132657
 
132529
- // let resiPos;
132530
- // if(me.cfg.aligntool == 'tmalign') {
132531
- // resiPos = j - baseResi;
132658
+ // if(me.cfg.aligntool == 'tmalign') { // tmalign: just one residue in this for loop
132659
+ // resi = ic.qt_start_end[chainIndex][i].t_start;
132532
132660
  // }
132533
132661
  // else {
132534
- // resiPos = j;
132662
+ // let resiPos = (bRealign || me.cfg.aligntool != 'tmalign') ? j : j - baseResi;
132663
+ // let resiPos;
132664
+ // if(me.cfg.aligntool == 'tmalign') {
132665
+ // resiPos = j - baseResi;
132666
+ // }
132667
+ // else {
132668
+ // // resiPos = (bRealign) ? j : j - baseResi;
132669
+ // resiPos = j;
132670
+ // }
132671
+
132672
+ let resiPos = j;
132673
+
132674
+ resi = ic.ParserUtilsCls.getResi(chainidArray[0], resiPos);
132675
+ resid = chainidArray[0] + '_' + resi;
132535
132676
  // }
132536
- let resiPos = j;
132537
- resi = ic.ParserUtilsCls.getResi(chainidArray[0], resiPos);
132538
- resid = chainidArray[0] + '_' + resi;
132539
132677
 
132540
132678
  resid2range_t[resid] = 1;
132541
132679
  if(j < start_t) start_t = j;
@@ -132549,14 +132687,18 @@ class SetSeqAlign {
132549
132687
 
132550
132688
  let resid2rangeArray = Object.keys(resid2range_t);
132551
132689
  resid2rangeArray.sort(function(a, b) {
132552
- return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
132690
+ // return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
132691
+ let idArray1 = me.utilsCls.getIdArray(a);
132692
+ let idArray2 = me.utilsCls.getIdArray(b);
132693
+ return parseInt(idArray1[2]) - parseInt(idArray2[2]);
132553
132694
  });
132554
132695
 
132555
132696
  // assign range to each resi
132556
132697
  let prevResi = -999, start = 0, end = 0, residArray = [], prevEnd = 0;
132557
132698
  for(let i = 0, il = resid2rangeArray.length; i < il; ++i) {
132558
132699
  let resid = resid2rangeArray[i];
132559
- let resi = resid.split('_')[2];
132700
+ let idArray = me.utilsCls.getIdArray(resid);
132701
+ let resi = idArray[2];
132560
132702
 
132561
132703
  if(i == 0) {
132562
132704
  start = resi;
@@ -132596,7 +132738,7 @@ class SetSeqAlign {
132596
132738
  let resid = chainid1 + '_' + resi;
132597
132739
 
132598
132740
  // let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : j + baseResi;
132599
- let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132741
+ let jAdjusted = (me.cfg.aligntool == 'seqalign') ? j : ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132600
132742
 
132601
132743
  //if(j + baseResi < start_t || j + baseResi > end_t) {
132602
132744
  if(jAdjusted < start_t || jAdjusted > end_t) {
@@ -132614,6 +132756,7 @@ class SetSeqAlign {
132614
132756
  resObject.color2 = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by conservation
132615
132757
  // resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
132616
132758
  resObject.class = (resid2range_t[resid]) ? 'icn3d-cons' : 'icn3d-nalign';
132759
+
132617
132760
  ic.alnChainsSeq[chainid1].push(resObject);
132618
132761
 
132619
132762
  if(resid2range_t[resid]) {
@@ -132747,7 +132890,7 @@ class SetSeqAlign {
132747
132890
  if(ic.alnChainsSeq[chainid1]) {
132748
132891
  for(let j = 0, jl = ic.alnChainsSeq[chainid1].length; j < jl; ++j) {
132749
132892
  //add gap before the mapping region
132750
- //if(parseInt(ic.alnChainsSeq[chainid1][j].resi) == parseInt(resi_t)) {
132893
+ // if(parseInt(ic.alnChainsSeq[chainid1][j].resi) == parseInt(resi_t)) {
132751
132894
  if(ic.alnChainsSeq[chainid1][j].resi == resi_t) {
132752
132895
  pos_t = j;
132753
132896
  break;
@@ -132773,7 +132916,6 @@ class SetSeqAlign {
132773
132916
  for(let j = 0, jl = alignedChainIndice.length - 1; j < jl; ++j) {
132774
132917
  let chainidTmp = chainidArray[alignedChainIndice[j]];
132775
132918
  let gapResObject = this.getResObject(chainidTmp, true);
132776
-
132777
132919
  //for(let k = 0, kl = len - nGap; k < kl; ++k) {
132778
132920
  for(let k = 0, kl = len; k < kl; ++k) {
132779
132921
  ic.alnChainsSeq[chainidTmp].splice(pos_t, 0, gapResObject);
@@ -132790,6 +132932,7 @@ class SetSeqAlign {
132790
132932
  // let resn2 = this.getResn(chainid, start + j);
132791
132933
  let resi2 = (bRealign && me.cfg.aligntool == 'tmalign') ? start + j : ic.ParserUtilsCls.getResi(chainid, start + j);
132792
132934
  let resn2 = this.getResnFromResi(chainid, resi2);
132935
+
132793
132936
  let resn1 = '-';
132794
132937
  let bAlign = false;
132795
132938
  let resObject = this.getResObject(chainid, false, bAlign, resi2, resn2, resn1);
@@ -132797,9 +132940,17 @@ class SetSeqAlign {
132797
132940
  }
132798
132941
  }
132799
132942
 
132943
+ getTemplatePosFromOriPos(chainid1, start, end, bRealign) { let ic = this.icn3d; ic.icn3dui;
132944
+ let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
132945
+ let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
132946
+
132947
+ let result1 = this.getResiPosInTemplate(chainid1, startResi);
132948
+ let result2 = this.getResiPosInTemplate(chainid1, endResi);
132949
+
132950
+ return {"pos1": result1.pos, "pos2": result2.pos};
132951
+ }
132952
+
132800
132953
  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
132954
  if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
132804
132955
  let startResi = start;
132805
132956
  let endResi = end;
@@ -132873,9 +133024,6 @@ class SetSeqAlign {
132873
133024
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
132874
133025
 
132875
133026
  let result;
132876
-
132877
- let nGapInTemplate = 0; // number of gaps inserted into the template sequence
132878
- let startPosInTemplate = 0; // position in the template sequence to start the mapping
132879
133027
 
132880
133028
  // need to improve when tmalign with residue number with postfix such as 52A in 4ORZ_C,5ESV_H
132881
133029
  // start and end should be positions, not original residue numbers.
@@ -132885,8 +133033,7 @@ class SetSeqAlign {
132885
133033
  }
132886
133034
 
132887
133035
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
132888
- let start1, start2, end1, end2, resiStart1, start1Pos;
132889
-
133036
+ let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
132890
133037
  if(bRealign && me.cfg.aligntool == 'tmalign') { // real residue numbers are stored
132891
133038
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start);
132892
133039
  start2 = parseInt(ic.qt_start_end[chainIndex][i].q_start);
@@ -132901,7 +133048,7 @@ class SetSeqAlign {
132901
133048
  // 1. before the mapped residues
132902
133049
  resiStart1 = start1;
132903
133050
  start1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_start);
132904
- this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133051
+ end1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
132905
133052
  }
132906
133053
  else {
132907
133054
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start - 1);
@@ -132912,28 +133059,49 @@ class SetSeqAlign {
132912
133059
  // 1. before the mapped residues
132913
133060
  resiStart1 = ic.ParserUtilsCls.getResi(chainid1, start1);
132914
133061
  start1Pos = start1;
133062
+ end1Pos = end1;
132915
133063
  }
132916
133064
  //let range = resid2range_t[chainid1 + '_' + resiStart1];
132917
-
133065
+
132918
133066
  // if the mapping does not start from start_t, add gaps to the query seq
132919
133067
  if(i == 0) {
132920
- startPosInTemplate = start1Pos;
132921
133068
 
132922
- result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
132923
- //result = this.getTemplatePosFromOriResi(chainid1, start_t, start1Pos, bRealign);
132924
- pos1 = result.pos1;
132925
- pos2 = result.pos2;
133069
+ if(me.cfg.aligntool == 'seqalign') {
133070
+ result = this.getTemplatePosFromOriPos(chainid1, start_t, start1Pos, bRealign);
132926
133071
 
132927
- if(start1 > start_t) {
132928
- //if(start1Pos > start_t) {
132929
- for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
132930
- ic.alnChainsSeq[chainid2].push(gapResObject2);
133072
+ pos1 = result.pos1;
133073
+ pos2 = result.pos2;
133074
+
133075
+ //if(start1 > start_t) {
133076
+ if(start1Pos > start_t) {
133077
+ for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133078
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
133079
+ }
133080
+ }
133081
+ }
133082
+ else {
133083
+ result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
133084
+
133085
+ pos1 = result.pos1;
133086
+ pos2 = result.pos2;
133087
+
133088
+ if(start1 > start_t) {
133089
+ //if(start1Pos > start_t) {
133090
+ for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133091
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
133092
+ }
132931
133093
  }
132932
133094
  }
132933
133095
  }
132934
133096
  else {
132935
133097
  //let notAlnLen1 = start1 - (prevIndex1 + 1);
132936
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
133098
+ //!!!
133099
+ if(me.cfg.aligntool == 'seqalign') {
133100
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, start1Pos, bRealign);
133101
+ }
133102
+ else {
133103
+ result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
133104
+ }
132937
133105
  pos1 = result.pos1;
132938
133106
  pos2 = result.pos2;
132939
133107
  let notAlnLen1 = pos2 - (pos1 + 1);
@@ -132944,46 +133112,48 @@ class SetSeqAlign {
132944
133112
 
132945
133113
  // insert non-aligned residues in query seq
132946
133114
  this.insertNotAlignRes(chainid2, prevIndex2+1, notAlnLen2, bRealign);
133115
+
132947
133116
  if(notAlnLen1 >= notAlnLen2) {
132948
133117
  // add gaps before the query sequence
132949
133118
  for(let j = 0, jl = notAlnLen1 - notAlnLen2; j < jl; ++j) {
132950
133119
  ic.alnChainsSeq[chainid2].push(gapResObject2);
132951
- }
133120
+ }
132952
133121
  }
132953
133122
  else {
132954
133123
  // check the number of gaps before resiStart1 (n), and insert 'notAlnLen2 - notAlnLen1 - n' gaps
132955
133124
  this.addGapAllAlnChains(chainidArray, alignedChainIndice, chainid1, resiStart1, notAlnLen2 - notAlnLen1);
132956
- nGapInTemplate += (notAlnLen2 - notAlnLen1);
132957
133125
  }
132958
133126
  }
132959
133127
 
132960
133128
  // 2. In the mapped residues
132961
- result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
132962
- //result = this.getTemplatePosFromOriResi(chainid1, start1Pos, end1Pos, bRealign);
133129
+ if(me.cfg.aligntool == 'seqalign') {
133130
+ result = this.getTemplatePosFromOriPos(chainid1, start1Pos, end1Pos, bRealign);
133131
+ }
133132
+ else {
133133
+ result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
133134
+ }
132963
133135
  pos1 = result.pos1;
132964
133136
  pos2 = result.pos2;
132965
-
133137
+
132966
133138
  let k = 0;
132967
133139
  if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
132968
133140
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
132969
- let resiAdjust = (bRealign && me.cfg.aligntool == 'tmalign') ? 0 : - startPosInTemplate + nGapInTemplate;
132970
133141
  for(let j = pos1; j <= pos2; ++j) {
132971
133142
  // inherit the gaps from the template
132972
- if(ic.alnChainsSeq[chainid1][j + resiAdjust].resn == '-') {
133143
+ if(ic.alnChainsSeq[chainid1][j].resn == '-') {
132973
133144
  ic.alnChainsSeq[chainid2].push(gapResObject2);
132974
133145
  }
132975
133146
  else {
132976
133147
  let resi1 = (bRealign && me.cfg.aligntool == 'tmalign') ? start1 + k : ic.ParserUtilsCls.getResi(chainid1, start1 + k);
132977
133148
  let resi2 = (bRealign && me.cfg.aligntool == 'tmalign') ? start2 + k : ic.ParserUtilsCls.getResi(chainid2, start2 + k);
132978
-
132979
133149
  let resn1 = this.getResnFromResi(chainid1, resi1); //this.getResn(chainid1, start1 + k);
132980
133150
  let resn2 = this.getResnFromResi(chainid2, resi2); //this.getResn(chainid2, start2 + k);
132981
-
133151
+
132982
133152
  let bAlign = true;
132983
133153
  let resObject = this.getResObject(chainid2, false, bAlign, resi2, resn2, resn1);
132984
133154
  ic.alnChainsSeq[chainid2].push(resObject);
132985
133155
  // update color in the template
132986
- ic.alnChainsSeq[chainid1][j + resiAdjust].color = resObject.color;
133156
+ ic.alnChainsSeq[chainid1][j].color = resObject.color;
132987
133157
 
132988
133158
  ic.chainsMapping[chainid1][chainid1 + '_' + resi1] = resn1 + resi1;
132989
133159
  ic.chainsMapping[chainid2][chainid2 + '_' + resi2] = resn1 + resi1;
@@ -133001,7 +133171,12 @@ class SetSeqAlign {
133001
133171
  }
133002
133172
 
133003
133173
  // add gaps at the end
133004
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
133174
+ if(me.cfg.aligntool == 'seqalign') {
133175
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, end_t, bRealign);
133176
+ }
133177
+ else {
133178
+ result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
133179
+ }
133005
133180
  pos1 = result.pos1;
133006
133181
  pos2 = result.pos2;
133007
133182
  for(let i = pos1; i < pos2; ++i) {
@@ -133021,7 +133196,7 @@ class SetSeqAlign {
133021
133196
 
133022
133197
  for(let i = 0, il = ic.qt_start_end[index].length; i < il; ++i) {
133023
133198
  let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
133024
-
133199
+
133025
133200
  start1 = ic.qt_start_end[index][i].t_start;
133026
133201
  start2 = ic.qt_start_end[index][i].q_start;
133027
133202
  end1 = ic.qt_start_end[index][i].t_end;
@@ -133339,8 +133514,8 @@ class SetSeqAlign {
133339
133514
 
133340
133515
  setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
133341
133516
  //set MSA
133342
- let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
133343
- let chainArrayClustal = [];
133517
+ let fastaFormat = '', clustalwFormat = 'CLUSTALW\n\n', resbyresFormat = '';
133518
+ let chainArrayClustalw = [];
133344
133519
 
133345
133520
  let consArray = [], resiArrayTemplate = [];
133346
133521
  let chainidTemplate = chainidArray[0];
@@ -133409,8 +133584,8 @@ class SetSeqAlign {
133409
133584
 
133410
133585
  fastaFormat += '\n';
133411
133586
 
133412
- chainArrayClustal.push(clustalwArray);
133413
- if(i == il - 1) chainArrayClustal.push(consArray);
133587
+ chainArrayClustalw.push(clustalwArray);
133588
+ if(i == il - 1) chainArrayClustalw.push(consArray);
133414
133589
 
133415
133590
  // residue by residue
133416
133591
  let resiRangeStr1 = ic.resid2specCls.resi2range(resiArrayTarget, true);
@@ -133419,10 +133594,10 @@ class SetSeqAlign {
133419
133594
  if(i > 0) resbyresFormat += resiRangeStr1 + ' | ' + resiRangeStr2 + '\n';
133420
133595
  }
133421
133596
 
133422
- // CLUSTALWW
133423
- for(let j = 0, jl = chainArrayClustal[0].length; j < jl; ++j) {
133424
- for(let i = 0, il = chainArrayClustal.length; i < il; ++i) {
133425
- clustalwFormat += chainArrayClustal[i][j] + '\n';
133597
+ // CLUSTALW
133598
+ for(let j = 0, jl = chainArrayClustalw[0].length; j < jl; ++j) {
133599
+ for(let i = 0, il = chainArrayClustalw.length; i < il; ++i) {
133600
+ clustalwFormat += chainArrayClustalw[i][j] + '\n';
133426
133601
  }
133427
133602
  clustalwFormat += '\n';
133428
133603
  }
@@ -133889,7 +134064,7 @@ class LoadPDB {
133889
134064
  //if(residueNum !== prevResidueNum) {
133890
134065
 
133891
134066
  if(oriResidueNum !== prevOriResidueNum) {
133892
- let residue = me.utilsCls.residueName2Abbr(resn);
134067
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
133893
134068
  ic.residueId2Name[residueNum] = residue;
133894
134069
 
133895
134070
  if(serial !== 1 && prevResidueNum !== '') ic.residues[prevResidueNum] = residuesTmp;
@@ -134336,7 +134511,7 @@ class LoadPDB {
134336
134511
 
134337
134512
  for(let chainid in chains) {
134338
134513
  if(pdbid !== undefined) {
134339
- let textArray = chainid.split('_');
134514
+ let textArray = me.utilsCls.getIdArray(chainid);
134340
134515
  if(textArray[0] !== pdbid) continue; // skip different chain
134341
134516
  }
134342
134517
 
@@ -134444,15 +134619,15 @@ class LoadCIF {
134444
134619
  loadCIF(bcifData, bcifid, bText, bAppend, supercell) { let ic = this.icn3d, me = ic.icn3dui;
134445
134620
  ic.cifText = bText;
134446
134621
  ic.cifData = bcifData;
134447
-
134622
+
134448
134623
  if(supercell === undefined) {
134449
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true };
134624
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134450
134625
  }
134451
134626
  else if(supercell === 0) {
134452
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: false };
134627
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134453
134628
  }
134454
134629
  else {
134455
- CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true };
134630
+ CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134456
134631
  }
134457
134632
 
134458
134633
  let hAtoms = {};
@@ -134468,7 +134643,7 @@ class LoadCIF {
134468
134643
  let serial, moleculeNum;
134469
134644
  // if(!bMutation && !bAppend) {
134470
134645
  if(!bAppend) {
134471
- ic.init();
134646
+ ic.init(undefined, true); // keep original configurations, such as color, style, etc. when loading multiple structures
134472
134647
  moleculeNum = 0; //1;
134473
134648
  serial = 0;
134474
134649
  }
@@ -134512,11 +134687,13 @@ class LoadCIF {
134512
134687
 
134513
134688
  if (parsed.isError) {
134514
134689
  // report error:
134515
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
134690
+ var aaa = 1; //alert("2 The Binary CIF data can NOT be parsed: " + parsed.toString());
134516
134691
  return;
134517
134692
  }
134518
134693
 
134519
134694
  let block = parsed.result.dataBlocks[0];
134695
+
134696
+ if(!block) continue;
134520
134697
 
134521
134698
  if(block.getCategory("_entry")) {
134522
134699
  id = block.getCategory("_entry").getColumn("id").getString(0);
@@ -134755,6 +134932,8 @@ class LoadCIF {
134755
134932
  ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
134756
134933
  ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
134757
134934
  ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
134935
+
134936
+ 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
134937
  }
134759
134938
 
134760
134939
  // if (record === 'ENDMDL') {
@@ -135099,7 +135278,7 @@ class LoadCIF {
135099
135278
 
135100
135279
  // if(oriResidueNum !== prevOriResidueNum) {
135101
135280
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
135102
- let residue = me.utilsCls.residueName2Abbr(resn);
135281
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
135103
135282
 
135104
135283
  ic.residueId2Name[residueNum] = residue;
135105
135284
 
@@ -136398,6 +136577,16 @@ class ApplyCommand {
136398
136577
  ic.opts['unitcell'] = 'no';
136399
136578
  ic.drawCls.draw();
136400
136579
  }
136580
+ else if(command.indexOf('define unitcell') !== -1) {
136581
+ let itemArray = command.split(' | ');
136582
+ ic.cell = {};
136583
+ ic.cell.length_a = parseFloat(itemArray[1]);
136584
+ ic.cell.length_b = parseFloat(itemArray[2]);
136585
+ ic.cell.length_c = parseFloat(itemArray[3]);
136586
+ ic.cell.angle_alpha = parseFloat(itemArray[4]);
136587
+ ic.cell.angle_beta = parseFloat(itemArray[5]);
136588
+ ic.cell.angle_gamma = parseFloat(itemArray[6]);
136589
+ }
136401
136590
  else if(command == 'set fog on') {
136402
136591
  ic.opts['fog'] = 'yes';
136403
136592
  ic.fogCls.setFog(true);
@@ -136428,7 +136617,7 @@ class ApplyCommand {
136428
136617
  let pos = command.lastIndexOf(' ');
136429
136618
  let supercell = parseInt(command.substr(pos + 1));
136430
136619
 
136431
- await me.htmlCls.clickMenuCls.setSupercell(supercell);
136620
+ me.htmlCls.clickMenuCls.setSupercell(supercell);
136432
136621
  }
136433
136622
  else if(command == 'set chemicalbinding show') {
136434
136623
  ic.setOptionCls.setOption('chemicalbinding', 'show');
@@ -136863,7 +137052,8 @@ class ApplyCommand {
136863
137052
  else if(commandOri.indexOf('select interaction') == 0) {
136864
137053
  let idArray = commandOri.substr(commandOri.lastIndexOf(' ') + 1).split(',');
136865
137054
  if(idArray !== null) {
136866
- let mmdbid = idArray[0].split('_')[0];
137055
+ let itemArray = me.utilsCls.getIdArray(idArray[0]);
137056
+ let mmdbid = itemArray[0];
136867
137057
  if(!ic.b2DShown) ic.ParserUtilsCls.download2Ddgm(mmdbid.toUpperCase());
136868
137058
 
136869
137059
  ic.diagram2dCls.selectInteraction(idArray[0], idArray[1]);
@@ -138709,7 +138899,7 @@ class DefinedSets {
138709
138899
 
138710
138900
  }
138711
138901
 
138712
- selectCombinedSets(strSets, commandname) { let ic = this.icn3d; ic.icn3dui;
138902
+ selectCombinedSets(strSets, commandname) { let ic = this.icn3d, me = ic.icn3dui;
138713
138903
  let idArray = strSets.split(' ');
138714
138904
 
138715
138905
  let orArray = [], andArray = [], notArray = [];
@@ -138717,7 +138907,7 @@ class DefinedSets {
138717
138907
 
138718
138908
  for(let i = 0, il = idArray.length; i < il; ++i) {
138719
138909
  // replace 1CD8_A_1 with 1CD8_A1
138720
- let tmpArray = idArray[i].split('_');
138910
+ let tmpArray = me.utilsCls.getIdArray(idArray[i]);
138721
138911
  if(tmpArray.length == 3 && !isNaN(tmpArray[2])) {
138722
138912
  idArray[i] = tmpArray[0] + '_' + tmpArray[1] + tmpArray[2];
138723
138913
  }
@@ -139719,7 +139909,7 @@ class LoadScript {
139719
139909
 
139720
139910
  // load pdb, mmcif, mmdb, cid
139721
139911
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
139722
- if(id.length == 4) id = id.toUpperCase();
139912
+ if(id.length == 4 || id.indexOf('pdb_') == 0) id = id.toUpperCase();
139723
139913
 
139724
139914
  // skip loading the structure if
139725
139915
  // 1. PDB was in the iCn3D PNG Image file
@@ -139766,6 +139956,10 @@ class LoadScript {
139766
139956
  me.cfg.mmcifid = id;
139767
139957
  await ic.mmcifParserCls.downloadMmcif(id);
139768
139958
  }
139959
+ else if(command.indexOf('load cod') !== -1) {
139960
+ me.cfg.codid = id;
139961
+ await ic.mmcifParserCls.downloadCod(id);
139962
+ }
139769
139963
  else if(command.indexOf('load mmdb ') !== -1 || command.indexOf('load mmdb1 ') !== -1) {
139770
139964
  me.cfg.mmdbid = id;
139771
139965
  me.cfg.bu = 1;
@@ -140280,7 +140474,7 @@ class SelectByCommand {
140280
140474
 
140281
140475
  // convert 1TOP_A:20 to $1TOP.A:20
140282
140476
  if(commandArray[i].indexOf('_') !== -1) {
140283
- let itemArray = commandArray[i].split('_');
140477
+ let itemArray = me.utilsCls.getIdArray(commandArray[i]);
140284
140478
  if(itemArray.length ==2 ) {
140285
140479
  commandArray[i] = '$' + itemArray[0] + '.' + itemArray[1];
140286
140480
  }
@@ -141527,6 +141721,15 @@ class Resid2spec {
141527
141721
  return Object.keys(residueHash);
141528
141722
  }
141529
141723
 
141724
+ atoms2chains(atoms) {var ic = this.icn3d; ic.icn3dui;
141725
+ let chains = {};
141726
+ for(let i in atoms) {
141727
+ let atom = ic.atoms[i];
141728
+ chains[atom.structure + '_' + atom.chain] = 1;
141729
+ }
141730
+ return chains;
141731
+ }
141732
+
141530
141733
  atoms2structureArray(atoms) {var ic = this.icn3d; ic.icn3dui;
141531
141734
  let structures = {};
141532
141735
  for(let i in atoms) {
@@ -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
 
@@ -149159,10 +149345,10 @@ class ResizeCanvas {
149159
149345
  //me.htmlCls.HEIGHT = $( window ).height();
149160
149346
  me.utilsCls.setViewerWidthHeight(ic.icn3dui);
149161
149347
 
149162
- let width = me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
149163
- let height = me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
149348
+ me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
149349
+ 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, true, true);
149166
149352
  });
149167
149353
  }
149168
149354
  }
@@ -153912,8 +154098,8 @@ class iCn3D {
153912
154098
  }
153913
154099
  }
153914
154100
  //When users first load a structure, call this function to empty previous settings.
153915
- iCn3D.prototype.init = function (bKeepCmd) {
153916
- this.init_base();
154101
+ iCn3D.prototype.init = function (bClearCmd, bKeepConfig) {
154102
+ this.init_base(bClearCmd, bKeepConfig);
153917
154103
 
153918
154104
  this.molTitle = "";
153919
154105
 
@@ -153933,8 +154119,8 @@ iCn3D.prototype.init = function (bKeepCmd) {
153933
154119
  this.axes = [];
153934
154120
  };
153935
154121
 
153936
- iCn3D.prototype.init_base = function (bKeepCmd) {
153937
- this.resetConfig();
154122
+ iCn3D.prototype.init_base = function (bClearCmd, bKeepConfig) {
154123
+ if(!bKeepConfig) this.resetConfig();
153938
154124
 
153939
154125
  this.structures = {}; // structure name -> array of chains
153940
154126
  this.chains = {}; // structure_chain name -> atom hash
@@ -154028,7 +154214,7 @@ iCn3D.prototype.init_base = function (bKeepCmd) {
154028
154214
  this.transformCls.rotateCount = 0;
154029
154215
  this.transformCls.rotateCountMax = 20;
154030
154216
 
154031
- if(bKeepCmd) this.commands = [];
154217
+ if(bClearCmd) this.commands = [];
154032
154218
 
154033
154219
  this.axes = [];
154034
154220
 
@@ -154124,7 +154310,7 @@ class iCn3DUI {
154124
154310
  //even when multiple iCn3D viewers are shown together.
154125
154311
  this.pre = this.cfg.divid + "_";
154126
154312
 
154127
- this.REVISION = '3.54.3';
154313
+ this.REVISION = '3.54.4';
154128
154314
 
154129
154315
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154130
154316
  this.bNode = (Object.keys(window).length < 3) ? true : false;
@@ -154220,9 +154406,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154220
154406
  resize: function( event, ui ) {
154221
154407
  me.htmlCls.WIDTH = ui.size.width; //$("#" + ic.pre + "canvas").width();
154222
154408
  me.htmlCls.HEIGHT = ui.size.height; //$("#" + ic.pre + "canvas").height();
154223
- if(ic !== undefined && !me.icn3d.bFullscreen) {
154224
- ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
154225
- }
154409
+ // if(ic !== undefined && !me.icn3d.bFullscreen) {
154410
+ // ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
154411
+ // }
154226
154412
  }
154227
154413
  });
154228
154414
 
@@ -154326,7 +154512,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154326
154512
  let domainidArray = me.cfg.matchedchains.split(',');
154327
154513
  let chainidArray = [];
154328
154514
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
154329
- let idArray = domainidArray[i].split('_');
154515
+ let idArray = me.utilsCls.getIdArray(domainidArray[i]);
154330
154516
  chainidArray.push(idArray[0] + '_' + idArray[1]);
154331
154517
  }
154332
154518
 
@@ -154369,14 +154555,14 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154369
154555
  await ic.pdbParserCls.downloadUrl(url, type, me.cfg.command);
154370
154556
  }
154371
154557
  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
154558
+ // 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
154559
  ic.inputid = me.cfg.mmtfid;
154374
154560
  ic.loadCmd = 'load mmtf ' + me.cfg.mmtfid;
154375
154561
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154376
154562
  await ic.bcifParserCls.downloadBcif(me.cfg.mmtfid);
154377
154563
  }
154378
154564
  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
154565
+ // 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
154566
  ic.inputid = me.cfg.bcifid;
154381
154567
  ic.loadCmd = 'load bcif ' + me.cfg.bcifid;
154382
154568
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -154551,6 +154737,12 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154551
154737
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154552
154738
  await ic.mmcifParserCls.downloadMmcif(me.cfg.mmcifid);
154553
154739
  }
154740
+ else if(me.cfg.codid !== undefined) {
154741
+ ic.inputid = me.cfg.codid;
154742
+ ic.loadCmd = 'load cod ' + me.cfg.codid;
154743
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154744
+ await ic.mmcifParserCls.downloadCod(me.cfg.codid);
154745
+ }
154554
154746
  else if(me.cfg.align !== undefined) {
154555
154747
  // ic.bNCBI = true;
154556
154748
  if(me.cfg.align.indexOf('185055,') != -1) {
@@ -154711,6 +154903,8 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
154711
154903
 
154712
154904
  reject('error');
154713
154905
  }
154906
+
154907
+ me.icn3d.ParserUtilsCls.hideLoading();
154714
154908
  }
154715
154909
  else {
154716
154910
  me.icn3d.ParserUtilsCls.showLoading();
@@ -154863,18 +155057,6 @@ iCn3DUI.prototype.setDialogAjax = function() { let me = this;
154863
155057
  });
154864
155058
  };
154865
155059
 
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
155060
  // required by npm
154879
155061
  class printMsg {
154880
155062
  constructor() {