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.module.js CHANGED
@@ -172,7 +172,8 @@ $NGL_shaderTextHash['SphereImpostor.frag'] = ["#define STANDARD",
172
172
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
173
173
  " #endif",
174
174
  " #ifdef FOG_EXP2",
175
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
175
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
176
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
176
177
  " #else",
177
178
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
178
179
  " #endif",
@@ -636,7 +637,8 @@ $NGL_shaderTextHash['CylinderImpostor.frag'] = ["#define STANDARD",
636
637
  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
637
638
  " #endif",
638
639
  " #ifdef FOG_EXP2",
639
- " float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
640
+ " //float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );",
641
+ " float fogFactor = ( 1.0 - exp2( - fogDensity * fogDensity * depth * depth * 1.442695 ) );",
640
642
  " #else",
641
643
  " float fogFactor = smoothstep( fogNear, fogFar, depth );",
642
644
  " #endif",
@@ -2603,6 +2605,105 @@ var CIFTools;
2603
2605
  return out;
2604
2606
  };
2605
2607
  }
2608
+ /**
2609
+ * Options for filling the unit cell of a core CIF by lattice translation
2610
+ * (applied after the symmetry operators have generated the contents of one cell).
2611
+ * nx, ny, nz : number of unit cells along a, b, c (supercell); default 1 1 1
2612
+ * wholeMolecules : keep every molecule / discrete chemical species intact. Atoms are grouped into
2613
+ * bonded fragments (covalent radii + bondTolerance, periodic), each fragment is
2614
+ * "unwrapped" so that it is contiguous (it may stick out of the unit cell), and the
2615
+ * fragment is placed in the cell that contains its centre. Fragments that are
2616
+ * infinite (chains, layers, frameworks, ionic lattices such as NaCl) cannot be made
2617
+ * whole and are handled as before (wrapped into the cell, see 'boundary'). default true
2618
+ * bondTolerance : extra distance (Angstrom) added to the sum of covalent radii when detecting bonds; default 0.4
2619
+ * boundary : for atoms that are NOT part of a whole molecule, also emit the periodic image of every
2620
+ * atom lying on a cell face/edge/corner (e.g. NaCl -> 14 Na + 13 Cl instead of 4 Na + 4 Cl);
2621
+ * default true.
2622
+ * Usage (before loading the file): CIFTools.Text.coreCifOptions = {nx: 2, ny: 2, nz: 2, wholeMolecules: true};
2623
+ */
2624
+ Text.coreCifOptions = {
2625
+ nx: 1, ny: 1, nz: 1,
2626
+ wholeMolecules: true, // new; set false for the old wrapped behaviour
2627
+ bondTolerance: 0.4, // new; raise it if bonds are missed, lower it if unrelated atoms get joined, default 0.4
2628
+ boundary: true
2629
+ };
2630
+ // covalent radii (Angstrom, Cordero et al. 2008) used for bond detection
2631
+ var coreCovRadii = { H: 0.31, D: 0.31, He: 0.28, Li: 1.28, Be: 0.96, B: 0.84, C: 0.76, N: 0.71, O: 0.66, F: 0.57, Ne: 0.58,
2632
+ Na: 1.66, Mg: 1.41, Al: 1.21, Si: 1.11, P: 1.07, S: 1.05, Cl: 1.02, Ar: 1.06, K: 2.03, Ca: 1.76, Sc: 1.70, Ti: 1.60, V: 1.53,
2633
+ Cr: 1.39, Mn: 1.39, Fe: 1.32, Co: 1.26, Ni: 1.24, Cu: 1.32, Zn: 1.22, Ga: 1.22, Ge: 1.20, As: 1.19, Se: 1.20, Br: 1.20, Kr: 1.16,
2634
+ Rb: 2.20, Sr: 1.95, Y: 1.90, Zr: 1.75, Nb: 1.64, Mo: 1.54, Tc: 1.47, Ru: 1.46, Rh: 1.42, Pd: 1.39, Ag: 1.45, Cd: 1.44, In: 1.42,
2635
+ Sn: 1.39, Sb: 1.39, Te: 1.38, I: 1.39, Xe: 1.40, Cs: 2.44, Ba: 2.15, La: 2.07, Ce: 2.04, Pr: 2.03, Nd: 2.01, Sm: 1.98, Eu: 1.98,
2636
+ Gd: 1.96, Tb: 1.94, Dy: 1.92, Ho: 1.92, Er: 1.89, Tm: 1.90, Yb: 1.87, Lu: 1.87, Hf: 1.75, Ta: 1.70, W: 1.62, Re: 1.51, Os: 1.44,
2637
+ Ir: 1.41, Pt: 1.36, Au: 1.36, Hg: 1.32, Tl: 1.45, Pb: 1.46, Bi: 1.48 };
2638
+ // g: fractional coordinates wrapped into [0,1). Returns all translated copies of g.
2639
+ function coreLatticeImages(g, nx, ny, nz, bBoundary) {
2640
+ var eps = 1e-3, n = [nx, ny, nz], ranges = [], out = [], k, i, r, x, y, z;
2641
+ for (k = 0; k < 3; k++) {
2642
+ r = [];
2643
+ for (i = 0; i < n[k]; i++) r.push(g[k] + i);
2644
+ if (bBoundary && Math.abs(g[k]) < eps) r.push(g[k] + n[k]); // atom on the 0-face also sits on the far face
2645
+ ranges.push(r);
2646
+ }
2647
+ for (x = 0; x < ranges[0].length; x++)
2648
+ for (y = 0; y < ranges[1].length; y++)
2649
+ for (z = 0; z < ranges[2].length; z++)
2650
+ out.push([ranges[0][x], ranges[1][y], ranges[2][z]]);
2651
+ return out;
2652
+ }
2653
+ /**
2654
+ * Group atoms (fractional coordinates wrapped into the cell) into bonded fragments, taking periodic
2655
+ * images into account. Every atom of a fragment gets an integer lattice translation T so that
2656
+ * (g + T) forms a contiguous molecule. A fragment that reaches its own periodic image
2657
+ * (chain / layer / framework) is flagged as infinite.
2658
+ * atoms : [{el, g:[fx,fy,fz]}] toCart : fractional -> Cartesian (linear part only)
2659
+ * h : interplanar spacings of the cell along a, b, c tol : bond tolerance (Angstrom)
2660
+ */
2661
+ function coreFindMolecules(atoms, toCart, h, tol) {
2662
+ var N = atoms.length, nb = [], rad = [], i, j, k, e, m, q;
2663
+ for (i = 0; i < N; i++) { nb.push([]); rad.push(coreCovRadii[atoms[i].el] || 1.5); }
2664
+ for (i = 0; i < N; i++) {
2665
+ for (j = i; j < N; j++) {
2666
+ var d = [atoms[j].g[0] - atoms[i].g[0], atoms[j].g[1] - atoms[i].g[1], atoms[j].g[2] - atoms[i].g[2]];
2667
+ var rc = rad[i] + rad[j] + tol, cand = [[], [], []], dt, t;
2668
+ for (k = 0; k < 3; k++) {
2669
+ var base = -Math.round(d[k]);
2670
+ for (dt = -1; dt <= 1; dt++) {
2671
+ t = base + dt;
2672
+ if (Math.abs(d[k] + t) * h[k] <= rc) cand[k].push(t);
2673
+ }
2674
+ }
2675
+ for (var a = 0; a < cand[0].length; a++) for (var b = 0; b < cand[1].length; b++) for (var c = 0; c < cand[2].length; c++) {
2676
+ var tv = [cand[0][a], cand[1][b], cand[2][c]];
2677
+ if (i === j) { // bond to own image: record each translation pair only once
2678
+ if (tv[0] === 0 && tv[1] === 0 && tv[2] === 0) continue;
2679
+ if (tv[0] < 0 || (tv[0] === 0 && (tv[1] < 0 || (tv[1] === 0 && tv[2] < 0)))) continue;
2680
+ }
2681
+ var cc = toCart([d[0] + tv[0], d[1] + tv[1], d[2] + tv[2]]);
2682
+ var d2 = cc[0] * cc[0] + cc[1] * cc[1] + cc[2] * cc[2];
2683
+ if (d2 < rc * rc && d2 > 0.25) { // > 0.5 A: closer atoms are disorder alternatives, not bonds
2684
+ nb[i].push({ j: j, t: tv });
2685
+ nb[j].push({ j: i, t: [-tv[0], -tv[1], -tv[2]] });
2686
+ }
2687
+ }
2688
+ }
2689
+ }
2690
+ var T = new Array(N), comps = [], s, queue, members, infinite, cur, tj, o;
2691
+ for (s = 0; s < N; s++) {
2692
+ if (T[s]) continue;
2693
+ T[s] = [0, 0, 0]; queue = [s]; members = [s]; infinite = false;
2694
+ for (q = 0; q < queue.length; q++) {
2695
+ cur = queue[q];
2696
+ for (e = 0; e < nb[cur].length; e++) {
2697
+ o = nb[cur][e];
2698
+ tj = [T[cur][0] + o.t[0], T[cur][1] + o.t[1], T[cur][2] + o.t[2]];
2699
+ if (!T[o.j]) { T[o.j] = tj; queue.push(o.j); members.push(o.j); }
2700
+ else if (T[o.j][0] !== tj[0] || T[o.j][1] !== tj[1] || T[o.j][2] !== tj[2]) infinite = true;
2701
+ }
2702
+ }
2703
+ comps.push({ members: members, infinite: infinite });
2704
+ }
2705
+ return { T: T, comps: comps };
2706
+ }
2606
2707
  function convertCoreCif(data) {
2607
2708
  var tk = coreTokens(data), i = 0, n = tk.length, single = {}, loops = [], name = 'data_core', t, cols, rows, cur;
2608
2709
  function isTag(x) { return x && !x.t && x.v.charAt(0) === '_'; }
@@ -2656,7 +2757,21 @@ var CIFTools;
2656
2757
  '_atom_site.label_comp_id', '_atom_site.label_asym_id', '_atom_site.label_entity_id', '_atom_site.label_seq_id',
2657
2758
  '_atom_site.Cartn_x', '_atom_site.Cartn_y', '_atom_site.Cartn_z', '_atom_site.occupancy', '_atom_site.B_iso_or_equiv',
2658
2759
  '_atom_site.auth_seq_id', '_atom_site.auth_asym_id', '_atom_site.pdbx_PDB_model_num');
2659
- var serial = 0, seen = [], r, s, f, g, k, dup, j, sym, el, lab, cart;
2760
+ var serial = 0, r, s, f, g, k, dup, j, sym, el, lab, cart;
2761
+ var o = Text.coreCifOptions || {}, images, im;
2762
+ var opt = {
2763
+ nx: Math.max(1, parseInt(o.nx) || 1), ny: Math.max(1, parseInt(o.ny) || 1), nz: Math.max(1, parseInt(o.nz) || 1),
2764
+ boundary: (o.boundary === undefined) ? true : !!o.boundary,
2765
+ wholeMolecules: (o.wholeMolecules === undefined) ? true : !!o.wholeMolecules,
2766
+ bondTolerance: (o.bondTolerance === undefined || isNaN(parseFloat(o.bondTolerance))) ? 0.4 : parseFloat(o.bondTolerance)
2767
+ };
2768
+ function emit(at, frac) {
2769
+ var cart = toCart(frac);
2770
+ out.push(['HETATM', ++serial, at.el, at.lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2771
+ at.occ, '0.00', 1, 'A', 1].join(' '));
2772
+ }
2773
+ // 1) all symmetry-generated atoms of one cell, wrapped into [0,1)
2774
+ var list = [];
2660
2775
  for (r = 0; r < atoms.rows.length; r++) {
2661
2776
  var row = atoms.rows[r];
2662
2777
  if (get(row, '_atom_site_calc_flag') === 'dum') continue; // dummy atoms
@@ -2665,6 +2780,7 @@ var CIFTools;
2665
2780
  sym = get(row, '_atom_site_type_symbol'); if (sym === '?') sym = lab;
2666
2781
  el = (sym.match(/^[A-Za-z]{1,2}/) || ['X'])[0];
2667
2782
  el = el.charAt(0).toUpperCase() + el.substr(1).toLowerCase();
2783
+ var occ = coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy'));
2668
2784
  var mySeen = [];
2669
2785
  for (s = 0; s < symops.length; s++) {
2670
2786
  g = symops[s](f).map(function (v) { return v - Math.floor(v + 1e-6); });
@@ -2674,9 +2790,49 @@ var CIFTools;
2674
2790
  }
2675
2791
  if (dup) continue;
2676
2792
  mySeen.push(g);
2677
- cart = toCart(g);
2678
- out.push(['HETATM', ++serial, el, lab, '.', 'MOL', 'A', 1, '.', cart[0].toFixed(3), cart[1].toFixed(3), cart[2].toFixed(3),
2679
- coreToNumber(get(row, '_atom_site_occupancy') === '?' ? 1 : get(row, '_atom_site_occupancy')), '0.00', 1, 'A', 1].join(' '));
2793
+ list.push({ el: el, lab: lab, occ: occ, g: g });
2794
+ }
2795
+ }
2796
+ // 2) emit them, either as whole molecules or simply wrapped into the cell
2797
+ var mol = null;
2798
+ if (opt.wholeMolecules && list.length) {
2799
+ var Vc = a * b * cc * vol, sinal = Math.sqrt(1 - cosa * cosa), sinbe = Math.sqrt(1 - cosb * cosb);
2800
+ var hh = [Vc / (b * cc * sinal), Vc / (a * cc * sinbe), Vc / (a * b * sing)];
2801
+ if (isFinite(hh[0] + hh[1] + hh[2]) && hh[0] > 0 && hh[1] > 0 && hh[2] > 0) mol = coreFindMolecules(list, toCart, hh, opt.bondTolerance);
2802
+ }
2803
+ var ci, m, at, ix, iy, iz, mean, shift;
2804
+ if (mol) {
2805
+ for (ci = 0; ci < mol.comps.length; ci++) {
2806
+ var comp = mol.comps[ci];
2807
+ if (comp.infinite) { // cannot be made whole: wrap into the cell as before
2808
+ for (m = 0; m < comp.members.length; m++) {
2809
+ at = list[comp.members[m]];
2810
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2811
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2812
+ }
2813
+ continue;
2814
+ }
2815
+ // contiguous molecule: place it in the cell that holds its centre, keep all atoms together
2816
+ mean = [0, 0, 0];
2817
+ for (m = 0; m < comp.members.length; m++) {
2818
+ at = list[comp.members[m]];
2819
+ for (k = 0; k < 3; k++) mean[k] += (at.g[k] + mol.T[comp.members[m]][k]) / comp.members.length;
2820
+ }
2821
+ shift = [-Math.floor(mean[0] + 1e-6), -Math.floor(mean[1] + 1e-6), -Math.floor(mean[2] + 1e-6)];
2822
+ for (ix = 0; ix < opt.nx; ix++) for (iy = 0; iy < opt.ny; iy++) for (iz = 0; iz < opt.nz; iz++) {
2823
+ for (m = 0; m < comp.members.length; m++) {
2824
+ at = list[comp.members[m]];
2825
+ var tt = mol.T[comp.members[m]];
2826
+ emit(at, [at.g[0] + tt[0] + shift[0] + ix, at.g[1] + tt[1] + shift[1] + iy, at.g[2] + tt[2] + shift[2] + iz]);
2827
+ }
2828
+ }
2829
+ }
2830
+ }
2831
+ else {
2832
+ for (m = 0; m < list.length; m++) {
2833
+ at = list[m];
2834
+ images = coreLatticeImages(at.g, opt.nx, opt.ny, opt.nz, opt.boundary);
2835
+ for (im = 0; im < images.length; im++) emit(at, images[im]);
2680
2836
  }
2681
2837
  }
2682
2838
  out.push('#');
@@ -2977,7 +3133,7 @@ var CIFTools;
2977
3133
  // This approach to binary parsing wastes a bit of memory to trade for speed compared to:
2978
3134
  //
2979
3135
  // let value = buffer.subarray(offset, offset + length); //new Uint8Array(buffer.buffer, offset, length);
2980
- //
3136
+ //
2981
3137
  // It turns out that using the view created by subarray probably uses DataView
2982
3138
  // in the background, which causes the element access to be several times slower
2983
3139
  // than creating the new byte array.
@@ -4301,7 +4457,7 @@ var CIFTools;
4301
4457
  if (index === void 0) {
4302
4458
  // increment the length
4303
4459
  accLength += s.length;
4304
- // store the string and index
4460
+ // store the string and index
4305
4461
  index = strings.length;
4306
4462
  strings[index] = s;
4307
4463
  map[s] = index;
@@ -56270,7 +56426,7 @@ class UtilsCls {
56270
56426
  }
56271
56427
 
56272
56428
  //Convert a three-letter residue name to a one-letter residue abbreviation, e.g., 'LYS' to 'K', or ' A' to 'A' for nucleotides.
56273
- residueName2Abbr(residueName) { this.icn3dui;
56429
+ residueName2Abbr(residueName, bOneLetter) { this.icn3dui;
56274
56430
  let pos = residueName.indexOf(' ');
56275
56431
  if(pos > 0) {
56276
56432
  residueName = residueName.substr(0, pos);
@@ -56365,7 +56521,12 @@ class UtilsCls {
56365
56521
  return 'O';
56366
56522
 
56367
56523
  default:
56368
- return residueName.trim();
56524
+ if(bOneLetter) {
56525
+ return 'X';
56526
+ }
56527
+ else {
56528
+ return residueName.trim();
56529
+ }
56369
56530
  }
56370
56531
  }
56371
56532
 
@@ -56441,15 +56602,20 @@ class UtilsCls {
56441
56602
  }
56442
56603
 
56443
56604
  getIdArray(resid) { this.icn3dui;
56444
- //var idArray = resid.split('_');
56445
56605
  let idArray = [];
56446
56606
 
56447
56607
  if(resid) {
56448
- let pos1 = resid.indexOf('_');
56449
- let pos2 = resid.lastIndexOf('_');
56450
- idArray.push(resid.substr(0, pos1));
56451
- idArray.push(resid.substr(pos1 + 1, pos2 - pos1 - 1));
56452
- idArray.push(resid.substr(pos2 + 1));
56608
+ let itemArray = resid.split('_');
56609
+
56610
+ if(resid.indexOf('pdb_') == 0 ) { // e.g., pdb_00001GPK_A_15
56611
+ idArray.push(itemArray[0] + '_' + itemArray[1]);
56612
+ for(let i = 2, il = itemArray.length; i < il; ++i) {
56613
+ idArray.push(itemArray[i]);
56614
+ }
56615
+ }
56616
+ else {
56617
+ idArray = itemArray;
56618
+ }
56453
56619
  }
56454
56620
 
56455
56621
  return idArray;
@@ -56460,12 +56626,12 @@ class UtilsCls {
56460
56626
  let bArray = b.split(',');
56461
56627
  let aIdArray, bIdArray;
56462
56628
  if(type == 'save1') {
56463
- aIdArray = me.utilsCls.getIdArray(aArray[0]); //aArray[0].split('_');
56464
- bIdArray = me.utilsCls.getIdArray(bArray[0]); //bArray[0].split('_');
56629
+ aIdArray = me.utilsCls.getIdArray(aArray[0]);
56630
+ bIdArray = me.utilsCls.getIdArray(bArray[0]);
56465
56631
  }
56466
56632
  else if(type == 'save2') {
56467
- aIdArray = me.utilsCls.getIdArray(aArray[1]); //aArray[1].split('_');
56468
- bIdArray = me.utilsCls.getIdArray(bArray[1]); //bArray[1].split('_');
56633
+ aIdArray = me.utilsCls.getIdArray(aArray[1]);
56634
+ bIdArray = me.utilsCls.getIdArray(bArray[1]);
56469
56635
  }
56470
56636
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
56471
56637
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
@@ -56775,6 +56941,29 @@ class ParasCls {
56775
56941
  CM: 1.69
56776
56942
  };
56777
56943
 
56944
+ this.ionRadii = { // https://en.wikipedia.org/wiki/Ionic_radius
56945
+ H: 1.40, HE: 0.28, LI: 0.76, BE: 0.45, B: 0.27,
56946
+ C: 0.16, N: 1.46, O: 1.40, F: 1.33, NE: 0.58,
56947
+ NA: 1.02, MG: 0.72, AL: 0.54, SI: 0.40, P: 0.38,
56948
+ S: 1.84, CL: 1.81, AR: 1.06, K: 1.38, CA: 1.00,
56949
+ SC: 0.75, TI: 0.86, V: 0.79, CR: 0.73, MN: 0.67,
56950
+ FE: 0.55, CO: 0.65, NI: 0.69, CU: 0.73, ZN: 0.74,
56951
+ GA: 0.62, GE: 0.73, AS: 0.58, SE: 1.98, BR: 1.96,
56952
+ KR: 1.16, RB: 1.52, SR: 1.18, Y: 0.90, ZR: 0.72,
56953
+ NB: 0.72, MO: 0.69, TC: 0.65, RU: 0.68, RH: 0.67,
56954
+ PD: 0.86, AG: 1.15, CD: 0.95, IN: 0.80, SN: 1.02,
56955
+ SB: 0.76, TE: 0.97, I: 2.20, XE: 0.48, CS: 1.67,
56956
+ BA: 1.35, LA: 1.03, CE: 1.01, PR: 0.99, ND: 1.29,
56957
+ PM: 0.97, SM: 1.22, EU: 1.17, GD: 0.94, TB: 0.92,
56958
+ DY: 1.07, HO: 0.90, ER: 0.89, TM: 1.03, YB: 1.02,
56959
+ LU: 0.86, HF: 0.71, TA: 0.72, W: 0.66, RE: 0.63,
56960
+ OS: 0.63, IR: 0.68, PT: 0.80, AU: 1.37, HG: 1.19,
56961
+ TL: 1.50, PB: 1.19, BI: 1.03, PO: 0.94, AT: 0.62,
56962
+ RN: 1.50, FR: 1.80, RA: 1.48, AC: 1.07, TH: 0.94,
56963
+ PA: 1.04, U: 1.03, NP: 1.10, PU: 1.00, AM: 1.26,
56964
+ CM: 0.97
56965
+ };
56966
+
56778
56967
  /*
56779
56968
  this.surfaces = {
56780
56969
  1: undefined,
@@ -58357,6 +58546,9 @@ class ClickMenu {
58357
58546
  me.myEventCls.onIds("#" + me.pre + "mn1_mmcifid", "click", function(e) { me.icn3d; //e.preventDefault();
58358
58547
  me.htmlCls.dialogCls.openDlg('dl_mmcifid', 'Please input mmCIF ID');
58359
58548
  });
58549
+ me.myEventCls.onIds("#" + me.pre + "mn1_codid", "click", function(e) { me.icn3d; //e.preventDefault();
58550
+ me.htmlCls.dialogCls.openDlg('dl_codid', 'Please input COD ID');
58551
+ });
58360
58552
 
58361
58553
  me.myEventCls.onIds("#" + me.pre + "mn1_mmdbid", "click", function(e) { me.icn3d; //e.preventDefault();
58362
58554
  me.htmlCls.dialogCls.openDlg('dl_mmdbid', 'Please input MMDB or PDB ID');
@@ -58896,7 +59088,7 @@ class ClickMenu {
58896
59088
  thisClass.setLogCmd("link to compounds with structure similar to CID " + ic.inputid + ": " + url, false);
58897
59089
  }
58898
59090
  else {
58899
- let idArray = ic.inputid.split('_');
59091
+ let idArray = me.utilsCls.getIdArray(ic.inputid);
58900
59092
 
58901
59093
  if(idArray.length === 1) {
58902
59094
  url = me.htmlCls.baseUrl + "vastplus/vastplus.cgi?uid=" + ic.inputid;
@@ -59958,6 +60150,16 @@ class ClickMenu {
59958
60150
 
59959
60151
  }
59960
60152
 
60153
+ setSupercell(n) { let me = this.icn3dui, ic = me.icn3d;
60154
+ if(ic.cifData) {
60155
+ ic.loadCIFCls.loadCIF(ic.cifData, undefined, ic.cifText, false, n);
60156
+
60157
+ ic.setStyleCls.setAtomStyleByOptions(ic.opts);
60158
+ ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
60159
+ ic.drawCls.draw();
60160
+ }
60161
+ }
60162
+
59961
60163
  clickMenu6() { let me = this.icn3dui, ic = me.icn3d;
59962
60164
  if(me.bNode) return;
59963
60165
 
@@ -59975,6 +60177,23 @@ class ClickMenu {
59975
60177
  ic.drawCls.draw();
59976
60178
  });
59977
60179
 
60180
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly0", "click", function(e) { me.icn3d; //e.preventDefault();
60181
+ thisClass.setSupercell(0);
60182
+ thisClass.setLogCmd('set supercell 0', true);
60183
+ });
60184
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly1", "click", function(e) { me.icn3d; //e.preventDefault();
60185
+ thisClass.setSupercell(1);
60186
+ thisClass.setLogCmd('set supercell 1', true);
60187
+ });
60188
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly2", "click", function(e) { me.icn3d; //e.preventDefault();
60189
+ thisClass.setSupercell(2);
60190
+ thisClass.setLogCmd('set supercell 2', true);
60191
+ });
60192
+ me.myEventCls.onIds("#" + me.pre + "mn6_assembly3", "click", function(e) { me.icn3d; //e.preventDefault();
60193
+ thisClass.setSupercell(3);
60194
+ thisClass.setLogCmd('set supercell 3', true);
60195
+ });
60196
+
59978
60197
  me.myEventCls.onIds("#" + me.pre + "mn6_igrefYes", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
59979
60198
  ic.bRunRefnumAgain = true;
59980
60199
 
@@ -61329,6 +61548,7 @@ class SetMenu {
61329
61548
  html += this.getLink('mn1_opmid', 'OPM PDB ID ' + me.htmlCls.wifiStr, undefined, 2);
61330
61549
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
61331
61550
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
61551
+ // html += this.getLink('mn1_codid', 'COD ID ' + me.htmlCls.wifiStr, 1, 2);
61332
61552
 
61333
61553
  html += this.getLink('mn1_cid', 'PubChem CID/Name/InChI ' + me.htmlCls.wifiStr, 1, 2);
61334
61554
  html += this.getLink('mn1_smiles', 'Chemical SMILES ', undefined, 2);
@@ -62569,13 +62789,20 @@ class SetMenu {
62569
62789
 
62570
62790
  html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
62571
62791
 
62572
- 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;
62792
+ let bInputid = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
62573
62793
 
62574
- if(bOnePdb) {
62794
+ //if(bInputid) {
62575
62795
  html += this.getMenuText('assemblyWrapper', 'Assembly', undefined, 1, 1);
62576
62796
  html += "<ul>";
62577
62797
 
62578
- if(!me.cfg.bu) {
62798
+ if(!bInputid || me.cfg.mmcifid !== undefined || me.cfg.bcifid !== undefined || me.cfg.mmtfid !== undefined) { // e.g., cif file input
62799
+ html += this.getRadio('mn6_assembly', 'mn6_assembly0', 'Biological Assembly', undefined, 1, 2);
62800
+ html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', undefined, 1, 2);
62801
+ html += this.getRadio('mn6_assembly', 'mn6_assembly1', '1 x 1 x 1', true, 1, 2);
62802
+ html += this.getRadio('mn6_assembly', 'mn6_assembly2', '2 x 2 x 2', undefined, undefined, 2);
62803
+ html += this.getRadio('mn6_assembly', 'mn6_assembly3', '3 x 3 x 3', undefined, 1, 2);
62804
+ }
62805
+ else if(!me.cfg.bu) {
62579
62806
  html += this.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly', undefined, 1, 2);
62580
62807
  html += this.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', true, 1, 2);
62581
62808
  }
@@ -62586,12 +62813,12 @@ class SetMenu {
62586
62813
 
62587
62814
  html += "</ul>";
62588
62815
  html += "</li>";
62589
- }
62816
+ //}
62590
62817
 
62591
62818
  html += this.getMenuText('mn6_symmetrywrap', 'Symmetry', undefined, undefined, 1);
62592
62819
 
62593
62820
  html += "<ul>";
62594
- if(bOnePdb) html += this.getLink('mn6_symmetry', 'from PDB(precalculated) ' + me.htmlCls.wifiStr, undefined, 2);
62821
+ if(bInputid) html += this.getLink('mn6_symmetry', 'from PDB(precalculated) ' + me.htmlCls.wifiStr, undefined, 2);
62595
62822
 
62596
62823
  html += this.getLink('mn6_symd', 'from SymD(Dynamic) ' + me.htmlCls.wifiStr, undefined, 2);
62597
62824
  html += this.getLink('mn6_clear_sym', 'Clear SymD Symmetry', undefined, 2);
@@ -63828,6 +64055,12 @@ class SetDialog {
63828
64055
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
63829
64056
  html += "</div>";
63830
64057
 
64058
+ html += me.htmlCls.divStr + "dl_codid' class='" + dialogClass + "'>";
64059
+ html += this.addNotebookTitle('dl_codid', 'Please input a COD ID');
64060
+ html += "COD ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "codid' value='1000041' size=8> ";
64061
+ html += me.htmlCls.buttonStr + "reload_cod'>Load</button>";
64062
+ html += "</div>";
64063
+
63831
64064
  html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
63832
64065
  html += this.addNotebookTitle('dl_mmdbid', 'Please input an MMDB ID');
63833
64066
  html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
@@ -65324,7 +65557,7 @@ class Events {
65324
65557
  }
65325
65558
  }
65326
65559
 
65327
- async readFile(bAppend, files, index, dataStrAll, bmmCIF, bPng) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
65560
+ async readFile(bAppend, files, index, dataStrAll, bmmCIF, bPng, fileType) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
65328
65561
  let file = files[index];
65329
65562
  let commandName = (bAppend) ? 'append': 'load';
65330
65563
  commandName += (bmmCIF) ? ' mmcif file ' : (bPng) ? ' png file ' : ' pdb file ';
@@ -65374,7 +65607,7 @@ class Events {
65374
65607
  ic.dAtoms = {};
65375
65608
  }
65376
65609
  if(bmmCIF) {
65377
- await ic.mmcifParserCls.loadMultipleMmcifData(dataStrAll, undefined, bAppend);
65610
+ await ic.mmcifParserCls.loadMultipleMmcifData(dataStrAll, undefined, bAppend, fileType);
65378
65611
  }
65379
65612
  else {
65380
65613
  await ic.pdbParserCls.loadPdbData(dataStrAll, undefined, undefined, bAppend);
@@ -65400,7 +65633,12 @@ class Events {
65400
65633
  };
65401
65634
 
65402
65635
  if (typeof file === "object") {
65403
- reader.readAsText(file);
65636
+ if(bmmCIF && fileType == 'bcif') {
65637
+ reader.readAsArrayBuffer(file);
65638
+ }
65639
+ else {
65640
+ reader.readAsText(file);
65641
+ }
65404
65642
  }
65405
65643
  }
65406
65644
 
@@ -65485,7 +65723,7 @@ class Events {
65485
65723
  let idArray = ids.split(',');
65486
65724
 
65487
65725
  if(!bAppend) {
65488
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
65726
+ if(idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
65489
65727
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
65490
65728
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65491
65729
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65497,8 +65735,8 @@ class Events {
65497
65735
  }
65498
65736
  }
65499
65737
  else {
65500
- // single MMDB ID could show memebranes
65501
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
65738
+ // single MMDB ID could show membranes
65739
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || idArray[0].indexOf('pdb_') == 0 || !isNaN(idArray[0])) ) {
65502
65740
  thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
65503
65741
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65504
65742
  window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
@@ -65986,7 +66224,7 @@ class Events {
65986
66224
  if(!me.cfg.notebook) dialog.dialog( "close" );
65987
66225
  thisClass.setLogCmd("load mmtf " + $("#" + me.pre + "mmtfid").val(), false);
65988
66226
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
65989
- window.open(hostUrl + '?mmtfid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
66227
+ window.open(hostUrl + '?bcifid=' + $("#" + me.pre + "mmtfid").val(), urlTarget);
65990
66228
  }
65991
66229
  });
65992
66230
 
@@ -66330,7 +66568,7 @@ class Events {
66330
66568
  await ic.scapCls.retrieveScap(snp, bInteraction);
66331
66569
  thisClass.setLogCmd('scap interaction ' + snp, true);
66332
66570
 
66333
- let idArray = snp.split('_'); //stru_chain_resi_snp
66571
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
66334
66572
  let select = '.' + idArray[1] + ':' + idArray[2];
66335
66573
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
66336
66574
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -66369,7 +66607,6 @@ class Events {
66369
66607
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66370
66608
  window.open(hostUrl + '?mmcifid=' + $("#" + me.pre + "mmcifid").val(), urlTarget);
66371
66609
  });
66372
-
66373
66610
  me.myEventCls.onIds("#" + me.pre + "mmcifid", "keyup", function(e) { let ic = me.icn3d;
66374
66611
  if (e.keyCode === 13) {
66375
66612
  e.preventDefault();
@@ -66380,6 +66617,23 @@ class Events {
66380
66617
  }
66381
66618
  });
66382
66619
 
66620
+ me.myEventCls.onIds("#" + me.pre + "reload_cod", "click", function(e) { let ic = me.icn3d;
66621
+ e.preventDefault();
66622
+ if(!me.cfg.notebook) dialog.dialog( "close" );
66623
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
66624
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66625
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
66626
+ });
66627
+ me.myEventCls.onIds("#" + me.pre + "codid", "keyup", function(e) { let ic = me.icn3d;
66628
+ if (e.keyCode === 13) {
66629
+ e.preventDefault();
66630
+ if(!me.cfg.notebook) dialog.dialog( "close" );
66631
+ thisClass.setLogCmd("load cod " + $("#" + me.pre + "codid").val(), false);
66632
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
66633
+ window.open(hostUrl + '?codid=' + $("#" + me.pre + "codid").val(), urlTarget);
66634
+ }
66635
+ });
66636
+
66383
66637
 
66384
66638
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { let ic = me.icn3d;
66385
66639
  e.preventDefault();
@@ -68935,8 +69189,8 @@ class Events {
68935
69189
  let fileName = file.name;
68936
69190
 
68937
69191
  let fileType = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase();
68938
- if(fileType == 'pdb' || fileType == 'mmcif' || fileType == 'png') {
68939
- await me.htmlCls.eventsCls.readFile(true, files, i, '', (fileType == 'mmcif'), (fileType == 'png'));
69192
+ if(fileType == 'pdb' || fileType == 'mmcif' || fileType == 'cif' || fileType == 'bcif' || fileType == 'png') {
69193
+ await me.htmlCls.eventsCls.readFile(true, files, i, '', (fileType == 'mmcif' || fileType == 'cif' || fileType == 'bcif'), (fileType == 'png'), fileType);
68940
69194
  }
68941
69195
  else if(fileType == 'bcf') {
68942
69196
  await thisClass.openBcf(file);
@@ -68965,7 +69219,7 @@ class Events {
68965
69219
  await ic.scapCls.retrieveScap(snp, bInteraction);
68966
69220
  thisClass.setLogCmd('scap interaction ' + snp, true);
68967
69221
 
68968
- let idArray = snp.split('_'); //stru_chain_resi_snp
69222
+ let idArray = me.utilsCls.getIdArray(snp); //stru_chain_resi_snp
68969
69223
  let select = '.' + idArray[1] + ':' + idArray[2];
68970
69224
  let name = 'snp_' + idArray[1] + '_' + idArray[2];
68971
69225
  thisClass.setLogCmd("select " + select + " | name " + name, true);
@@ -78989,6 +79243,43 @@ class Camera {
78989
79243
  // }
78990
79244
  }
78991
79245
 
79246
+ // Keep the slab plane at the same position relative to the molecule when zooming.
79247
+ // In perspective mode zooming moves the camera along the view direction, so the near plane
79248
+ // (distance from the camera) has to move with it. In orthographic mode zooming only changes
79249
+ // the frustum size and the camera does not move, so the slab plane already stays fixed.
79250
+ updateSlabByZoom() { let ic = this.icn3d, me = ic.icn3dui;
79251
+ if(ic.opts['slab'] !== 'yes' || me.bNode) return;
79252
+ if(ic.opts.camera.toLowerCase() !== 'perspective') return;
79253
+
79254
+ let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
79255
+ if(bInstance) return; // near plane is fixed at 0.1 for instancing
79256
+
79257
+ let cam = (ic.bControlGl) ? window.cam : ic.cam;
79258
+ let controls = (ic.bControlGl) ? window.controls : ic.controls;
79259
+
79260
+ // at zoom = 1 the slab plane is ic.maxD * camMaxDFactor from the camera, i.e. the plane through
79261
+ // the center (or 10 angstroms in front of it when fog is on to keep some surrounding residues)
79262
+ let offset = (ic.camMaxDFactorFog !== undefined) ? 10 : 0;
79263
+
79264
+ // current distance from the camera to the center of rotation, which changes with zooming
79265
+ let dist = cam.position.distanceTo(controls.target);
79266
+
79267
+ // keep the plane at the same position relative to the molecule
79268
+ let nearClip = Math.max(0.1, dist - offset);
79269
+
79270
+ if(Math.abs(cam.near - nearClip) > 1e-6) {
79271
+ cam.near = nearClip;
79272
+ cam.updateProjectionMatrix();
79273
+ if(ic.cam && ic.cam !== cam) {
79274
+ ic.cam.near = nearClip;
79275
+ ic.cam.updateProjectionMatrix();
79276
+ }
79277
+ }
79278
+
79279
+ // the impostor shaders (spheres, cylinders) clip with the nearClip uniform
79280
+ if(ic.uniforms && ic.uniforms.nearClip) ic.uniforms.nearClip.value = nearClip;
79281
+ }
79282
+
78992
79283
  setSlab() { let ic = this.icn3d, me = ic.icn3dui;
78993
79284
  if(ic.bControlGl && !me.bNode) {
78994
79285
  let maxD = ic.maxD;
@@ -79104,7 +79395,8 @@ class Fog {
79104
79395
  else {
79105
79396
  // adjust
79106
79397
  let zoomFactor = (ic._zoomFactor > 1) ? ic._zoomFactor * 1.0 : ic._zoomFactor;
79107
- ic.scene.fog = new Fog$1(background, 2.5 * ic.maxD * zoomFactor, 4 * ic.maxD * zoomFactor);
79398
+ let fogStrength = 2; // 1 = current, >1 = stronger
79399
+ ic.scene.fog = new Fog$1(background, (3 - 0.5 / fogStrength) * ic.maxD * zoomFactor, (3 + 1.0 / fogStrength) * ic.maxD * zoomFactor);
79108
79400
  ic.bSetFog = true;
79109
79401
  ic.camMaxDFactorFog = 3;
79110
79402
  }
@@ -81329,6 +81621,8 @@ class Tube {
81329
81621
 
81330
81622
  let prevAxis1 = new Vector3$1(), prevAxis2;
81331
81623
  for (let i = 0, lim = pnts.length; i < lim; ++i) {
81624
+ if(!pnts[i]) continue;
81625
+
81332
81626
  let r, idx = (i - 1) * axisDivInv;
81333
81627
 
81334
81628
  if (i === 0) {
@@ -81361,7 +81655,7 @@ class Tube {
81361
81655
  }
81362
81656
 
81363
81657
  let delta, axis1, axis2;
81364
- if (i < lim - 1) {
81658
+ if (i < lim - 1 && pnts[i + 1]) {
81365
81659
  delta = pnts[i].clone().sub(pnts[i + 1]);
81366
81660
  axis1 = new Vector3$1(0, -delta.z, delta.y).normalize().multiplyScalar(r);
81367
81661
  axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
@@ -85347,7 +85641,6 @@ class Surface {
85347
85641
  let chainStr = (Object.keys(chainHash).length > 1) ? '<th>Chain</th>' : '';
85348
85642
  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>';
85349
85643
  for(let resid in ic.resid2area) {
85350
- //var idArray = resid.split('_');
85351
85644
  let pos = resid.lastIndexOf('_');
85352
85645
  let resn = resid.substr(pos + 1);
85353
85646
 
@@ -86001,6 +86294,8 @@ class ApplyClbonds {
86001
86294
  // only apply to displayed atoms
86002
86295
  // if(!ic.dAtoms.hasOwnProperty(line.serial1) || !ic.dAtoms.hasOwnProperty(line.serial2)) continue;
86003
86296
 
86297
+ if(!ic.atoms[line.serial1] || !ic.atoms[line.serial2]) continue;
86298
+
86004
86299
  line.position1 = ic.atoms[line.serial1].coord;
86005
86300
  line.position2 = ic.atoms[line.serial2].coord;
86006
86301
 
@@ -86131,6 +86426,7 @@ class ApplyClbonds {
86131
86426
  if(type == 'chemical') continue; // just connect checmicals together
86132
86427
 
86133
86428
  if(ic.clbondpnts[atom0.structure] === undefined) ic.clbondpnts[atom0.structure] = [];
86429
+ if(ic.clbondpnts[atom1.structure] === undefined) ic.clbondpnts[atom1.structure] = [];
86134
86430
  ic.clbondpnts[atom0.structure].push(resid0);
86135
86431
  ic.clbondpnts[atom1.structure].push(resid1);
86136
86432
 
@@ -86676,9 +86972,9 @@ class ApplyOther {
86676
86972
  }
86677
86973
  }
86678
86974
 
86679
- ic.lineCls.createLines(ic.lines);
86680
- if(!ic.planes) ic.planes = [];
86681
- ic.cylinderCls.createPlanes(ic.planes);
86975
+ // ic.lineCls.createLines(ic.lines);
86976
+ // if(!ic.planes) ic.planes = [];
86977
+ // ic.cylinderCls.createPlanes(ic.planes);
86682
86978
  // }
86683
86979
 
86684
86980
  // distance sets
@@ -86801,6 +87097,10 @@ class ApplyOther {
86801
87097
  ic.pk = 3;
86802
87098
  break;
86803
87099
  }
87100
+
87101
+ ic.lineCls.createLines(ic.lines);
87102
+ if(!ic.planes) ic.planes = [];
87103
+ ic.cylinderCls.createPlanes(ic.planes);
86804
87104
  }
86805
87105
 
86806
87106
  applyChemicalbindingOptions(options) { let ic = this.icn3d, me = ic.icn3dui;
@@ -87947,6 +88247,8 @@ class Impostor {
87947
88247
 
87948
88248
  let shiness = ic.shininess / 100.0 * 0.5;
87949
88249
 
88250
+ let fogRGB = background.clone().convertLinearToSRGB();
88251
+
87950
88252
  ic.uniforms = UniformsUtils.merge([
87951
88253
  UniformsLib.common,
87952
88254
  {
@@ -87967,7 +88269,8 @@ class Impostor {
87967
88269
  nearClip: { type: "f", value: nearClip },
87968
88270
  ortho: { type: "f", value: 0.0 },
87969
88271
  shrink: { type: "f", value: 0.13 },
87970
- fogColor: { type: "v3", value: [background.r, background.g, background.b] },
88272
+ //fogColor: { type: "v3", value: [background.r, background.g, background.b] },
88273
+ fogColor: { type: "v3", value: [fogRGB.r, fogRGB.g, fogRGB.b] },
87971
88274
  fogNear: { type: "f", value: near },
87972
88275
  fogFar: { type: "f", value: far },
87973
88276
  fogDensity: { type: "f", value: 2.0 }
@@ -106200,6 +106503,9 @@ class WebGLPathTracer {
106200
106503
 
106201
106504
  cam = this.setDirectLight(cam);
106202
106505
 
106506
+ // move the slab plane according to the zoom
106507
+ if(ic.opts['slab'] === 'yes') ic.cameraCls.updateSlabByZoom();
106508
+
106203
106509
  if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
106204
106510
 
106205
106511
  if(ic.bVr) {
@@ -109763,7 +110069,7 @@ class AnnoCddSite {
109763
110069
  ic.bAjaxCddSite = true;
109764
110070
  }
109765
110071
 
109766
- getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d; ic.icn3dui;
110072
+ getResiArrayStr(resiNCBIArray, chainid) { let ic = this.icn3d, me = ic.icn3dui;
109767
110073
  let resiArrayStr = '';
109768
110074
  for(let i = 0, il = resiNCBIArray.length; i < il; ++i) {
109769
110075
  let resiNCBI = resiNCBIArray[i] + 1; // zero-based
@@ -109771,7 +110077,8 @@ class AnnoCddSite {
109771
110077
  let resid = ic.ncbi2resid[residNCBI];
109772
110078
  if(!resid) resid = residNCBI; // this happens sometimes, e.g., Q9Y4K1
109773
110079
 
109774
- let resi = resid.split('_')[2];
110080
+ let idArray = me.utilsCls.getIdArray(resid);
110081
+ let resi = idArray[2];
109775
110082
  if(i > 0) resiArrayStr += ',';
109776
110083
  resiArrayStr += resi;
109777
110084
  }
@@ -110867,7 +111174,8 @@ class AnnoIg {
110867
111174
  let residArray = Object.keys(residHash);
110868
111175
 
110869
111176
  // delete the following loops
110870
- let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, residArray[residArray.length - 1].split('_')[2]);
111177
+ let idArray = me.utilsCls.getIdArray(residArray[residArray.length - 1]);
111178
+ let lastPos = ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110871
111179
 
110872
111180
  for(let j = lastPos + 1, jl = ic.chainsSeq[chnid].length; j < jl; ++j) {
110873
111181
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -110883,7 +111191,8 @@ class AnnoIg {
110883
111191
  }
110884
111192
 
110885
111193
  // delete the previous loops
110886
- ic.setSeqAlignCls.getPosFromResi(chnid, residArray[0].split('_')[2]);
111194
+ idArray = me.utilsCls.getIdArray(residArray[0]);
111195
+ ic.setSeqAlignCls.getPosFromResi(chnid, idArray[2]);
110887
111196
 
110888
111197
  for(let j = lastPos - 1; j >= 0; --j) {
110889
111198
  let resi = ic.chainsSeq[chnid][j].resi;
@@ -111886,8 +112195,9 @@ class AnnoSnpClinVar {
111886
112195
  let residHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chnid]);
111887
112196
  // for(let i = 1, il = ic.giSeq[chnid].length; i <= il; ++i) {
111888
112197
  for(let resid in residHash) {
111889
- let i = resid.split('_')[2];
111890
-
112198
+ let idArray = me.utilsCls.getIdArray(resid);
112199
+ let i = idArray[2];
112200
+
111891
112201
  if(resi2index[i] !== undefined) {
111892
112202
  ++snpCnt;
111893
112203
  let allDiseaseTitle = '';
@@ -114080,7 +114390,6 @@ class Domain3d {
114080
114390
  // if(fromPos >= start && toPos <= end) {
114081
114391
  if(ssCnt > 0) jsonStr += ', ';
114082
114392
  jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
114083
- // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
114084
114393
  jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
114085
114394
  ++ssCnt;
114086
114395
  // }
@@ -114097,7 +114406,6 @@ class Domain3d {
114097
114406
  for(let j = startAll; j <= endAll; ++j) {
114098
114407
  let ncbiResid = chnid + '_' + j;
114099
114408
  let resid = ic.ncbi2resid[ncbiResid];
114100
- resid.split('_')[2];
114101
114409
 
114102
114410
  let pos = j;
114103
114411
 
@@ -114105,7 +114413,6 @@ class Domain3d {
114105
114413
 
114106
114414
  if(!residueHash.hasOwnProperty(resid)) {
114107
114415
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
114108
- // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
114109
114416
  }
114110
114417
  else {
114111
114418
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -114114,7 +114421,6 @@ class Domain3d {
114114
114421
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
114115
114422
 
114116
114423
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
114117
- // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
114118
114424
  }
114119
114425
 
114120
114426
  ++domainCnt;
@@ -119952,7 +120258,6 @@ class GetGraph {
119952
120258
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
119953
120259
  let node = graphJson.nodes[i];
119954
120260
  //node.r: 1_1_1KQ2_A_1
119955
- //var idArray = node.r.split('_');
119956
120261
  let idArray = [];
119957
120262
  idArray.push('');
119958
120263
  idArray.push('');
@@ -120131,8 +120436,8 @@ class GetGraph {
120131
120436
  compNode(a, b, bReverseChain) { let ic = this.icn3d, me = ic.icn3dui;
120132
120437
  let resid1 = a.r.substr(4); // 1_1_1KQ2_A_1
120133
120438
  let resid2 = b.r.substr(4); // 1_1_1KQ2_A_1
120134
- let aIdArray = me.utilsCls.getIdArray(resid1); //resid1.split('_');
120135
- let bIdArray = me.utilsCls.getIdArray(resid2); //resid2.split('_');
120439
+ let aIdArray = me.utilsCls.getIdArray(resid1);
120440
+ let bIdArray = me.utilsCls.getIdArray(resid2);
120136
120441
  let aChainid = aIdArray[0] + '_' + aIdArray[1];
120137
120442
  let bChainid = bIdArray[0] + '_' + bIdArray[1];
120138
120443
  let aResi = parseInt(aIdArray[2]);
@@ -121185,7 +121490,7 @@ class ViewInterPairs {
121185
121490
  residname2 =(type == 'save1') ? residname1_residname2[1] : residname1_residname2[0];
121186
121491
 
121187
121492
  // stru_chain_resi_resn
121188
- let ids = residname1.split('_');
121493
+ let ids = me.utilsCls.getIdArray(residname1);
121189
121494
  if(i > 0 && residname1 != prevResidname1) {
121190
121495
  bondCnt.push({res1: prevResidname1, res2: residname2List, cntHbond: cntHbond, cntIonic: cntIonic, cntContact: cntContact, cntHalegen: cntHalegen, cntPication: cntPication, cntPistacking: cntPistacking});
121191
121496
 
@@ -122586,8 +122891,8 @@ class AlignParser {
122586
122891
  //var scale = data2.transform.scale / factor;
122587
122892
  let tMaster = data2.transform.translate.master;
122588
122893
  let tMVector = new Vector3$1(tMaster[0] / factor, tMaster[1] / factor, tMaster[2] / factor);
122589
- let tSlave = data2.transform.translate.slave;
122590
- let tSVector = new Vector3$1(tSlave[0] / factor, tSlave[1] / factor, tSlave[2] / factor);
122894
+ let tQuery = data2.transform.translate.slave; // actually means query protein
122895
+ let tSVector = new Vector3$1(tQuery[0] / factor, tQuery[1] / factor, tQuery[2] / factor);
122591
122896
  let rotation = data2.transform.rotate;
122592
122897
  let rMatrix = [];
122593
122898
  for(let i = 0, il = rotation.length; i < il; ++i) { // 9 elements
@@ -122831,44 +123136,6 @@ class ChainalignParser {
122831
123136
  // calculate secondary structures with applyCommandDssp
122832
123137
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
122833
123138
  await ic.pdbParserCls.applyCommandDssp(true);
122834
- //!!!
122835
- /*
122836
- // original version =============
122837
- // align PDB chains
122838
- for(let index in ic.pdbChainIndexHash) {
122839
- //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
122840
- let idArray = ic.pdbChainIndexHash[index].split('_');
122841
- mmdbid_q = idArray[0];
122842
- let chain_q = idArray[1];
122843
- mmdbid_t = idArray[2];
122844
- let chain_t = idArray[3];
122845
-
122846
- thisClass.transformStructure(mmdbid_q, index-1, 'query');
122847
- }
122848
-
122849
- // dynamically align pairs in ic.afChainIndexHash
122850
- let ajaxArray = [], indexArray = [], struArray = [];
122851
- let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
122852
- let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
122853
-
122854
- let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
122855
-
122856
- for(let index in ic.afChainIndexHash) {
122857
- let idArray = ic.afChainIndexHash[index].split('_');
122858
- mmdbid_q = idArray[0];
122859
- let chain_q = idArray[1];
122860
- let chainid_q = mmdbid_q + '_' + chain_q;
122861
-
122862
- mmdbid_t = idArray[2];
122863
- let chain_t = idArray[3];
122864
- let chainid_t = mmdbid_t + '_' + chain_t;
122865
-
122866
- // let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t, true).hAtoms : ic.chains[chainid_t];
122867
- // let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q, true).hAtoms : ic.chains[chainid_q];
122868
- let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainid_t, true).hAtoms : ic.chains[chainid_t];
122869
- let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainid_q, true).hAtoms : ic.chains[chainid_q];
122870
- // end of original version =============
122871
- */
122872
123139
 
122873
123140
  // new version to be done for VASTsrv ==============
122874
123141
  // dynamically align pairs in all chainids
@@ -123337,10 +123604,10 @@ class ChainalignParser {
123337
123604
  return chainidArray;
123338
123605
  }
123339
123606
 
123340
- addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
123607
+ addPostfixForStructureids(structArray) { let ic = this.icn3d, me = ic.icn3dui;
123341
123608
  let struct2cnt = {};
123342
123609
  for(let i = 0, il = structArray.length; i < il; ++i) {
123343
- 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
123610
+ 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
123344
123611
 
123345
123612
  let struct = structArray[i].toUpperCase();
123346
123613
 
@@ -123364,6 +123631,8 @@ class ChainalignParser {
123364
123631
 
123365
123632
  ic.opts['proteins'] = 'c alpha trace';
123366
123633
 
123634
+ if(!chainalign) return;
123635
+
123367
123636
  let alignArray = chainalign.split(',');
123368
123637
  let domainArray = (me.cfg.domainids) ? me.cfg.domainids.split(',') : [];
123369
123638
  if(domainArray.length < alignArray.length) domainArray = [];
@@ -123436,7 +123705,7 @@ class ChainalignParser {
123436
123705
  let domainalign = (domainArray.length > 0) ? domainArray[index] + "," + domainArray[0] : undefined;
123437
123706
 
123438
123707
  // TM-align (me.cfg.aligntool == 'tmalign') needs to input PDB
123439
- if(me.cfg.aligntool != 'tmalign' && ic.mmdbid_t.length == 4 && ic.mmdbid_q.length == 4) {
123708
+ 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)) {
123440
123709
  let urlalign;
123441
123710
 
123442
123711
  if(domainArray.length > 0) {
@@ -123725,7 +123994,7 @@ class ChainalignParser {
123725
123994
  }
123726
123995
  else {
123727
123996
  for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
123728
- if(structArrayTmp[i].toLowerCase().substr(0,8) == 'pdb_0000') structArrayTmp[i] = structArrayTmp[i].substr(8); // temperary support long PDB ID such as pdb_00001tup
123997
+ 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
123729
123998
 
123730
123999
  let id = structArrayTmp[i].toUpperCase();
123731
124000
  if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
@@ -125256,6 +125525,19 @@ class MmcifParser {
125256
125525
  await ic.opmParserCls.loadOpmData(data, mmcifid, undefined, 'mmcif', undefined, bText);
125257
125526
  }
125258
125527
 
125528
+ async downloadCod(codid) { let ic = this.icn3d, me = ic.icn3dui;
125529
+ //ic.bCid = undefined;
125530
+
125531
+ ic.ParserUtilsCls.setYourNote(codid.toUpperCase() + '(COD) in iCn3D');
125532
+
125533
+ let url = "https://www.crystallography.net/cod/" + codid + ".cif";
125534
+ // let url = "https://www.crystallography.net/cif/1/00/00/1000041.cif";
125535
+ let data = await me.getAjaxPromise(url, 'text', true);
125536
+
125537
+ let bText = true;
125538
+ ic.loadCIFCls.loadCIF(data, codid, bText);
125539
+ }
125540
+
125259
125541
  async downloadMmcifSymmetry(mmcifid, type) { let ic = this.icn3d, me = ic.icn3dui;
125260
125542
  try {
125261
125543
  // let url = "https://files.rcsb.org/download/" + mmcifid + ".cif";
@@ -125360,14 +125642,20 @@ class MmcifParser {
125360
125642
  }
125361
125643
  }
125362
125644
 
125363
- async loadMultipleMmcifData(data, mmcifid, bAppend) { let ic = this.icn3d; ic.icn3dui;
125364
- let bText = true;
125645
+ async loadMultipleMmcifData(data, mmcifid, bAppend, fileType) { let ic = this.icn3d; ic.icn3dui;
125646
+ let bText = (fileType == 'bcif') ? false : true;
125647
+
125365
125648
  ic.loadCIFCls.loadCIF(data, mmcifid, bText, bAppend);
125366
125649
 
125367
125650
  if(Object.keys(ic.structures).length > 1) {
125368
125651
  ic.opts['color'] = 'structure';
125369
125652
  }
125370
125653
 
125654
+ if(Object.keys(ic.proteins).length == 0 || Object.keys(ic.nucleotides).length == 0) {
125655
+ ic.pk = 1;
125656
+ ic.opts['pk'] = 'atom';
125657
+ }
125658
+
125371
125659
  ic.opmParserCls.modifyUIMapAssembly();
125372
125660
 
125373
125661
  await ic.pdbParserCls.addSecondary(bAppend);
@@ -125461,9 +125749,10 @@ class MmdbParser {
125461
125749
  me.cfg.query_id = idArray[0];
125462
125750
  me.cfg.blast_rep_id = idArray[1];
125463
125751
 
125464
- let mmdbid = me.cfg.blast_rep_id.split('_')[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
125752
+ let textArray = me.utilsCls.getIdArray(me.cfg.blast_rep_id);
125753
+ let mmdbid = textArray[0]; // 1TSR_A, XP_003256700.1, Q9H3D4.1
125465
125754
 
125466
- if(mmdbid.length == 4) { // pdb
125755
+ if(mmdbid.length == 4 || mmdbid.indexOf('pdb_') == 0) { // pdb
125467
125756
  await this.downloadMmdb(mmdbid);
125468
125757
  }
125469
125758
  else {
@@ -125615,7 +125904,7 @@ class MmdbParser {
125615
125904
  if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
125616
125905
  // save a set named me.cfg.ligand
125617
125906
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
125618
- let idArray = Object.keys(residueHash)[0].split('_');
125907
+ let idArray = me.utilsCls.getIdArray(Object.keys(residueHash)[0]);
125619
125908
  let select = '.' + idArray[1] + ':' + idArray[2];
125620
125909
 
125621
125910
  await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
@@ -125992,7 +126281,7 @@ class BcifParser {
125992
126281
 
125993
126282
  if (parsed.isError) {
125994
126283
  // report error:
125995
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
126284
+ var aaa = 1; //alert("1 The Binary CIF data can NOT be parsed: " + parsed.toString());
125996
126285
  return;
125997
126286
  }
125998
126287
 
@@ -126957,7 +127246,8 @@ class OpmParser {
126957
127246
  if(!pdbid) pdbid = ic.defaultPdbId;
126958
127247
 
126959
127248
  //if(me.cfg.mmtfid === undefined && me.cfg.bcifid === undefined) { // skip opm for bcif files
126960
- let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + pdbid.toLowerCase();
127249
+ let shortPdbid = pdbid.indexOf('pdb_0000') == 0 ? pdbid.substr(8) : pdbid;
127250
+ let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + shortPdbid.toLowerCase();
126961
127251
 
126962
127252
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
126963
127253
 
@@ -128033,7 +128323,7 @@ class DcdParser {
128033
128323
  }
128034
128324
 
128035
128325
  for(let j in residuesOri) {
128036
- let idArray = j.split('_');
128326
+ let idArray = me.utilsCls.getIdArray(j);
128037
128327
  let structure2 = idArray[0] + molNum;
128038
128328
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
128039
128329
  ic.residues[residid2] = {};
@@ -128044,7 +128334,7 @@ class DcdParser {
128044
128334
  }
128045
128335
 
128046
128336
  for(let j in chainsOri) {
128047
- let idArray = j.split('_');
128337
+ let idArray = me.utilsCls.getIdArray(j);
128048
128338
  let structure2 = idArray[0] + molNum;
128049
128339
  let chainid2 = structure2 + '_' + idArray[1];
128050
128340
 
@@ -128075,7 +128365,7 @@ class DcdParser {
128075
128365
 
128076
128366
  // set ic.ncbi2resid and ic.resid2ncbi
128077
128367
  for(let chainid in chainsOri) {
128078
- let idArray = chainid.split('_');
128368
+ let idArray = me.utilsCls.getIdArray(chainid);
128079
128369
  let structure2 = idArray[0] + molNum;
128080
128370
  let chainid2 = structure2 + '_' + idArray[1];
128081
128371
 
@@ -128639,7 +128929,7 @@ class XtcParser {
128639
128929
  }
128640
128930
 
128641
128931
  for(let j in residuesOri) {
128642
- let idArray = j.split('_');
128932
+ let idArray = me.utilsCls.getIdArray(j);
128643
128933
  let structure2 = idArray[0] + molNum;
128644
128934
  let residid2 = structure2 + '_' + idArray[1] + '_' + idArray[2];
128645
128935
  ic.residues[residid2] = {};
@@ -128650,7 +128940,7 @@ class XtcParser {
128650
128940
  }
128651
128941
 
128652
128942
  for(let j in chainsOri) {
128653
- let idArray = j.split('_');
128943
+ let idArray = me.utilsCls.getIdArray(j);
128654
128944
  let structure2 = idArray[0] + molNum;
128655
128945
  let chainid2 = structure2 + '_' + idArray[1];
128656
128946
 
@@ -128681,7 +128971,7 @@ class XtcParser {
128681
128971
 
128682
128972
  // set ic.ncbi2resid and ic.resid2ncbi
128683
128973
  for(let chainid in chainsOri) {
128684
- let idArray = chainid.split('_');
128974
+ let idArray = me.utilsCls.getIdArray(chainid);
128685
128975
  let structure2 = idArray[0] + molNum;
128686
128976
  let chainid2 = structure2 + '_' + idArray[1];
128687
128977
 
@@ -128907,9 +129197,8 @@ class MsaParser {
128907
129197
 
128908
129198
  // realign based on residue by residue
128909
129199
  let alignment_final = ic.inputChainidArray.join(',');
128910
-
128911
129200
  if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
128912
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
129201
+ 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...");
128913
129202
  return;
128914
129203
  }
128915
129204
 
@@ -128967,7 +129256,7 @@ class MsaParser {
128967
129256
  }
128968
129257
 
128969
129258
  if(type == 'clustalw') {
128970
- if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
129259
+ if(line.substr(0, 1) != '.' && line.substr(0, 1) != '*') {
128971
129260
  let chainid_seq = line.split(/\s+/);
128972
129261
  let idArray = chainid_seq[0].split('|');
128973
129262
  let result = this.getChainid(idArray, bStart && !bSecBlock);
@@ -128992,9 +129281,11 @@ class MsaParser {
128992
129281
  seq = '';
128993
129282
 
128994
129283
  let pos = line.indexOf(' ');
129284
+ if(pos == -1) pos = line.length;
128995
129285
  let idArray = line.substr(1, pos).split('|');
128996
-
129286
+
128997
129287
  if(idArray.length == 1) {
129288
+ bFound = true;
128998
129289
  chainid = idArray[0];
128999
129290
  }
129000
129291
  else {
@@ -129058,8 +129349,9 @@ class MsaParser {
129058
129349
  ic.inputChainidArray.push(chainid + '_A');
129059
129350
  }
129060
129351
  }
129061
- else if(chainid.indexOf('_') != -1) { // PDB ID
129062
- let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
129352
+ else if(chainid.indexOf('_') != -1 || chainid.indexOf('pdb_') != -1) { // PDB ID
129353
+ let idArray = me.utilsCls.getIdArray(chainid);
129354
+ let stru = idArray[0];
129063
129355
  ic.struArray.push(stru);
129064
129356
  ic.inputChainidArray.push(chainid);
129065
129357
  }
@@ -129141,7 +129433,7 @@ class RealignParser {
129141
129433
  }
129142
129434
 
129143
129435
  // ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn.substr(0, 3)).substr(0, 1)});
129144
- ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn).substr(0, 1)});
129436
+ ic.realignResid[chainid].push({'resid': chainid + '_' + atom.resi, 'resn': me.utilsCls.residueName2Abbr(atom.resn, true)});
129145
129437
 
129146
129438
  struct2chain[atom.structure] = atom.structure + '_' + atom.chain;
129147
129439
 
@@ -129184,7 +129476,8 @@ class RealignParser {
129184
129476
 
129185
129477
  async parseChainRealignPredefined(chainidArray, struct2SeqHash, struct2CoorHash, struct2resid) { let ic = this.icn3d, me = ic.icn3dui;
129186
129478
 
129187
- let toStruct = chainidArray[0].substr(0, chainidArray[0].indexOf('_')); //.toUpperCase();
129479
+ let itemArray1 = me.utilsCls.getIdArray(chainidArray[0]);
129480
+ let toStruct = itemArray1[0];
129188
129481
 
129189
129482
  let hAtoms = {}, rmsd;
129190
129483
 
@@ -129197,13 +129490,14 @@ class RealignParser {
129197
129490
  ic.qt_start_end = [];
129198
129491
 
129199
129492
  let chainidHash = {};
129200
- for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
129201
- let fromStruct = chainidArray[index + 1].substr(0, chainidArray[index + 1].indexOf('_')); //.toUpperCase();
129493
+ for(let index = 0, indexl = chainidArray.length - 1; index < indexl; ++index) {
129494
+ let itemArray2 = me.utilsCls.getIdArray(chainidArray[index + 1]);
129495
+ let fromStruct = itemArray2[0];
129202
129496
 
129203
129497
  //if(toStruct == fromStruct) fromStruct += me.htmlCls.postfix;
129204
129498
 
129205
- let chainTo = toStruct + chainidArray[0].substr(chainidArray[0].indexOf('_'));
129206
- let chainFrom = fromStruct + chainidArray[index + 1].substr(chainidArray[index + 1].indexOf('_'));
129499
+ let chainTo = toStruct + '_' + itemArray1[1];
129500
+ let chainFrom = fromStruct + '_' + itemArray2[1];
129207
129501
  chainidHash[chainTo] = 1;
129208
129502
  chainidHash[chainFrom] = 1;
129209
129503
 
@@ -129238,7 +129532,7 @@ class RealignParser {
129238
129532
 
129239
129533
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, result.hAtoms);
129240
129534
  rmsd = parseFloat(result.rmsd);
129241
- }
129535
+ }
129242
129536
 
129243
129537
  // If rmsd from vastsrv is too large, realign the chains
129244
129538
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
@@ -129460,15 +129754,6 @@ class RealignParser {
129460
129754
  prevChainid = chainidArrayTmp[i];
129461
129755
  }
129462
129756
 
129463
- // use the model from Membranome as template
129464
- // if(ic.bAfMem && chainidArray.length == 2) {
129465
- // if(chainidArray[1].split('_')[0] == pdbidTemplate) {
129466
- // let tmp = chainidArray[0];
129467
- // chainidArray[0] = chainidArray[1];
129468
- // chainidArray[1] = tmp;
129469
- // }
129470
- // }
129471
-
129472
129757
  let bRealign = true;
129473
129758
  ic.qt_start_end = []; // reset the alignment
129474
129759
 
@@ -129713,12 +129998,12 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129713
129998
  let predefinedResArray, predefinedResPair;
129714
129999
 
129715
130000
  if(bPredefined) {
129716
- me.cfg.resdef.replace(/; /gi, ': ');
129717
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
129718
- // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
129719
-
130001
+ let tmpStr = me.cfg.resdef.replace(/; /gi, ': ');
130002
+ // predefinedResArray = decodeURIComponent(tmpStr).trim().replace(/\+/gi, ' ').split(': ');
130003
+ predefinedResArray = tmpStr.replace(/\+/gi, ' ').split(': ');
130004
+
129720
130005
  if(predefinedResArray.length != chainidArray.length - 1) {
129721
- var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
130006
+ 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...");
129722
130007
  return;
129723
130008
  }
129724
130009
  }
@@ -129727,8 +130012,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129727
130012
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
129728
130013
  //if(bPredefined) predefinedRes = predefinedResArray[i].trim();
129729
130014
 
129730
- let pos = chainidArray[i].indexOf('_');
129731
- let mmdbid = chainidArray[i].substr(0, pos); //.toUpperCase();
130015
+ let itemArray = me.utilsCls.getIdArray(chainidArray[i]);
130016
+ let mmdbid = itemArray[0]; //.toUpperCase();
129732
130017
 
129733
130018
  // if(!bRealign) mmdbid = mmdbid.toUpperCase();
129734
130019
 
@@ -129736,7 +130021,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129736
130021
  mmdbid_t = mmdbid;
129737
130022
  }
129738
130023
 
129739
- let chainid = mmdbid + chainidArray[i].substr(pos);
130024
+ let chainid = mmdbid + '_' + itemArray[1];
129740
130025
  if(i == 0) chainid_t = chainid;
129741
130026
 
129742
130027
  if(!ic.chainsSeq || !ic.chainsSeq[chainid]) {
@@ -129765,7 +130050,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129765
130050
  if(!struct2CoorHash[chainidpair]) struct2CoorHash[chainidpair] = {};
129766
130051
  if(!struct2resid[chainidpair]) struct2resid[chainidpair] = {};
129767
130052
 
129768
- // master
130053
+ // template
129769
130054
  resiArray = predefinedResPair[0].split(",");
129770
130055
 
129771
130056
  result = thisClass.getSeqCoorResid(resiArray, chainid_t);
@@ -129780,7 +130065,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129780
130065
  struct2CoorHash[chainidpair][mmdbid_t] = struct2CoorHash[chainidpair][mmdbid_t].concat(result.coor);
129781
130066
  struct2resid[chainidpair][mmdbid_t] = struct2resid[chainidpair][mmdbid_t].concat(result.resid);
129782
130067
 
129783
- // slave
130068
+ // query
129784
130069
  resiArray = predefinedResPair[1].split(",");
129785
130070
 
129786
130071
  result = thisClass.getSeqCoorResid(resiArray, chainid);
@@ -129808,7 +130093,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129808
130093
  }
129809
130094
  }
129810
130095
  else {
129811
- if(i == 0) { // master
130096
+ if(i == 0) { // template
129812
130097
  //base = parseInt(ic.chainsSeq[chainid][0].resi);
129813
130098
 
129814
130099
  resiArray = [];
@@ -129848,7 +130133,7 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
129848
130133
  bSelectedBoth = true;
129849
130134
 
129850
130135
  let resn = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]).resn;
129851
- struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn);
130136
+ struct2SeqHash[chainid] += me.utilsCls.residueName2Abbr(resn, true);
129852
130137
 
129853
130138
  struct2CoorHash[chainid] = struct2CoorHash[chainid].concat(this.getResCoorArray(resid));
129854
130139
 
@@ -132163,9 +132448,6 @@ class LoadAtomData {
132163
132448
  atm.coord = new Vector3$1(atm.coord.x, atm.coord.y, atm.coord.z);
132164
132449
  }
132165
132450
 
132166
- // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
132167
- let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn);
132168
-
132169
132451
  if((type === 'mmdbid' || type === 'align') && ic.bFullUi ) {
132170
132452
  // set ic.mmdbMolidResid2mmdbChainResi
132171
132453
  if(ic.mmdbMolidResid2mmdbChainResi === undefined) ic.mmdbMolidResid2mmdbChainResi = {};
@@ -132307,6 +132589,8 @@ class LoadAtomData {
132307
132589
  }
132308
132590
  }
132309
132591
 
132592
+ // let oneLetterRes = me.utilsCls.residueName2Abbr(atm.resn.substr(0, 3));
132593
+ let oneLetterRes = (atm.het) ? me.utilsCls.residueName2Abbr(atm.resn) : me.utilsCls.residueName2Abbr(atm.resn, true);
132310
132594
  ic.residueId2Name[residueid] = oneLetterRes;
132311
132595
 
132312
132596
  let secondaries = '-';
@@ -132654,11 +132938,11 @@ class SetSeqAlign {
132654
132938
  ic.nconsHash2 = {};
132655
132939
  ic.nalignHash2 = {};
132656
132940
 
132657
- let msaSameColor = [];
132658
- // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132659
- for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132660
- msaSameColor.push(1);
132661
- }
132941
+ // let msaSameColor = [];
132942
+ // // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132943
+ // for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132944
+ // msaSameColor.push(1);
132945
+ // }
132662
132946
 
132663
132947
  for(let i = 0, il = seqalign.length; i < il; ++i) {
132664
132948
  // first sequence
@@ -132667,44 +132951,30 @@ class SetSeqAlign {
132667
132951
 
132668
132952
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
132669
132953
  chainid1 = mmdbid1 + '_' + chain1;
132670
-
132671
- let id2aligninfo = {};
132672
- let start = alignData.sequence.length, end = -1;
132673
- let bStart = false;
132954
+ alignData.sequence.length;
132674
132955
  for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
132675
132956
  // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132676
- let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132677
- let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
132678
- resn =(resn === ' ' || resn === '') ? 'X' : resn;
132679
-
132680
- let aligned =(alignData.sequence[j][3]) ? 1 : 0;
132681
-
132682
- if(aligned == 1) {
132683
- if(j < start && !bStart) {
132684
- start = j;
132685
- bStart = true; // set start just once
132686
- }
132687
- if(j > end) end = j;
132688
- }
132957
+ (ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132958
+ (alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
132689
132959
 
132690
- id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132960
+ (alignData.sequence[j][3]) ? 1 : 0;
132691
132961
  }
132692
132962
 
132693
132963
  // second sequence
132694
132964
  alignData = seqalign[i][1];
132695
132965
 
132696
- for(let j = start; j <= end; ++j) {
132697
- // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132698
- let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132966
+ // for(let j = start; j <= end; ++j) {
132967
+ // // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132968
+ // let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132699
132969
 
132700
- let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132970
+ // let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132701
132971
 
132702
- if(aligned === 2) { // aligned
132703
- if(id2aligninfo[j].resn != resn) {
132704
- msaSameColor[j] = 0;
132705
- }
132706
- }
132707
- }
132972
+ // if(aligned === 2) { // aligned
132973
+ // if(id2aligninfo[j].resn != resn) {
132974
+ // msaSameColor[j] = 0;
132975
+ // }
132976
+ // }
132977
+ // }
132708
132978
  }
132709
132979
 
132710
132980
  for(let i = 0, il = seqalign.length; i < il; ++i) {
@@ -132803,7 +133073,7 @@ class SetSeqAlign {
132803
133073
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132804
133074
  }
132805
133075
 
132806
- color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
133076
+ // color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132807
133077
 
132808
133078
  // mapping, use the firstsequence as the reference structure
132809
133079
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132822,7 +133092,7 @@ class SetSeqAlign {
132822
133092
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132823
133093
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132824
133094
 
132825
- msaSameColor[j] = 2; // not aligned
133095
+ // msaSameColor[j] = 2; // not aligned
132826
133096
  }
132827
133097
 
132828
133098
  // chain1
@@ -132947,8 +133217,7 @@ class SetSeqAlign {
132947
133217
  return pos;
132948
133218
  }
132949
133219
 
132950
- getResnFromResi(chainid, resi) { let ic = this.icn3d; ic.icn3dui;
132951
- /*
133220
+ getResnFromResi(chainid, resi) { let ic = this.icn3d, me = ic.icn3dui;
132952
133221
  let pos = this.getPosFromResi(chainid, resi);
132953
133222
  if(!pos) return '?';
132954
133223
 
@@ -132963,8 +133232,8 @@ class SetSeqAlign {
132963
133232
  }
132964
133233
 
132965
133234
  return resn;
132966
- */
132967
133235
 
133236
+ /*
132968
133237
  let resid = chainid + '_' + resi;
132969
133238
  let resn = ic.residueId2Name[resid];
132970
133239
  if(!resn) {
@@ -132972,6 +133241,7 @@ class SetSeqAlign {
132972
133241
  }
132973
133242
 
132974
133243
  return resn;
133244
+ */
132975
133245
  }
132976
133246
 
132977
133247
  getResiAferAlign(chainid, bRealign, pos) { let ic = this.icn3d, me = ic.icn3dui;
@@ -133316,7 +133586,7 @@ class SetSeqAlign {
133316
133586
  let start1, end1;
133317
133587
 
133318
133588
  //ic.qt_start_end is zero-based
133319
- if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment
133589
+ if(!bRealign && me.cfg.aligntool != 'tmalign') { // vast alignment or seqalign
133320
133590
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start) - 1;
133321
133591
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end) - 1;
133322
133592
  }
@@ -133351,15 +133621,18 @@ class SetSeqAlign {
133351
133621
 
133352
133622
  let resid2rangeArray = Object.keys(resid2range_t);
133353
133623
  resid2rangeArray.sort(function(a, b) {
133354
- return parseInt(a.split('_')[2]) - parseInt(b.split('_')[2]);
133624
+ let idArray1 = me.utilsCls.getIdArray(a);
133625
+ let idArray2 = me.utilsCls.getIdArray(b);
133626
+ return parseInt(idArray1[2]) - parseInt(idArray2[2]);
133355
133627
  });
133356
133628
 
133357
133629
  // assign range to each resi
133358
133630
  let prevResi = -999, start = 0, end = 0, residArray = [], prevEnd = 0;
133359
133631
  for(let i = 0, il = resid2rangeArray.length; i < il; ++i) {
133360
133632
  let resid = resid2rangeArray[i];
133361
- let resi = resid.split('_')[2];
133362
-
133633
+ let idArray = me.utilsCls.getIdArray(resid);
133634
+ let resi = idArray[2];
133635
+
133363
133636
  if(i == 0) {
133364
133637
  start = resi;
133365
133638
  }
@@ -133398,7 +133671,9 @@ class SetSeqAlign {
133398
133671
  let resid = chainid1 + '_' + resi;
133399
133672
 
133400
133673
  // let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : j + baseResi;
133401
- let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
133674
+ //let jAdjusted = ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
133675
+ //!!!
133676
+ let jAdjusted = (me.cfg.aligntool != 'tmalign') ? j : ic.ParserUtilsCls.getResiNCBI(chainid1, resi) - 1;
133402
133677
 
133403
133678
  //if(j + baseResi < start_t || j + baseResi > end_t) {
133404
133679
  if(jAdjusted < start_t || jAdjusted > end_t) {
@@ -133599,21 +133874,23 @@ class SetSeqAlign {
133599
133874
  }
133600
133875
  }
133601
133876
 
133602
- getTemplatePosFromOriResi(chainid1, start, end, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
133603
- // let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
133604
- // let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
133605
- if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
133606
- let startResi = start;
133607
- let endResi = end;
133877
+ getTemplatePosFromOriPos(chainid1, start, end, bRealign) { let ic = this.icn3d; ic.icn3dui;
133878
+ //!!!
133879
+ let startResi = ic.ParserUtilsCls.getResi(chainid1, start);
133880
+ let endResi = ic.ParserUtilsCls.getResi(chainid1, end);
133881
+
133882
+ // if(bRealign && me.cfg.aligntool == 'tmalign') { // vast alignment
133883
+ // let startResi = start;
133884
+ // let endResi = end;
133608
133885
 
133609
133886
  let result1 = this.getResiPosInTemplate(chainid1, startResi);
133610
133887
  let result2 = this.getResiPosInTemplate(chainid1, endResi);
133611
133888
 
133612
133889
  return {"pos1": result1.pos, "pos2": result2.pos};
133613
- }
133614
- else {
133615
- return {"pos1": start, "pos2": end};
133616
- }
133890
+ // }
133891
+ // else {
133892
+ // return {"pos1": start, "pos2": end};
133893
+ // }
133617
133894
  }
133618
133895
 
133619
133896
  mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
@@ -133685,11 +133962,11 @@ class SetSeqAlign {
133685
133962
  start_t = ic.ParserUtilsCls.getResi(chainid1, start_t);
133686
133963
  end_t = ic.ParserUtilsCls.getResi(chainid1, end_t);
133687
133964
  }
133688
-
133965
+ console.log("### me.cfg.aligntool " + me.cfg.aligntool + " bRealign " + bRealign );
133689
133966
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
133690
- let start1, start2, end1, end2, resiStart1, start1Pos;
133967
+ let start1, start2, end1, end2, resiStart1, start1Pos, end1Pos;
133691
133968
 
133692
- if(bRealign && me.cfg.aligntool == 'tmalign') { // real residue numbers are stored
133969
+ if(bRealign && (me.cfg.aligntool == 'tmalign')) { // real residue numbers are stored
133693
133970
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start);
133694
133971
  start2 = parseInt(ic.qt_start_end[chainIndex][i].q_start);
133695
133972
  end1 = parseInt(ic.qt_start_end[chainIndex][i].t_end);
@@ -133703,7 +133980,7 @@ class SetSeqAlign {
133703
133980
  // 1. before the mapped residues
133704
133981
  resiStart1 = start1;
133705
133982
  start1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_start);
133706
- this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133983
+ end1Pos = this.getPosFromResi(chainid1, ic.qt_start_end[chainIndex][i].t_end);
133707
133984
  }
133708
133985
  else {
133709
133986
  start1 = parseInt(ic.qt_start_end[chainIndex][i].t_start - 1);
@@ -133714,6 +133991,7 @@ class SetSeqAlign {
133714
133991
  // 1. before the mapped residues
133715
133992
  resiStart1 = ic.ParserUtilsCls.getResi(chainid1, start1);
133716
133993
  start1Pos = start1;
133994
+ end1Pos = end1;
133717
133995
  }
133718
133996
  //let range = resid2range_t[chainid1 + '_' + resiStart1];
133719
133997
 
@@ -133721,13 +133999,15 @@ class SetSeqAlign {
133721
133999
  if(i == 0) {
133722
134000
  startPosInTemplate = start1Pos;
133723
134001
 
133724
- result = this.getTemplatePosFromOriResi(chainid1, start_t, start1, bRealign);
133725
- //result = this.getTemplatePosFromOriResi(chainid1, start_t, start1Pos, bRealign);
134002
+ //!!!
134003
+ // result = this.getTemplatePosFromOriPos(chainid1, start_t, start1, bRealign);
134004
+ result = this.getTemplatePosFromOriPos(chainid1, start_t, start1Pos, bRealign);
133726
134005
  pos1 = result.pos1;
133727
134006
  pos2 = result.pos2;
133728
134007
 
133729
- if(start1 > start_t) {
133730
- //if(start1Pos > start_t) {
134008
+ //!!!
134009
+ // if(start1 > start_t) {
134010
+ if(start1Pos > start_t) {
133731
134011
  for(let j = 0, jl = pos2 - pos1; j < jl; ++j) {
133732
134012
  ic.alnChainsSeq[chainid2].push(gapResObject2);
133733
134013
  }
@@ -133735,7 +134015,7 @@ class SetSeqAlign {
133735
134015
  }
133736
134016
  else {
133737
134017
  //let notAlnLen1 = start1 - (prevIndex1 + 1);
133738
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, start1, bRealign);
134018
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, start1, bRealign);
133739
134019
  pos1 = result.pos1;
133740
134020
  pos2 = result.pos2;
133741
134021
  let notAlnLen1 = pos2 - (pos1 + 1);
@@ -133760,15 +134040,16 @@ class SetSeqAlign {
133760
134040
  }
133761
134041
 
133762
134042
  // 2. In the mapped residues
133763
- result = this.getTemplatePosFromOriResi(chainid1, start1, end1, bRealign);
133764
- //result = this.getTemplatePosFromOriResi(chainid1, start1Pos, end1Pos, bRealign);
134043
+ // result = this.getTemplatePosFromOriPos(chainid1, start1, end1, bRealign);
134044
+ result = this.getTemplatePosFromOriPos(chainid1, start1Pos, end1Pos, bRealign);
133765
134045
  pos1 = result.pos1;
133766
134046
  pos2 = result.pos2;
133767
134047
 
133768
134048
  let k = 0;
133769
134049
  if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
133770
134050
  if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
133771
- let resiAdjust = (bRealign && me.cfg.aligntool == 'tmalign') ? 0 : - startPosInTemplate + nGapInTemplate;
134051
+ //!!!!!!
134052
+ let resiAdjust = ((bRealign && me.cfg.aligntool == 'tmalign') || me.cfg.aligntool == 'seqalign') ? 0 : - startPosInTemplate + nGapInTemplate;
133772
134053
  for(let j = pos1; j <= pos2; ++j) {
133773
134054
  // inherit the gaps from the template
133774
134055
  if(ic.alnChainsSeq[chainid1][j + resiAdjust].resn == '-') {
@@ -133803,7 +134084,7 @@ class SetSeqAlign {
133803
134084
  }
133804
134085
 
133805
134086
  // add gaps at the end
133806
- result = this.getTemplatePosFromOriResi(chainid1, prevIndex1, end_t, bRealign);
134087
+ result = this.getTemplatePosFromOriPos(chainid1, prevIndex1, end_t, bRealign);
133807
134088
  pos1 = result.pos1;
133808
134089
  pos2 = result.pos2;
133809
134090
  for(let i = pos1; i < pos2; ++i) {
@@ -134139,7 +134420,7 @@ class SetSeqAlign {
134139
134420
  }
134140
134421
  }
134141
134422
 
134142
- setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
134423
+ setMsaFormat(chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
134143
134424
  //set MSA
134144
134425
  let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
134145
134426
  let chainArrayClustal = [];
@@ -134151,7 +134432,9 @@ class SetSeqAlign {
134151
134432
  fastaFormat += '>' + chainid + '\n';
134152
134433
 
134153
134434
  let clustalwArray = [];
134154
- let clustalwLine = chainid.padEnd(20, ' ');
134435
+ let itemArray = me.utilsCls.getIdArray(chainid);
134436
+ let chainidStr = 'pdb|' + itemArray[0] + '|' + itemArray[1];
134437
+ let clustalwLine = chainidStr.padEnd(20, ' ');
134155
134438
  let consLine = ''.padEnd(20, ' ');
134156
134439
 
134157
134440
  let resiArrayTarget = [], resiArrayQuery = [];
@@ -134691,7 +134974,7 @@ class LoadPDB {
134691
134974
  //if(residueNum !== prevResidueNum) {
134692
134975
 
134693
134976
  if(oriResidueNum !== prevOriResidueNum) {
134694
- let residue = me.utilsCls.residueName2Abbr(resn);
134977
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
134695
134978
  ic.residueId2Name[residueNum] = residue;
134696
134979
 
134697
134980
  if(serial !== 1 && prevResidueNum !== '') ic.residues[prevResidueNum] = residuesTmp;
@@ -134829,11 +135112,14 @@ class LoadPDB {
134829
135112
  prevCarbonArray.push(atom);
134830
135113
  }
134831
135114
 
135115
+ // remove trailing digits in the residue name, e.g., "Na1" -> "NA"
135116
+ let resnSimple = atom.resn.trim().replace(/\d+$/, '').toUpperCase();
135117
+
134832
135118
  if(atom.resn === 'HOH' || atom.resn === 'WAT' || atom.resn === 'SOL') {
134833
135119
  ic.water[atom.serial] = 1;
134834
135120
  atom.color = me.parasCls.atomColors[atom.elem];
134835
135121
  }
134836
- else if($.inArray(atom.resn.trim(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
135122
+ else if($.inArray(resnSimple, me.parasCls.ionsArray) !== -1 || $.inArray(atom.elem.trim().toUpperCase(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
134837
135123
  ic.ions[atom.serial] = 1;
134838
135124
  atom.color = me.parasCls.atomColors[atom.elem];
134839
135125
  }
@@ -134884,6 +135170,13 @@ class LoadPDB {
134884
135170
  }
134885
135171
  } // end of for
134886
135172
 
135173
+ 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) {
135174
+ for(let serial in ic.ions) {
135175
+ let atom = ic.atoms[serial];
135176
+ me.parasCls.vdwRadii[atom.elem.toUpperCase()] = me.parasCls.ionRadii[atom.elem.toUpperCase()];
135177
+ }
135178
+ }
135179
+
134887
135180
  // last residue
134888
135181
  //refreshBonds();
134889
135182
  this.refreshBonds(curResAtoms, prevCarbonArray[0]);
@@ -135128,7 +135421,7 @@ class LoadPDB {
135128
135421
 
135129
135422
  for(let chainid in chains) {
135130
135423
  if(pdbid !== undefined) {
135131
- let textArray = chainid.split('_');
135424
+ let textArray = me.utilsCls.getIdArray(chainid);
135132
135425
  if(textArray[0] !== pdbid) continue; // skip different chain
135133
135426
  }
135134
135427
 
@@ -135233,7 +135526,20 @@ class LoadCIF {
135233
135526
  return secondarySet.has(resid.substr(resid.indexOf('_') + 1));
135234
135527
  }
135235
135528
 
135236
- loadCIF(bcifData, bcifid, bText, bAppend) { let ic = this.icn3d, me = ic.icn3dui;
135529
+ loadCIF(bcifData, bcifid, bText, bAppend, supercell) { let ic = this.icn3d, me = ic.icn3dui;
135530
+ ic.cifText = bText;
135531
+ ic.cifData = bcifData;
135532
+
135533
+ if(supercell === undefined) {
135534
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135535
+ }
135536
+ else if(supercell === 0) {
135537
+ CIFTools.Text.coreCifOptions = { nx: 1, ny: 1, nz: 1, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135538
+ }
135539
+ else {
135540
+ CIFTools.Text.coreCifOptions = { nx: supercell, ny: supercell, nz: supercell, boundary: true, wholeMolecules: true, bondTolerance: 0.4 };
135541
+ }
135542
+
135237
135543
  let hAtoms = {};
135238
135544
 
135239
135545
  let bNMR = false;
@@ -135247,7 +135553,7 @@ class LoadCIF {
135247
135553
  let serial, moleculeNum;
135248
135554
  // if(!bMutation && !bAppend) {
135249
135555
  if(!bAppend) {
135250
- ic.init();
135556
+ ic.init(undefined, true); // keep original configurations, such as color, style, etc. when loading multiple structures
135251
135557
  moleculeNum = 0; //1;
135252
135558
  serial = 0;
135253
135559
  }
@@ -135286,17 +135592,18 @@ class LoadCIF {
135286
135592
  helixStart = [];
135287
135593
  helixEnd = [];
135288
135594
 
135289
-
135290
135595
  // bcifData could be binary or text
135291
135596
  let parsed = (bText) ? CIFTools.Text.parse(cifArray[index]) : CIFTools.Binary.parse(cifArray[index]);
135292
135597
 
135293
135598
  if (parsed.isError) {
135294
135599
  // report error:
135295
- var aaa = 1; //alert("The Binary CIF data can NOT be parsed: " + parsed.toString());
135600
+ var aaa = 1; //alert("2 The Binary CIF data can NOT be parsed: " + parsed.toString());
135296
135601
  return;
135297
135602
  }
135298
135603
 
135299
135604
  let block = parsed.result.dataBlocks[0];
135605
+
135606
+ if(!block) continue;
135300
135607
 
135301
135608
  if(block.getCategory("_entry")) {
135302
135609
  id = block.getCategory("_entry").getColumn("id").getString(0);
@@ -135535,6 +135842,8 @@ class LoadCIF {
135535
135842
  ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
135536
135843
  ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
135537
135844
  ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
135845
+
135846
+ 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);
135538
135847
  }
135539
135848
 
135540
135849
  // if (record === 'ENDMDL') {
@@ -135879,7 +136188,7 @@ class LoadCIF {
135879
136188
 
135880
136189
  // if(oriResidueNum !== prevOriResidueNum) {
135881
136190
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
135882
- let residue = me.utilsCls.residueName2Abbr(resn);
136191
+ let residue = (atomDetails.het) ? me.utilsCls.residueName2Abbr(resn) : me.utilsCls.residueName2Abbr(resn, true);
135883
136192
 
135884
136193
  ic.residueId2Name[residueNum] = residue;
135885
136194
 
@@ -136086,17 +136395,19 @@ class LoadCIF {
136086
136395
  }
136087
136396
  }
136088
136397
  else if(atom.het) {
136398
+ let resnSimple = atom.resn.trim().replace(/\d+$/, '').toUpperCase();
136399
+
136089
136400
  if(atom.resn === 'HOH' || atom.resn === 'WAT' || atom.resn === 'SOL') {
136090
136401
  ic.water[atom.serial] = 1;
136091
136402
  }
136092
- else if($.inArray(atom.resn, me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
136403
+ else if($.inArray(resnSimple, me.parasCls.ionsArray) !== -1 || $.inArray(atom.elem.trim().toUpperCase(), me.parasCls.ionsArray) !== -1 || atom.elem.trim() === atom.resn.trim()) {
136093
136404
  ic.ions[atom.serial] = 1;
136094
136405
  }
136095
136406
  else {
136096
136407
  ic.chemicals[atom.serial] = 1;
136097
136408
  }
136098
136409
 
136099
- atom.color = me.parasCls.atomColors[atom.elem];
136410
+ atom.color = me.parasCls.atomColors[atom.elem.toUpperCase()];
136100
136411
  }
136101
136412
 
136102
136413
  if(!(curChain === atom.chain && curResi === atom.resi)) {
@@ -136117,6 +136428,13 @@ class LoadCIF {
136117
136428
  }
136118
136429
  } // end of for
136119
136430
 
136431
+ 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) {
136432
+ for(let serial in ic.ions) {
136433
+ let atom = ic.atoms[serial];
136434
+ me.parasCls.vdwRadii[atom.elem.toUpperCase()] = me.parasCls.ionRadii[atom.elem.toUpperCase()];
136435
+ }
136436
+ }
136437
+
136120
136438
  // last residue
136121
136439
  //refreshBonds();
136122
136440
  ic.loadPDBCls.refreshBonds(curResAtoms, prevCarbonArray[0]);
@@ -137169,6 +137487,16 @@ class ApplyCommand {
137169
137487
  ic.opts['unitcell'] = 'no';
137170
137488
  ic.drawCls.draw();
137171
137489
  }
137490
+ else if(command.indexOf('define unitcell') !== -1) {
137491
+ let itemArray = command.split(' | ');
137492
+ ic.cell = {};
137493
+ ic.cell.length_a = parseFloat(itemArray[1]);
137494
+ ic.cell.length_b = parseFloat(itemArray[2]);
137495
+ ic.cell.length_c = parseFloat(itemArray[3]);
137496
+ ic.cell.angle_alpha = parseFloat(itemArray[4]);
137497
+ ic.cell.angle_beta = parseFloat(itemArray[5]);
137498
+ ic.cell.angle_gamma = parseFloat(itemArray[6]);
137499
+ }
137172
137500
  else if(command == 'set fog on') {
137173
137501
  ic.opts['fog'] = 'yes';
137174
137502
  ic.fogCls.setFog(true);
@@ -137195,6 +137523,12 @@ class ApplyCommand {
137195
137523
  else if(command == 'set assembly off') {
137196
137524
  ic.bAssembly = false;
137197
137525
  }
137526
+ else if(command.indexOf('set supercell') !== -1) {
137527
+ let pos = command.lastIndexOf(' ');
137528
+ let supercell = parseInt(command.substr(pos + 1));
137529
+
137530
+ me.htmlCls.clickMenuCls.setSupercell(supercell);
137531
+ }
137198
137532
  else if(command == 'set chemicalbinding show') {
137199
137533
  ic.setOptionCls.setOption('chemicalbinding', 'show');
137200
137534
  }
@@ -137628,7 +137962,8 @@ class ApplyCommand {
137628
137962
  else if(commandOri.indexOf('select interaction') == 0) {
137629
137963
  let idArray = commandOri.substr(commandOri.lastIndexOf(' ') + 1).split(',');
137630
137964
  if(idArray !== null) {
137631
- let mmdbid = idArray[0].split('_')[0];
137965
+ let itemArray = me.utilsCls.getIdArray(idArray[0]);
137966
+ let mmdbid = itemArray[0];
137632
137967
  if(!ic.b2DShown) ic.ParserUtilsCls.download2Ddgm(mmdbid.toUpperCase());
137633
137968
 
137634
137969
  ic.diagram2dCls.selectInteraction(idArray[0], idArray[1]);
@@ -139474,7 +139809,7 @@ class DefinedSets {
139474
139809
 
139475
139810
  }
139476
139811
 
139477
- selectCombinedSets(strSets, commandname) { let ic = this.icn3d; ic.icn3dui;
139812
+ selectCombinedSets(strSets, commandname) { let ic = this.icn3d, me = ic.icn3dui;
139478
139813
  let idArray = strSets.split(' ');
139479
139814
 
139480
139815
  let orArray = [], andArray = [], notArray = [];
@@ -139482,7 +139817,7 @@ class DefinedSets {
139482
139817
 
139483
139818
  for(let i = 0, il = idArray.length; i < il; ++i) {
139484
139819
  // replace 1CD8_A_1 with 1CD8_A1
139485
- let tmpArray = idArray[i].split('_');
139820
+ let tmpArray = me.utilsCls.getIdArray(idArray[i]);
139486
139821
  if(tmpArray.length == 3 && !isNaN(tmpArray[2])) {
139487
139822
  idArray[i] = tmpArray[0] + '_' + tmpArray[1] + tmpArray[2];
139488
139823
  }
@@ -140484,7 +140819,7 @@ class LoadScript {
140484
140819
 
140485
140820
  // load pdb, mmcif, mmdb, cid
140486
140821
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
140487
- if(id.length == 4) id = id.toUpperCase();
140822
+ if(id.length == 4 || id.indexOf('pdb_') == 0) id = id.toUpperCase();
140488
140823
 
140489
140824
  // skip loading the structure if
140490
140825
  // 1. PDB was in the iCn3D PNG Image file
@@ -140531,6 +140866,10 @@ class LoadScript {
140531
140866
  me.cfg.mmcifid = id;
140532
140867
  await ic.mmcifParserCls.downloadMmcif(id);
140533
140868
  }
140869
+ else if(command.indexOf('load cod') !== -1) {
140870
+ me.cfg.codid = id;
140871
+ await ic.mmcifParserCls.downloadCod(id);
140872
+ }
140534
140873
  else if(command.indexOf('load mmdb ') !== -1 || command.indexOf('load mmdb1 ') !== -1) {
140535
140874
  me.cfg.mmdbid = id;
140536
140875
  me.cfg.bu = 1;
@@ -141045,7 +141384,7 @@ class SelectByCommand {
141045
141384
 
141046
141385
  // convert 1TOP_A:20 to $1TOP.A:20
141047
141386
  if(commandArray[i].indexOf('_') !== -1) {
141048
- let itemArray = commandArray[i].split('_');
141387
+ let itemArray = me.utilsCls.getIdArray(commandArray[i]);
141049
141388
  if(itemArray.length ==2 ) {
141050
141389
  commandArray[i] = '$' + itemArray[0] + '.' + itemArray[1];
141051
141390
  }
@@ -141850,7 +142189,7 @@ class Selection {
141850
142189
 
141851
142190
  resetAll() { let ic = this.icn3d, me = ic.icn3dui;
141852
142191
  ic.maxD = ic.oriMaxD;
141853
- ic.center = ic.oriCenter.clone();
142192
+ ic.center = (ic.oriCenter) ? ic.oriCenter.clone() : new THREE.Vector3(0, 0, 0);
141854
142193
 
141855
142194
  ic.opts = me.hashUtilsCls.cloneHash(ic.optsOri);
141856
142195
 
@@ -143926,24 +144265,6 @@ class Dssp {
143926
144265
  if(!me.bNode) console.log("domainid: " + domainid);
143927
144266
  }
143928
144267
 
143929
- // count the number of matched strands
143930
- // let strandHash = {};
143931
- // for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
143932
- // let seg = queryData[0].segs[j];
143933
- // let q_start = parseInt(seg.q_start)
143934
-
143935
- // let strand = this.getStrandFromRefnum(q_start);
143936
- // strandHash[strand] = 1;
143937
- // }
143938
-
143939
- // let tmAdjust = 0.1;
143940
-
143941
- // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
143942
- // if(!domainid2segs.hasOwnProperty(domainid) ||
143943
- // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
143944
- // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
143945
- // ) {
143946
-
143947
144268
  // use TM-score alone
143948
144269
  if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
143949
144270
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res + '_' + queryData[0].score2;
@@ -145275,7 +145596,7 @@ class Scap {
145275
145596
  let snpArray = snp.split(','); //stru_chain_resi_snp
145276
145597
  let atomHash = {}, snpResidArray = [], chainResi2pdb = {};
145277
145598
  for(let i = 0, il = snpArray.length; i < il; ++i) {
145278
- let idArray = snpArray[i].split('_'); //stru_chain_resi_snp
145599
+ let idArray = me.utilsCls.getIdArray(snpArray[i]); //stru_chain_resi_snp
145279
145600
 
145280
145601
  let resid = idArray[0] + '_' + idArray[1] + '_' + idArray[2];
145281
145602
  atomHash = me.hashUtilsCls.unionHash(atomHash, ic.residues[resid]);
@@ -148427,7 +148748,8 @@ class Diagram2d {
148427
148748
  if(refnumLabel) {
148428
148749
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
148429
148750
  if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
148430
- ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
148751
+ let idArray = me.utilsCls.getIdArray(resid);
148752
+ ic.refnum2resn[domainid][refnumStr] = resn + idArray[2];
148431
148753
  }
148432
148754
  }
148433
148755
 
@@ -149927,7 +150249,8 @@ class ResizeCanvas {
149927
150249
  let width = me.htmlCls.WIDTH; // - me.htmlCls.LESSWIDTH_RESIZE;
149928
150250
  let height = me.htmlCls.HEIGHT; // - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT;
149929
150251
 
149930
- if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
150252
+ // if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height);
150253
+ if(ic !== undefined && !ic.bFullscreen) thisClass.resizeCanvas(width, height, true, true);
149931
150254
  });
149932
150255
  }
149933
150256
  }
@@ -150155,7 +150478,7 @@ class Transform {
150155
150478
 
150156
150479
  //reset ic.maxD
150157
150480
  ic.maxD = ic.oriMaxD;
150158
- ic.center = ic.oriCenter.clone();
150481
+ ic.center = (ic.oriCenter) ? ic.oriCenter.clone() : new Vector3$1(0, 0, 0);
150159
150482
 
150160
150483
  if(ic.ori_chemicalbinding == 'show') {
150161
150484
  ic.bSkipChemicalbinding = false;
@@ -154677,8 +155000,8 @@ class iCn3D {
154677
155000
  }
154678
155001
  }
154679
155002
  //When users first load a structure, call this function to empty previous settings.
154680
- iCn3D.prototype.init = function (bKeepCmd) {
154681
- this.init_base();
155003
+ iCn3D.prototype.init = function (bKeepCmd, bKeepConfig) {
155004
+ this.init_base(bKeepCmd, bKeepConfig);
154682
155005
 
154683
155006
  this.molTitle = "";
154684
155007
 
@@ -154698,8 +155021,8 @@ iCn3D.prototype.init = function (bKeepCmd) {
154698
155021
  this.axes = [];
154699
155022
  };
154700
155023
 
154701
- iCn3D.prototype.init_base = function (bKeepCmd) {
154702
- this.resetConfig();
155024
+ iCn3D.prototype.init_base = function (bKeepCmd, bKeepConfig) {
155025
+ if(!bKeepConfig) this.resetConfig();
154703
155026
 
154704
155027
  this.structures = {}; // structure name -> array of chains
154705
155028
  this.chains = {}; // structure_chain name -> atom hash
@@ -154889,7 +155212,7 @@ class iCn3DUI {
154889
155212
  //even when multiple iCn3D viewers are shown together.
154890
155213
  this.pre = this.cfg.divid + "_";
154891
155214
 
154892
- this.REVISION = '3.54.2';
155215
+ this.REVISION = '3.54.4';
154893
155216
 
154894
155217
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154895
155218
  this.bNode = (Object.keys(window).length < 3) ? true : false;
@@ -155091,7 +155414,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155091
155414
  let domainidArray = me.cfg.matchedchains.split(',');
155092
155415
  let chainidArray = [];
155093
155416
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
155094
- let idArray = domainidArray[i].split('_');
155417
+ let idArray = me.utilsCls.getIdArray(domainidArray[i]);
155095
155418
  chainidArray.push(idArray[0] + '_' + idArray[1]);
155096
155419
  }
155097
155420
 
@@ -155134,14 +155457,14 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155134
155457
  await ic.pdbParserCls.downloadUrl(url, type, me.cfg.command);
155135
155458
  }
155136
155459
  else if(me.cfg.mmtfid !== undefined) {
155137
- 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
155460
+ // 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
155138
155461
  ic.inputid = me.cfg.mmtfid;
155139
155462
  ic.loadCmd = 'load mmtf ' + me.cfg.mmtfid;
155140
155463
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155141
155464
  await ic.bcifParserCls.downloadBcif(me.cfg.mmtfid);
155142
155465
  }
155143
155466
  else if(me.cfg.bcifid !== undefined) {
155144
- 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
155467
+ // 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
155145
155468
  ic.inputid = me.cfg.bcifid;
155146
155469
  ic.loadCmd = 'load bcif ' + me.cfg.bcifid;
155147
155470
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -155316,6 +155639,12 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
155316
155639
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155317
155640
  await ic.mmcifParserCls.downloadMmcif(me.cfg.mmcifid);
155318
155641
  }
155642
+ else if(me.cfg.codid !== undefined) {
155643
+ ic.inputid = me.cfg.codid;
155644
+ ic.loadCmd = 'load cod ' + me.cfg.codid;
155645
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
155646
+ await ic.mmcifParserCls.downloadCod(me.cfg.codid);
155647
+ }
155319
155648
  else if(me.cfg.align !== undefined) {
155320
155649
  // ic.bNCBI = true;
155321
155650
  if(me.cfg.align.indexOf('185055,') != -1) {
@@ -155476,6 +155805,8 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
155476
155805
 
155477
155806
  reject('error');
155478
155807
  }
155808
+
155809
+ me.icn3d.ParserUtilsCls.hideLoading();
155479
155810
  }
155480
155811
  else {
155481
155812
  me.icn3d.ParserUtilsCls.showLoading();
@@ -155628,18 +155959,6 @@ iCn3DUI.prototype.setDialogAjax = function() { let me = this;
155628
155959
  });
155629
155960
  };
155630
155961
 
155631
- /*
155632
- iCn3DUI.prototype.setIcn3dui = function(id) { let me = this;
155633
- let idArray = id.split('_'); // id: div0_reload_pdbfile
155634
- ic.pre = idArray[0] + "_";
155635
- if(window.icn3duiHash !== undefined && window.icn3duiHash.hasOwnProperty(idArray[0])) { // for multiple 3D display
155636
- me = window.icn3duiHash[idArray[0]];
155637
- }
155638
- return me;
155639
- };
155640
- */
155641
-
155642
-
155643
155962
  // required by npm
155644
155963
  class printMsg {
155645
155964
  constructor() {