icn3d 3.54.5 → 3.54.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/icn3d.js +598 -279
  2. package/icn3d.min.js +12 -6
  3. package/icn3d.module.js +598 -279
  4. package/package.json +1 -1
package/icn3d.js CHANGED
@@ -179,7 +179,8 @@ $NGL_shaderTextHash['SphereImpostor.frag'] = ["#define STANDARD",
179
179
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
180
180
  " #endif",
181
181
  " #ifdef FOG_EXP2",
182
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
182
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
183
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
183
184
  " #else",
184
185
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
185
186
  " #endif",
@@ -643,7 +644,8 @@ $NGL_shaderTextHash['CylinderImpostor.frag'] = ["#define STANDARD",
643
644
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
644
645
  " #endif",
645
646
  " #ifdef FOG_EXP2",
646
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
647
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
648
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
647
649
  " #else",
648
650
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
649
651
  " #endif",
@@ -2610,6 +2612,105 @@ var CIFTools;
2610
2612
  return out;
2611
2613
  };
2612
2614
  }
2615
+ /**
2616
+ * Options for filling the unit cell of a core CIF by lattice translation
2617
+ * (applied after the symmetry operators have generated the contents of one cell).
2618
+ * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2619
+ * wholeMolecules : keep every molecule / discrete chemical species intact. Atoms are grouped into
2620
+ * bonded fragments (covalent radii + bondTolerance, periodic), each fragment is
2621
+ * "unwrapped" so that it is contiguous (it may stick out of the unit cell), and the
2622
+ * fragment is placed in the cell that contains its centre. Fragments that are
2623
+ * infinite (chains, layers, frameworks, ionic lattices such as NaCl) cannot be made
2624
+ * whole and are handled as before (wrapped into the cell, see 'boundary'). default true
2625
+ * bondTolerance : extra distance (Angstrom) added to the sum of covalent radii when detecting bonds; default 0.4
2626
+ * boundary : for atoms that are NOT part of a whole molecule, also emit the periodic image of every
2627
+ * atom lying on a cell face/edge/corner (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl);
2628
+ * default true.
2629
+ * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, wholeMolecules: true};
2630
+ */
2631
+ Text.coreCifOptions = {
2632
+ nx: 1, ny: 1, nz: 1,
2633
+ wholeMolecules: true, // new; set false for the old wrapped behaviour
2634
+ bondTolerance: 0.4, // new; raise it if bonds are missed, lower it if unrelated atoms get joined, default 0.4
2635
+ boundary: true
2636
+ };
2637
+ // covalent radii (Angstrom, Cordero et al. 2008) used for bond detection
2638
+ var coreCovRadii = { H: 0.31, D: 0.31, He: 0.28, Li: 1.28, Be: 0.96, B: 0.84, C: 0.76, N: 0.71, O: 0.66, F: 0.57, Ne: 0.58,
2639
+ Na: 1.66, Mg: 1.41, Al: 1.21, Si: 1.11, P: 1.07, S: 1.05, Cl: 1.02, Ar: 1.06, K: 2.03, Ca: 1.76, Sc: 1.70, Ti: 1.60, V: 1.53,
2640
+ Cr: 1.39, Mn: 1.39, Fe: 1.32, Co: 1.26, Ni: 1.24, Cu: 1.32, Zn: 1.22, Ga: 1.22, Ge: 1.20, As: 1.19, Se: 1.20, Br: 1.20, Kr: 1.16,
2641
+ Rb: 2.20, Sr: 1.95, Y: 1.90, Zr: 1.75, Nb: 1.64, Mo: 1.54, Tc: 1.47, Ru: 1.46, Rh: 1.42, Pd: 1.39, Ag: 1.45, Cd: 1.44, In: 1.42,
2642
+ Sn: 1.39, Sb: 1.39, Te: 1.38, I: 1.39, Xe: 1.40, Cs: 2.44, Ba: 2.15, La: 2.07, Ce: 2.04, Pr: 2.03, Nd: 2.01, Sm: 1.98, Eu: 1.98,
2643
+ Gd: 1.96, Tb: 1.94, Dy: 1.92, Ho: 1.92, Er: 1.89, Tm: 1.90, Yb: 1.87, Lu: 1.87, Hf: 1.75, Ta: 1.70, W: 1.62, Re: 1.51, Os: 1.44,
2644
+ Ir: 1.41, Pt: 1.36, Au: 1.36, Hg: 1.32, Tl: 1.45, Pb: 1.46, Bi: 1.48 };
2645
+ // g: fractional coordinates wrapped into [0,1). Returns all translated copies of g.
2646
+ function coreLatticeImages(g, nx, ny, nz, bBoundary) {
2647
+ var eps = 1e-3, n = [nx, ny, nz], ranges = [], out = [], k, i, r, x, y, z;
2648
+ for (k = 0; k < 3; k++) {
2649
+ r = [];
2650
+ for (i = 0; i < n[k]; i++) r.push(g[k] + i);
2651
+ if (bBoundary && Math.abs(g[k]) < eps) r.push(g[k] + n[k]); // atom on the 0-face also sits on the far face
2652
+ ranges.push(r);
2653
+ }
2654
+ for (x = 0; x < ranges[0].length; x++)
2655
+ for (y = 0; y < ranges[1].length; y++)
2656
+ for (z = 0; z < ranges[2].length; z++)
2657
+ out.push([ranges[0][x], ranges[1][y], ranges[2][z]]);
2658
+ return out;
2659
+ }
2660
+ /**
2661
+ * Group atoms (fractional coordinates wrapped into the cell) into bonded fragments, taking periodic
2662
+ * images into account. Every atom of a fragment gets an integer lattice translation T so that
2663
+ * (g + T) forms a contiguous molecule. A fragment that reaches its own periodic image
2664
+ * (chain / layer / framework) is flagged as infinite.
2665
+ * atoms : [{el, g:[fx,fy,fz]}] toCart : fractional -> Cartesian (linear part only)
2666
+ * h : interplanar spacings of the cell along a, b, c tol : bond tolerance (Angstrom)
2667
+ */
2668
+ function coreFindMolecules(atoms, toCart, h, tol) {
2669
+ var N = atoms.length, nb = [], rad = [], i, j, k, e, m, q;
2670
+ for (i = 0; i < N; i++) { nb.push([]); rad.push(coreCovRadii[atoms[i].el] || 1.5); }
2671
+ for (i = 0; i < N; i++) {
2672
+ for (j = i; j < N; j++) {
2673
+ var d = [atoms[j].g[0] - atoms[i].g[0], atoms[j].g[1] - atoms[i].g[1], atoms[j].g[2] - atoms[i].g[2]];
2674
+ var rc = rad[i] + rad[j] + tol, cand = [[], [], []], dt, t;
2675
+ for (k = 0; k < 3; k++) {
2676
+ var base = -Math.round(d[k]);
2677
+ for (dt = -1; dt <= 1; dt++) {
2678
+ t = base + dt;
2679
+ if (Math.abs(d[k] + t) * h[k] <= rc) cand[k].push(t);
2680
+ }
2681
+ }
2682
+ for (var a = 0; a < cand[0].length; a++) for (var b = 0; b < cand[1].length; b++) for (var c = 0; c < cand[2].length; c++) {
2683
+ var tv = [cand[0][a], cand[1][b], cand[2][c]];
2684
+ if (i === j) { // bond to own image: record each translation pair only once
2685
+ if (tv[0] === 0 && tv[1] === 0 && tv[2] === 0) continue;
2686
+ if (tv[0] < 0 || (tv[0] === 0 && (tv[1] < 0 || (tv[1] === 0 && tv[2] < 0)))) continue;
2687
+ }
2688
+ var cc = toCart([d[0] + tv[0], d[1] + tv[1], d[2] + tv[2]]);
2689
+ var d2 = cc[0] * cc[0] + cc[1] * cc[1] + cc[2] * cc[2];
2690
+ if (d2 < rc * rc && d2 > 0.25) { // > 0.5 A: closer atoms are disorder alternatives, not bonds
2691
+ nb[i].push({ j: j, t: tv });
2692
+ nb[j].push({ j: i, t: [-tv[0], -tv[1], -tv[2]] });
2693
+ }
2694
+ }
2695
+ }
2696
+ }
2697
+ var T = new Array(N), comps = [], s, queue, members, infinite, cur, tj, o;
2698
+ for (s = 0; s < N; s++) {
2699
+ if (T[s]) continue;
2700
+ T[s] = [0, 0, 0]; queue = [s]; members = [s]; infinite = false;
2701
+ for (q = 0; q < queue.length; q++) {
2702
+ cur = queue[q];
2703
+ for (e = 0; e < nb[cur].length; e++) {
2704
+ o = nb[cur][e];
2705
+ tj = [T[cur][0] + o.t[0], T[cur][1] + o.t[1], T[cur][2] + o.t[2]];
2706
+ if (!T[o.j]) { T[o.j] = tj; queue.push(o.j); members.push(o.j); }
2707
+ else if (T[o.j][0] !== tj[0] || T[o.j][1] !== tj[1] || T[o.j][2] !== tj[2]) infinite = true;
2708
+ }
2709
+ }
2710
+ comps.push({ members: members, infinite: infinite });
2711
+ }
2712
+ return { T: T, comps: comps };
2713
+ }
2613
2714
  function convertCoreCif(data) {
2614
2715
  var tk = coreTokens(data), i = 0, n = tk.length, single = {}, loops = [], name = 'data_core', t, cols, rows, cur;
2615
2716
  function isTag(x) { return x && !x.t && x.v.charAt(0) === '_'; }
@@ -2663,7 +2764,21 @@ var CIFTools;
2663
2764
  '_atom_site.label_comp_id', '_atom_site.label_asym_id', '_atom_site.label_entity_id', '_atom_site.label_seq_id',
2664
2765
  '_atom_site.Cartn_x', '_atom_site.Cartn_y', '_atom_site.Cartn_z', '_atom_site.occupancy', '_atom_site.B_iso_or_equiv',
2665
2766
  '_atom_site.auth_seq_id', '_atom_site.auth_asym_id', '_atom_site.pdbx_PDB_model_num');
2666
- var serial = 0, seen = [], r, s, f, g, k, dup, j, sym, el, lab, cart;
2767
+ var serial = 0, r, s, f, g, k, dup, j, sym, el, lab, cart;
2768
+ var o = Text.coreCifOptions || {}, images, im;
2769
+ var opt = {
2770
+ nx: Math.max(1, parseInt(o.nx) || 1), ny: Math.max(1, parseInt(o.ny) || 1), nz: Math.max(1, parseInt(o.nz) || 1),
2771
+ boundary: (o.boundary === undefined) ? true : !!o.boundary,
2772
+ wholeMolecules: (o.wholeMolecules === undefined) ? true : !!o.wholeMolecules,
2773
+ bondTolerance: (o.bondTolerance === undefined || isNaN(parseFloat(o.bondTolerance))) ? 0.4 : parseFloat(o.bondTolerance)
2774
+ };
2775
+ function emit(at, frac) {
2776
+ var cart = toCart(frac);
2777
+ out.push(['HETATM', ++serial, at.el, at.lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2778
+ at.occ, '0.00', 1, 'A', 1].join(' '));
2779
+ }
2780
+ // 1) all symmetry-generated atoms of one cell, wrapped into [0,1)
2781
+ var list = [];
2667
2782
  for (r = 0; r < atoms.rows.length; r++) {
2668
2783
  var row = atoms.rows[r];
2669
2784
  if (get(row, '_atom_site_calc_flag') === 'dum') continue; // dummy atoms
@@ -2672,6 +2787,7 @@ var CIFTools;
2672
2787
  sym = get(row, '_atom_site_type_symbol'); if (sym === '?') sym = lab;
2673
2788
  el = (sym.match(/^[A-Za-z]{1,2}/) || ['X'])[0];
2674
2789
  el = el.charAt(0).toUpperCase() + el.substr(1).toLowerCase();
2790
+ var occ = coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy'));
2675
2791
  var mySeen = [];
2676
2792
  for (s = 0; s < symops.length; s++) {
2677
2793
  g = symops[s](f).map(function (v) { return v - Math.floor(v + 1e-6); });
@@ -2681,9 +2797,49 @@ var CIFTools;
2681
2797
  }
2682
2798
  if (dup) continue;
2683
2799
  mySeen.push(g);
2684
- cart = toCart(g);
2685
- out.push(['HETATM', ++serial, el, lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2686
- coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy')), '0.00', 1, 'A', 1].join(' '));
2800
+ list.push({ el: el, lab: lab, occ: occ, g: g });
2801
+ }
2802
+ }
2803
+ // 2) emit them, either as whole molecules or simply wrapped into the cell
2804
+ var mol = null;
2805
+ if (opt.wholeMolecules && list.length) {
2806
+ var Vc = a * b * cc * vol, sinal = Math.sqrt(1 - cosa * cosa), sinbe = Math.sqrt(1 - cosb * cosb);
2807
+ var hh = [Vc / (b * cc * sinal), Vc / (a * cc * sinbe), Vc / (a * b * sing)];
2808
+ if (isFinite(hh[0] + hh[1] + hh[2]) && hh[0] > 0 && hh[1] > 0 && hh[2] > 0) mol = coreFindMolecules(list, toCart, hh, opt.bondTolerance);
2809
+ }
2810
+ var ci, m, at, ix, iy, iz, mean, shift;
2811
+ if (mol) {
2812
+ for (ci = 0; ci < mol.comps.length; ci++) {
2813
+ var comp = mol.comps[ci];
2814
+ if (comp.infinite) { // cannot be made whole: wrap into the cell as before
2815
+ for (m = 0; m < comp.members.length; m++) {
2816
+ at = list[comp.members[m]];
2817
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2818
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2819
+ }
2820
+ continue;
2821
+ }
2822
+ // contiguous molecule: place it in the cell that holds its centre, keep all atoms together
2823
+ mean = [0, 0, 0];
2824
+ for (m = 0; m < comp.members.length; m++) {
2825
+ at = list[comp.members[m]];
2826
+ for (k = 0; k < 3; k++) mean[k] += (at.g[k] + mol.T[comp.members[m]][k]) / comp.members.length;
2827
+ }
2828
+ shift = [-Math.floor(mean[0] + 1e-6), -Math.floor(mean[1] + 1e-6), -Math.floor(mean[2] + 1e-6)];
2829
+ for (ix = 0; ix < opt.nx; ix++) for (iy = 0; iy < opt.ny; iy++) for (iz = 0; iz < opt.nz; iz++) {
2830
+ for (m = 0; m < comp.members.length; m++) {
2831
+ at = list[comp.members[m]];
2832
+ var tt = mol.T[comp.members[m]];
2833
+ emit(at, [at.g[0] + tt[0] + shift[0] + ix, at.g[1] + tt[1] + shift[1] + iy, at.g[2] + tt[2] + shift[2] + iz]);
2834
+ }
2835
+ }
2836
+ }
2837
+ }
2838
+ else {
2839
+ for (m = 0; m < list.length; m++) {
2840
+ at = list[m];
2841
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2842
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2687
2843
  }
2688
2844
  }
2689
2845
  out.push('#');
@@ -2984,7 +3140,7 @@ var CIFTools;
2984
3140
  // This approach to binary parsing wastes a bit of memory to trade for speed compared to:
2985
3141
  //
2986
3142
  // let value = buffer.subarray(offset, offset + length); //new Uint8Array(buffer.buffer, offset, length);
2987
- //
3143
+ //
2988
3144
  // It turns out that using the view created by subarray probably uses DataView
2989
3145
  // in the background, which causes the element access to be several times slower
2990
3146
  // than creating the new byte array.
@@ -4308,7 +4464,7 @@ var CIFTools;
4308
4464
  if (index === void 0) {
4309
4465
  // increment the length
4310
4466
  accLength += s.length;
4311
- // store the string and index
4467
+ // store the string and index
4312
4468
  index = strings.length;
4313
4469
  strings[index] = s;
4314
4470
  map[s] = index;
@@ -55369,7 +55525,7 @@ class UtilsCls {
55369
55525
  }
55370
55526
 
55371
55527
  //Convert a three-letter residue name to a one-letter residue abbreviation, e.g., 'LYS' to 'K', or ' A' to 'A' for nucleotides.
55372
- residueName2Abbr(residueName) { this.icn3dui;
55528
+ residueName2Abbr(residueName, bOneLetter) { this.icn3dui;
55373
55529
  let pos = residueName.indexOf(' ');
55374
55530
  if(pos > 0) {
55375
55531
  residueName = residueName.substr(0, pos);
@@ -55464,7 +55620,12 @@ class UtilsCls {
55464
55620
  return 'O';
55465
55621
 
55466
55622
  default:
55467
- return residueName.trim();
55623
+ if(bOneLetter) {
55624
+ return 'X';
55625
+ }
55626
+ else {
55627
+ return residueName.trim();
55628
+ }
55468
55629
  }
55469
55630
  }
55470
55631
 
@@ -55540,15 +55701,20 @@ class UtilsCls {
55540
55701
  }
55541
55702
 
55542
55703
  getIdArray(resid) { this.icn3dui;
55543
- //var idArray = resid.split('_');
55544
55704
  let idArray = [];
55545
55705
 
55546
55706
  if(resid) {
55547
- let pos1 = resid.indexOf('_');
55548
- let pos2 = resid.lastIndexOf('_');
55549
- idArray.push(resid.substr(0, pos1));
55550
- idArray.push(resid.substr(pos1 + 1, pos2 - pos1 - 1));
55551
- idArray.push(resid.substr(pos2 + 1));
55707
+ let itemArray = resid.split('_');
55708
+
55709
+ if(resid.indexOf('pdb_') == 0 ) { // e.g., pdb_00001GPK_A_15
55710
+ idArray.push(itemArray[0] + '_' + itemArray[1]);
55711
+ for(let i = 2, il = itemArray.length; i < il; ++i) {
55712
+ idArray.push(itemArray[i]);
55713
+ }
55714
+ }
55715
+ else {
55716
+ idArray = itemArray;
55717
+ }
55552
55718
  }
55553
55719
 
55554
55720
  return idArray;
@@ -55559,12 +55725,12 @@ class UtilsCls {
55559
55725
  let bArray = b.split(',');
55560
55726
  let aIdArray, bIdArray;
55561
55727
  if(type == 'save1') {
55562
- aIdArray = me.utilsCls.getIdArray(aArray[0]); //aArray[0].split('_');
55563
- bIdArray = me.utilsCls.getIdArray(bArray[0]); //bArray[0].split('_');
55728
+ aIdArray = me.utilsCls.getIdArray(aArray[0]);
55729
+ bIdArray = me.utilsCls.getIdArray(bArray[0]);
55564
55730
  }
55565
55731
  else if(type == 'save2') {
55566
- aIdArray = me.utilsCls.getIdArray(aArray[1]); //aArray[1].split('_');
55567
- bIdArray = me.utilsCls.getIdArray(bArray[1]); //bArray[1].split('_');
55732
+ aIdArray = me.utilsCls.getIdArray(aArray[1]);
55733
+ bIdArray = me.utilsCls.getIdArray(bArray[1]);
55568
55734
  }
55569
55735
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
55570
55736
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
@@ -55874,6 +56040,29 @@ class ParasCls {
55874
56040
  CM: 1.69
55875
56041
  };
55876
56042
 
56043
+ this.ionRadii = { // https://en.wikipedia.org/wiki/Ionic_radius
56044
+ H: 1.40, HE: 0.28, LI: 0.76, BE: 0.45, B: 0.27,
56045
+ C: 0.16, N: 1.46, O: 1.40, F: 1.33, NE: 0.58,
56046
+ NA: 1.02, MG: 0.72, AL: 0.54, SI: 0.40, P: 0.38,
56047
+ S: 1.84, CL: 1.81, AR: 1.06, K: 1.38, CA: 1.00,
56048
+ SC: 0.75, TI: 0.86, V: 0.79, CR: 0.73, MN: 0.67,
56049
+ FE: 0.55, CO: 0.65, NI: 0.69, CU: 0.73, ZN: 0.74,
56050
+ GA: 0.62, GE: 0.73, AS: 0.58, SE: 1.98, BR: 1.96,
56051
+ KR: 1.16, RB: 1.52, SR: 1.18, Y: 0.90, ZR: 0.72,
56052
+ NB: 0.72, MO: 0.69, TC: 0.65, RU: 0.68, RH: 0.67,
56053
+ PD: 0.86, AG: 1.15, CD: 0.95, IN: 0.80, SN: 1.02,
56054
+ SB: 0.76, TE: 0.97, I: 2.20, XE: 0.48, CS: 1.67,
56055
+ BA: 1.35, LA: 1.03, CE: 1.01, PR: 0.99, ND: 1.29,
56056
+ PM: 0.97, SM: 1.22, EU: 1.17, GD: 0.94, TB: 0.92,
56057
+ DY: 1.07, HO: 0.90, ER: 0.89, TM: 1.03, YB: 1.02,
56058
+ LU: 0.86, HF: 0.71, TA: 0.72, W: 0.66, RE: 0.63,
56059
+ OS: 0.63, IR: 0.68, PT: 0.80, AU: 1.37, HG: 1.19,
56060
+ TL: 1.50, PB: 1.19, BI: 1.03, PO: 0.94, AT: 0.62,
56061
+ RN: 1.50, FR: 1.80, RA: 1.48, AC: 1.07, TH: 0.94,
56062
+ PA: 1.04, U: 1.03, NP: 1.10, PU: 1.00, AM: 1.26,
56063
+ CM: 0.97
56064
+ };
56065
+
55877
56066
  /*
55878
56067
  this.surfaces = {
55879
56068
  1: undefined,
@@ -57456,6 +57645,9 @@ class ClickMenu {
57456
57645
  me.myEventCls.onIds("#" + me.pre + "mn1_mmcifid", "click", function(e) { me.icn3d; //e.preventDefault();
57457
57646
  me.htmlCls.dialogCls.openDlg('dl_mmcifid', 'Please input mmCIF ID');
57458
57647
  });
57648
+ me.myEventCls.onIds("#" + me.pre + "mn1_codid", "click", function(e) { me.icn3d; //e.preventDefault();
57649
+ me.htmlCls.dialogCls.openDlg('dl_codid', 'Please input COD ID');
57650
+ });
57459
57651
 
57460
57652
  me.myEventCls.onIds("#" + me.pre + "mn1_mmdbid", "click", function(e) { me.icn3d; //e.preventDefault();
57461
57653
  me.htmlCls.dialogCls.openDlg('dl_mmdbid', 'Please input MMDB or PDB ID');
@@ -57995,7 +58187,7 @@ class ClickMenu {
57995
58187
  thisClass.setLogCmd("link to compounds with structure similar to CID " + ic.inputid + ": " + url, false);
57996
58188
  }
57997
58189
  else {
57998
- let idArray = ic.inputid.split('_');
58190
+ let idArray = me.utilsCls.getIdArray(ic.inputid);
57999
58191
 
58000
58192
  if(idArray.length === 1) {
58001
58193
  url = me.htmlCls.baseUrl + "vastplus/vastplus.cgi?uid=" + ic.inputid;
@@ -59057,6 +59249,16 @@ class ClickMenu {
59057
59249
 
59058
59250
  }
59059
59251
 
59252
+ setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
59253
+ if(ic.cifData) {
59254
+ ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
59255
+
59256
+ ic.setStyleCls.setAtomStyleByOptions(ic.opts);
59257
+ ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
59258
+ ic.drawCls.draw();
59259
+ }
59260
+ }
59261
+
59060
59262
  clickMenu6() { let me = this.icn3dui, ic = me.icn3d;
59061
59263
  if(me.bNode) return;
59062
59264
 
@@ -59074,6 +59276,23 @@ class ClickMenu {
59074
59276
  ic.drawCls.draw();
59075
59277
  });
59076
59278
 
59279
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", function(e) { me.icn3d; //e.preventDefault();
59280
+ thisClass.setSupercell(0);
59281
+ thisClass.setLogCmd('set supercell 0', true);
59282
+ });
59283
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", function(e) { me.icn3d; //e.preventDefault();
59284
+ thisClass.setSupercell(1);
59285
+ thisClass.setLogCmd('set supercell 1', true);
59286
+ });
59287
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", function(e) { me.icn3d; //e.preventDefault();
59288
+ thisClass.setSupercell(2);
59289
+ thisClass.setLogCmd('set supercell 2', true);
59290
+ });
59291
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", function(e) { me.icn3d; //e.preventDefault();
59292
+ thisClass.setSupercell(3);
59293
+ thisClass.setLogCmd('set supercell 3', true);
59294
+ });
59295
+
59077
59296
  me.myEventCls.onIds("#" + me.pre + "mn6_igrefYes", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
59078
59297
  ic.bRunRefnumAgain = true;
59079
59298
 
@@ -60428,6 +60647,7 @@ class SetMenu {
60428
60647
  html += this.getLink('mn1_opmid', 'OPM PDB ID ' + me.htmlCls.wifiStr, undefined, 2);
60429
60648
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
60430
60649
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
60650
+ // html += this.getLink('mn1_codid', 'COD ID ' + me.htmlCls.wifiStr, 1, 2);
60431
60651
 
60432
60652
  html += this.getLink('mn1_cid', 'PubChem CID/Name/InChI ' + me.htmlCls.wifiStr, 1, 2);
60433
60653
  html += this.getLink('mn1_smiles', 'Chemical SMILES ', undefined, 2);
@@ -61668,13 +61888,20 @@ class SetMenu {
61668
61888
 
61669
61889
  html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
61670
61890
 
61671
- let bOnePdb = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
61891
+ let bInputid = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
61672
61892
 
61673
- if(bOnePdb) {
61893
+ //if(bInputid) {
61674
61894
  html += this.getMenuText('assemblyWrapper', 'Assembly', undefined, 1, 1);
61675
61895
  html += "<ul>";
61676
61896
 
61677
- if(!me.cfg.bu) {
61897
+ if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined) { // e.g., cif file input
61898
+ html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Biological Assembly', undefined, 1, 2);
61899
+ html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', undefined, 1, 2);
61900
+ html += this.getRadio('mn6_assembly', 'mn6_assembly1', '1 x 1 x 1', true, 1, 2);
61901
+ html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, undefined, 2);
61902
+ html += this.getRadio('mn6_assembly', 'mn6_assembly3', '3 x 3 x 3', undefined, 1, 2);
61903
+ }
61904
+ else if(!me.cfg.bu) {
61678
61905
  html += this.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly', undefined, 1, 2);
61679
61906
  html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', true, 1, 2);
61680
61907
  }
@@ -61685,12 +61912,12 @@ class SetMenu {
61685
61912
 
61686
61913
  html += "</ul>";
61687
61914
  html += "</li>";
61688
- }
61915
+ //}
61689
61916
 
61690
61917
  html += this.getMenuText('mn6_symmetrywrap', 'Symmetry', undefined, undefined, 1);
61691
61918
 
61692
61919
  html += "<ul>";
61693
- if(bOnePdb) html += this.getLink('mn6_symmetry', 'from PDB(precalculated) ' + me.htmlCls.wifiStr, undefined, 2);
61920
+ if(bInputid) html += this.getLink('mn6_symmetry', 'from PDB(precalculated) ' + me.htmlCls.wifiStr, undefined, 2);
61694
61921
 
61695
61922
  html += this.getLink('mn6_symd', 'from SymD(Dynamic) ' + me.htmlCls.wifiStr, undefined, 2);
61696
61923
  html += this.getLink('mn6_clear_sym', 'Clear SymD Symmetry', undefined, 2);
@@ -62927,6 +63154,12 @@ class SetDialog {
62927
63154
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
62928
63155
  html += "</div>";
62929
63156
 
63157
+ html += me.htmlCls.divStr + "dl_codid' class='" + dialogClass + "'>";
63158
+ html += this.addNotebookTitle('dl_codid', 'Please input a COD ID');
63159
+ html += "COD ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "codid' value='1000041' size=8> ";
63160
+ html += me.htmlCls.buttonStr + "reload_cod'>Load</button>";
63161
+ html += "</div>";
63162
+
62930
63163
  html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
62931
63164
  html += this.addNotebookTitle('dl_mmdbid', 'Please input an MMDB ID');
62932
63165
  html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
@@ -64423,7 +64656,7 @@ class Events {
64423
64656
  }
64424
64657
  }
64425
64658
 
64426
- async readFile(bAppend, files, index, dataStrAll, bmmCIF, bPng) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
64659
+ async readFile(bAppend, files, index, dataStrAll, bmmCIF, bPng, fileType) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
64427
64660
  let file = files[index];
64428
64661
  let commandName = (bAppend) ? 'append': 'load';
64429
64662
  commandName += (bmmCIF) ? ' mmcif file ' : (bPng) ? ' png file ' : ' pdb file ';
@@ -64473,7 +64706,7 @@ class Events {
64473
64706
  ic.dAtoms = {};
64474
64707
  }
64475
64708
  if(bmmCIF) {
64476
- await ic.mmcifParserCls.loadMultipleMmcifData(dataStrAll, undefined, bAppend);
64709
+ await ic.mmcifParserCls.loadMultipleMmcifData(dataStrAll, undefined, bAppend, fileType);
64477
64710
  }
64478
64711
  else {
64479
64712
  await ic.pdbParserCls.loadPdbData(dataStrAll, undefined, undefined, bAppend);
@@ -64499,7 +64732,12 @@ class Events {
64499
64732
  };
64500
64733
 
64501
64734
  if (typeof file === "object") {
64502
- reader.readAsText(file);
64735
+ if(bmmCIF && fileType == 'bcif') {
64736
+ reader.readAsArrayBuffer(file);
64737
+ }
64738
+ else {
64739
+ reader.readAsText(file);
64740
+ }
64503
64741
  }
64504
64742
  }
64505
64743
 
@@ -64584,7 +64822,7 @@ class Events {
64584
64822
  let idArray = ids.split(',');
64585
64823
 
64586
64824
  if(!bAppend) {
64587
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64825
+ if(idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64588
64826
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64589
64827
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64590
64828
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -64596,8 +64834,8 @@ class Events {
64596
64834
  }
64597
64835
  }
64598
64836
  else {
64599
- // single MMDB ID could show memebranes
64600
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
64837
+ // single MMDB ID could show membranes
64838
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
64601
64839
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
64602
64840
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
64603
64841
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65085,7 +65323,7 @@ class Events {
65085
65323
  if(!me.cfg.notebook) dialog.dialog( "close" );
65086
65324
  thisClass.setLogCmd("load mmtf " + $("#" + me.pre + "mmtfid").val(), false);
65087
65325
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65088
- window.open(hostUrl + '?mmtfid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65326
+ window.open(hostUrl + '?bcifid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65089
65327
  }
65090
65328
  });
65091
65329
 
@@ -65429,7 +65667,7 @@ class Events {
65429
65667
  await ic.scapCls.retrieveScap(snp, bInteraction);
65430
65668
  thisClass.setLogCmd('scap interaction ' + snp, true);
65431
65669
 
65432
- let idArray = snp.split('_'); //stru_chain_resi_snp
65670
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
65433
65671
  let select = '.' + idArray[1] + ':' + idArray[2];
65434
65672
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
65435
65673
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -65468,7 +65706,6 @@ class Events {
65468
65706
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65469
65707
  window.open(hostUrl + '?mmcifid=' + $("#" + me.pre + "mmcifid").val(), urlTarget);
65470
65708
  });
65471
-
65472
65709
  me.myEventCls.onIds("#" + me.pre + "mmcifid", "keyup", function(e) { let ic = me.icn3d;
65473
65710
  if (e.keyCode === 13) {
65474
65711
  e.preventDefault();
@@ -65479,6 +65716,23 @@ class Events {
65479
65716
  }
65480
65717
  });
65481
65718
 
65719
+ me.myEventCls.onIds("#" + me.pre + "reload_cod", "click", function(e) { let ic = me.icn3d;
65720
+ e.preventDefault();
65721
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65722
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65723
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65724
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65725
+ });
65726
+ me.myEventCls.onIds("#" + me.pre + "codid", "keyup", function(e) { let ic = me.icn3d;
65727
+ if (e.keyCode === 13) {
65728
+ e.preventDefault();
65729
+ if(!me.cfg.notebook) dialog.dialog( "close" );
65730
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
65731
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65732
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
65733
+ }
65734
+ });
65735
+
65482
65736
 
65483
65737
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { let ic = me.icn3d;
65484
65738
  e.preventDefault();
@@ -68034,8 +68288,8 @@ class Events {
68034
68288
  let fileName = file.name;
68035
68289
 
68036
68290
  let fileType = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase();
68037
- if(fileType == 'pdb' || fileType == 'mmcif' || fileType == 'png') {
68038
- await me.htmlCls.eventsCls.readFile(true, files, i, '', (fileType == 'mmcif'), (fileType == 'png'));
68291
+ if(fileType == 'pdb' || fileType == 'mmcif' || fileType == 'cif' || fileType == 'bcif' || fileType == 'png') {
68292
+ await me.htmlCls.eventsCls.readFile(true, files, i, '', (fileType == 'mmcif' || fileType == 'cif' || fileType == 'bcif'), (fileType == 'png'), fileType);
68039
68293
  }
68040
68294
  else if(fileType == 'bcf') {
68041
68295
  await thisClass.openBcf(file);
@@ -68064,7 +68318,7 @@ class Events {
68064
68318
  await ic.scapCls.retrieveScap(snp, bInteraction);
68065
68319
  thisClass.setLogCmd('scap interaction ' + snp, true);
68066
68320
 
68067
- let idArray = snp.split('_'); //stru_chain_resi_snp
68321
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
68068
68322
  let select = '.' + idArray[1] + ':' + idArray[2];
68069
68323
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
68070
68324
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -78088,6 +78342,43 @@ class Camera {
78088
78342
  // }
78089
78343
  }
78090
78344
 
78345
+ // Keep the slab plane at the same position relative to the molecule when zooming.
78346
+ // In perspective mode zooming moves the camera along the view direction, so the near plane
78347
+ // (distance from the camera) has to move with it. In orthographic mode zooming only changes
78348
+ // the frustum size and the camera does not move, so the slab plane already stays fixed.
78349
+ updateSlabByZoom() { let ic = this.icn3d, me = ic.icn3dui;
78350
+ if(ic.opts['slab'] !== 'yes' || me.bNode) return;
78351
+ if(ic.opts.camera.toLowerCase() !== 'perspective') return;
78352
+
78353
+ let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
78354
+ if(bInstance) return; // near plane is fixed at 0.1 for instancing
78355
+
78356
+ let cam = (ic.bControlGl) ? window.cam : ic.cam;
78357
+ let controls = (ic.bControlGl) ? window.controls : ic.controls;
78358
+
78359
+ // at zoom = 1 the slab plane is ic.maxD * camMaxDFactor from the camera, i.e. the plane through
78360
+ // the center (or 10 angstroms in front of it when fog is on to keep some surrounding residues)
78361
+ let offset = (ic.camMaxDFactorFog !== undefined) ? 10 : 0;
78362
+
78363
+ // current distance from the camera to the center of rotation, which changes with zooming
78364
+ let dist = cam.position.distanceTo(controls.target);
78365
+
78366
+ // keep the plane at the same position relative to the molecule
78367
+ let nearClip = Math.max(0.1, dist - offset);
78368
+
78369
+ if(Math.abs(cam.near - nearClip) > 1e-6) {
78370
+ cam.near = nearClip;
78371
+ cam.updateProjectionMatrix();
78372
+ if(ic.cam && ic.cam !== cam) {
78373
+ ic.cam.near = nearClip;
78374
+ ic.cam.updateProjectionMatrix();
78375
+ }
78376
+ }
78377
+
78378
+ // the impostor shaders (spheres, cylinders) clip with the nearClip uniform
78379
+ if(ic.uniforms && ic.uniforms.nearClip) ic.uniforms.nearClip.value = nearClip;
78380
+ }
78381
+
78091
78382
  setSlab() { let ic = this.icn3d, me = ic.icn3dui;
78092
78383
  if(ic.bControlGl && !me.bNode) {
78093
78384
  let maxD = ic.maxD;
@@ -78203,7 +78494,8 @@ class Fog {
78203
78494
  else {
78204
78495
  // adjust
78205
78496
  let zoomFactor = (ic._zoomFactor > 1) ? ic._zoomFactor * 1.0 : ic._zoomFactor;
78206
- ic.scene.fog = new Fog$1(background, 2.5 * ic.maxD * zoomFactor, 4 * ic.maxD * zoomFactor);
78497
+ let fogStrength = 2; // 1 = current, >1 = stronger
78498
+ ic.scene.fog = new Fog$1(background, (3 - 0.5 / fogStrength) * ic.maxD * zoomFactor, (3 + 1.0 / fogStrength) * ic.maxD * zoomFactor);
78207
78499
  ic.bSetFog = true;
78208
78500
  ic.camMaxDFactorFog = 3;
78209
78501
  }
@@ -80428,6 +80720,8 @@ class Tube {
80428
80720
 
80429
80721
  let prevAxis1 = new Vector3$1(), prevAxis2;
80430
80722
  for (let i = 0, lim = pnts.length; i < lim; ++i) {
80723
+ if(!pnts[i]) continue;
80724
+
80431
80725
  let r, idx = (i - 1) * axisDivInv;
80432
80726
 
80433
80727
  if (i === 0) {
@@ -80460,7 +80754,7 @@ class Tube {
80460
80754
  }
80461
80755
 
80462
80756
  let delta, axis1, axis2;
80463
- if (i < lim - 1) {
80757
+ if (i < lim - 1 && pnts[i + 1]) {
80464
80758
  delta = pnts[i].clone().sub(pnts[i + 1]);
80465
80759
  axis1 = new Vector3$1(0, -delta.z, delta.y).normalize().multiplyScalar(r);
80466
80760
  axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
@@ -84446,7 +84740,6 @@ class Surface {
84446
84740
  let chainStr = (Object.keys(chainHash).length > 1) ? '<th>Chain</th>' : '';
84447
84741
  html += '<tr>' + structureStr + chainStr + '<th>Residue</th><th>Number</th><th>SASA (&#8491;<sup>2</sup>)</th><th>Percent Out</th><th>In/Out</th></tr>';
84448
84742
  for(let resid in ic.resid2area) {
84449
- //var idArray = resid.split('_');
84450
84743
  let pos = resid.lastIndexOf('_');
84451
84744
  let resn = resid.substr(pos + 1);
84452
84745
 
@@ -85100,6 +85393,8 @@ class ApplyClbonds {
85100
85393
  // only apply to displayed atoms
85101
85394
  // if(!ic.dAtoms.hasOwnProperty(line.serial1) || !ic.dAtoms.hasOwnProperty(line.serial2)) continue;
85102
85395
 
85396
+ if(!ic.atoms[line.serial1] || !ic.atoms[line.serial2]) continue;
85397
+
85103
85398
  line.position1 = ic.atoms[line.serial1].coord;
85104
85399
  line.position2 = ic.atoms[line.serial2].coord;
85105
85400
 
@@ -85230,6 +85525,7 @@ class ApplyClbonds {
85230
85525
  if(type == 'chemical') continue; // just connect checmicals together
85231
85526
 
85232
85527
  if(ic.clbondpnts[atom0.structure] === undefined) ic.clbondpnts[atom0.structure] = [];
85528
+ if(ic.clbondpnts[atom1.structure] === undefined) ic.clbondpnts[atom1.structure] = [];
85233
85529
  ic.clbondpnts[atom0.structure].push(resid0);
85234
85530
  ic.clbondpnts[atom1.structure].push(resid1);
85235
85531
 
@@ -85775,9 +86071,9 @@ class ApplyOther {
85775
86071
  }
85776
86072
  }
85777
86073
 
85778
- ic.lineCls.createLines(ic.lines);
85779
- if(!ic.planes) ic.planes = [];
85780
- ic.cylinderCls.createPlanes(ic.planes);
86074
+ // ic.lineCls.createLines(ic.lines);
86075
+ // if(!ic.planes) ic.planes = [];
86076
+ // ic.cylinderCls.createPlanes(ic.planes);
85781
86077
  // }
85782
86078
 
85783
86079
  // distance sets
@@ -85900,6 +86196,10 @@ class ApplyOther {
85900
86196
  ic.pk = 3;
85901
86197
  break;
85902
86198
  }
86199
+
86200
+ ic.lineCls.createLines(ic.lines);
86201
+ if(!ic.planes) ic.planes = [];
86202
+ ic.cylinderCls.createPlanes(ic.planes);
85903
86203
  }
85904
86204
 
85905
86205
  applyChemicalbindingOptions(options) { let ic = this.icn3d, me = ic.icn3dui;
@@ -87046,6 +87346,8 @@ class Impostor {
87046
87346
 
87047
87347
  let shiness = ic.shininess / 100.0 * 0.5;
87048
87348
 
87349
+ let fogRGB = background.clone().convertLinearToSRGB();
87350
+
87049
87351
  ic.uniforms = UniformsUtils.merge([
87050
87352
  UniformsLib.common,
87051
87353
  {
@@ -87066,7 +87368,8 @@ class Impostor {
87066
87368
  nearClip: { type: "f", value: nearClip },
87067
87369
  ortho: { type: "f", value: 0.0 },
87068
87370
  shrink: { type: "f", value: 0.13 },
87069
- fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87371
+ //fogColor: { type: "v3", value: [background.r, background.g, background.b] },
87372
+ fogColor: { type: "v3", value: [fogRGB.r, fogRGB.g, fogRGB.b] },
87070
87373
  fogNear: { type: "f", value: near },
87071
87374
  fogFar: { type: "f", value: far },
87072
87375
  fogDensity: { type: "f", value: 2.0 }
@@ -105299,6 +105602,9 @@ class WebGLPathTracer {
105299
105602
 
105300
105603
  cam = this.setDirectLight(cam);
105301
105604
 
105605
+ // move the slab plane according to the zoom
105606
+ if(ic.opts['slab'] === 'yes') ic.cameraCls.updateSlabByZoom();
105607
+
105302
105608
  if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
105303
105609
 
105304
105610
  if(ic.bVr) {
@@ -108862,7 +109168,7 @@ class AnnoCddSite {
108862
109168
  ic.bAjaxCddSite = true;
108863
109169
  }
108864
109170
 
108865
- getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d; ic.icn3dui;
109171
+ getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d, me = ic.icn3dui;
108866
109172
  let resiArrayStr = '';
108867
109173
  for(let i = 0, il = resiNCBIArray.length; i < il; ++i) {
108868
109174
  let resiNCBI = resiNCBIArray[i] + 1; // zero-based
@@ -108870,7 +109176,8 @@ class AnnoCddSite {
108870
109176
  let resid = ic.ncbi2resid[residNCBI];
108871
109177
  if(!resid) resid = residNCBI; // this happens sometimes, e.g., Q9Y4K1
108872
109178
 
108873
- let resi = resid.split('_')[2];
109179
+ let idArray = me.utilsCls.getIdArray(resid);
109180
+ let resi = idArray[2];
108874
109181
  if(i > 0) resiArrayStr += ',';
108875
109182
  resiArrayStr += resi;
108876
109183
  }
@@ -109966,7 +110273,8 @@ class AnnoIg {
109966
110273
  let residArray = Object.keys(residHash);
109967
110274
 
109968
110275
  // delete the following loops
109969
- let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, residArray[residArray.length - 1].split('_')[2]);
110276
+ let idArray = me.utilsCls.getIdArray(residArray[residArray.length - 1]);
110277
+ let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
109970
110278
 
109971
110279
  for(let j = lastPos + 1, jl = ic.chainsSeq[chnid].length; j < jl; ++j) {
109972
110280
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -109982,7 +110290,8 @@ class AnnoIg {
109982
110290
  }
109983
110291
 
109984
110292
  // delete the previous loops
109985
- ic.setSeqAlignCls.getPosFromResi(chnid, residArray[0].split('_')[2]);
110293
+ idArray = me.utilsCls.getIdArray(residArray[0]);
110294
+ ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
109986
110295
 
109987
110296
  for(let j = lastPos - 1; j >= 0; --j) {
109988
110297
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -110985,8 +111294,9 @@ class AnnoSnpClinVar {
110985
111294
  let residHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chnid]);
110986
111295
  // for(let i = 1, il = ic.giSeq[chnid].length; i <= il; ++i) {
110987
111296
  for(let resid in residHash) {
110988
- let i = resid.split('_')[2];
110989
-
111297
+ let idArray = me.utilsCls.getIdArray(resid);
111298
+ let i = idArray[2];
111299
+
110990
111300
  if(resi2index[i] !== undefined) {
110991
111301
  ++snpCnt;
110992
111302
  let allDiseaseTitle = '';
@@ -113179,7 +113489,6 @@ class Domain3d {
113179
113489
  // if(fromPos >= start && toPos <= end) {
113180
113490
  if(ssCnt > 0) jsonStr += ', ';
113181
113491
  jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
113182
- // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
113183
113492
  jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
113184
113493
  ++ssCnt;
113185
113494
  // }
@@ -113196,7 +113505,6 @@ class Domain3d {
113196
113505
  for(let j = startAll; j <= endAll; ++j) {
113197
113506
  let ncbiResid = chnid + '_' + j;
113198
113507
  let resid = ic.ncbi2resid[ncbiResid];
113199
- resid.split('_')[2];
113200
113508
 
113201
113509
  let pos = j;
113202
113510
 
@@ -113204,7 +113512,6 @@ class Domain3d {
113204
113512
 
113205
113513
  if(!residueHash.hasOwnProperty(resid)) {
113206
113514
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113207
- // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
113208
113515
  }
113209
113516
  else {
113210
113517
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -113213,7 +113520,6 @@ class Domain3d {
113213
113520
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
113214
113521
 
113215
113522
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
113216
- // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
113217
113523
  }
113218
113524
 
113219
113525
  ++domainCnt;
@@ -119051,7 +119357,6 @@ class GetGraph {
119051
119357
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
119052
119358
  let node = graphJson.nodes[i];
119053
119359
  //node.r: 1_1_1KQ2_A_1
119054
- //var idArray = node.r.split('_');
119055
119360
  let idArray = [];
119056
119361
  idArray.push('');
119057
119362
  idArray.push('');
@@ -119230,8 +119535,8 @@ class GetGraph {
119230
119535
  compNode(a, b, bReverseChain) { let ic = this.icn3d, me = ic.icn3dui;
119231
119536
  let resid1 = a.r.substr(4); // 1_1_1KQ2_A_1
119232
119537
  let resid2 = b.r.substr(4); // 1_1_1KQ2_A_1
119233
- let aIdArray = me.utilsCls.getIdArray(resid1); //resid1.split('_');
119234
- let bIdArray = me.utilsCls.getIdArray(resid2); //resid2.split('_');
119538
+ let aIdArray = me.utilsCls.getIdArray(resid1);
119539
+ let bIdArray = me.utilsCls.getIdArray(resid2);
119235
119540
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
119236
119541
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
119237
119542
  let aResi = parseInt(aIdArray[2]);
@@ -120284,7 +120589,7 @@ class ViewInterPairs {
120284
120589
  residname2 =(type == 'save1') ? residname1_residname2[1] : residname1_residname2[0];
120285
120590
 
120286
120591
  // stru_chain_resi_resn
120287
- let ids = residname1.split('_');
120592
+ let ids = me.utilsCls.getIdArray(residname1);
120288
120593
  if(i > 0 && residname1 != prevResidname1) {
120289
120594
  bondCnt.push({res1: prevResidname1, res2: residname2List, cntHbond: cntHbond, cntIonic: cntIonic, cntContact: cntContact, cntHalegen: cntHalegen, cntPication: cntPication, cntPistacking: cntPistacking});
120290
120595
 
@@ -121685,8 +121990,8 @@ class AlignParser {
121685
121990
  //var scale = data2.transform.scale / factor;
121686
121991
  let tMaster = data2.transform.translate.master;
121687
121992
  let tMVector = new Vector3$1(tMaster[0] / factor, tMaster[1] / factor, tMaster[2] / factor);
121688
- let tSlave = data2.transform.translate.slave;
121689
- let tSVector = new Vector3$1(tSlave[0] / factor, tSlave[1] / factor, tSlave[2] / factor);
121993
+ let tQuery = data2.transform.translate.slave; // actually means query protein
121994
+ let tSVector = new Vector3$1(tQuery[0] / factor, tQuery[1] / factor, tQuery[2] / factor);
121690
121995
  let rotation = data2.transform.rotate;
121691
121996
  let rMatrix = [];
121692
121997
  for(let i = 0, il = rotation.length; i < il; ++i) { // 9 elements
@@ -121930,44 +122235,6 @@ class ChainalignParser {
121930
122235
  // calculate secondary structures with applyCommandDssp
121931
122236
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
121932
122237
  await ic.pdbParserCls.applyCommandDssp(true);
121933
- //!!!
121934
- /*
121935
- // original version =============
121936
- // align PDB chains
121937
- for(let index in ic.pdbChainIndexHash) {
121938
- //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
121939
- let idArray = ic.pdbChainIndexHash[index].split('_');
121940
- mmdbid_q = idArray[0];
121941
- let chain_q = idArray[1];
121942
- mmdbid_t = idArray[2];
121943
- let chain_t = idArray[3];
121944
-
121945
- thisClass.transformStructure(mmdbid_q, index-1, 'query');
121946
- }
121947
-
121948
- // dynamically align pairs in ic.afChainIndexHash
121949
- let ajaxArray = [], indexArray = [], struArray = [];
121950
- let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
121951
- let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
121952
-
121953
- let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
121954
-
121955
- for(let index in ic.afChainIndexHash) {
121956
- let idArray = ic.afChainIndexHash[index].split('_');
121957
- mmdbid_q = idArray[0];
121958
- let chain_q = idArray[1];
121959
- let chainid_q = mmdbid_q + '_' + chain_q;
121960
-
121961
- mmdbid_t = idArray[2];
121962
- let chain_t = idArray[3];
121963
- let chainid_t = mmdbid_t + '_' + chain_t;
121964
-
121965
- // let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t, true).hAtoms : ic.chains[chainid_t];
121966
- // let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q, true).hAtoms : ic.chains[chainid_q];
121967
- let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainid_t, true).hAtoms : ic.chains[chainid_t];
121968
- let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainid_q, true).hAtoms : ic.chains[chainid_q];
121969
- // end of original version =============
121970
- */
121971
122238
 
121972
122239
  // new version to be done for VASTsrv ==============
121973
122240
  // dynamically align pairs in all chainids
@@ -122436,10 +122703,10 @@ class ChainalignParser {
122436
122703
  return chainidArray;
122437
122704
  }
122438
122705
 
122439
- addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
122706
+ addPostfixForStructureids(structArray) { let ic = this.icn3d, me = ic.icn3dui;
122440
122707
  let struct2cnt = {};
122441
122708
  for(let i = 0, il = structArray.length; i < il; ++i) {
122442
- if(structArray[i].toLowerCase().toLowerCase().substr(0,8) == 'pdb_0000') structArray[i] = structArray[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122709
+ if((me.cfg.mmdbid != undefined || me.cfg.pdbid != undefined) && structArray[i].toLowerCase().toLowerCase().substr(0,8) == 'pdb_0000') structArray[i] = structArray[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122443
122710
 
122444
122711
  let struct = structArray[i].toUpperCase();
122445
122712
 
@@ -122463,6 +122730,8 @@ class ChainalignParser {
122463
122730
 
122464
122731
  ic.opts['proteins'] = 'c alpha trace';
122465
122732
 
122733
+ if(!chainalign) return;
122734
+
122466
122735
  let alignArray = chainalign.split(',');
122467
122736
  let domainArray = (me.cfg.domainids) ? me.cfg.domainids.split(',') : [];
122468
122737
  if(domainArray.length < alignArray.length) domainArray = [];
@@ -122535,7 +122804,7 @@ class ChainalignParser {
122535
122804
  let domainalign = (domainArray.length > 0) ? domainArray[index] + "," + domainArray[0] : undefined;
122536
122805
 
122537
122806
  // TM-align (me.cfg.aligntool == 'tmalign') needs to input PDB
122538
- if(me.cfg.aligntool != 'tmalign' && ic.mmdbid_t.length == 4 && ic.mmdbid_q.length == 4) {
122807
+ if(me.cfg.aligntool != 'tmalign' && (ic.mmdbid_t.length == 4 || ic.mmdbid_t.indexOf('pdb_') == 0) && (ic.mmdbid_q.length == 4 || ic.mmdbid_q.indexOf('pdb_') == 0)) {
122539
122808
  let urlalign;
122540
122809
 
122541
122810
  if(domainArray.length > 0) {
@@ -122824,7 +123093,7 @@ class ChainalignParser {
122824
123093
  }
122825
123094
  else {
122826
123095
  for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
122827
- if(structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
123096
+ if((me.cfg.mmdbid != undefined || me.cfg.pdbid != undefined) && structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
122828
123097
 
122829
123098
  let id = structArrayTmp[i].toUpperCase();
122830
123099
  if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
@@ -124355,6 +124624,19 @@ class MmcifParser {
124355
124624
  await ic.opmParserCls.loadOpmData(data, mmcifid, undefined, 'mmcif', undefined, bText);
124356
124625
  }
124357
124626
 
124627
+ async downloadCod(codid) { let ic = this.icn3d, me = ic.icn3dui;
124628
+ //ic.bCid = undefined;
124629
+
124630
+ ic.ParserUtilsCls.setYourNote(codid.toUpperCase() + '(COD) in iCn3D');
124631
+
124632
+ let url = "https://www.crystallography.net/cod/" + codid + ".cif";
124633
+ // let url = "https://www.crystallography.net/cif/1/00/00/1000041.cif";
124634
+ let data = await me.getAjaxPromise(url, 'text', true);
124635
+
124636
+ let bText = true;
124637
+ ic.loadCIFCls.loadCIF(data, codid, bText);
124638
+ }
124639
+
124358
124640
  async downloadMmcifSymmetry(mmcifid, type) { let ic = this.icn3d, me = ic.icn3dui;
124359
124641
  try {
124360
124642
  // let url = "https://files.rcsb.org/download/" + mmcifid + ".cif";
@@ -124459,14 +124741,20 @@ class MmcifParser {
124459
124741
  }
124460
124742
  }
124461
124743
 
124462
- async loadMultipleMmcifData(data, mmcifid, bAppend) { let ic = this.icn3d; ic.icn3dui;
124463
- let bText = true;
124744
+ async loadMultipleMmcifData(data, mmcifid, bAppend, fileType) { let ic = this.icn3d; ic.icn3dui;
124745
+ let bText = (fileType == 'bcif') ? false : true;
124746
+
124464
124747
  ic.loadCIFCls.loadCIF(data, mmcifid, bText, bAppend);
124465
124748
 
124466
124749
  if(Object.keys(ic.structures).length > 1) {
124467
124750
  ic.opts['color'] = 'structure';
124468
124751
  }
124469
124752
 
124753
+ if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
124754
+ ic.pk = 1;
124755
+ ic.opts['pk'] = 'atom';
124756
+ }
124757
+
124470
124758
  ic.opmParserCls.modifyUIMapAssembly();
124471
124759
 
124472
124760
  await ic.pdbParserCls.addSecondary(bAppend);
@@ -124560,9 +124848,10 @@ class MmdbParser {
124560
124848
  me.cfg.query_id = idArray[0];
124561
124849
  me.cfg.blast_rep_id = idArray[1];
124562
124850
 
124563
- let mmdbid = me.cfg.blast_rep_id.split('_')[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124851
+ let textArray = me.utilsCls.getIdArray(me.cfg.blast_rep_id);
124852
+ let mmdbid = textArray[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
124564
124853
 
124565
- if(mmdbid.length == 4) { // pdb
124854
+ if(mmdbid.length == 4 || mmdbid.indexOf('pdb_') == 0) { // pdb
124566
124855
  await this.downloadMmdb(mmdbid);
124567
124856
  }
124568
124857
  else {
@@ -124714,7 +125003,7 @@ class MmdbParser {
124714
125003
  if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
124715
125004
  // save a set named me.cfg.ligand
124716
125005
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
124717
- let idArray = Object.keys(residueHash)[0].split('_');
125006
+ let idArray = me.utilsCls.getIdArray(Object.keys(residueHash)[0]);
124718
125007
  let select = '.' + idArray[1] + ':' + idArray[2];
124719
125008
 
124720
125009
  await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
@@ -125091,7 +125380,7 @@ class BcifParser {
125091
125380
 
125092
125381
  if (parsed.isError) {
125093
125382
  // report error:
125094
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
125383
+ var aaa = 1; //alert("1 The Binary CIF data can NOT be parsed: " + parsed.toString());
125095
125384
  return;
125096
125385
  }
125097
125386
 
@@ -126056,7 +126345,8 @@ class OpmParser {
126056
126345
  if(!pdbid) pdbid = ic.defaultPdbId;
126057
126346
 
126058
126347
  //if(me.cfg.mmtfid === undefined && me.cfg.bcifid === undefined) { // skip opm for bcif files
126059
- let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + pdbid.toLowerCase();
126348
+ let shortPdbid = pdbid.indexOf('pdb_0000') == 0 ? pdbid.substr(8) : pdbid;
126349
+ let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + shortPdbid.toLowerCase();
126060
126350
 
126061
126351
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
126062
126352
 
@@ -127132,7 +127422,7 @@ class DcdParser {
127132
127422
  }
127133
127423
 
127134
127424
  for(let j in residuesOri) {
127135
- let idArray = j.split('_');
127425
+ let idArray = me.utilsCls.getIdArray(j);
127136
127426
  let structure2 = idArray[0] + molNum;
127137
127427
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127138
127428
  ic.residues[residid2] = {};
@@ -127143,7 +127433,7 @@ class DcdParser {
127143
127433
  }
127144
127434
 
127145
127435
  for(let j in chainsOri) {
127146
- let idArray = j.split('_');
127436
+ let idArray = me.utilsCls.getIdArray(j);
127147
127437
  let structure2 = idArray[0] + molNum;
127148
127438
  let chainid2 = structure2 + '_' + idArray[1];
127149
127439
 
@@ -127174,7 +127464,7 @@ class DcdParser {
127174
127464
 
127175
127465
  // set ic.ncbi2resid and ic.resid2ncbi
127176
127466
  for(let chainid in chainsOri) {
127177
- let idArray = chainid.split('_');
127467
+ let idArray = me.utilsCls.getIdArray(chainid);
127178
127468
  let structure2 = idArray[0] + molNum;
127179
127469
  let chainid2 = structure2 + '_' + idArray[1];
127180
127470
 
@@ -127738,7 +128028,7 @@ class XtcParser {
127738
128028
  }
127739
128029
 
127740
128030
  for(let j in residuesOri) {
127741
- let idArray = j.split('_');
128031
+ let idArray = me.utilsCls.getIdArray(j);
127742
128032
  let structure2 = idArray[0] + molNum;
127743
128033
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
127744
128034
  ic.residues[residid2] = {};
@@ -127749,7 +128039,7 @@ class XtcParser {
127749
128039
  }
127750
128040
 
127751
128041
  for(let j in chainsOri) {
127752
- let idArray = j.split('_');
128042
+ let idArray = me.utilsCls.getIdArray(j);
127753
128043
  let structure2 = idArray[0] + molNum;
127754
128044
  let chainid2 = structure2 + '_' + idArray[1];
127755
128045
 
@@ -127780,7 +128070,7 @@ class XtcParser {
127780
128070
 
127781
128071
  // set ic.ncbi2resid and ic.resid2ncbi
127782
128072
  for(let chainid in chainsOri) {
127783
- let idArray = chainid.split('_');
128073
+ let idArray = me.utilsCls.getIdArray(chainid);
127784
128074
  let structure2 = idArray[0] + molNum;
127785
128075
  let chainid2 = structure2 + '_' + idArray[1];
127786
128076
 
@@ -128006,9 +128296,8 @@ class MsaParser {
128006
128296
 
128007
128297
  // realign based on residue by residue
128008
128298
  let alignment_final = ic.inputChainidArray.join(',');
128009
-
128010
128299
  if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
128011
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
128300
+ var aaa = 1; //alert("Please make sure the number of chains " + (alignment_final.split(',').length - 1) + " and the lines of predefined residues " + predefinedres.split(': ').length + " are the same...");
128012
128301
  return;
128013
128302
  }
128014
128303
 
@@ -128066,7 +128355,7 @@ class MsaParser {
128066
128355
  }
128067
128356
 
128068
128357
  if(type == 'clustalw') {
128069
- if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
128358
+ if(line.substr(0, 1) != '.' && line.substr(0, 1) != '*') {
128070
128359
  let chainid_seq = line.split(/\s+/);
128071
128360
  let idArray = chainid_seq[0].split('|');
128072
128361
  let result = this.getChainid(idArray, bStart && !bSecBlock);
@@ -128091,9 +128380,11 @@ class MsaParser {
128091
128380
  seq = '';
128092
128381
 
128093
128382
  let pos = line.indexOf(' ');
128383
+ if(pos == -1) pos = line.length;
128094
128384
  let idArray = line.substr(1, pos).split('|');
128095
-
128385
+
128096
128386
  if(idArray.length == 1) {
128387
+ bFound = true;
128097
128388
  chainid = idArray[0];
128098
128389
  }
128099
128390
  else {
@@ -128157,8 +128448,9 @@ class MsaParser {
128157
128448
  ic.inputChainidArray.push(chainid + '_A');
128158
128449
  }
128159
128450
  }
128160
- else if(chainid.indexOf('_') != -1) { // PDB ID
128161
- let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
128451
+ else if(chainid.indexOf('_') != -1 || chainid.indexOf('pdb_') != -1) { // PDB ID
128452
+ let idArray = me.utilsCls.getIdArray(chainid);
128453
+ let stru = idArray[0];
128162
128454
  ic.struArray.push(stru);
128163
128455
  ic.inputChainidArray.push(chainid);
128164
128456
  }
@@ -128240,7 +128532,7 @@ class RealignParser {
128240
128532
  }
128241
128533
 
128242
128534
  // ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn.substr(0, 3)).substr(0, 1)});
128243
- ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn).substr(0, 1)});
128535
+ ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn, true)});
128244
128536
 
128245
128537
  struct2chain[atom.structure] = atom.structure + '_' + atom.chain;
128246
128538
 
@@ -128283,7 +128575,8 @@ class RealignParser {
128283
128575
 
128284
128576
  async parseChainRealignPredefined(chainidArray, struct2SeqHash, struct2CoorHash, struct2resid) { let ic = this.icn3d, me = ic.icn3dui;
128285
128577
 
128286
- let toStruct = chainidArray[0].substr(0, chainidArray[0].indexOf('_')); //.toUpperCase();
128578
+ let itemArray1 = me.utilsCls.getIdArray(chainidArray[0]);
128579
+ let toStruct = itemArray1[0];
128287
128580
 
128288
128581
  let hAtoms = {}, rmsd;
128289
128582
 
@@ -128296,13 +128589,14 @@ class RealignParser {
128296
128589
  ic.qt_start_end = [];
128297
128590
 
128298
128591
  let chainidHash = {};
128299
- for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
128300
- let fromStruct = chainidArray[index + 1].substr(0, chainidArray[index + 1].indexOf('_')); //.toUpperCase();
128592
+ for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
128593
+ let itemArray2 = me.utilsCls.getIdArray(chainidArray[index + 1]);
128594
+ let fromStruct = itemArray2[0];
128301
128595
 
128302
128596
  //if(toStruct == fromStruct) fromStruct += me.htmlCls.postfix;
128303
128597
 
128304
- let chainTo = toStruct + chainidArray[0].substr(chainidArray[0].indexOf('_'));
128305
- let chainFrom = fromStruct + chainidArray[index + 1].substr(chainidArray[index + 1].indexOf('_'));
128598
+ let chainTo = toStruct + '_' + itemArray1[1];
128599
+ let chainFrom = fromStruct + '_' + itemArray2[1];
128306
128600
  chainidHash[chainTo] = 1;
128307
128601
  chainidHash[chainFrom] = 1;
128308
128602
 
@@ -128337,7 +128631,7 @@ class RealignParser {
128337
128631
 
128338
128632
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, result.hAtoms);
128339
128633
  rmsd = parseFloat(result.rmsd);
128340
- }
128634
+ }
128341
128635
 
128342
128636
  // If rmsd from vastsrv is too large, realign the chains
128343
128637
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
@@ -128559,15 +128853,6 @@ class RealignParser {
128559
128853
  prevChainid = chainidArrayTmp[i];
128560
128854
  }
128561
128855
 
128562
- // use the model from Membranome as template
128563
- // if(ic.bAfMem && chainidArray.length == 2) {
128564
- // if(chainidArray[1].split('_')[0] == pdbidTemplate) {
128565
- // let tmp = chainidArray[0];
128566
- // chainidArray[0] = chainidArray[1];
128567
- // chainidArray[1] = tmp;
128568
- // }
128569
- // }
128570
-
128571
128856
  let bRealign = true;
128572
128857
  ic.qt_start_end = []; // reset the alignment
128573
128858
 
@@ -128812,12 +129097,12 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128812
129097
  let predefinedResArray, predefinedResPair;
128813
129098
 
128814
129099
  if(bPredefined) {
128815
- me.cfg.resdef.replace(/; /gi, ': ');
128816
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
128817
- // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
128818
-
129100
+ let tmpStr = me.cfg.resdef.replace(/; /gi, ': ');
129101
+ // predefinedResArray = decodeURIComponent(tmpStr).trim().replace(/\+/gi, ' ').split(': ');
129102
+ predefinedResArray = tmpStr.replace(/\+/gi, ' ').split(': ');
129103
+
128819
129104
  if(predefinedResArray.length != chainidArray.length - 1) {
128820
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
129105
+ var aaa = 1; //alert("Please make sure the number of chains " + (chainidArray.length - 1) + " and the lines of predefined residues " + predefinedResArray.length + " are the same...");
128821
129106
  return;
128822
129107
  }
128823
129108
  }
@@ -128826,8 +129111,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128826
129111
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
128827
129112
  //if(bPredefined) predefinedRes = predefinedResArray[i].trim();
128828
129113
 
128829
- let pos = chainidArray[i].indexOf('_');
128830
- let mmdbid = chainidArray[i].substr(0, pos); //.toUpperCase();
129114
+ let itemArray = me.utilsCls.getIdArray(chainidArray[i]);
129115
+ let mmdbid = itemArray[0]; //.toUpperCase();
128831
129116
 
128832
129117
  // if(!bRealign) mmdbid = mmdbid.toUpperCase();
128833
129118
 
@@ -128835,7 +129120,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128835
129120
  mmdbid_t = mmdbid;
128836
129121
  }
128837
129122
 
128838
- let chainid = mmdbid + chainidArray[i].substr(pos);
129123
+ let chainid = mmdbid + '_' + itemArray[1];
128839
129124
  if(i == 0) chainid_t = chainid;
128840
129125
 
128841
129126
  if(!ic.chainsSeq || !ic.chainsSeq[chainid]) {
@@ -128864,7 +129149,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128864
129149
  if(!struct2CoorHash[chainidpair]) struct2CoorHash[chainidpair] = {};
128865
129150
  if(!struct2resid[chainidpair]) struct2resid[chainidpair] = {};
128866
129151
 
128867
- // master
129152
+ // template
128868
129153
  resiArray = predefinedResPair[0].split(",");
128869
129154
 
128870
129155
  result = thisClass.getSeqCoorResid(resiArray, chainid_t);
@@ -128879,7 +129164,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128879
129164
  struct2CoorHash[chainidpair][mmdbid_t] = struct2CoorHash[chainidpair][mmdbid_t].concat(result.coor);
128880
129165
  struct2resid[chainidpair][mmdbid_t] = struct2resid[chainidpair][mmdbid_t].concat(result.resid);
128881
129166
 
128882
- // slave
129167
+ // query
128883
129168
  resiArray = predefinedResPair[1].split(",");
128884
129169
 
128885
129170
  result = thisClass.getSeqCoorResid(resiArray, chainid);
@@ -128907,7 +129192,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128907
129192
  }
128908
129193
  }
128909
129194
  else {
128910
- if(i == 0) { // master
129195
+ if(i == 0) { // template
128911
129196
  //base = parseInt(ic.chainsSeq[chainid][0].resi);
128912
129197
 
128913
129198
  resiArray = [];
@@ -128947,7 +129232,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
128947
129232
  bSelectedBoth = true;
128948
129233
 
128949
129234
  let resn = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]).resn;
128950
- struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn);
129235
+ struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn, true);
128951
129236
 
128952
129237
  struct2CoorHash[chainid] = struct2CoorHash[chainid].concat(this.getResCoorArray(resid));
128953
129238
 
@@ -131262,9 +131547,6 @@ class LoadAtomData {
131262
131547
  atm.coord = new Vector3$1(atm.coord.x, atm.coord.y, atm.coord.z);
131263
131548
  }
131264
131549
 
131265
- // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131266
- let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn);
131267
-
131268
131550
  if((type === 'mmdbid' || type === 'align') && ic.bFullUi ) {
131269
131551
  // set ic.mmdbMolidResid2mmdbChainResi
131270
131552
  if(ic.mmdbMolidResid2mmdbChainResi === undefined) ic.mmdbMolidResid2mmdbChainResi = {};
@@ -131406,6 +131688,8 @@ class LoadAtomData {
131406
131688
  }
131407
131689
  }
131408
131690
 
131691
+ // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
131692
+ let oneLetterRes = (atm.het) ? me.utilsCls.residueName2Abbr(atm.resn) : me.utilsCls.residueName2Abbr(atm.resn, true);
131409
131693
  ic.residueId2Name[residueid] = oneLetterRes;
131410
131694
 
131411
131695
  let secondaries = '-';
@@ -131753,11 +132037,11 @@ class SetSeqAlign {
131753
132037
  ic.nconsHash2 = {};
131754
132038
  ic.nalignHash2 = {};
131755
132039
 
131756
- let msaSameColor = [];
131757
- // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
131758
- for(let i = 0, il = seqalign[0].length; i < il; ++i) {
131759
- msaSameColor.push(1);
131760
- }
132040
+ // let msaSameColor = [];
132041
+ // // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132042
+ // for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132043
+ // msaSameColor.push(1);
132044
+ // }
131761
132045
 
131762
132046
  for(let i = 0, il = seqalign.length; i < il; ++i) {
131763
132047
  // first sequence
@@ -131766,44 +132050,30 @@ class SetSeqAlign {
131766
132050
 
131767
132051
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
131768
132052
  chainid1 = mmdbid1 + '_' + chain1;
131769
-
131770
- let id2aligninfo = {};
131771
- let start = alignData.sequence.length, end = -1;
131772
- let bStart = false;
132053
+ alignData.sequence.length;
131773
132054
  for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
131774
132055
  // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131775
- let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
131776
- let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131777
- resn =(resn === ' ' || resn === '') ? 'X' : resn;
131778
-
131779
- let aligned =(alignData.sequence[j][3]) ? 1 : 0;
131780
-
131781
- if(aligned == 1) {
131782
- if(j < start && !bStart) {
131783
- start = j;
131784
- bStart = true; // set start just once
131785
- }
131786
- if(j > end) end = j;
131787
- }
132056
+ (ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132057
+ (alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131788
132058
 
131789
- id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132059
+ (alignData.sequence[j][3]) ? 1 : 0;
131790
132060
  }
131791
132061
 
131792
132062
  // second sequence
131793
132063
  alignData = seqalign[i][1];
131794
132064
 
131795
- for(let j = start; j <= end; ++j) {
131796
- // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131797
- let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132065
+ // for(let j = start; j <= end; ++j) {
132066
+ // // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132067
+ // let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
131798
132068
 
131799
- let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132069
+ // let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
131800
132070
 
131801
- if(aligned === 2) { // aligned
131802
- if(id2aligninfo[j].resn != resn) {
131803
- msaSameColor[j] = 0;
131804
- }
131805
- }
131806
- }
132071
+ // if(aligned === 2) { // aligned
132072
+ // if(id2aligninfo[j].resn != resn) {
132073
+ // msaSameColor[j] = 0;
132074
+ // }
132075
+ // }
132076
+ // }
131807
132077
  }
131808
132078
 
131809
132079
  for(let i = 0, il = seqalign.length; i < il; ++i) {
@@ -131902,7 +132172,7 @@ class SetSeqAlign {
131902
132172
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
131903
132173
  }
131904
132174
 
131905
- color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132175
+ // color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
131906
132176
 
131907
132177
  // mapping, use the firstsequence as the reference structure
131908
132178
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -131921,7 +132191,7 @@ class SetSeqAlign {
131921
132191
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
131922
132192
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
131923
132193
 
131924
- msaSameColor[j] = 2; // not aligned
132194
+ // msaSameColor[j] = 2; // not aligned
131925
132195
  }
131926
132196
 
131927
132197
  // chain1
@@ -132046,8 +132316,7 @@ class SetSeqAlign {
132046
132316
  return pos;
132047
132317
  }
132048
132318
 
132049
- getResnFromResi(chainid, resi) { let ic = this.icn3d; ic.icn3dui;
132050
- /*
132319
+ getResnFromResi(chainid, resi) { let ic = this.icn3d, me = ic.icn3dui;
132051
132320
  let pos = this.getPosFromResi(chainid, resi);
132052
132321
  if(!pos) return '?';
132053
132322
 
@@ -132062,8 +132331,8 @@ class SetSeqAlign {
132062
132331
  }
132063
132332
 
132064
132333
  return resn;
132065
- */
132066
132334
 
132335
+ /*
132067
132336
  let resid = chainid + '_' + resi;
132068
132337
  let resn = ic.residueId2Name[resid];
132069
132338
  if(!resn) {
@@ -132071,6 +132340,7 @@ class SetSeqAlign {
132071
132340
  }
132072
132341
 
132073
132342
  return resn;
132343
+ */
132074
132344
  }
132075
132345
 
132076
132346
  getResiAferAlign(chainid, bRealign, pos) { let ic = this.icn3d, me = ic.icn3dui;
@@ -132415,7 +132685,7 @@ class SetSeqAlign {
132415
132685
  let start1, end1;
132416
132686
 
132417
132687
  //ic.qt_start_end is zero-based
132418
- if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
132688
+ if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment or seqalign
132419
132689
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
132420
132690
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
132421
132691
  }
@@ -132450,15 +132720,18 @@ class SetSeqAlign {
132450
132720
 
132451
132721
  let resid2rangeArray = Object.keys(resid2range_t);
132452
132722
  resid2rangeArray.sort(function(a, b) {
132453
- return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
132723
+ let idArray1 = me.utilsCls.getIdArray(a);
132724
+ let idArray2 = me.utilsCls.getIdArray(b);
132725
+ return parseInt(idArray1[2]) - parseInt(idArray2[2]);
132454
132726
  });
132455
132727
 
132456
132728
  // assign range to each resi
132457
132729
  let prevResi = -999, start = 0, end = 0, residArray = [], prevEnd = 0;
132458
132730
  for(let i = 0, il = resid2rangeArray.length; i < il; ++i) {
132459
132731
  let resid = resid2rangeArray[i];
132460
- let resi = resid.split('_')[2];
132461
-
132732
+ let idArray = me.utilsCls.getIdArray(resid);
132733
+ let resi = idArray[2];
132734
+
132462
132735
  if(i == 0) {
132463
132736
  start = resi;
132464
132737
  }
@@ -132497,7 +132770,9 @@ class SetSeqAlign {
132497
132770
  let resid = chainid1 + '_' + resi;
132498
132771
 
132499
132772
  // let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : j + baseResi;
132500
- let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132773
+ //let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132774
+ //!!!
132775
+ let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
132501
132776
 
132502
132777
  //if(j + baseResi < start_t || j + baseResi > end_t) {
132503
132778
  if(jAdjusted < start_t || jAdjusted > end_t) {
@@ -132698,21 +132973,23 @@ class SetSeqAlign {
132698
132973
  }
132699
132974
  }
132700
132975
 
132701
- getTemplatePosFromOriResi(chainid1, start, end, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
132702
- // let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
132703
- // let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
132704
- if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
132705
- let startResi = start;
132706
- let endResi = end;
132976
+ getTemplatePosFromOriPos(chainid1, start, end, bRealign) { let ic = this.icn3d; ic.icn3dui;
132977
+ //!!!
132978
+ let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
132979
+ let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
132980
+
132981
+ // if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
132982
+ // let startResi = start;
132983
+ // let endResi = end;
132707
132984
 
132708
132985
  let result1 = this.getResiPosInTemplate(chainid1, startResi);
132709
132986
  let result2 = this.getResiPosInTemplate(chainid1, endResi);
132710
132987
 
132711
132988
  return {"pos1": result1.pos, "pos2": result2.pos};
132712
- }
132713
- else {
132714
- return {"pos1": start, "pos2": end};
132715
- }
132989
+ // }
132990
+ // else {
132991
+ // return {"pos1": start, "pos2": end};
132992
+ // }
132716
132993
  }
132717
132994
 
132718
132995
  mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
@@ -132784,11 +133061,11 @@ class SetSeqAlign {
132784
133061
  start_t = ic.ParserUtilsCls.getResi(chainid1, start_t);
132785
133062
  end_t = ic.ParserUtilsCls.getResi(chainid1, end_t);
132786
133063
  }
132787
-
133064
+ console.log("### me.cfg.aligntool " + me.cfg.aligntool + " bRealign " + bRealign );
132788
133065
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
132789
- let start1, start2, end1, end2, resiStart1, start1Pos;
133066
+ let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
132790
133067
 
132791
- if(bRealign && me.cfg.aligntool == 'tmalign') { // real residue numbers are stored
133068
+ if(bRealign && (me.cfg.aligntool == 'tmalign')) { // real residue numbers are stored
132792
133069
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start);
132793
133070
  start2 = parseInt(ic.qt_start_end[chainIndex][i].q_start);
132794
133071
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end);
@@ -132802,7 +133079,7 @@ class SetSeqAlign {
132802
133079
  // 1. before the mapped residues
132803
133080
  resiStart1 = start1;
132804
133081
  start1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_start);
132805
- this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133082
+ end1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
132806
133083
  }
132807
133084
  else {
132808
133085
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start - 1);
@@ -132813,6 +133090,7 @@ class SetSeqAlign {
132813
133090
  // 1. before the mapped residues
132814
133091
  resiStart1 = ic.ParserUtilsCls.getResi(chainid1, start1);
132815
133092
  start1Pos = start1;
133093
+ end1Pos = end1;
132816
133094
  }
132817
133095
  //let range = resid2range_t[chainid1 + '_' + resiStart1];
132818
133096
 
@@ -132820,13 +133098,15 @@ class SetSeqAlign {
132820
133098
  if(i == 0) {
132821
133099
  startPosInTemplate = start1Pos;
132822
133100
 
132823
- result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
132824
- //result = this.getTemplatePosFromOriResi(chainid1, start_t, start1Pos, bRealign);
133101
+ //!!!
133102
+ // result = this.getTemplatePosFromOriPos(chainid1, start_t, start1, bRealign);
133103
+ result = this.getTemplatePosFromOriPos(chainid1, start_t, start1Pos, bRealign);
132825
133104
  pos1 = result.pos1;
132826
133105
  pos2 = result.pos2;
132827
133106
 
132828
- if(start1 > start_t) {
132829
- //if(start1Pos > start_t) {
133107
+ //!!!
133108
+ // if(start1 > start_t) {
133109
+ if(start1Pos > start_t) {
132830
133110
  for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
132831
133111
  ic.alnChainsSeq[chainid2].push(gapResObject2);
132832
133112
  }
@@ -132834,7 +133114,7 @@ class SetSeqAlign {
132834
133114
  }
132835
133115
  else {
132836
133116
  //let notAlnLen1 = start1 - (prevIndex1 + 1);
132837
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
133117
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, start1, bRealign);
132838
133118
  pos1 = result.pos1;
132839
133119
  pos2 = result.pos2;
132840
133120
  let notAlnLen1 = pos2 - (pos1 + 1);
@@ -132859,15 +133139,16 @@ class SetSeqAlign {
132859
133139
  }
132860
133140
 
132861
133141
  // 2. In the mapped residues
132862
- result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
132863
- //result = this.getTemplatePosFromOriResi(chainid1, start1Pos, end1Pos, bRealign);
133142
+ // result = this.getTemplatePosFromOriPos(chainid1, start1, end1, bRealign);
133143
+ result = this.getTemplatePosFromOriPos(chainid1, start1Pos, end1Pos, bRealign);
132864
133144
  pos1 = result.pos1;
132865
133145
  pos2 = result.pos2;
132866
133146
 
132867
133147
  let k = 0;
132868
133148
  if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
132869
133149
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
132870
- let resiAdjust = (bRealign && me.cfg.aligntool == 'tmalign') ? 0 : - startPosInTemplate + nGapInTemplate;
133150
+ //!!!!!!
133151
+ let resiAdjust = ((bRealign && me.cfg.aligntool == 'tmalign') || me.cfg.aligntool == 'seqalign') ? 0 : - startPosInTemplate + nGapInTemplate;
132871
133152
  for(let j = pos1; j <= pos2; ++j) {
132872
133153
  // inherit the gaps from the template
132873
133154
  if(ic.alnChainsSeq[chainid1][j + resiAdjust].resn == '-') {
@@ -132902,7 +133183,7 @@ class SetSeqAlign {
132902
133183
  }
132903
133184
 
132904
133185
  // add gaps at the end
132905
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
133186
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, end_t, bRealign);
132906
133187
  pos1 = result.pos1;
132907
133188
  pos2 = result.pos2;
132908
133189
  for(let i = pos1; i < pos2; ++i) {
@@ -133238,7 +133519,7 @@ class SetSeqAlign {
133238
133519
  }
133239
133520
  }
133240
133521
 
133241
- setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
133522
+ setMsaFormat(chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
133242
133523
  //set MSA
133243
133524
  let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
133244
133525
  let chainArrayClustal = [];
@@ -133250,7 +133531,9 @@ class SetSeqAlign {
133250
133531
  fastaFormat += '>' + chainid + '\n';
133251
133532
 
133252
133533
  let clustalwArray = [];
133253
- let clustalwLine = chainid.padEnd(20, ' ');
133534
+ let itemArray = me.utilsCls.getIdArray(chainid);
133535
+ let chainidStr = 'pdb|' + itemArray[0] + '|' + itemArray[1];
133536
+ let clustalwLine = chainidStr.padEnd(20, ' ');
133254
133537
  let consLine = ''.padEnd(20, ' ');
133255
133538
 
133256
133539
  let resiArrayTarget = [], resiArrayQuery = [];
@@ -133790,7 +134073,7 @@ class LoadPDB {
133790
134073
  //if(residueNum !== prevResidueNum) {
133791
134074
 
133792
134075
  if(oriResidueNum !== prevOriResidueNum) {
133793
- let residue = me.utilsCls.residueName2Abbr(resn);
134076
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
133794
134077
  ic.residueId2Name[residueNum] = residue;
133795
134078
 
133796
134079
  if(serial !== 1 && prevResidueNum !== '') ic.residues[prevResidueNum] = residuesTmp;
@@ -133928,11 +134211,14 @@ class LoadPDB {
133928
134211
  prevCarbonArray.push(atom);
133929
134212
  }
133930
134213
 
134214
+ // remove trailing digits in the residue name, e.g., "Na1" -> "NA"
134215
+ let resnSimple = atom.resn.trim().replace(/\d+$/, '').toUpperCase();
134216
+
133931
134217
  if(atom.resn === 'HOH' || atom.resn === 'WAT' || atom.resn === 'SOL') {
133932
134218
  ic.water[atom.serial] = 1;
133933
134219
  atom.color = me.parasCls.atomColors[atom.elem];
133934
134220
  }
133935
- else if($.inArray(atom.resn.trim(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
134221
+ else if($.inArray(resnSimple, me.parasCls.ionsArray) !== -1 || $.inArray(atom.elem.trim().toUpperCase(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
133936
134222
  ic.ions[atom.serial] = 1;
133937
134223
  atom.color = me.parasCls.atomColors[atom.elem];
133938
134224
  }
@@ -133983,6 +134269,13 @@ class LoadPDB {
133983
134269
  }
133984
134270
  } // end of for
133985
134271
 
134272
+ if(Object.keys(ic.ions).length > 0 && Object.keys(ic.proteins).length == 0 && Object.keys(ic.nucleotides).length == 0 && Object.keys(ic.chemicals).length == 0 && Object.keys(ic.water).length == 0) {
134273
+ for(let serial in ic.ions) {
134274
+ let atom = ic.atoms[serial];
134275
+ me.parasCls.vdwRadii[atom.elem.toUpperCase()] = me.parasCls.ionRadii[atom.elem.toUpperCase()];
134276
+ }
134277
+ }
134278
+
133986
134279
  // last residue
133987
134280
  //refreshBonds();
133988
134281
  this.refreshBonds(curResAtoms, prevCarbonArray[0]);
@@ -134227,7 +134520,7 @@ class LoadPDB {
134227
134520
 
134228
134521
  for(let chainid in chains) {
134229
134522
  if(pdbid !== undefined) {
134230
- let textArray = chainid.split('_');
134523
+ let textArray = me.utilsCls.getIdArray(chainid);
134231
134524
  if(textArray[0] !== pdbid) continue; // skip different chain
134232
134525
  }
134233
134526
 
@@ -134332,7 +134625,20 @@ class LoadCIF {
134332
134625
  return secondarySet.has(resid.substr(resid.indexOf('_') + 1));
134333
134626
  }
134334
134627
 
134335
- loadCIF(bcifData, bcifid, bText, bAppend) { let ic = this.icn3d, me = ic.icn3dui;
134628
+ loadCIF(bcifData, bcifid, bText, bAppend, supercell) { let ic = this.icn3d, me = ic.icn3dui;
134629
+ ic.cifText = bText;
134630
+ ic.cifData = bcifData;
134631
+
134632
+ if(supercell === undefined) {
134633
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134634
+ }
134635
+ else if(supercell === 0) {
134636
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134637
+ }
134638
+ else {
134639
+ CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
134640
+ }
134641
+
134336
134642
  let hAtoms = {};
134337
134643
 
134338
134644
  let bNMR = false;
@@ -134346,7 +134652,7 @@ class LoadCIF {
134346
134652
  let serial, moleculeNum;
134347
134653
  // if(!bMutation && !bAppend) {
134348
134654
  if(!bAppend) {
134349
- ic.init();
134655
+ ic.init(undefined, true); // keep original configurations, such as color, style, etc. when loading multiple structures
134350
134656
  moleculeNum = 0; //1;
134351
134657
  serial = 0;
134352
134658
  }
@@ -134385,17 +134691,18 @@ class LoadCIF {
134385
134691
  helixStart = [];
134386
134692
  helixEnd = [];
134387
134693
 
134388
-
134389
134694
  // bcifData could be binary or text
134390
134695
  let parsed = (bText) ? CIFTools.Text.parse(cifArray[index]) : CIFTools.Binary.parse(cifArray[index]);
134391
134696
 
134392
134697
  if (parsed.isError) {
134393
134698
  // report error:
134394
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
134699
+ var aaa = 1; //alert("2 The Binary CIF data can NOT be parsed: " + parsed.toString());
134395
134700
  return;
134396
134701
  }
134397
134702
 
134398
134703
  let block = parsed.result.dataBlocks[0];
134704
+
134705
+ if(!block) continue;
134399
134706
 
134400
134707
  if(block.getCategory("_entry")) {
134401
134708
  id = block.getCategory("_entry").getColumn("id").getString(0);
@@ -134634,6 +134941,8 @@ class LoadCIF {
134634
134941
  ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
134635
134942
  ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
134636
134943
  ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
134944
+
134945
+ me.htmlCls.clickMenuCls.setLogCmd("define unitcell | " + ic.cell.length_a + " | " + ic.cell.length_b + " | " + ic.cell.length_c + " | " + ic.cell.angle_alpha + " | " + ic.cell.angle_beta + " | " + ic.cell.angle_gamma, true);
134637
134946
  }
134638
134947
 
134639
134948
  // if (record === 'ENDMDL') {
@@ -134978,7 +135287,7 @@ class LoadCIF {
134978
135287
 
134979
135288
  // if(oriResidueNum !== prevOriResidueNum) {
134980
135289
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
134981
- let residue = me.utilsCls.residueName2Abbr(resn);
135290
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
134982
135291
 
134983
135292
  ic.residueId2Name[residueNum] = residue;
134984
135293
 
@@ -135185,17 +135494,19 @@ class LoadCIF {
135185
135494
  }
135186
135495
  }
135187
135496
  else if(atom.het) {
135497
+ let resnSimple = atom.resn.trim().replace(/\d+$/, '').toUpperCase();
135498
+
135188
135499
  if(atom.resn === 'HOH' || atom.resn === 'WAT' || atom.resn === 'SOL') {
135189
135500
  ic.water[atom.serial] = 1;
135190
135501
  }
135191
- else if($.inArray(atom.resn, me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
135502
+ else if($.inArray(resnSimple, me.parasCls.ionsArray) !== -1 || $.inArray(atom.elem.trim().toUpperCase(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
135192
135503
  ic.ions[atom.serial] = 1;
135193
135504
  }
135194
135505
  else {
135195
135506
  ic.chemicals[atom.serial] = 1;
135196
135507
  }
135197
135508
 
135198
- atom.color = me.parasCls.atomColors[atom.elem];
135509
+ atom.color = me.parasCls.atomColors[atom.elem.toUpperCase()];
135199
135510
  }
135200
135511
 
135201
135512
  if(!(curChain === atom.chain && curResi === atom.resi)) {
@@ -135216,6 +135527,13 @@ class LoadCIF {
135216
135527
  }
135217
135528
  } // end of for
135218
135529
 
135530
+ if(Object.keys(ic.ions).length > 0 && Object.keys(ic.proteins).length == 0 && Object.keys(ic.nucleotides).length == 0 && Object.keys(ic.chemicals).length == 0 && Object.keys(ic.water).length == 0) {
135531
+ for(let serial in ic.ions) {
135532
+ let atom = ic.atoms[serial];
135533
+ me.parasCls.vdwRadii[atom.elem.toUpperCase()] = me.parasCls.ionRadii[atom.elem.toUpperCase()];
135534
+ }
135535
+ }
135536
+
135219
135537
  // last residue
135220
135538
  //refreshBonds();
135221
135539
  ic.loadPDBCls.refreshBonds(curResAtoms, prevCarbonArray[0]);
@@ -136268,6 +136586,16 @@ class ApplyCommand {
136268
136586
  ic.opts['unitcell'] = 'no';
136269
136587
  ic.drawCls.draw();
136270
136588
  }
136589
+ else if(command.indexOf('define unitcell') !== -1) {
136590
+ let itemArray = command.split(' | ');
136591
+ ic.cell = {};
136592
+ ic.cell.length_a = parseFloat(itemArray[1]);
136593
+ ic.cell.length_b = parseFloat(itemArray[2]);
136594
+ ic.cell.length_c = parseFloat(itemArray[3]);
136595
+ ic.cell.angle_alpha = parseFloat(itemArray[4]);
136596
+ ic.cell.angle_beta = parseFloat(itemArray[5]);
136597
+ ic.cell.angle_gamma = parseFloat(itemArray[6]);
136598
+ }
136271
136599
  else if(command == 'set fog on') {
136272
136600
  ic.opts['fog'] = 'yes';
136273
136601
  ic.fogCls.setFog(true);
@@ -136294,6 +136622,12 @@ class ApplyCommand {
136294
136622
  else if(command == 'set assembly off') {
136295
136623
  ic.bAssembly = false;
136296
136624
  }
136625
+ else if(command.indexOf('set supercell') !== -1) {
136626
+ let pos = command.lastIndexOf(' ');
136627
+ let supercell = parseInt(command.substr(pos + 1));
136628
+
136629
+ me.htmlCls.clickMenuCls.setSupercell(supercell);
136630
+ }
136297
136631
  else if(command == 'set chemicalbinding show') {
136298
136632
  ic.setOptionCls.setOption('chemicalbinding', 'show');
136299
136633
  }
@@ -136727,7 +137061,8 @@ class ApplyCommand {
136727
137061
  else if(commandOri.indexOf('select interaction') == 0) {
136728
137062
  let idArray = commandOri.substr(commandOri.lastIndexOf(' ') + 1).split(',');
136729
137063
  if(idArray !== null) {
136730
- let mmdbid = idArray[0].split('_')[0];
137064
+ let itemArray = me.utilsCls.getIdArray(idArray[0]);
137065
+ let mmdbid = itemArray[0];
136731
137066
  if(!ic.b2DShown) ic.ParserUtilsCls.download2Ddgm(mmdbid.toUpperCase());
136732
137067
 
136733
137068
  ic.diagram2dCls.selectInteraction(idArray[0], idArray[1]);
@@ -138573,7 +138908,7 @@ class DefinedSets {
138573
138908
 
138574
138909
  }
138575
138910
 
138576
- selectCombinedSets(strSets, commandname) { let ic = this.icn3d; ic.icn3dui;
138911
+ selectCombinedSets(strSets, commandname) { let ic = this.icn3d, me = ic.icn3dui;
138577
138912
  let idArray = strSets.split(' ');
138578
138913
 
138579
138914
  let orArray = [], andArray = [], notArray = [];
@@ -138581,7 +138916,7 @@ class DefinedSets {
138581
138916
 
138582
138917
  for(let i = 0, il = idArray.length; i < il; ++i) {
138583
138918
  // replace 1CD8_A_1 with 1CD8_A1
138584
- let tmpArray = idArray[i].split('_');
138919
+ let tmpArray = me.utilsCls.getIdArray(idArray[i]);
138585
138920
  if(tmpArray.length == 3 && !isNaN(tmpArray[2])) {
138586
138921
  idArray[i] = tmpArray[0] + '_' + tmpArray[1] + tmpArray[2];
138587
138922
  }
@@ -139583,7 +139918,7 @@ class LoadScript {
139583
139918
 
139584
139919
  // load pdb, mmcif, mmdb, cid
139585
139920
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
139586
- if(id.length == 4) id = id.toUpperCase();
139921
+ if(id.length == 4 || id.indexOf('pdb_') == 0) id = id.toUpperCase();
139587
139922
 
139588
139923
  // skip loading the structure if
139589
139924
  // 1. PDB was in the iCn3D PNG Image file
@@ -139630,6 +139965,10 @@ class LoadScript {
139630
139965
  me.cfg.mmcifid = id;
139631
139966
  await ic.mmcifParserCls.downloadMmcif(id);
139632
139967
  }
139968
+ else if(command.indexOf('load cod') !== -1) {
139969
+ me.cfg.codid = id;
139970
+ await ic.mmcifParserCls.downloadCod(id);
139971
+ }
139633
139972
  else if(command.indexOf('load mmdb ') !== -1 || command.indexOf('load mmdb1 ') !== -1) {
139634
139973
  me.cfg.mmdbid = id;
139635
139974
  me.cfg.bu = 1;
@@ -140144,7 +140483,7 @@ class SelectByCommand {
140144
140483
 
140145
140484
  // convert 1TOP_A:20 to $1TOP.A:20
140146
140485
  if(commandArray[i].indexOf('_') !== -1) {
140147
- let itemArray = commandArray[i].split('_');
140486
+ let itemArray = me.utilsCls.getIdArray(commandArray[i]);
140148
140487
  if(itemArray.length ==2 ) {
140149
140488
  commandArray[i] = '$' + itemArray[0] + '.' + itemArray[1];
140150
140489
  }
@@ -140949,7 +141288,7 @@ class Selection {
140949
141288
 
140950
141289
  resetAll() { let ic = this.icn3d, me = ic.icn3dui;
140951
141290
  ic.maxD = ic.oriMaxD;
140952
- ic.center = ic.oriCenter.clone();
141291
+ ic.center = (ic.oriCenter) ? ic.oriCenter.clone() : new THREE.Vector3(0, 0, 0);
140953
141292
 
140954
141293
  ic.opts = me.hashUtilsCls.cloneHash(ic.optsOri);
140955
141294
 
@@ -143025,24 +143364,6 @@ class Dssp {
143025
143364
  if(!me.bNode) console.log("domainid: " + domainid);
143026
143365
  }
143027
143366
 
143028
- // count the number of matched strands
143029
- // let strandHash = {};
143030
- // for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
143031
- // let seg = queryData[0].segs[j];
143032
- // let q_start = parseInt(seg.q_start)
143033
-
143034
- // let strand = this.getStrandFromRefnum(q_start);
143035
- // strandHash[strand] = 1;
143036
- // }
143037
-
143038
- // let tmAdjust = 0.1;
143039
-
143040
- // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
143041
- // if(!domainid2segs.hasOwnProperty(domainid) ||
143042
- // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
143043
- // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
143044
- // ) {
143045
-
143046
143367
  // use TM-score alone
143047
143368
  if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
143048
143369
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res + '_' + queryData[0].score2;
@@ -144374,7 +144695,7 @@ class Scap {
144374
144695
  let snpArray = snp.split(','); //stru_chain_resi_snp
144375
144696
  let atomHash = {}, snpResidArray = [], chainResi2pdb = {};
144376
144697
  for(let i = 0, il = snpArray.length; i < il; ++i) {
144377
- let idArray = snpArray[i].split('_'); //stru_chain_resi_snp
144698
+ let idArray = me.utilsCls.getIdArray(snpArray[i]); //stru_chain_resi_snp
144378
144699
 
144379
144700
  let resid = idArray[0] + '_' + idArray[1] + '_' + idArray[2];
144380
144701
  atomHash = me.hashUtilsCls.unionHash(atomHash, ic.residues[resid]);
@@ -147526,7 +147847,8 @@ class Diagram2d {
147526
147847
  if(refnumLabel) {
147527
147848
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
147528
147849
  if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
147529
- ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
147850
+ let idArray = me.utilsCls.getIdArray(resid);
147851
+ ic.refnum2resn[domainid][refnumStr] = resn + idArray[2];
147530
147852
  }
147531
147853
  }
147532
147854
 
@@ -149026,7 +149348,8 @@ class ResizeCanvas {
149026
149348
  let width = me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
149027
149349
  let height = me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
149028
149350
 
149029
- if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
149351
+ // if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
149352
+ if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height, true, true);
149030
149353
  });
149031
149354
  }
149032
149355
  }
@@ -149254,7 +149577,7 @@ class Transform {
149254
149577
 
149255
149578
  //reset ic.maxD
149256
149579
  ic.maxD = ic.oriMaxD;
149257
- ic.center = ic.oriCenter.clone();
149580
+ ic.center = (ic.oriCenter) ? ic.oriCenter.clone() : new Vector3$1(0, 0, 0);
149258
149581
 
149259
149582
  if(ic.ori_chemicalbinding == 'show') {
149260
149583
  ic.bSkipChemicalbinding = false;
@@ -153776,8 +154099,8 @@ class iCn3D {
153776
154099
  }
153777
154100
  }
153778
154101
  //When users first load a structure, call this function to empty previous settings.
153779
- iCn3D.prototype.init = function (bKeepCmd) {
153780
- this.init_base();
154102
+ iCn3D.prototype.init = function (bKeepCmd, bKeepConfig) {
154103
+ this.init_base(bKeepCmd, bKeepConfig);
153781
154104
 
153782
154105
  this.molTitle = "";
153783
154106
 
@@ -153797,8 +154120,8 @@ iCn3D.prototype.init = function (bKeepCmd) {
153797
154120
  this.axes = [];
153798
154121
  };
153799
154122
 
153800
- iCn3D.prototype.init_base = function (bKeepCmd) {
153801
- this.resetConfig();
154123
+ iCn3D.prototype.init_base = function (bKeepCmd, bKeepConfig) {
154124
+ if(!bKeepConfig) this.resetConfig();
153802
154125
 
153803
154126
  this.structures = {}; // structure name -> array of chains
153804
154127
  this.chains = {}; // structure_chain name -> atom hash
@@ -153988,7 +154311,7 @@ class iCn3DUI {
153988
154311
  //even when multiple iCn3D viewers are shown together.
153989
154312
  this.pre = this.cfg.divid + "_";
153990
154313
 
153991
- this.REVISION = '3.54.2';
154314
+ this.REVISION = '3.54.4';
153992
154315
 
153993
154316
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
153994
154317
  this.bNode = (Object.keys(window).length < 3) ? true : false;
@@ -154190,7 +154513,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154190
154513
  let domainidArray = me.cfg.matchedchains.split(',');
154191
154514
  let chainidArray = [];
154192
154515
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
154193
- let idArray = domainidArray[i].split('_');
154516
+ let idArray = me.utilsCls.getIdArray(domainidArray[i]);
154194
154517
  chainidArray.push(idArray[0] + '_' + idArray[1]);
154195
154518
  }
154196
154519
 
@@ -154233,14 +154556,14 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154233
154556
  await ic.pdbParserCls.downloadUrl(url, type, me.cfg.command);
154234
154557
  }
154235
154558
  else if(me.cfg.mmtfid !== undefined) {
154236
- if(me.cfg.mmtfid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.mmtfid = me.cfg.mmtfid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154559
+ // if(me.cfg.mmtfid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.mmtfid = me.cfg.mmtfid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154237
154560
  ic.inputid = me.cfg.mmtfid;
154238
154561
  ic.loadCmd = 'load mmtf ' + me.cfg.mmtfid;
154239
154562
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154240
154563
  await ic.bcifParserCls.downloadBcif(me.cfg.mmtfid);
154241
154564
  }
154242
154565
  else if(me.cfg.bcifid !== undefined) {
154243
- if(me.cfg.bcifid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.bcifid = me.cfg.bcifid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154566
+ // if(me.cfg.bcifid.toLowerCase().substr(0,8) == 'pdb_0000') me.cfg.bcifid = me.cfg.bcifid.substr(8); // temperary support long PDB ID such as pdb_00001tup
154244
154567
  ic.inputid = me.cfg.bcifid;
154245
154568
  ic.loadCmd = 'load bcif ' + me.cfg.bcifid;
154246
154569
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -154415,6 +154738,12 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
154415
154738
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154416
154739
  await ic.mmcifParserCls.downloadMmcif(me.cfg.mmcifid);
154417
154740
  }
154741
+ else if(me.cfg.codid !== undefined) {
154742
+ ic.inputid = me.cfg.codid;
154743
+ ic.loadCmd = 'load cod ' + me.cfg.codid;
154744
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
154745
+ await ic.mmcifParserCls.downloadCod(me.cfg.codid);
154746
+ }
154418
154747
  else if(me.cfg.align !== undefined) {
154419
154748
  // ic.bNCBI = true;
154420
154749
  if(me.cfg.align.indexOf('185055,') != -1) {
@@ -154575,6 +154904,8 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
154575
154904
 
154576
154905
  reject('error');
154577
154906
  }
154907
+
154908
+ me.icn3d.ParserUtilsCls.hideLoading();
154578
154909
  }
154579
154910
  else {
154580
154911
  me.icn3d.ParserUtilsCls.showLoading();
@@ -154727,18 +155058,6 @@ iCn3DUI.prototype.setDialogAjax = function() { let me = this;
154727
155058
  });
154728
155059
  };
154729
155060
 
154730
- /*
154731
- iCn3DUI.prototype.setIcn3dui = function(id) { let me = this;
154732
- let idArray = id.split('_'); // id: div0_reload_pdbfile
154733
- ic.pre = idArray[0] + "_";
154734
- if(window.icn3duiHash !== undefined && window.icn3duiHash.hasOwnProperty(idArray[0])) { // for multiple 3D display
154735
- me = window.icn3duiHash[idArray[0]];
154736
- }
154737
- return me;
154738
- };
154739
- */
154740
-
154741
-
154742
155061
  // required by npm
154743
155062
  class printMsg {
154744
155063
  constructor() {