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.module.js CHANGED
@@ -172,7 +172,8 @@ $NGL_shaderTextHash['SphereImpostor.frag'] = ["#define STANDARD",
172
172
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
173
173
  " #endif",
174
174
  " #ifdef FOG_EXP2",
175
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
175
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
176
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
176
177
  " #else",
177
178
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
178
179
  " #endif",
@@ -636,7 +637,8 @@ $NGL_shaderTextHash['CylinderImpostor.frag'] = ["#define STANDARD",
636
637
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
637
638
  " #endif",
638
639
  " #ifdef FOG_EXP2",
639
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
640
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
641
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
640
642
  " #else",
641
643
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
642
644
  " #endif",
@@ -2606,13 +2608,33 @@ var CIFTools;
2606
2608
  /**
2607
2609
  * Options for filling the unit cell of a core CIF by lattice translation
2608
2610
  * (applied after the symmetry operators have generated the contents of one cell).
2609
- * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2610
- * boundary : also emit the periodic image of every atom lying on a cell face/edge/corner
2611
- * (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl); default true.
2612
- * Set to false to get the original behavior (atoms wrapped into [0,1) only).
2613
- * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, boundary: true};
2611
+ * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2612
+ * wholeMolecules : keep every molecule / discrete chemical species intact. Atoms are grouped into
2613
+ * bonded fragments (covalent radii + bondTolerance, periodic), each fragment is
2614
+ * "unwrapped" so that it is contiguous (it may stick out of the unit cell), and the
2615
+ * fragment is placed in the cell that contains its centre. Fragments that are
2616
+ * infinite (chains, layers, frameworks, ionic lattices such as NaCl) cannot be made
2617
+ * whole and are handled as before (wrapped into the cell, see 'boundary'). default true
2618
+ * bondTolerance : extra distance (Angstrom) added to the sum of covalent radii when detecting bonds; default 0.4
2619
+ * boundary : for atoms that are NOT part of a whole molecule, also emit the periodic image of every
2620
+ * atom lying on a cell face/edge/corner (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl);
2621
+ * default true.
2622
+ * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, wholeMolecules: true};
2614
2623
  */
2615
- Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true };
2624
+ Text.coreCifOptions = {
2625
+ nx: 1, ny: 1, nz: 1,
2626
+ wholeMolecules: true, // new; set false for the old wrapped behaviour
2627
+ bondTolerance: 0.4, // new; raise it if bonds are missed, lower it if unrelated atoms get joined, default 0.4
2628
+ boundary: true
2629
+ };
2630
+ // covalent radii (Angstrom, Cordero et al. 2008) used for bond detection
2631
+ 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,
2632
+ 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,
2633
+ 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,
2634
+ 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,
2635
+ 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,
2636
+ 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,
2637
+ Ir: 1.41, Pt: 1.36, Au: 1.36, Hg: 1.32, Tl: 1.45, Pb: 1.46, Bi: 1.48 };
2616
2638
  // g: fractional coordinates wrapped into [0,1). Returns all translated copies of g.
2617
2639
  function coreLatticeImages(g, nx, ny, nz, bBoundary) {
2618
2640
  var eps = 1e-3, n = [nx, ny, nz], ranges = [], out = [], k, i, r, x, y, z;
@@ -2628,6 +2650,60 @@ var CIFTools;
2628
2650
  out.push([ranges[0][x], ranges[1][y], ranges[2][z]]);
2629
2651
  return out;
2630
2652
  }
2653
+ /**
2654
+ * Group atoms (fractional coordinates wrapped into the cell) into bonded fragments, taking periodic
2655
+ * images into account. Every atom of a fragment gets an integer lattice translation T so that
2656
+ * (g + T) forms a contiguous molecule. A fragment that reaches its own periodic image
2657
+ * (chain / layer / framework) is flagged as infinite.
2658
+ * atoms : [{el, g:[fx,fy,fz]}] toCart : fractional -> Cartesian (linear part only)
2659
+ * h : interplanar spacings of the cell along a, b, c tol : bond tolerance (Angstrom)
2660
+ */
2661
+ function coreFindMolecules(atoms, toCart, h, tol) {
2662
+ var N = atoms.length, nb = [], rad = [], i, j, k, e, m, q;
2663
+ for (i = 0; i < N; i++) { nb.push([]); rad.push(coreCovRadii[atoms[i].el] || 1.5); }
2664
+ for (i = 0; i < N; i++) {
2665
+ for (j = i; j < N; j++) {
2666
+ 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]];
2667
+ var rc = rad[i] + rad[j] + tol, cand = [[], [], []], dt, t;
2668
+ for (k = 0; k < 3; k++) {
2669
+ var base = -Math.round(d[k]);
2670
+ for (dt = -1; dt <= 1; dt++) {
2671
+ t = base + dt;
2672
+ if (Math.abs(d[k] + t) * h[k] <= rc) cand[k].push(t);
2673
+ }
2674
+ }
2675
+ 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++) {
2676
+ var tv = [cand[0][a], cand[1][b], cand[2][c]];
2677
+ if (i === j) { // bond to own image: record each translation pair only once
2678
+ if (tv[0] === 0 && tv[1] === 0 && tv[2] === 0) continue;
2679
+ if (tv[0] < 0 || (tv[0] === 0 && (tv[1] < 0 || (tv[1] === 0 && tv[2] < 0)))) continue;
2680
+ }
2681
+ var cc = toCart([d[0] + tv[0], d[1] + tv[1], d[2] + tv[2]]);
2682
+ var d2 = cc[0] * cc[0] + cc[1] * cc[1] + cc[2] * cc[2];
2683
+ if (d2 < rc * rc && d2 > 0.25) { // > 0.5 A: closer atoms are disorder alternatives, not bonds
2684
+ nb[i].push({ j: j, t: tv });
2685
+ nb[j].push({ j: i, t: [-tv[0], -tv[1], -tv[2]] });
2686
+ }
2687
+ }
2688
+ }
2689
+ }
2690
+ var T = new Array(N), comps = [], s, queue, members, infinite, cur, tj, o;
2691
+ for (s = 0; s < N; s++) {
2692
+ if (T[s]) continue;
2693
+ T[s] = [0, 0, 0]; queue = [s]; members = [s]; infinite = false;
2694
+ for (q = 0; q < queue.length; q++) {
2695
+ cur = queue[q];
2696
+ for (e = 0; e < nb[cur].length; e++) {
2697
+ o = nb[cur][e];
2698
+ tj = [T[cur][0] + o.t[0], T[cur][1] + o.t[1], T[cur][2] + o.t[2]];
2699
+ if (!T[o.j]) { T[o.j] = tj; queue.push(o.j); members.push(o.j); }
2700
+ else if (T[o.j][0] !== tj[0] || T[o.j][1] !== tj[1] || T[o.j][2] !== tj[2]) infinite = true;
2701
+ }
2702
+ }
2703
+ comps.push({ members: members, infinite: infinite });
2704
+ }
2705
+ return { T: T, comps: comps };
2706
+ }
2631
2707
  function convertCoreCif(data) {
2632
2708
  var tk = coreTokens(data), i = 0, n = tk.length, single = {}, loops = [], name = 'data_core', t, cols, rows, cur;
2633
2709
  function isTag(x) { return x && !x.t && x.v.charAt(0) === '_'; }
@@ -2681,12 +2757,21 @@ var CIFTools;
2681
2757
  '_atom_site.label_comp_id', '_atom_site.label_asym_id', '_atom_site.label_entity_id', '_atom_site.label_seq_id',
2682
2758
  '_atom_site.Cartn_x', '_atom_site.Cartn_y', '_atom_site.Cartn_z', '_atom_site.occupancy', '_atom_site.B_iso_or_equiv',
2683
2759
  '_atom_site.auth_seq_id', '_atom_site.auth_asym_id', '_atom_site.pdbx_PDB_model_num');
2684
- var serial = 0, seen = [], r, s, f, g, k, dup, j, sym, el, lab, cart;
2760
+ var serial = 0, r, s, f, g, k, dup, j, sym, el, lab, cart;
2685
2761
  var o = Text.coreCifOptions || {}, images, im;
2686
2762
  var opt = {
2687
2763
  nx: Math.max(1, parseInt(o.nx) || 1), ny: Math.max(1, parseInt(o.ny) || 1), nz: Math.max(1, parseInt(o.nz) || 1),
2688
- boundary: (o.boundary === undefined) ? true : !!o.boundary
2764
+ boundary: (o.boundary === undefined) ? true : !!o.boundary,
2765
+ wholeMolecules: (o.wholeMolecules === undefined) ? true : !!o.wholeMolecules,
2766
+ bondTolerance: (o.bondTolerance === undefined || isNaN(parseFloat(o.bondTolerance))) ? 0.4 : parseFloat(o.bondTolerance)
2689
2767
  };
2768
+ function emit(at, frac) {
2769
+ var cart = toCart(frac);
2770
+ out.push(['HETATM', ++serial, at.el, at.lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2771
+ at.occ, '0.00', 1, 'A', 1].join(' '));
2772
+ }
2773
+ // 1) all symmetry-generated atoms of one cell, wrapped into [0,1)
2774
+ var list = [];
2690
2775
  for (r = 0; r < atoms.rows.length; r++) {
2691
2776
  var row = atoms.rows[r];
2692
2777
  if (get(row, '_atom_site_calc_flag') === 'dum') continue; // dummy atoms
@@ -2695,6 +2780,7 @@ var CIFTools;
2695
2780
  sym = get(row, '_atom_site_type_symbol'); if (sym === '?') sym = lab;
2696
2781
  el = (sym.match(/^[A-Za-z]{1,2}/) || ['X'])[0];
2697
2782
  el = el.charAt(0).toUpperCase() + el.substr(1).toLowerCase();
2783
+ var occ = coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy'));
2698
2784
  var mySeen = [];
2699
2785
  for (s = 0; s < symops.length; s++) {
2700
2786
  g = symops[s](f).map(function (v) { return v - Math.floor(v + 1e-6); });
@@ -2704,15 +2790,51 @@ var CIFTools;
2704
2790
  }
2705
2791
  if (dup) continue;
2706
2792
  mySeen.push(g);
2707
- // fill the cell (and optional supercell) by lattice translation of the symmetry-generated site
2708
- images = coreLatticeImages(g, opt.nx, opt.ny, opt.nz, opt.boundary);
2709
- for (im = 0; im < images.length; im++) {
2710
- cart = toCart(images[im]);
2711
- out.push(['HETATM', ++serial, el, lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2712
- coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy')), '0.00', 1, 'A', 1].join(' '));
2793
+ list.push({ el: el, lab: lab, occ: occ, g: g });
2794
+ }
2795
+ }
2796
+ // 2) emit them, either as whole molecules or simply wrapped into the cell
2797
+ var mol = null;
2798
+ if (opt.wholeMolecules && list.length) {
2799
+ var Vc = a * b * cc * vol, sinal = Math.sqrt(1 - cosa * cosa), sinbe = Math.sqrt(1 - cosb * cosb);
2800
+ var hh = [Vc / (b * cc * sinal), Vc / (a * cc * sinbe), Vc / (a * b * sing)];
2801
+ if (isFinite(hh[0] + hh[1] + hh[2]) && hh[0] > 0 && hh[1] > 0 && hh[2] > 0) mol = coreFindMolecules(list, toCart, hh, opt.bondTolerance);
2802
+ }
2803
+ var ci, m, at, ix, iy, iz, mean, shift;
2804
+ if (mol) {
2805
+ for (ci = 0; ci < mol.comps.length; ci++) {
2806
+ var comp = mol.comps[ci];
2807
+ if (comp.infinite) { // cannot be made whole: wrap into the cell as before
2808
+ for (m = 0; m < comp.members.length; m++) {
2809
+ at = list[comp.members[m]];
2810
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2811
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2812
+ }
2813
+ continue;
2814
+ }
2815
+ // contiguous molecule: place it in the cell that holds its centre, keep all atoms together
2816
+ mean = [0, 0, 0];
2817
+ for (m = 0; m < comp.members.length; m++) {
2818
+ at = list[comp.members[m]];
2819
+ for (k = 0; k < 3; k++) mean[k] += (at.g[k] + mol.T[comp.members[m]][k]) / comp.members.length;
2820
+ }
2821
+ shift = [-Math.floor(mean[0] + 1e-6), -Math.floor(mean[1] + 1e-6), -Math.floor(mean[2] + 1e-6)];
2822
+ for (ix = 0; ix < opt.nx; ix++) for (iy = 0; iy < opt.ny; iy++) for (iz = 0; iz < opt.nz; iz++) {
2823
+ for (m = 0; m < comp.members.length; m++) {
2824
+ at = list[comp.members[m]];
2825
+ var tt = mol.T[comp.members[m]];
2826
+ 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]);
2827
+ }
2713
2828
  }
2714
2829
  }
2715
2830
  }
2831
+ else {
2832
+ for (m = 0; m < list.length; m++) {
2833
+ at = list[m];
2834
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2835
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2836
+ }
2837
+ }
2716
2838
  out.push('#');
2717
2839
  return out.join('\n') + '\n';
2718
2840
  }
@@ -3011,7 +3133,7 @@ var CIFTools;
3011
3133
  // This approach to binary parsing wastes a bit of memory to trade for speed compared to:
3012
3134
  //
3013
3135
  // let value = buffer.subarray(offset, offset + length); //new Uint8Array(buffer.buffer, offset, length);
3014
- //
3136
+ //
3015
3137
  // It turns out that using the view created by subarray probably uses DataView
3016
3138
  // in the background, which causes the element access to be several times slower
3017
3139
  // than creating the new byte array.
@@ -4335,7 +4457,7 @@ var CIFTools;
4335
4457
  if (index === void 0) {
4336
4458
  // increment the length
4337
4459
  accLength += s.length;
4338
- // store the string and index
4460
+ // store the string and index
4339
4461
  index = strings.length;
4340
4462
  strings[index] = s;
4341
4463
  map[s] = index;
@@ -56304,7 +56426,7 @@ class UtilsCls {
56304
56426
  }
56305
56427
 
56306
56428
  //Convert a three-letter residue name to a one-letter residue abbreviation, e.g., 'LYS' to 'K', or ' A' to 'A' for nucleotides.
56307
- residueName2Abbr(residueName) { this.icn3dui;
56429
+ residueName2Abbr(residueName, bOneLetter) { this.icn3dui;
56308
56430
  let pos = residueName.indexOf(' ');
56309
56431
  if(pos > 0) {
56310
56432
  residueName = residueName.substr(0, pos);
@@ -56399,7 +56521,12 @@ class UtilsCls {
56399
56521
  return 'O';
56400
56522
 
56401
56523
  default:
56402
- return residueName.trim();
56524
+ if(bOneLetter) {
56525
+ return 'X';
56526
+ }
56527
+ else {
56528
+ return residueName.trim();
56529
+ }
56403
56530
  }
56404
56531
  }
56405
56532
 
@@ -56475,15 +56602,20 @@ class UtilsCls {
56475
56602
  }
56476
56603
 
56477
56604
  getIdArray(resid) { this.icn3dui;
56478
- //var idArray = resid.split('_');
56479
56605
  let idArray = [];
56480
56606
 
56481
56607
  if(resid) {
56482
- let pos1 = resid.indexOf('_');
56483
- let pos2 = resid.lastIndexOf('_');
56484
- idArray.push(resid.substr(0, pos1));
56485
- idArray.push(resid.substr(pos1 + 1, pos2 - pos1 - 1));
56486
- idArray.push(resid.substr(pos2 + 1));
56608
+ let itemArray = resid.split('_');
56609
+
56610
+ if(resid.indexOf('pdb_') == 0 ) { // e.g., pdb_00001GPK_A_15
56611
+ idArray.push(itemArray[0] + '_' + itemArray[1]);
56612
+ for(let i = 2, il = itemArray.length; i < il; ++i) {
56613
+ idArray.push(itemArray[i]);
56614
+ }
56615
+ }
56616
+ else {
56617
+ idArray = itemArray;
56618
+ }
56487
56619
  }
56488
56620
 
56489
56621
  return idArray;
@@ -56494,12 +56626,12 @@ class UtilsCls {
56494
56626
  let bArray = b.split(',');
56495
56627
  let aIdArray, bIdArray;
56496
56628
  if(type == 'save1') {
56497
- aIdArray = me.utilsCls.getIdArray(aArray[0]); //aArray[0].split('_');
56498
- bIdArray = me.utilsCls.getIdArray(bArray[0]); //bArray[0].split('_');
56629
+ aIdArray = me.utilsCls.getIdArray(aArray[0]);
56630
+ bIdArray = me.utilsCls.getIdArray(bArray[0]);
56499
56631
  }
56500
56632
  else if(type == 'save2') {
56501
- aIdArray = me.utilsCls.getIdArray(aArray[1]); //aArray[1].split('_');
56502
- bIdArray = me.utilsCls.getIdArray(bArray[1]); //bArray[1].split('_');
56633
+ aIdArray = me.utilsCls.getIdArray(aArray[1]);
56634
+ bIdArray = me.utilsCls.getIdArray(bArray[1]);
56503
56635
  }
56504
56636
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
56505
56637
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
@@ -58414,6 +58546,9 @@ class ClickMenu {
58414
58546
  me.myEventCls.onIds("#" + me.pre + "mn1_mmcifid", "click", function(e) { me.icn3d; //e.preventDefault();
58415
58547
  me.htmlCls.dialogCls.openDlg('dl_mmcifid', 'Please input mmCIF ID');
58416
58548
  });
58549
+ me.myEventCls.onIds("#" + me.pre + "mn1_codid", "click", function(e) { me.icn3d; //e.preventDefault();
58550
+ me.htmlCls.dialogCls.openDlg('dl_codid', 'Please input COD ID');
58551
+ });
58417
58552
 
58418
58553
  me.myEventCls.onIds("#" + me.pre + "mn1_mmdbid", "click", function(e) { me.icn3d; //e.preventDefault();
58419
58554
  me.htmlCls.dialogCls.openDlg('dl_mmdbid', 'Please input MMDB or PDB ID');
@@ -58953,7 +59088,7 @@ class ClickMenu {
58953
59088
  thisClass.setLogCmd("link to compounds with structure similar to CID " + ic.inputid + ": " + url, false);
58954
59089
  }
58955
59090
  else {
58956
- let idArray = ic.inputid.split('_');
59091
+ let idArray = me.utilsCls.getIdArray(ic.inputid);
58957
59092
 
58958
59093
  if(idArray.length === 1) {
58959
59094
  url = me.htmlCls.baseUrl + "vastplus/vastplus.cgi?uid=" + ic.inputid;
@@ -60015,17 +60150,14 @@ class ClickMenu {
60015
60150
 
60016
60151
  }
60017
60152
 
60018
- async setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
60019
- ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
60020
-
60021
- if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
60022
- ic.pk = 1;
60023
- ic.opts['pk'] = 'atom';
60153
+ setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
60154
+ if(ic.cifData) {
60155
+ ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
60156
+
60157
+ ic.setStyleCls.setAtomStyleByOptions(ic.opts);
60158
+ ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
60159
+ ic.drawCls.draw();
60024
60160
  }
60025
-
60026
- ic.setStyleCls.setAtomStyleByOptions(ic.opts);
60027
- ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
60028
- await ic.ParserUtilsCls.renderStructure();
60029
60161
  }
60030
60162
 
60031
60163
  clickMenu6() { let me = this.icn3dui, ic = me.icn3d;
@@ -60045,20 +60177,20 @@ class ClickMenu {
60045
60177
  ic.drawCls.draw();
60046
60178
  });
60047
60179
 
60048
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", async function(e) { me.icn3d; //e.preventDefault();
60049
- await thisClass.setSupercell(0);
60180
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", function(e) { me.icn3d; //e.preventDefault();
60181
+ thisClass.setSupercell(0);
60050
60182
  thisClass.setLogCmd('set supercell 0', true);
60051
60183
  });
60052
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", async function(e) { me.icn3d; //e.preventDefault();
60053
- await thisClass.setSupercell(1);
60184
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", function(e) { me.icn3d; //e.preventDefault();
60185
+ thisClass.setSupercell(1);
60054
60186
  thisClass.setLogCmd('set supercell 1', true);
60055
60187
  });
60056
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", async function(e) { me.icn3d; //e.preventDefault();
60057
- await thisClass.setSupercell(2);
60188
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", function(e) { me.icn3d; //e.preventDefault();
60189
+ thisClass.setSupercell(2);
60058
60190
  thisClass.setLogCmd('set supercell 2', true);
60059
60191
  });
60060
- me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", async function(e) { me.icn3d; //e.preventDefault();
60061
- await thisClass.setSupercell(3);
60192
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", function(e) { me.icn3d; //e.preventDefault();
60193
+ thisClass.setSupercell(3);
60062
60194
  thisClass.setLogCmd('set supercell 3', true);
60063
60195
  });
60064
60196
 
@@ -61416,6 +61548,7 @@ class SetMenu {
61416
61548
  html += this.getLink('mn1_opmid', 'OPM PDB ID ' + me.htmlCls.wifiStr, undefined, 2);
61417
61549
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
61418
61550
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
61551
+ // html += this.getLink('mn1_codid', 'COD ID ' + me.htmlCls.wifiStr, 1, 2);
61419
61552
 
61420
61553
  html += this.getLink('mn1_cid', 'PubChem CID/Name/InChI ' + me.htmlCls.wifiStr, 1, 2);
61421
61554
  html += this.getLink('mn1_smiles', 'Chemical SMILES ', undefined, 2);
@@ -61470,7 +61603,7 @@ class SetMenu {
61470
61603
  //html += this.getMenuText('mn1_fold', 'AlphaFold/ESM', undefined, undefined, 1);
61471
61604
  html += this.getMenuText('mn1_fold', 'Predict by Seq.', undefined, undefined, 1);
61472
61605
  html += "<ul>";
61473
- html += this.getLink('mn1_esmfold', 'ESMFold', undefined, 2);
61606
+ //html += this.getLink('mn1_esmfold', 'ESMFold', undefined, 2);
61474
61607
  //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);
61475
61608
  html += this.getLink('mn1_alphafold', 'AlphaFold2 via ColabFold' + me.htmlCls.wifiStr, undefined, 2);
61476
61609
  html += "</ul>";
@@ -62656,16 +62789,17 @@ class SetMenu {
62656
62789
 
62657
62790
  html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
62658
62791
 
62659
- 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;
62792
+ 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;
62660
62793
 
62661
62794
  //if(bInputid) {
62662
62795
  html += this.getMenuText('assemblyWrapper', 'Assembly', undefined, 1, 1);
62663
62796
  html += "<ul>";
62664
62797
 
62665
- if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined) { // e.g., cif file input
62666
- html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Original Assembly', undefined, 1, 2);
62798
+ if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined) { // e.g., cif file input
62799
+ html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Biological Assembly', undefined, 1, 2);
62800
+ html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', undefined, 1, 2);
62667
62801
  html += this.getRadio('mn6_assembly', 'mn6_assembly1', '1 x 1 x 1', true, 1, 2);
62668
- html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, 1, 2);
62802
+ html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, undefined, 2);
62669
62803
  html += this.getRadio('mn6_assembly', 'mn6_assembly3', '3 x 3 x 3', undefined, 1, 2);
62670
62804
  }
62671
62805
  else if(!me.cfg.bu) {
@@ -63074,7 +63208,6 @@ class Dialog {
63074
63208
  if(status.bSetsInit2) thisClass.openDlg2Ddgm(me.pre + 'dl_definedsets');
63075
63209
  }
63076
63210
  else {
63077
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
63078
63211
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
63079
63212
  }
63080
63213
  }
@@ -63163,7 +63296,6 @@ class Dialog {
63163
63296
  let status = thisClass.getDialogStatus().status;
63164
63297
 
63165
63298
  if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bHbondplot2) &&(!status.bLigplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
63166
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
63167
63299
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
63168
63300
  }
63169
63301
  },
@@ -63208,8 +63340,7 @@ class Dialog {
63208
63340
  }
63209
63341
  }
63210
63342
  else {
63211
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH,(me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) * 0.5, true);
63212
- ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH,(me.htmlCls.HEIGHT) * 0.5, true);
63343
+ //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH,(me.htmlCls.HEIGHT) * 0.5, true);
63213
63344
 
63214
63345
  //height =(me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) * 0.5;
63215
63346
  height =(me.htmlCls.HEIGHT) * 0.5;
@@ -63249,7 +63380,6 @@ class Dialog {
63249
63380
  if(status.bSetsInit2) thisClass.openDlg2Ddgm(me.pre + 'dl_definedsets');
63250
63381
  }
63251
63382
  else {
63252
- //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
63253
63383
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
63254
63384
  }
63255
63385
  }
@@ -63921,6 +64051,12 @@ class SetDialog {
63921
64051
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
63922
64052
  html += "</div>";
63923
64053
 
64054
+ html += me.htmlCls.divStr + "dl_codid' class='" + dialogClass + "'>";
64055
+ html += this.addNotebookTitle('dl_codid', 'Please input a COD ID');
64056
+ html += "COD ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "codid' value='1000041' size=8> ";
64057
+ html += me.htmlCls.buttonStr + "reload_cod'>Load</button>";
64058
+ html += "</div>";
64059
+
63924
64060
  html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
63925
64061
  html += this.addNotebookTitle('dl_mmdbid', 'Please input an MMDB ID');
63926
64062
  html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
@@ -65376,7 +65512,20 @@ class Events {
65376
65512
  let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
65377
65513
 
65378
65514
  if(nameArray.length == 0) {
65379
- nameArray = $("#" + me.pre + "atomsCustom").val();
65515
+ // nameArray = $("#" + me.pre + "atomsCustom").val();
65516
+
65517
+ // choose the first chain for each structure
65518
+ nameArray = [];
65519
+ let structureHash = {};
65520
+ let chains = ic.resid2specCls.atoms2chains(ic.hAtoms);
65521
+
65522
+ for(let chainid in chains) {
65523
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
65524
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
65525
+ nameArray.push(chainid);
65526
+ structureHash[atom.structure] = 1;
65527
+ }
65528
+ }
65380
65529
  }
65381
65530
 
65382
65531
  if(nameArray.length > 0) {
@@ -65396,20 +65545,6 @@ class Events {
65396
65545
  }
65397
65546
 
65398
65547
  if(bMsa) {
65399
- // choose the first chain for each structure
65400
- if(nameArray.length == 0) {
65401
- nameArray = [];
65402
- let structureHash = {};
65403
-
65404
- for(let chainid in ic.chains) {
65405
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
65406
- if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
65407
- nameArray.push(chainid);
65408
- structureHash[atom.structure] = 1;
65409
- }
65410
- }
65411
- }
65412
-
65413
65548
  await ic.realignParserCls.realignOnStructAlignMsa(nameArray);
65414
65549
  }
65415
65550
  else {
@@ -65583,7 +65718,7 @@ class Events {
65583
65718
  let idArray = ids.split(',');
65584
65719
 
65585
65720
  if(!bAppend) {
65586
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
65721
+ if(idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
65587
65722
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
65588
65723
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65589
65724
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65595,8 +65730,8 @@ class Events {
65595
65730
  }
65596
65731
  }
65597
65732
  else {
65598
- // single MMDB ID could show memebranes
65599
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
65733
+ // single MMDB ID could show membranes
65734
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
65600
65735
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
65601
65736
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65602
65737
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -66084,7 +66219,7 @@ class Events {
66084
66219
  if(!me.cfg.notebook) dialog.dialog( "close" );
66085
66220
  thisClass.setLogCmd("load mmtf " + $("#" + me.pre + "mmtfid").val(), false);
66086
66221
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66087
- window.open(hostUrl + '?mmtfid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
66222
+ window.open(hostUrl + '?bcifid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
66088
66223
  }
66089
66224
  });
66090
66225
 
@@ -66428,7 +66563,7 @@ class Events {
66428
66563
  await ic.scapCls.retrieveScap(snp, bInteraction);
66429
66564
  thisClass.setLogCmd('scap interaction ' + snp, true);
66430
66565
 
66431
- let idArray = snp.split('_'); //stru_chain_resi_snp
66566
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
66432
66567
  let select = '.' + idArray[1] + ':' + idArray[2];
66433
66568
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
66434
66569
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -66467,7 +66602,6 @@ class Events {
66467
66602
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66468
66603
  window.open(hostUrl + '?mmcifid=' + $("#" + me.pre + "mmcifid").val(), urlTarget);
66469
66604
  });
66470
-
66471
66605
  me.myEventCls.onIds("#" + me.pre + "mmcifid", "keyup", function(e) { let ic = me.icn3d;
66472
66606
  if (e.keyCode === 13) {
66473
66607
  e.preventDefault();
@@ -66478,6 +66612,23 @@ class Events {
66478
66612
  }
66479
66613
  });
66480
66614
 
66615
+ me.myEventCls.onIds("#" + me.pre + "reload_cod", "click", function(e) { let ic = me.icn3d;
66616
+ e.preventDefault();
66617
+ if(!me.cfg.notebook) dialog.dialog( "close" );
66618
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
66619
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66620
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
66621
+ });
66622
+ me.myEventCls.onIds("#" + me.pre + "codid", "keyup", function(e) { let ic = me.icn3d;
66623
+ if (e.keyCode === 13) {
66624
+ e.preventDefault();
66625
+ if(!me.cfg.notebook) dialog.dialog( "close" );
66626
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
66627
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66628
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
66629
+ }
66630
+ });
66631
+
66481
66632
 
66482
66633
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { let ic = me.icn3d;
66483
66634
  e.preventDefault();
@@ -69063,7 +69214,7 @@ class Events {
69063
69214
  await ic.scapCls.retrieveScap(snp, bInteraction);
69064
69215
  thisClass.setLogCmd('scap interaction ' + snp, true);
69065
69216
 
69066
- let idArray = snp.split('_'); //stru_chain_resi_snp
69217
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
69067
69218
  let select = '.' + idArray[1] + ':' + idArray[2];
69068
69219
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
69069
69220
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -79087,6 +79238,43 @@ class Camera {
79087
79238
  // }
79088
79239
  }
79089
79240
 
79241
+ // Keep the slab plane at the same position relative to the molecule when zooming.
79242
+ // In perspective mode zooming moves the camera along the view direction, so the near plane
79243
+ // (distance from the camera) has to move with it. In orthographic mode zooming only changes
79244
+ // the frustum size and the camera does not move, so the slab plane already stays fixed.
79245
+ updateSlabByZoom() { let ic = this.icn3d, me = ic.icn3dui;
79246
+ if(ic.opts['slab'] !== 'yes' || me.bNode) return;
79247
+ if(ic.opts.camera.toLowerCase() !== 'perspective') return;
79248
+
79249
+ let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
79250
+ if(bInstance) return; // near plane is fixed at 0.1 for instancing
79251
+
79252
+ let cam = (ic.bControlGl) ? window.cam : ic.cam;
79253
+ let controls = (ic.bControlGl) ? window.controls : ic.controls;
79254
+
79255
+ // at zoom = 1 the slab plane is ic.maxD * camMaxDFactor from the camera, i.e. the plane through
79256
+ // the center (or 10 angstroms in front of it when fog is on to keep some surrounding residues)
79257
+ let offset = (ic.camMaxDFactorFog !== undefined) ? 10 : 0;
79258
+
79259
+ // current distance from the camera to the center of rotation, which changes with zooming
79260
+ let dist = cam.position.distanceTo(controls.target);
79261
+
79262
+ // keep the plane at the same position relative to the molecule
79263
+ let nearClip = Math.max(0.1, dist - offset);
79264
+
79265
+ if(Math.abs(cam.near - nearClip) > 1e-6) {
79266
+ cam.near = nearClip;
79267
+ cam.updateProjectionMatrix();
79268
+ if(ic.cam && ic.cam !== cam) {
79269
+ ic.cam.near = nearClip;
79270
+ ic.cam.updateProjectionMatrix();
79271
+ }
79272
+ }
79273
+
79274
+ // the impostor shaders (spheres, cylinders) clip with the nearClip uniform
79275
+ if(ic.uniforms && ic.uniforms.nearClip) ic.uniforms.nearClip.value = nearClip;
79276
+ }
79277
+
79090
79278
  setSlab() { let ic = this.icn3d, me = ic.icn3dui;
79091
79279
  if(ic.bControlGl && !me.bNode) {
79092
79280
  let maxD = ic.maxD;
@@ -79202,7 +79390,8 @@ class Fog {
79202
79390
  else {
79203
79391
  // adjust
79204
79392
  let zoomFactor = (ic._zoomFactor > 1) ? ic._zoomFactor * 1.0 : ic._zoomFactor;
79205
- ic.scene.fog = new Fog$1(background, 2.5 * ic.maxD * zoomFactor, 4 * ic.maxD * zoomFactor);
79393
+ let fogStrength = 2; // 1 = current, >1 = stronger
79394
+ ic.scene.fog = new Fog$1(background, (3 - 0.5 / fogStrength) * ic.maxD * zoomFactor, (3 + 1.0 / fogStrength) * ic.maxD * zoomFactor);
79206
79395
  ic.bSetFog = true;
79207
79396
  ic.camMaxDFactorFog = 3;
79208
79397
  }
@@ -81427,6 +81616,8 @@ class Tube {
81427
81616
 
81428
81617
  let prevAxis1 = new Vector3$1(), prevAxis2;
81429
81618
  for (let i = 0, lim = pnts.length; i < lim; ++i) {
81619
+ if(!pnts[i]) continue;
81620
+
81430
81621
  let r, idx = (i - 1) * axisDivInv;
81431
81622
 
81432
81623
  if (i === 0) {
@@ -81459,7 +81650,7 @@ class Tube {
81459
81650
  }
81460
81651
 
81461
81652
  let delta, axis1, axis2;
81462
- if (i < lim - 1) {
81653
+ if (i < lim - 1 && pnts[i + 1]) {
81463
81654
  delta = pnts[i].clone().sub(pnts[i + 1]);
81464
81655
  axis1 = new Vector3$1(0, -delta.z, delta.y).normalize().multiplyScalar(r);
81465
81656
  axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
@@ -85445,7 +85636,6 @@ class Surface {
85445
85636
  let chainStr = (Object.keys(chainHash).length > 1) ? '<th>Chain</th>' : '';
85446
85637
  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>';
85447
85638
  for(let resid in ic.resid2area) {
85448
- //var idArray = resid.split('_');
85449
85639
  let pos = resid.lastIndexOf('_');
85450
85640
  let resn = resid.substr(pos + 1);
85451
85641
 
@@ -86099,6 +86289,8 @@ class ApplyClbonds {
86099
86289
  // only apply to displayed atoms
86100
86290
  // if(!ic.dAtoms.hasOwnProperty(line.serial1) || !ic.dAtoms.hasOwnProperty(line.serial2)) continue;
86101
86291
 
86292
+ if(!ic.atoms[line.serial1] || !ic.atoms[line.serial2]) continue;
86293
+
86102
86294
  line.position1 = ic.atoms[line.serial1].coord;
86103
86295
  line.position2 = ic.atoms[line.serial2].coord;
86104
86296
 
@@ -86229,6 +86421,7 @@ class ApplyClbonds {
86229
86421
  if(type == 'chemical') continue; // just connect checmicals together
86230
86422
 
86231
86423
  if(ic.clbondpnts[atom0.structure] === undefined) ic.clbondpnts[atom0.structure] = [];
86424
+ if(ic.clbondpnts[atom1.structure] === undefined) ic.clbondpnts[atom1.structure] = [];
86232
86425
  ic.clbondpnts[atom0.structure].push(resid0);
86233
86426
  ic.clbondpnts[atom1.structure].push(resid1);
86234
86427
 
@@ -86774,9 +86967,9 @@ class ApplyOther {
86774
86967
  }
86775
86968
  }
86776
86969
 
86777
- ic.lineCls.createLines(ic.lines);
86778
- if(!ic.planes) ic.planes = [];
86779
- ic.cylinderCls.createPlanes(ic.planes);
86970
+ // ic.lineCls.createLines(ic.lines);
86971
+ // if(!ic.planes) ic.planes = [];
86972
+ // ic.cylinderCls.createPlanes(ic.planes);
86780
86973
  // }
86781
86974
 
86782
86975
  // distance sets
@@ -86899,6 +87092,10 @@ class ApplyOther {
86899
87092
  ic.pk = 3;
86900
87093
  break;
86901
87094
  }
87095
+
87096
+ ic.lineCls.createLines(ic.lines);
87097
+ if(!ic.planes) ic.planes = [];
87098
+ ic.cylinderCls.createPlanes(ic.planes);
86902
87099
  }
86903
87100
 
86904
87101
  applyChemicalbindingOptions(options) { let ic = this.icn3d, me = ic.icn3dui;
@@ -88045,6 +88242,8 @@ class Impostor {
88045
88242
 
88046
88243
  let shiness = ic.shininess / 100.0 * 0.5;
88047
88244
 
88245
+ let fogRGB = background.clone().convertLinearToSRGB();
88246
+
88048
88247
  ic.uniforms = UniformsUtils.merge([
88049
88248
  UniformsLib.common,
88050
88249
  {
@@ -88065,7 +88264,8 @@ class Impostor {
88065
88264
  nearClip: { type: "f", value: nearClip },
88066
88265
  ortho: { type: "f", value: 0.0 },
88067
88266
  shrink: { type: "f", value: 0.13 },
88068
- fogColor: { type: "v3", value: [background.r, background.g, background.b] },
88267
+ //fogColor: { type: "v3", value: [background.r, background.g, background.b] },
88268
+ fogColor: { type: "v3", value: [fogRGB.r, fogRGB.g, fogRGB.b] },
88069
88269
  fogNear: { type: "f", value: near },
88070
88270
  fogFar: { type: "f", value: far },
88071
88271
  fogDensity: { type: "f", value: 2.0 }
@@ -106298,6 +106498,9 @@ class WebGLPathTracer {
106298
106498
 
106299
106499
  cam = this.setDirectLight(cam);
106300
106500
 
106501
+ // move the slab plane according to the zoom
106502
+ if(ic.opts['slab'] === 'yes') ic.cameraCls.updateSlabByZoom();
106503
+
106301
106504
  if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
106302
106505
 
106303
106506
  if(ic.bVr) {
@@ -109861,7 +110064,7 @@ class AnnoCddSite {
109861
110064
  ic.bAjaxCddSite = true;
109862
110065
  }
109863
110066
 
109864
- getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d; ic.icn3dui;
110067
+ getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d, me = ic.icn3dui;
109865
110068
  let resiArrayStr = '';
109866
110069
  for(let i = 0, il = resiNCBIArray.length; i < il; ++i) {
109867
110070
  let resiNCBI = resiNCBIArray[i] + 1; // zero-based
@@ -109869,7 +110072,8 @@ class AnnoCddSite {
109869
110072
  let resid = ic.ncbi2resid[residNCBI];
109870
110073
  if(!resid) resid = residNCBI; // this happens sometimes, e.g., Q9Y4K1
109871
110074
 
109872
- let resi = resid.split('_')[2];
110075
+ let idArray = me.utilsCls.getIdArray(resid);
110076
+ let resi = idArray[2];
109873
110077
  if(i > 0) resiArrayStr += ',';
109874
110078
  resiArrayStr += resi;
109875
110079
  }
@@ -110965,7 +111169,8 @@ class AnnoIg {
110965
111169
  let residArray = Object.keys(residHash);
110966
111170
 
110967
111171
  // delete the following loops
110968
- let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, residArray[residArray.length - 1].split('_')[2]);
111172
+ let idArray = me.utilsCls.getIdArray(residArray[residArray.length - 1]);
111173
+ let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110969
111174
 
110970
111175
  for(let j = lastPos + 1, jl = ic.chainsSeq[chnid].length; j < jl; ++j) {
110971
111176
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -110981,7 +111186,8 @@ class AnnoIg {
110981
111186
  }
110982
111187
 
110983
111188
  // delete the previous loops
110984
- ic.setSeqAlignCls.getPosFromResi(chnid, residArray[0].split('_')[2]);
111189
+ idArray = me.utilsCls.getIdArray(residArray[0]);
111190
+ ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110985
111191
 
110986
111192
  for(let j = lastPos - 1; j >= 0; --j) {
110987
111193
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -111984,8 +112190,9 @@ class AnnoSnpClinVar {
111984
112190
  let residHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chnid]);
111985
112191
  // for(let i = 1, il = ic.giSeq[chnid].length; i <= il; ++i) {
111986
112192
  for(let resid in residHash) {
111987
- let i = resid.split('_')[2];
111988
-
112193
+ let idArray = me.utilsCls.getIdArray(resid);
112194
+ let i = idArray[2];
112195
+
111989
112196
  if(resi2index[i] !== undefined) {
111990
112197
  ++snpCnt;
111991
112198
  let allDiseaseTitle = '';
@@ -114178,7 +114385,6 @@ class Domain3d {
114178
114385
  // if(fromPos >= start && toPos <= end) {
114179
114386
  if(ssCnt > 0) jsonStr += ', ';
114180
114387
  jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
114181
- // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
114182
114388
  jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
114183
114389
  ++ssCnt;
114184
114390
  // }
@@ -114195,7 +114401,6 @@ class Domain3d {
114195
114401
  for(let j = startAll; j <= endAll; ++j) {
114196
114402
  let ncbiResid = chnid + '_' + j;
114197
114403
  let resid = ic.ncbi2resid[ncbiResid];
114198
- resid.split('_')[2];
114199
114404
 
114200
114405
  let pos = j;
114201
114406
 
@@ -114203,7 +114408,6 @@ class Domain3d {
114203
114408
 
114204
114409
  if(!residueHash.hasOwnProperty(resid)) {
114205
114410
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
114206
- // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
114207
114411
  }
114208
114412
  else {
114209
114413
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -114212,7 +114416,6 @@ class Domain3d {
114212
114416
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
114213
114417
 
114214
114418
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
114215
- // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
114216
114419
  }
114217
114420
 
114218
114421
  ++domainCnt;
@@ -120050,7 +120253,6 @@ class GetGraph {
120050
120253
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
120051
120254
  let node = graphJson.nodes[i];
120052
120255
  //node.r: 1_1_1KQ2_A_1
120053
- //var idArray = node.r.split('_');
120054
120256
  let idArray = [];
120055
120257
  idArray.push('');
120056
120258
  idArray.push('');
@@ -120229,8 +120431,8 @@ class GetGraph {
120229
120431
  compNode(a, b, bReverseChain) { let ic = this.icn3d, me = ic.icn3dui;
120230
120432
  let resid1 = a.r.substr(4); // 1_1_1KQ2_A_1
120231
120433
  let resid2 = b.r.substr(4); // 1_1_1KQ2_A_1
120232
- let aIdArray = me.utilsCls.getIdArray(resid1); //resid1.split('_');
120233
- let bIdArray = me.utilsCls.getIdArray(resid2); //resid2.split('_');
120434
+ let aIdArray = me.utilsCls.getIdArray(resid1);
120435
+ let bIdArray = me.utilsCls.getIdArray(resid2);
120234
120436
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
120235
120437
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
120236
120438
  let aResi = parseInt(aIdArray[2]);
@@ -121283,7 +121485,7 @@ class ViewInterPairs {
121283
121485
  residname2 =(type == 'save1') ? residname1_residname2[1] : residname1_residname2[0];
121284
121486
 
121285
121487
  // stru_chain_resi_resn
121286
- let ids = residname1.split('_');
121488
+ let ids = me.utilsCls.getIdArray(residname1);
121287
121489
  if(i > 0 && residname1 != prevResidname1) {
121288
121490
  bondCnt.push({res1: prevResidname1, res2: residname2List, cntHbond: cntHbond, cntIonic: cntIonic, cntContact: cntContact, cntHalegen: cntHalegen, cntPication: cntPication, cntPistacking: cntPistacking});
121289
121491
 
@@ -122684,8 +122886,8 @@ class AlignParser {
122684
122886
  //var scale = data2.transform.scale / factor;
122685
122887
  let tMaster = data2.transform.translate.master;
122686
122888
  let tMVector = new Vector3$1(tMaster[0] / factor, tMaster[1] / factor, tMaster[2] / factor);
122687
- let tSlave = data2.transform.translate.slave;
122688
- let tSVector = new Vector3$1(tSlave[0] / factor, tSlave[1] / factor, tSlave[2] / factor);
122889
+ let tQuery = data2.transform.translate.slave; // actually means query protein
122890
+ let tSVector = new Vector3$1(tQuery[0] / factor, tQuery[1] / factor, tQuery[2] / factor);
122689
122891
  let rotation = data2.transform.rotate;
122690
122892
  let rMatrix = [];
122691
122893
  for(let i = 0, il = rotation.length; i < il; ++i) { // 9 elements
@@ -122929,44 +123131,6 @@ class ChainalignParser {
122929
123131
  // calculate secondary structures with applyCommandDssp
122930
123132
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
122931
123133
  await ic.pdbParserCls.applyCommandDssp(true);
122932
- //!!!
122933
- /*
122934
- // original version =============
122935
- // align PDB chains
122936
- for(let index in ic.pdbChainIndexHash) {
122937
- //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
122938
- let idArray = ic.pdbChainIndexHash[index].split('_');
122939
- mmdbid_q = idArray[0];
122940
- let chain_q = idArray[1];
122941
- mmdbid_t = idArray[2];
122942
- let chain_t = idArray[3];
122943
-
122944
- thisClass.transformStructure(mmdbid_q, index-1, 'query');
122945
- }
122946
-
122947
- // dynamically align pairs in ic.afChainIndexHash
122948
- let ajaxArray = [], indexArray = [], struArray = [];
122949
- let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
122950
- let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
122951
-
122952
- let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
122953
-
122954
- for(let index in ic.afChainIndexHash) {
122955
- let idArray = ic.afChainIndexHash[index].split('_');
122956
- mmdbid_q = idArray[0];
122957
- let chain_q = idArray[1];
122958
- let chainid_q = mmdbid_q + '_' + chain_q;
122959
-
122960
- mmdbid_t = idArray[2];
122961
- let chain_t = idArray[3];
122962
- let chainid_t = mmdbid_t + '_' + chain_t;
122963
-
122964
- // let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t, true).hAtoms : ic.chains[chainid_t];
122965
- // let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q, true).hAtoms : ic.chains[chainid_q];
122966
- let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainid_t, true).hAtoms : ic.chains[chainid_t];
122967
- let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainid_q, true).hAtoms : ic.chains[chainid_q];
122968
- // end of original version =============
122969
- */
122970
123134
 
122971
123135
  // new version to be done for VASTsrv ==============
122972
123136
  // dynamically align pairs in all chainids
@@ -123435,10 +123599,10 @@ class ChainalignParser {
123435
123599
  return chainidArray;
123436
123600
  }
123437
123601
 
123438
- addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
123602
+ addPostfixForStructureids(structArray) { let ic = this.icn3d, me = ic.icn3dui;
123439
123603
  let struct2cnt = {};
123440
123604
  for(let i = 0, il = structArray.length; i < il; ++i) {
123441
- 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
123605
+ 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
123442
123606
 
123443
123607
  let struct = structArray[i].toUpperCase();
123444
123608
 
@@ -123462,6 +123626,8 @@ class ChainalignParser {
123462
123626
 
123463
123627
  ic.opts['proteins'] = 'c alpha trace';
123464
123628
 
123629
+ if(!chainalign) return;
123630
+
123465
123631
  let alignArray = chainalign.split(',');
123466
123632
  let domainArray = (me.cfg.domainids) ? me.cfg.domainids.split(',') : [];
123467
123633
  if(domainArray.length < alignArray.length) domainArray = [];
@@ -123534,7 +123700,7 @@ class ChainalignParser {
123534
123700
  let domainalign = (domainArray.length > 0) ? domainArray[index] + "," + domainArray[0] : undefined;
123535
123701
 
123536
123702
  // TM-align (me.cfg.aligntool == 'tmalign') needs to input PDB
123537
- if(me.cfg.aligntool != 'tmalign' && ic.mmdbid_t.length == 4 && ic.mmdbid_q.length == 4) {
123703
+ 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)) {
123538
123704
  let urlalign;
123539
123705
 
123540
123706
  if(domainArray.length > 0) {
@@ -123823,7 +123989,7 @@ class ChainalignParser {
123823
123989
  }
123824
123990
  else {
123825
123991
  for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
123826
- if(structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
123992
+ 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
123827
123993
 
123828
123994
  let id = structArrayTmp[i].toUpperCase();
123829
123995
  if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
@@ -125354,6 +125520,19 @@ class MmcifParser {
125354
125520
  await ic.opmParserCls.loadOpmData(data, mmcifid, undefined, 'mmcif', undefined, bText);
125355
125521
  }
125356
125522
 
125523
+ async downloadCod(codid) { let ic = this.icn3d, me = ic.icn3dui;
125524
+ //ic.bCid = undefined;
125525
+
125526
+ ic.ParserUtilsCls.setYourNote(codid.toUpperCase() + '(COD) in iCn3D');
125527
+
125528
+ let url = "https://www.crystallography.net/cod/" + codid + ".cif";
125529
+ // let url = "https://www.crystallography.net/cif/1/00/00/1000041.cif";
125530
+ let data = await me.getAjaxPromise(url, 'text', true);
125531
+
125532
+ let bText = true;
125533
+ ic.loadCIFCls.loadCIF(data, codid, bText);
125534
+ }
125535
+
125357
125536
  async downloadMmcifSymmetry(mmcifid, type) { let ic = this.icn3d, me = ic.icn3dui;
125358
125537
  try {
125359
125538
  // let url = "https://files.rcsb.org/download/" + mmcifid + ".cif";
@@ -125467,6 +125646,11 @@ class MmcifParser {
125467
125646
  ic.opts['color'] = 'structure';
125468
125647
  }
125469
125648
 
125649
+ if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
125650
+ ic.pk = 1;
125651
+ ic.opts['pk'] = 'atom';
125652
+ }
125653
+
125470
125654
  ic.opmParserCls.modifyUIMapAssembly();
125471
125655
 
125472
125656
  await ic.pdbParserCls.addSecondary(bAppend);
@@ -125560,9 +125744,10 @@ class MmdbParser {
125560
125744
  me.cfg.query_id = idArray[0];
125561
125745
  me.cfg.blast_rep_id = idArray[1];
125562
125746
 
125563
- let mmdbid = me.cfg.blast_rep_id.split('_')[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
125747
+ let textArray = me.utilsCls.getIdArray(me.cfg.blast_rep_id);
125748
+ let mmdbid = textArray[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
125564
125749
 
125565
- if(mmdbid.length == 4) { // pdb
125750
+ if(mmdbid.length == 4 || mmdbid.indexOf('pdb_') == 0) { // pdb
125566
125751
  await this.downloadMmdb(mmdbid);
125567
125752
  }
125568
125753
  else {
@@ -125714,7 +125899,7 @@ class MmdbParser {
125714
125899
  if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
125715
125900
  // save a set named me.cfg.ligand
125716
125901
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
125717
- let idArray = Object.keys(residueHash)[0].split('_');
125902
+ let idArray = me.utilsCls.getIdArray(Object.keys(residueHash)[0]);
125718
125903
  let select = '.' + idArray[1] + ':' + idArray[2];
125719
125904
 
125720
125905
  await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
@@ -125850,8 +126035,8 @@ class MmdbParser {
125850
126035
 
125851
126036
  if(type === undefined || type === 'target') {
125852
126037
  // if a command contains "load...", the commands should not be cleared with init()
125853
- let bKeepCmd = (ic.bCommandLoad) ? true : false;
125854
- if(!ic.bStatefile) ic.init(bKeepCmd);
126038
+ let bClearCmd = (ic.bCommandLoad) ? false : true;
126039
+ if(!ic.bStatefile) ic.init(bClearCmd);
125855
126040
 
125856
126041
  ic.chainsColor = {};
125857
126042
  ic.chainsGene = {};
@@ -126091,7 +126276,7 @@ class BcifParser {
126091
126276
 
126092
126277
  if (parsed.isError) {
126093
126278
  // report error:
126094
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
126279
+ var aaa = 1; //alert("1 The Binary CIF data can NOT be parsed: " + parsed.toString());
126095
126280
  return;
126096
126281
  }
126097
126282
 
@@ -127056,7 +127241,8 @@ class OpmParser {
127056
127241
  if(!pdbid) pdbid = ic.defaultPdbId;
127057
127242
 
127058
127243
  //if(me.cfg.mmtfid === undefined && me.cfg.bcifid === undefined) { // skip opm for bcif files
127059
- let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + pdbid.toLowerCase();
127244
+ let shortPdbid = pdbid.indexOf('pdb_0000') == 0 ? pdbid.substr(8) : pdbid;
127245
+ let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + shortPdbid.toLowerCase();
127060
127246
 
127061
127247
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
127062
127248
 
@@ -127318,8 +127504,8 @@ class PdbParser {
127318
127504
  async loadPdbData(data, pdbid, bOpm, bAppend, type, bLastQuery, bNoDssp, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
127319
127505
  if(!bAppend && (type === undefined || type === 'target')) {
127320
127506
  // if a command contains "load...", the commands should not be cleared with init()
127321
- let bKeepCmd = (ic.bCommandLoad) ? true : false;
127322
- if(!ic.bStatefile) ic.init(bKeepCmd);
127507
+ let bClearCmd = (ic.bCommandLoad) ? false : true;
127508
+ if(!ic.bStatefile) ic.init(bClearCmd);
127323
127509
  }
127324
127510
 
127325
127511
  let hAtoms = await ic.loadPDBCls.loadPDB(data, pdbid, bOpm, undefined, undefined, bAppend, type, bEsmfold); // defined in the core library
@@ -128132,7 +128318,7 @@ class DcdParser {
128132
128318
  }
128133
128319
 
128134
128320
  for(let j in residuesOri) {
128135
- let idArray = j.split('_');
128321
+ let idArray = me.utilsCls.getIdArray(j);
128136
128322
  let structure2 = idArray[0] + molNum;
128137
128323
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
128138
128324
  ic.residues[residid2] = {};
@@ -128143,7 +128329,7 @@ class DcdParser {
128143
128329
  }
128144
128330
 
128145
128331
  for(let j in chainsOri) {
128146
- let idArray = j.split('_');
128332
+ let idArray = me.utilsCls.getIdArray(j);
128147
128333
  let structure2 = idArray[0] + molNum;
128148
128334
  let chainid2 = structure2 + '_' + idArray[1];
128149
128335
 
@@ -128174,7 +128360,7 @@ class DcdParser {
128174
128360
 
128175
128361
  // set ic.ncbi2resid and ic.resid2ncbi
128176
128362
  for(let chainid in chainsOri) {
128177
- let idArray = chainid.split('_');
128363
+ let idArray = me.utilsCls.getIdArray(chainid);
128178
128364
  let structure2 = idArray[0] + molNum;
128179
128365
  let chainid2 = structure2 + '_' + idArray[1];
128180
128366
 
@@ -128738,7 +128924,7 @@ class XtcParser {
128738
128924
  }
128739
128925
 
128740
128926
  for(let j in residuesOri) {
128741
- let idArray = j.split('_');
128927
+ let idArray = me.utilsCls.getIdArray(j);
128742
128928
  let structure2 = idArray[0] + molNum;
128743
128929
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
128744
128930
  ic.residues[residid2] = {};
@@ -128749,7 +128935,7 @@ class XtcParser {
128749
128935
  }
128750
128936
 
128751
128937
  for(let j in chainsOri) {
128752
- let idArray = j.split('_');
128938
+ let idArray = me.utilsCls.getIdArray(j);
128753
128939
  let structure2 = idArray[0] + molNum;
128754
128940
  let chainid2 = structure2 + '_' + idArray[1];
128755
128941
 
@@ -128780,7 +128966,7 @@ class XtcParser {
128780
128966
 
128781
128967
  // set ic.ncbi2resid and ic.resid2ncbi
128782
128968
  for(let chainid in chainsOri) {
128783
- let idArray = chainid.split('_');
128969
+ let idArray = me.utilsCls.getIdArray(chainid);
128784
128970
  let structure2 = idArray[0] + molNum;
128785
128971
  let chainid2 = structure2 + '_' + idArray[1];
128786
128972
 
@@ -129006,9 +129192,8 @@ class MsaParser {
129006
129192
 
129007
129193
  // realign based on residue by residue
129008
129194
  let alignment_final = ic.inputChainidArray.join(',');
129009
-
129010
129195
  if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
129011
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
129196
+ 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...");
129012
129197
  return;
129013
129198
  }
129014
129199
 
@@ -129066,7 +129251,7 @@ class MsaParser {
129066
129251
  }
129067
129252
 
129068
129253
  if(type == 'clustalw') {
129069
- if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
129254
+ if(line.substr(0, 1) != '.' && line.substr(0, 1) != '*') {
129070
129255
  let chainid_seq = line.split(/\s+/);
129071
129256
  let idArray = chainid_seq[0].split('|');
129072
129257
  let result = this.getChainid(idArray, bStart && !bSecBlock);
@@ -129091,9 +129276,11 @@ class MsaParser {
129091
129276
  seq = '';
129092
129277
 
129093
129278
  let pos = line.indexOf(' ');
129279
+ if(pos == -1) pos = line.length;
129094
129280
  let idArray = line.substr(1, pos).split('|');
129095
-
129281
+
129096
129282
  if(idArray.length == 1) {
129283
+ bFound = true;
129097
129284
  chainid = idArray[0];
129098
129285
  }
129099
129286
  else {
@@ -129157,8 +129344,9 @@ class MsaParser {
129157
129344
  ic.inputChainidArray.push(chainid + '_A');
129158
129345
  }
129159
129346
  }
129160
- else if(chainid.indexOf('_') != -1) { // PDB ID
129161
- let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
129347
+ else if(chainid.indexOf('_') != -1 || chainid.indexOf('pdb_') != -1) { // PDB ID
129348
+ let idArray = me.utilsCls.getIdArray(chainid);
129349
+ let stru = idArray[0];
129162
129350
  ic.struArray.push(stru);
129163
129351
  ic.inputChainidArray.push(chainid);
129164
129352
  }
@@ -129240,7 +129428,7 @@ class RealignParser {
129240
129428
  }
129241
129429
 
129242
129430
  // ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn.substr(0, 3)).substr(0, 1)});
129243
- ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn).substr(0, 1)});
129431
+ ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn, true)});
129244
129432
 
129245
129433
  struct2chain[atom.structure] = atom.structure + '_' + atom.chain;
129246
129434
 
@@ -129283,7 +129471,8 @@ class RealignParser {
129283
129471
 
129284
129472
  async parseChainRealignPredefined(chainidArray, struct2SeqHash, struct2CoorHash, struct2resid) { let ic = this.icn3d, me = ic.icn3dui;
129285
129473
 
129286
- let toStruct = chainidArray[0].substr(0, chainidArray[0].indexOf('_')); //.toUpperCase();
129474
+ let itemArray1 = me.utilsCls.getIdArray(chainidArray[0]);
129475
+ let toStruct = itemArray1[0];
129287
129476
 
129288
129477
  let hAtoms = {}, rmsd;
129289
129478
 
@@ -129296,13 +129485,14 @@ class RealignParser {
129296
129485
  ic.qt_start_end = [];
129297
129486
 
129298
129487
  let chainidHash = {};
129299
- for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
129300
- let fromStruct = chainidArray[index + 1].substr(0, chainidArray[index + 1].indexOf('_')); //.toUpperCase();
129488
+ for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
129489
+ let itemArray2 = me.utilsCls.getIdArray(chainidArray[index + 1]);
129490
+ let fromStruct = itemArray2[0];
129301
129491
 
129302
129492
  //if(toStruct == fromStruct) fromStruct += me.htmlCls.postfix;
129303
129493
 
129304
- let chainTo = toStruct + chainidArray[0].substr(chainidArray[0].indexOf('_'));
129305
- let chainFrom = fromStruct + chainidArray[index + 1].substr(chainidArray[index + 1].indexOf('_'));
129494
+ let chainTo = toStruct + '_' + itemArray1[1];
129495
+ let chainFrom = fromStruct + '_' + itemArray2[1];
129306
129496
  chainidHash[chainTo] = 1;
129307
129497
  chainidHash[chainFrom] = 1;
129308
129498
 
@@ -129337,7 +129527,7 @@ class RealignParser {
129337
129527
 
129338
129528
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, result.hAtoms);
129339
129529
  rmsd = parseFloat(result.rmsd);
129340
- }
129530
+ }
129341
129531
 
129342
129532
  // If rmsd from vastsrv is too large, realign the chains
129343
129533
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
@@ -129559,15 +129749,6 @@ class RealignParser {
129559
129749
  prevChainid = chainidArrayTmp[i];
129560
129750
  }
129561
129751
 
129562
- // use the model from Membranome as template
129563
- // if(ic.bAfMem && chainidArray.length == 2) {
129564
- // if(chainidArray[1].split('_')[0] == pdbidTemplate) {
129565
- // let tmp = chainidArray[0];
129566
- // chainidArray[0] = chainidArray[1];
129567
- // chainidArray[1] = tmp;
129568
- // }
129569
- // }
129570
-
129571
129752
  let bRealign = true;
129572
129753
  ic.qt_start_end = []; // reset the alignment
129573
129754
 
@@ -129812,12 +129993,13 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129812
129993
  let predefinedResArray, predefinedResPair;
129813
129994
 
129814
129995
  if(bPredefined) {
129815
- me.cfg.resdef.replace(/; /gi, ': ');
129816
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
129817
- // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
129818
-
129996
+ me.cfg.resdef = decodeURIComponent(me.cfg.resdef).trim();
129997
+ let tmpStr = me.cfg.resdef.replace(/; /gi, ': ');
129998
+ // predefinedResArray = decodeURIComponent(tmpStr).trim().replace(/\+/gi, ' ').split(': ');
129999
+ predefinedResArray = tmpStr.replace(/\+/gi, ' ').split(': ');
130000
+
129819
130001
  if(predefinedResArray.length != chainidArray.length - 1) {
129820
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
130002
+ 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...");
129821
130003
  return;
129822
130004
  }
129823
130005
  }
@@ -129826,8 +130008,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129826
130008
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
129827
130009
  //if(bPredefined) predefinedRes = predefinedResArray[i].trim();
129828
130010
 
129829
- let pos = chainidArray[i].indexOf('_');
129830
- let mmdbid = chainidArray[i].substr(0, pos); //.toUpperCase();
130011
+ let itemArray = me.utilsCls.getIdArray(chainidArray[i]);
130012
+ let mmdbid = itemArray[0]; //.toUpperCase();
129831
130013
 
129832
130014
  // if(!bRealign) mmdbid = mmdbid.toUpperCase();
129833
130015
 
@@ -129835,7 +130017,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129835
130017
  mmdbid_t = mmdbid;
129836
130018
  }
129837
130019
 
129838
- let chainid = mmdbid + chainidArray[i].substr(pos);
130020
+ let chainid = mmdbid + '_' + itemArray[1];
129839
130021
  if(i == 0) chainid_t = chainid;
129840
130022
 
129841
130023
  if(!ic.chainsSeq || !ic.chainsSeq[chainid]) {
@@ -129864,7 +130046,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129864
130046
  if(!struct2CoorHash[chainidpair]) struct2CoorHash[chainidpair] = {};
129865
130047
  if(!struct2resid[chainidpair]) struct2resid[chainidpair] = {};
129866
130048
 
129867
- // master
130049
+ // template
129868
130050
  resiArray = predefinedResPair[0].split(",");
129869
130051
 
129870
130052
  result = thisClass.getSeqCoorResid(resiArray, chainid_t);
@@ -129879,7 +130061,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129879
130061
  struct2CoorHash[chainidpair][mmdbid_t] = struct2CoorHash[chainidpair][mmdbid_t].concat(result.coor);
129880
130062
  struct2resid[chainidpair][mmdbid_t] = struct2resid[chainidpair][mmdbid_t].concat(result.resid);
129881
130063
 
129882
- // slave
130064
+ // query
129883
130065
  resiArray = predefinedResPair[1].split(",");
129884
130066
 
129885
130067
  result = thisClass.getSeqCoorResid(resiArray, chainid);
@@ -129907,7 +130089,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129907
130089
  }
129908
130090
  }
129909
130091
  else {
129910
- if(i == 0) { // master
130092
+ if(i == 0) { // template
129911
130093
  //base = parseInt(ic.chainsSeq[chainid][0].resi);
129912
130094
 
129913
130095
  resiArray = [];
@@ -129947,7 +130129,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129947
130129
  bSelectedBoth = true;
129948
130130
 
129949
130131
  let resn = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]).resn;
129950
- struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn);
130132
+ struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn, true);
129951
130133
 
129952
130134
  struct2CoorHash[chainid] = struct2CoorHash[chainid].concat(this.getResCoorArray(resid));
129953
130135
 
@@ -132262,9 +132444,6 @@ class LoadAtomData {
132262
132444
  atm.coord = new Vector3$1(atm.coord.x, atm.coord.y, atm.coord.z);
132263
132445
  }
132264
132446
 
132265
- // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
132266
- let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn);
132267
-
132268
132447
  if((type === 'mmdbid' || type === 'align') && ic.bFullUi ) {
132269
132448
  // set ic.mmdbMolidResid2mmdbChainResi
132270
132449
  if(ic.mmdbMolidResid2mmdbChainResi === undefined) ic.mmdbMolidResid2mmdbChainResi = {};
@@ -132406,6 +132585,8 @@ class LoadAtomData {
132406
132585
  }
132407
132586
  }
132408
132587
 
132588
+ // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
132589
+ let oneLetterRes = (atm.het) ? me.utilsCls.residueName2Abbr(atm.resn) : me.utilsCls.residueName2Abbr(atm.resn, true);
132409
132590
  ic.residueId2Name[residueid] = oneLetterRes;
132410
132591
 
132411
132592
  let secondaries = '-';
@@ -132753,59 +132934,6 @@ class SetSeqAlign {
132753
132934
  ic.nconsHash2 = {};
132754
132935
  ic.nalignHash2 = {};
132755
132936
 
132756
- let msaSameColor = [];
132757
- // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132758
- for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132759
- msaSameColor.push(1);
132760
- }
132761
-
132762
- for(let i = 0, il = seqalign.length; i < il; ++i) {
132763
- // first sequence
132764
- let alignData = seqalign[i][0];
132765
- let molid1 = alignData.moleculeId;
132766
-
132767
- let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
132768
- chainid1 = mmdbid1 + '_' + chain1;
132769
-
132770
- let id2aligninfo = {};
132771
- let start = alignData.sequence.length, end = -1;
132772
- let bStart = false;
132773
- for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
132774
- // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132775
- let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132776
- let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
132777
- resn =(resn === ' ' || resn === '') ? 'X' : resn;
132778
-
132779
- let aligned =(alignData.sequence[j][3]) ? 1 : 0;
132780
-
132781
- if(aligned == 1) {
132782
- if(j < start && !bStart) {
132783
- start = j;
132784
- bStart = true; // set start just once
132785
- }
132786
- if(j > end) end = j;
132787
- }
132788
-
132789
- id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132790
- }
132791
-
132792
- // second sequence
132793
- alignData = seqalign[i][1];
132794
-
132795
- for(let j = start; j <= end; ++j) {
132796
- // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132797
- let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132798
-
132799
- let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132800
-
132801
- if(aligned === 2) { // aligned
132802
- if(id2aligninfo[j].resn != resn) {
132803
- msaSameColor[j] = 0;
132804
- }
132805
- }
132806
- }
132807
- }
132808
-
132809
132937
  for(let i = 0, il = seqalign.length; i < il; ++i) {
132810
132938
  // first sequence
132811
132939
  let alignData = seqalign[i][0];
@@ -132902,8 +133030,6 @@ class SetSeqAlign {
132902
133030
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132903
133031
  }
132904
133032
 
132905
- color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132906
-
132907
133033
  // mapping, use the firstsequence as the reference structure
132908
133034
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
132909
133035
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132920,8 +133046,6 @@ class SetSeqAlign {
132920
133046
 
132921
133047
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132922
133048
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132923
-
132924
- msaSameColor[j] = 2; // not aligned
132925
133049
  }
132926
133050
 
132927
133051
  // chain1
@@ -133301,7 +133425,7 @@ class SetSeqAlign {
133301
133425
  }
133302
133426
  }
133303
133427
  }
133304
-
133428
+
133305
133429
  for(let j = 0; j <= end1 - start1; ++j) {
133306
133430
  ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
133307
133431
 
@@ -133414,29 +133538,43 @@ class SetSeqAlign {
133414
133538
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
133415
133539
  let start1, end1;
133416
133540
 
133417
- //ic.qt_start_end is zero-based
133418
- if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
133419
- start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
133420
- end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
133421
- }
133422
- else {
133423
- start1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_start) - 1;
133424
- end1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_end) - 1;
133425
- }
133426
-
133541
+ // if(bRealign) { // real residue numbers are stored
133542
+ // start1 = ic.qt_start_end[chainIndex][i].t_start;
133543
+ // end1 = ic.qt_start_end[chainIndex][i].t_end;
133544
+ // }
133545
+ // else {
133546
+ //ic.qt_start_end is zero-based
133547
+ if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
133548
+ start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
133549
+ end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
133550
+ }
133551
+ else {
133552
+ start1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_start) - 1;
133553
+ end1 = ic.ParserUtilsCls.getResiNCBI(chainid1, ic.qt_start_end[chainIndex][i].t_end) - 1;
133554
+ }
133555
+ // }
133427
133556
  for(let j = start1; j <= end1; ++j) {
133428
133557
  let resi, resid;
133429
133558
 
133430
- // let resiPos;
133431
- // if(me.cfg.aligntool == 'tmalign') {
133432
- // resiPos = j - baseResi;
133559
+ // if(me.cfg.aligntool == 'tmalign') { // tmalign: just one residue in this for loop
133560
+ // resi = ic.qt_start_end[chainIndex][i].t_start;
133433
133561
  // }
133434
133562
  // else {
133435
- // resiPos = j;
133563
+ // let resiPos = (bRealign || me.cfg.aligntool != 'tmalign') ? j : j - baseResi;
133564
+ // let resiPos;
133565
+ // if(me.cfg.aligntool == 'tmalign') {
133566
+ // resiPos = j - baseResi;
133567
+ // }
133568
+ // else {
133569
+ // // resiPos = (bRealign) ? j : j - baseResi;
133570
+ // resiPos = j;
133571
+ // }
133572
+
133573
+ let resiPos = j;
133574
+
133575
+ resi = ic.ParserUtilsCls.getResi(chainidArray[0], resiPos);
133576
+ resid = chainidArray[0] + '_' + resi;
133436
133577
  // }
133437
- let resiPos = j;
133438
- resi = ic.ParserUtilsCls.getResi(chainidArray[0], resiPos);
133439
- resid = chainidArray[0] + '_' + resi;
133440
133578
 
133441
133579
  resid2range_t[resid] = 1;
133442
133580
  if(j < start_t) start_t = j;
@@ -133450,14 +133588,18 @@ class SetSeqAlign {
133450
133588
 
133451
133589
  let resid2rangeArray = Object.keys(resid2range_t);
133452
133590
  resid2rangeArray.sort(function(a, b) {
133453
- return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
133591
+ // return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
133592
+ let idArray1 = me.utilsCls.getIdArray(a);
133593
+ let idArray2 = me.utilsCls.getIdArray(b);
133594
+ return parseInt(idArray1[2]) - parseInt(idArray2[2]);
133454
133595
  });
133455
133596
 
133456
133597
  // assign range to each resi
133457
133598
  let prevResi = -999, start = 0, end = 0, residArray = [], prevEnd = 0;
133458
133599
  for(let i = 0, il = resid2rangeArray.length; i < il; ++i) {
133459
133600
  let resid = resid2rangeArray[i];
133460
- let resi = resid.split('_')[2];
133601
+ let idArray = me.utilsCls.getIdArray(resid);
133602
+ let resi = idArray[2];
133461
133603
 
133462
133604
  if(i == 0) {
133463
133605
  start = resi;
@@ -133497,7 +133639,7 @@ class SetSeqAlign {
133497
133639
  let resid = chainid1 + '_' + resi;
133498
133640
 
133499
133641
  // let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : j + baseResi;
133500
- let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
133642
+ let jAdjusted = (me.cfg.aligntool == 'seqalign') ? j : ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
133501
133643
 
133502
133644
  //if(j + baseResi < start_t || j + baseResi > end_t) {
133503
133645
  if(jAdjusted < start_t || jAdjusted > end_t) {
@@ -133515,6 +133657,7 @@ class SetSeqAlign {
133515
133657
  resObject.color2 = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by conservation
133516
133658
  // resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
133517
133659
  resObject.class = (resid2range_t[resid]) ? 'icn3d-cons' : 'icn3d-nalign';
133660
+
133518
133661
  ic.alnChainsSeq[chainid1].push(resObject);
133519
133662
 
133520
133663
  if(resid2range_t[resid]) {
@@ -133648,7 +133791,7 @@ class SetSeqAlign {
133648
133791
  if(ic.alnChainsSeq[chainid1]) {
133649
133792
  for(let j = 0, jl = ic.alnChainsSeq[chainid1].length; j < jl; ++j) {
133650
133793
  //add gap before the mapping region
133651
- //if(parseInt(ic.alnChainsSeq[chainid1][j].resi) == parseInt(resi_t)) {
133794
+ // if(parseInt(ic.alnChainsSeq[chainid1][j].resi) == parseInt(resi_t)) {
133652
133795
  if(ic.alnChainsSeq[chainid1][j].resi == resi_t) {
133653
133796
  pos_t = j;
133654
133797
  break;
@@ -133674,7 +133817,6 @@ class SetSeqAlign {
133674
133817
  for(let j = 0, jl = alignedChainIndice.length - 1; j < jl; ++j) {
133675
133818
  let chainidTmp = chainidArray[alignedChainIndice[j]];
133676
133819
  let gapResObject = this.getResObject(chainidTmp, true);
133677
-
133678
133820
  //for(let k = 0, kl = len - nGap; k < kl; ++k) {
133679
133821
  for(let k = 0, kl = len; k < kl; ++k) {
133680
133822
  ic.alnChainsSeq[chainidTmp].splice(pos_t, 0, gapResObject);
@@ -133691,6 +133833,7 @@ class SetSeqAlign {
133691
133833
  // let resn2 = this.getResn(chainid, start + j);
133692
133834
  let resi2 = (bRealign && me.cfg.aligntool == 'tmalign') ? start + j : ic.ParserUtilsCls.getResi(chainid, start + j);
133693
133835
  let resn2 = this.getResnFromResi(chainid, resi2);
133836
+
133694
133837
  let resn1 = '-';
133695
133838
  let bAlign = false;
133696
133839
  let resObject = this.getResObject(chainid, false, bAlign, resi2, resn2, resn1);
@@ -133698,9 +133841,17 @@ class SetSeqAlign {
133698
133841
  }
133699
133842
  }
133700
133843
 
133844
+ getTemplatePosFromOriPos(chainid1, start, end, bRealign) { let ic = this.icn3d; ic.icn3dui;
133845
+ let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
133846
+ let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
133847
+
133848
+ let result1 = this.getResiPosInTemplate(chainid1, startResi);
133849
+ let result2 = this.getResiPosInTemplate(chainid1, endResi);
133850
+
133851
+ return {"pos1": result1.pos, "pos2": result2.pos};
133852
+ }
133853
+
133701
133854
  getTemplatePosFromOriResi(chainid1, start, end, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
133702
- // let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
133703
- // let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
133704
133855
  if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
133705
133856
  let startResi = start;
133706
133857
  let endResi = end;
@@ -133774,9 +133925,6 @@ class SetSeqAlign {
133774
133925
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
133775
133926
 
133776
133927
  let result;
133777
-
133778
- let nGapInTemplate = 0; // number of gaps inserted into the template sequence
133779
- let startPosInTemplate = 0; // position in the template sequence to start the mapping
133780
133928
 
133781
133929
  // need to improve when tmalign with residue number with postfix such as 52A in 4ORZ_C,5ESV_H
133782
133930
  // start and end should be positions, not original residue numbers.
@@ -133786,8 +133934,7 @@ class SetSeqAlign {
133786
133934
  }
133787
133935
 
133788
133936
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
133789
- let start1, start2, end1, end2, resiStart1, start1Pos;
133790
-
133937
+ let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
133791
133938
  if(bRealign && me.cfg.aligntool == 'tmalign') { // real residue numbers are stored
133792
133939
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start);
133793
133940
  start2 = parseInt(ic.qt_start_end[chainIndex][i].q_start);
@@ -133802,7 +133949,7 @@ class SetSeqAlign {
133802
133949
  // 1. before the mapped residues
133803
133950
  resiStart1 = start1;
133804
133951
  start1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_start);
133805
- this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133952
+ end1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133806
133953
  }
133807
133954
  else {
133808
133955
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start - 1);
@@ -133813,28 +133960,49 @@ class SetSeqAlign {
133813
133960
  // 1. before the mapped residues
133814
133961
  resiStart1 = ic.ParserUtilsCls.getResi(chainid1, start1);
133815
133962
  start1Pos = start1;
133963
+ end1Pos = end1;
133816
133964
  }
133817
133965
  //let range = resid2range_t[chainid1 + '_' + resiStart1];
133818
-
133966
+
133819
133967
  // if the mapping does not start from start_t, add gaps to the query seq
133820
133968
  if(i == 0) {
133821
- startPosInTemplate = start1Pos;
133822
133969
 
133823
- result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
133824
- //result = this.getTemplatePosFromOriResi(chainid1, start_t, start1Pos, bRealign);
133825
- pos1 = result.pos1;
133826
- pos2 = result.pos2;
133970
+ if(me.cfg.aligntool == 'seqalign') {
133971
+ result = this.getTemplatePosFromOriPos(chainid1, start_t, start1Pos, bRealign);
133827
133972
 
133828
- if(start1 > start_t) {
133829
- //if(start1Pos > start_t) {
133830
- for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133831
- ic.alnChainsSeq[chainid2].push(gapResObject2);
133973
+ pos1 = result.pos1;
133974
+ pos2 = result.pos2;
133975
+
133976
+ //if(start1 > start_t) {
133977
+ if(start1Pos > start_t) {
133978
+ for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133979
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
133980
+ }
133981
+ }
133982
+ }
133983
+ else {
133984
+ result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
133985
+
133986
+ pos1 = result.pos1;
133987
+ pos2 = result.pos2;
133988
+
133989
+ if(start1 > start_t) {
133990
+ //if(start1Pos > start_t) {
133991
+ for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133992
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
133993
+ }
133832
133994
  }
133833
133995
  }
133834
133996
  }
133835
133997
  else {
133836
133998
  //let notAlnLen1 = start1 - (prevIndex1 + 1);
133837
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
133999
+ //!!!
134000
+ if(me.cfg.aligntool == 'seqalign') {
134001
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, start1Pos, bRealign);
134002
+ }
134003
+ else {
134004
+ result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
134005
+ }
133838
134006
  pos1 = result.pos1;
133839
134007
  pos2 = result.pos2;
133840
134008
  let notAlnLen1 = pos2 - (pos1 + 1);
@@ -133845,46 +134013,48 @@ class SetSeqAlign {
133845
134013
 
133846
134014
  // insert non-aligned residues in query seq
133847
134015
  this.insertNotAlignRes(chainid2, prevIndex2+1, notAlnLen2, bRealign);
134016
+
133848
134017
  if(notAlnLen1 >= notAlnLen2) {
133849
134018
  // add gaps before the query sequence
133850
134019
  for(let j = 0, jl = notAlnLen1 - notAlnLen2; j < jl; ++j) {
133851
134020
  ic.alnChainsSeq[chainid2].push(gapResObject2);
133852
- }
134021
+ }
133853
134022
  }
133854
134023
  else {
133855
134024
  // check the number of gaps before resiStart1 (n), and insert 'notAlnLen2 - notAlnLen1 - n' gaps
133856
134025
  this.addGapAllAlnChains(chainidArray, alignedChainIndice, chainid1, resiStart1, notAlnLen2 - notAlnLen1);
133857
- nGapInTemplate += (notAlnLen2 - notAlnLen1);
133858
134026
  }
133859
134027
  }
133860
134028
 
133861
134029
  // 2. In the mapped residues
133862
- result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
133863
- //result = this.getTemplatePosFromOriResi(chainid1, start1Pos, end1Pos, bRealign);
134030
+ if(me.cfg.aligntool == 'seqalign') {
134031
+ result = this.getTemplatePosFromOriPos(chainid1, start1Pos, end1Pos, bRealign);
134032
+ }
134033
+ else {
134034
+ result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
134035
+ }
133864
134036
  pos1 = result.pos1;
133865
134037
  pos2 = result.pos2;
133866
-
134038
+
133867
134039
  let k = 0;
133868
134040
  if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
133869
134041
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
133870
- let resiAdjust = (bRealign && me.cfg.aligntool == 'tmalign') ? 0 : - startPosInTemplate + nGapInTemplate;
133871
134042
  for(let j = pos1; j <= pos2; ++j) {
133872
134043
  // inherit the gaps from the template
133873
- if(ic.alnChainsSeq[chainid1][j + resiAdjust].resn == '-') {
134044
+ if(ic.alnChainsSeq[chainid1][j].resn == '-') {
133874
134045
  ic.alnChainsSeq[chainid2].push(gapResObject2);
133875
134046
  }
133876
134047
  else {
133877
134048
  let resi1 = (bRealign && me.cfg.aligntool == 'tmalign') ? start1 + k : ic.ParserUtilsCls.getResi(chainid1, start1 + k);
133878
134049
  let resi2 = (bRealign && me.cfg.aligntool == 'tmalign') ? start2 + k : ic.ParserUtilsCls.getResi(chainid2, start2 + k);
133879
-
133880
134050
  let resn1 = this.getResnFromResi(chainid1, resi1); //this.getResn(chainid1, start1 + k);
133881
134051
  let resn2 = this.getResnFromResi(chainid2, resi2); //this.getResn(chainid2, start2 + k);
133882
-
134052
+
133883
134053
  let bAlign = true;
133884
134054
  let resObject = this.getResObject(chainid2, false, bAlign, resi2, resn2, resn1);
133885
134055
  ic.alnChainsSeq[chainid2].push(resObject);
133886
134056
  // update color in the template
133887
- ic.alnChainsSeq[chainid1][j + resiAdjust].color = resObject.color;
134057
+ ic.alnChainsSeq[chainid1][j].color = resObject.color;
133888
134058
 
133889
134059
  ic.chainsMapping[chainid1][chainid1 + '_' + resi1] = resn1 + resi1;
133890
134060
  ic.chainsMapping[chainid2][chainid2 + '_' + resi2] = resn1 + resi1;
@@ -133902,7 +134072,12 @@ class SetSeqAlign {
133902
134072
  }
133903
134073
 
133904
134074
  // add gaps at the end
133905
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
134075
+ if(me.cfg.aligntool == 'seqalign') {
134076
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, end_t, bRealign);
134077
+ }
134078
+ else {
134079
+ result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
134080
+ }
133906
134081
  pos1 = result.pos1;
133907
134082
  pos2 = result.pos2;
133908
134083
  for(let i = pos1; i < pos2; ++i) {
@@ -133922,7 +134097,7 @@ class SetSeqAlign {
133922
134097
 
133923
134098
  for(let i = 0, il = ic.qt_start_end[index].length; i < il; ++i) {
133924
134099
  let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
133925
-
134100
+
133926
134101
  start1 = ic.qt_start_end[index][i].t_start;
133927
134102
  start2 = ic.qt_start_end[index][i].q_start;
133928
134103
  end1 = ic.qt_start_end[index][i].t_end;
@@ -134240,8 +134415,8 @@ class SetSeqAlign {
134240
134415
 
134241
134416
  setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
134242
134417
  //set MSA
134243
- let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
134244
- let chainArrayClustal = [];
134418
+ let fastaFormat = '', clustalwFormat = 'CLUSTALW\n\n', resbyresFormat = '';
134419
+ let chainArrayClustalw = [];
134245
134420
 
134246
134421
  let consArray = [], resiArrayTemplate = [];
134247
134422
  let chainidTemplate = chainidArray[0];
@@ -134310,8 +134485,8 @@ class SetSeqAlign {
134310
134485
 
134311
134486
  fastaFormat += '\n';
134312
134487
 
134313
- chainArrayClustal.push(clustalwArray);
134314
- if(i == il - 1) chainArrayClustal.push(consArray);
134488
+ chainArrayClustalw.push(clustalwArray);
134489
+ if(i == il - 1) chainArrayClustalw.push(consArray);
134315
134490
 
134316
134491
  // residue by residue
134317
134492
  let resiRangeStr1 = ic.resid2specCls.resi2range(resiArrayTarget, true);
@@ -134320,10 +134495,10 @@ class SetSeqAlign {
134320
134495
  if(i > 0) resbyresFormat += resiRangeStr1 + ' | ' + resiRangeStr2 + '\n';
134321
134496
  }
134322
134497
 
134323
- // CLUSTALWW
134324
- for(let j = 0, jl = chainArrayClustal[0].length; j < jl; ++j) {
134325
- for(let i = 0, il = chainArrayClustal.length; i < il; ++i) {
134326
- clustalwFormat += chainArrayClustal[i][j] + '\n';
134498
+ // CLUSTALW
134499
+ for(let j = 0, jl = chainArrayClustalw[0].length; j < jl; ++j) {
134500
+ for(let i = 0, il = chainArrayClustalw.length; i < il; ++i) {
134501
+ clustalwFormat += chainArrayClustalw[i][j] + '\n';
134327
134502
  }
134328
134503
  clustalwFormat += '\n';
134329
134504
  }
@@ -134790,7 +134965,7 @@ class LoadPDB {
134790
134965
  //if(residueNum !== prevResidueNum) {
134791
134966
 
134792
134967
  if(oriResidueNum !== prevOriResidueNum) {
134793
- let residue = me.utilsCls.residueName2Abbr(resn);
134968
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
134794
134969
  ic.residueId2Name[residueNum] = residue;
134795
134970
 
134796
134971
  if(serial !== 1 && prevResidueNum !== '') ic.residues[prevResidueNum] = residuesTmp;
@@ -135237,7 +135412,7 @@ class LoadPDB {
135237
135412
 
135238
135413
  for(let chainid in chains) {
135239
135414
  if(pdbid !== undefined) {
135240
- let textArray = chainid.split('_');
135415
+ let textArray = me.utilsCls.getIdArray(chainid);
135241
135416
  if(textArray[0] !== pdbid) continue; // skip different chain
135242
135417
  }
135243
135418
 
@@ -135345,15 +135520,15 @@ class LoadCIF {
135345
135520
  loadCIF(bcifData, bcifid, bText, bAppend, supercell) { let ic = this.icn3d, me = ic.icn3dui;
135346
135521
  ic.cifText = bText;
135347
135522
  ic.cifData = bcifData;
135348
-
135523
+
135349
135524
  if(supercell === undefined) {
135350
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true };
135525
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135351
135526
  }
135352
135527
  else if(supercell === 0) {
135353
- CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: false };
135528
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135354
135529
  }
135355
135530
  else {
135356
- CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true };
135531
+ CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135357
135532
  }
135358
135533
 
135359
135534
  let hAtoms = {};
@@ -135369,7 +135544,7 @@ class LoadCIF {
135369
135544
  let serial, moleculeNum;
135370
135545
  // if(!bMutation && !bAppend) {
135371
135546
  if(!bAppend) {
135372
- ic.init();
135547
+ ic.init(undefined, true); // keep original configurations, such as color, style, etc. when loading multiple structures
135373
135548
  moleculeNum = 0; //1;
135374
135549
  serial = 0;
135375
135550
  }
@@ -135413,11 +135588,13 @@ class LoadCIF {
135413
135588
 
135414
135589
  if (parsed.isError) {
135415
135590
  // report error:
135416
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
135591
+ var aaa = 1; //alert("2 The Binary CIF data can NOT be parsed: " + parsed.toString());
135417
135592
  return;
135418
135593
  }
135419
135594
 
135420
135595
  let block = parsed.result.dataBlocks[0];
135596
+
135597
+ if(!block) continue;
135421
135598
 
135422
135599
  if(block.getCategory("_entry")) {
135423
135600
  id = block.getCategory("_entry").getColumn("id").getString(0);
@@ -135656,6 +135833,8 @@ class LoadCIF {
135656
135833
  ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
135657
135834
  ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
135658
135835
  ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
135836
+
135837
+ 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);
135659
135838
  }
135660
135839
 
135661
135840
  // if (record === 'ENDMDL') {
@@ -136000,7 +136179,7 @@ class LoadCIF {
136000
136179
 
136001
136180
  // if(oriResidueNum !== prevOriResidueNum) {
136002
136181
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
136003
- let residue = me.utilsCls.residueName2Abbr(resn);
136182
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
136004
136183
 
136005
136184
  ic.residueId2Name[residueNum] = residue;
136006
136185
 
@@ -137299,6 +137478,16 @@ class ApplyCommand {
137299
137478
  ic.opts['unitcell'] = 'no';
137300
137479
  ic.drawCls.draw();
137301
137480
  }
137481
+ else if(command.indexOf('define unitcell') !== -1) {
137482
+ let itemArray = command.split(' | ');
137483
+ ic.cell = {};
137484
+ ic.cell.length_a = parseFloat(itemArray[1]);
137485
+ ic.cell.length_b = parseFloat(itemArray[2]);
137486
+ ic.cell.length_c = parseFloat(itemArray[3]);
137487
+ ic.cell.angle_alpha = parseFloat(itemArray[4]);
137488
+ ic.cell.angle_beta = parseFloat(itemArray[5]);
137489
+ ic.cell.angle_gamma = parseFloat(itemArray[6]);
137490
+ }
137302
137491
  else if(command == 'set fog on') {
137303
137492
  ic.opts['fog'] = 'yes';
137304
137493
  ic.fogCls.setFog(true);
@@ -137329,7 +137518,7 @@ class ApplyCommand {
137329
137518
  let pos = command.lastIndexOf(' ');
137330
137519
  let supercell = parseInt(command.substr(pos + 1));
137331
137520
 
137332
- await me.htmlCls.clickMenuCls.setSupercell(supercell);
137521
+ me.htmlCls.clickMenuCls.setSupercell(supercell);
137333
137522
  }
137334
137523
  else if(command == 'set chemicalbinding show') {
137335
137524
  ic.setOptionCls.setOption('chemicalbinding', 'show');
@@ -137764,7 +137953,8 @@ class ApplyCommand {
137764
137953
  else if(commandOri.indexOf('select interaction') == 0) {
137765
137954
  let idArray = commandOri.substr(commandOri.lastIndexOf(' ') + 1).split(',');
137766
137955
  if(idArray !== null) {
137767
- let mmdbid = idArray[0].split('_')[0];
137956
+ let itemArray = me.utilsCls.getIdArray(idArray[0]);
137957
+ let mmdbid = itemArray[0];
137768
137958
  if(!ic.b2DShown) ic.ParserUtilsCls.download2Ddgm(mmdbid.toUpperCase());
137769
137959
 
137770
137960
  ic.diagram2dCls.selectInteraction(idArray[0], idArray[1]);
@@ -139610,7 +139800,7 @@ class DefinedSets {
139610
139800
 
139611
139801
  }
139612
139802
 
139613
- selectCombinedSets(strSets, commandname) { let ic = this.icn3d; ic.icn3dui;
139803
+ selectCombinedSets(strSets, commandname) { let ic = this.icn3d, me = ic.icn3dui;
139614
139804
  let idArray = strSets.split(' ');
139615
139805
 
139616
139806
  let orArray = [], andArray = [], notArray = [];
@@ -139618,7 +139808,7 @@ class DefinedSets {
139618
139808
 
139619
139809
  for(let i = 0, il = idArray.length; i < il; ++i) {
139620
139810
  // replace 1CD8_A_1 with 1CD8_A1
139621
- let tmpArray = idArray[i].split('_');
139811
+ let tmpArray = me.utilsCls.getIdArray(idArray[i]);
139622
139812
  if(tmpArray.length == 3 && !isNaN(tmpArray[2])) {
139623
139813
  idArray[i] = tmpArray[0] + '_' + tmpArray[1] + tmpArray[2];
139624
139814
  }
@@ -140620,7 +140810,7 @@ class LoadScript {
140620
140810
 
140621
140811
  // load pdb, mmcif, mmdb, cid
140622
140812
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
140623
- if(id.length == 4) id = id.toUpperCase();
140813
+ if(id.length == 4 || id.indexOf('pdb_') == 0) id = id.toUpperCase();
140624
140814
 
140625
140815
  // skip loading the structure if
140626
140816
  // 1. PDB was in the iCn3D PNG Image file
@@ -140667,6 +140857,10 @@ class LoadScript {
140667
140857
  me.cfg.mmcifid = id;
140668
140858
  await ic.mmcifParserCls.downloadMmcif(id);
140669
140859
  }
140860
+ else if(command.indexOf('load cod') !== -1) {
140861
+ me.cfg.codid = id;
140862
+ await ic.mmcifParserCls.downloadCod(id);
140863
+ }
140670
140864
  else if(command.indexOf('load mmdb ') !== -1 || command.indexOf('load mmdb1 ') !== -1) {
140671
140865
  me.cfg.mmdbid = id;
140672
140866
  me.cfg.bu = 1;
@@ -141181,7 +141375,7 @@ class SelectByCommand {
141181
141375
 
141182
141376
  // convert 1TOP_A:20 to $1TOP.A:20
141183
141377
  if(commandArray[i].indexOf('_') !== -1) {
141184
- let itemArray = commandArray[i].split('_');
141378
+ let itemArray = me.utilsCls.getIdArray(commandArray[i]);
141185
141379
  if(itemArray.length ==2 ) {
141186
141380
  commandArray[i] = '$' + itemArray[0] + '.' + itemArray[1];
141187
141381
  }
@@ -142428,6 +142622,15 @@ class Resid2spec {
142428
142622
  return Object.keys(residueHash);
142429
142623
  }
142430
142624
 
142625
+ atoms2chains(atoms) {var ic = this.icn3d; ic.icn3dui;
142626
+ let chains = {};
142627
+ for(let i in atoms) {
142628
+ let atom = ic.atoms[i];
142629
+ chains[atom.structure + '_' + atom.chain] = 1;
142630
+ }
142631
+ return chains;
142632
+ }
142633
+
142431
142634
  atoms2structureArray(atoms) {var ic = this.icn3d; ic.icn3dui;
142432
142635
  let structures = {};
142433
142636
  for(let i in atoms) {
@@ -144062,24 +144265,6 @@ class Dssp {
144062
144265
  if(!me.bNode) console.log("domainid: " + domainid);
144063
144266
  }
144064
144267
 
144065
- // count the number of matched strands
144066
- // let strandHash = {};
144067
- // for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
144068
- // let seg = queryData[0].segs[j];
144069
- // let q_start = parseInt(seg.q_start)
144070
-
144071
- // let strand = this.getStrandFromRefnum(q_start);
144072
- // strandHash[strand] = 1;
144073
- // }
144074
-
144075
- // let tmAdjust = 0.1;
144076
-
144077
- // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
144078
- // if(!domainid2segs.hasOwnProperty(domainid) ||
144079
- // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
144080
- // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
144081
- // ) {
144082
-
144083
144268
  // use TM-score alone
144084
144269
  if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
144085
144270
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res + '_' + queryData[0].score2;
@@ -145411,7 +145596,7 @@ class Scap {
145411
145596
  let snpArray = snp.split(','); //stru_chain_resi_snp
145412
145597
  let atomHash = {}, snpResidArray = [], chainResi2pdb = {};
145413
145598
  for(let i = 0, il = snpArray.length; i < il; ++i) {
145414
- let idArray = snpArray[i].split('_'); //stru_chain_resi_snp
145599
+ let idArray = me.utilsCls.getIdArray(snpArray[i]); //stru_chain_resi_snp
145415
145600
 
145416
145601
  let resid = idArray[0] + '_' + idArray[1] + '_' + idArray[2];
145417
145602
  atomHash = me.hashUtilsCls.unionHash(atomHash, ic.residues[resid]);
@@ -148563,7 +148748,8 @@ class Diagram2d {
148563
148748
  if(refnumLabel) {
148564
148749
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
148565
148750
  if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
148566
- ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
148751
+ let idArray = me.utilsCls.getIdArray(resid);
148752
+ ic.refnum2resn[domainid][refnumStr] = resn + idArray[2];
148567
148753
  }
148568
148754
  }
148569
148755
 
@@ -150060,10 +150246,10 @@ class ResizeCanvas {
150060
150246
  //me.htmlCls.HEIGHT = $( window ).height();
150061
150247
  me.utilsCls.setViewerWidthHeight(ic.icn3dui);
150062
150248
 
150063
- let width = me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
150064
- let height = me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
150249
+ me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
150250
+ me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
150065
150251
 
150066
- if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
150252
+ //if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height, true, true);
150067
150253
  });
150068
150254
  }
150069
150255
  }
@@ -154813,8 +154999,8 @@ class iCn3D {
154813
154999
  }
154814
155000
  }
154815
155001
  //When users first load a structure, call this function to empty previous settings.
154816
- iCn3D.prototype.init = function (bKeepCmd) {
154817
- this.init_base();
155002
+ iCn3D.prototype.init = function (bClearCmd, bKeepConfig) {
155003
+ this.init_base(bClearCmd, bKeepConfig);
154818
155004
 
154819
155005
  this.molTitle = "";
154820
155006
 
@@ -154834,8 +155020,8 @@ iCn3D.prototype.init = function (bKeepCmd) {
154834
155020
  this.axes = [];
154835
155021
  };
154836
155022
 
154837
- iCn3D.prototype.init_base = function (bKeepCmd) {
154838
- this.resetConfig();
155023
+ iCn3D.prototype.init_base = function (bClearCmd, bKeepConfig) {
155024
+ if(!bKeepConfig) this.resetConfig();
154839
155025
 
154840
155026
  this.structures = {}; // structure name -> array of chains
154841
155027
  this.chains = {}; // structure_chain name -> atom hash
@@ -154929,7 +155115,7 @@ iCn3D.prototype.init_base = function (bKeepCmd) {
154929
155115
  this.transformCls.rotateCount = 0;
154930
155116
  this.transformCls.rotateCountMax = 20;
154931
155117
 
154932
- if(bKeepCmd) this.commands = [];
155118
+ if(bClearCmd) this.commands = [];
154933
155119
 
154934
155120
  this.axes = [];
154935
155121
 
@@ -155025,7 +155211,7 @@ class iCn3DUI {
155025
155211
  //even when multiple iCn3D viewers are shown together.
155026
155212
  this.pre = this.cfg.divid + "_";
155027
155213
 
155028
- this.REVISION = '3.54.3';
155214
+ this.REVISION = '3.54.4';
155029
155215
 
155030
155216
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
155031
155217
  this.bNode = (Object.keys(window).length < 3) ? true : false;
@@ -155121,9 +155307,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155121
155307
  resize: function( event, ui ) {
155122
155308
  me.htmlCls.WIDTH = ui.size.width; //$("#" + ic.pre + "canvas").width();
155123
155309
  me.htmlCls.HEIGHT = ui.size.height; //$("#" + ic.pre + "canvas").height();
155124
- if(ic !== undefined && !me.icn3d.bFullscreen) {
155125
- ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
155126
- }
155310
+ // if(ic !== undefined && !me.icn3d.bFullscreen) {
155311
+ // ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
155312
+ // }
155127
155313
  }
155128
155314
  });
155129
155315
 
@@ -155227,7 +155413,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155227
155413
  let domainidArray = me.cfg.matchedchains.split(',');
155228
155414
  let chainidArray = [];
155229
155415
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
155230
- let idArray = domainidArray[i].split('_');
155416
+ let idArray = me.utilsCls.getIdArray(domainidArray[i]);
155231
155417
  chainidArray.push(idArray[0] + '_' + idArray[1]);
155232
155418
  }
155233
155419
 
@@ -155270,14 +155456,14 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155270
155456
  await ic.pdbParserCls.downloadUrl(url, type, me.cfg.command);
155271
155457
  }
155272
155458
  else if(me.cfg.mmtfid !== undefined) {
155273
- 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
155459
+ // 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
155274
155460
  ic.inputid = me.cfg.mmtfid;
155275
155461
  ic.loadCmd = 'load mmtf ' + me.cfg.mmtfid;
155276
155462
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155277
155463
  await ic.bcifParserCls.downloadBcif(me.cfg.mmtfid);
155278
155464
  }
155279
155465
  else if(me.cfg.bcifid !== undefined) {
155280
- 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
155466
+ // 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
155281
155467
  ic.inputid = me.cfg.bcifid;
155282
155468
  ic.loadCmd = 'load bcif ' + me.cfg.bcifid;
155283
155469
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -155452,6 +155638,12 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155452
155638
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155453
155639
  await ic.mmcifParserCls.downloadMmcif(me.cfg.mmcifid);
155454
155640
  }
155641
+ else if(me.cfg.codid !== undefined) {
155642
+ ic.inputid = me.cfg.codid;
155643
+ ic.loadCmd = 'load cod ' + me.cfg.codid;
155644
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155645
+ await ic.mmcifParserCls.downloadCod(me.cfg.codid);
155646
+ }
155455
155647
  else if(me.cfg.align !== undefined) {
155456
155648
  // ic.bNCBI = true;
155457
155649
  if(me.cfg.align.indexOf('185055,') != -1) {
@@ -155612,6 +155804,8 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
155612
155804
 
155613
155805
  reject('error');
155614
155806
  }
155807
+
155808
+ me.icn3d.ParserUtilsCls.hideLoading();
155615
155809
  }
155616
155810
  else {
155617
155811
  me.icn3d.ParserUtilsCls.showLoading();
@@ -155764,18 +155958,6 @@ iCn3DUI.prototype.setDialogAjax = function() { let me = this;
155764
155958
  });
155765
155959
  };
155766
155960
 
155767
- /*
155768
- iCn3DUI.prototype.setIcn3dui = function(id) { let me = this;
155769
- let idArray = id.split('_'); // id: div0_reload_pdbfile
155770
- ic.pre = idArray[0] + "_";
155771
- if(window.icn3duiHash !== undefined && window.icn3duiHash.hasOwnProperty(idArray[0])) { // for multiple 3D display
155772
- me = window.icn3duiHash[idArray[0]];
155773
- }
155774
- return me;
155775
- };
155776
- */
155777
-
155778
-
155779
155961
  // required by npm
155780
155962
  class printMsg {
155781
155963
  constructor() {