icn3d 3.54.3 → 3.54.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.module.js CHANGED
@@ -2550,7 +2550,147 @@ var CIFTools;
2550
2550
  }
2551
2551
  return result(file);
2552
2552
  }
2553
+ /**
2554
+ * Small-molecule / crystallographic ("core") CIF support, e.g. files from COD.
2555
+ * Core CIF uses underscore names (_atom_site_label, _atom_site_fract_x) and fractional
2556
+ * coordinates, while iCn3D's loadCIF expects mmCIF names (_atom_site.label_atom_id)
2557
+ * and Cartesian coordinates. Without conversion getCategory("_atom_site") returns undefined.
2558
+ * This converts such a file to a minimal mmCIF text before it is parsed.
2559
+ */
2560
+ function isCoreCif(data) {
2561
+ return /^\s*_atom_site_fract_x\b/m.test(data) && !/^\s*_atom_site\./m.test(data);
2562
+ }
2563
+ // tokenize one CIF text keeping quotes; returns {tags:[...], loops:[{cols, rows}], singles:{}}
2564
+ function coreTokens(data) {
2565
+ var tokens = [], lines = data.split(/\r?\n/), i, line, m, re = /'([^']*)'(?=\s|$)|"([^"]*)"(?=\s|$)|(\S+)/g;
2566
+ for (i = 0; i < lines.length; i++) {
2567
+ line = lines[i];
2568
+ if (line.charAt(0) === ';') { // multi-line text field, skip it
2569
+ i++;
2570
+ while (i < lines.length && lines[i].charAt(0) !== ';') i++;
2571
+ tokens.push({ v: '?', t: 'text' });
2572
+ continue;
2573
+ }
2574
+ re.lastIndex = 0;
2575
+ while ((m = re.exec(line)) !== null) {
2576
+ if (m[3] !== undefined && m[3].charAt(0) === '#') break; // comment
2577
+ tokens.push(m[3] !== undefined ? { v: m[3] } : { v: (m[1] !== undefined ? m[1] : m[2]), t: 'quoted' });
2578
+ }
2579
+ }
2580
+ return tokens;
2581
+ }
2582
+ function coreToNumber(s) {
2583
+ var v = parseFloat(String(s).replace(/\(\d+\)$/, '')); // 0.7556(3) -> 0.7556
2584
+ return isNaN(v) ? 0 : v;
2585
+ }
2586
+ // symmetry operator like "1/2-x,y,1/2+z" -> function(frac) -> frac
2587
+ function coreSymop(str) {
2588
+ var parts = str.replace(/\s+/g, '').toLowerCase().split(','), rows = [], p, k, re = /([+-]?)(?:(\d+(?:\.\d+)?)(?:\/(\d+))?|([xyz]))/g, m, row, c;
2589
+ if (parts.length !== 3) return null;
2590
+ for (p = 0; p < 3; p++) {
2591
+ row = [0, 0, 0, 0]; // x y z const
2592
+ re.lastIndex = 0;
2593
+ while ((m = re.exec(parts[p])) !== null) {
2594
+ c = (m[1] === '-') ? -1 : 1;
2595
+ if (m[4]) { row['xyz'.indexOf(m[4])] += c; }
2596
+ else { row[3] += c * parseFloat(m[2]) / (m[3] ? parseFloat(m[3]) : 1); }
2597
+ }
2598
+ rows.push(row);
2599
+ }
2600
+ return function (f) {
2601
+ var out = [];
2602
+ for (k = 0; k < 3; k++) out.push(rows[k][0] * f[0] + rows[k][1] * f[1] + rows[k][2] * f[2] + rows[k][3]);
2603
+ return out;
2604
+ };
2605
+ }
2606
+ function convertCoreCif(data) {
2607
+ var tk = coreTokens(data), i = 0, n = tk.length, single = {}, loops = [], name = 'data_core', t, cols, rows, cur;
2608
+ function isTag(x) { return x && !x.t && x.v.charAt(0) === '_'; }
2609
+ while (i < n) {
2610
+ t = tk[i];
2611
+ if (!t.t && /^data_/i.test(t.v)) { name = t.v; i++; }
2612
+ else if (!t.t && /^loop_$/i.test(t.v)) {
2613
+ i++; cols = []; rows = [];
2614
+ while (i < n && isTag(tk[i])) cols.push(tk[i++].v.toLowerCase());
2615
+ cur = [];
2616
+ while (i < n && !isTag(tk[i]) && !(/^(loop_|data_)/i.test(tk[i].v) && !tk[i].t)) {
2617
+ cur.push(tk[i++].v);
2618
+ if (cur.length === cols.length) { rows.push(cur); cur = []; }
2619
+ }
2620
+ loops.push({ cols: cols, rows: rows });
2621
+ }
2622
+ else if (isTag(t)) { single[t.v.toLowerCase()] = (tk[i + 1] ? tk[i + 1].v : '?'); i += 2; }
2623
+ else i++;
2624
+ }
2625
+ var atoms = null, symops = [], l, c;
2626
+ for (l = 0; l < loops.length; l++) {
2627
+ if (loops[l].cols.indexOf('_atom_site_fract_x') >= 0) atoms = loops[l];
2628
+ c = loops[l].cols.indexOf('_symmetry_equiv_pos_as_xyz');
2629
+ if (c < 0) c = loops[l].cols.indexOf('_space_group_symop_operation_xyz');
2630
+ if (c >= 0) loops[l].rows.forEach(function (r) { var f = coreSymop(r[c]); if (f) symops.push(f); });
2631
+ }
2632
+ if (!atoms) return null;
2633
+ if (!symops.length) symops.push(coreSymop('x,y,z'));
2634
+
2635
+ // orthogonalization matrix (a along x, c* along z)
2636
+ var a = coreToNumber(single['_cell_length_a']), b = coreToNumber(single['_cell_length_b']), cc = coreToNumber(single['_cell_length_c']);
2637
+ var al = coreToNumber(single['_cell_angle_alpha'] || 90) * Math.PI / 180, be = coreToNumber(single['_cell_angle_beta'] || 90) * Math.PI / 180, ga = coreToNumber(single['_cell_angle_gamma'] || 90) * Math.PI / 180;
2638
+ var cosa = Math.cos(al), cosb = Math.cos(be), cosg = Math.cos(ga), sing = Math.sin(ga);
2639
+ var vol = Math.sqrt(1 - cosa * cosa - cosb * cosb - cosg * cosg + 2 * cosa * cosb * cosg);
2640
+ function toCart(f) {
2641
+ return [a * f[0] + b * cosg * f[1] + cc * cosb * f[2],
2642
+ b * sing * f[1] + cc * (cosa - cosb * cosg) / sing * f[2],
2643
+ cc * vol / sing * f[2]];
2644
+ }
2645
+ var col = {}; atoms.cols.forEach(function (x, k) { col[x] = k; });
2646
+ function get(r, key) { return (col[key] === undefined) ? '?' : r[col[key]]; }
2647
+
2648
+ var out = [name, '#', '_entry.id ' + name.substr(5), '#'];
2649
+ // core CIF "_cell_length_a" -> mmCIF "_cell.length_a" so iCn3D can parse the unit cell
2650
+ Object.keys(single).forEach(function (key) {
2651
+ if (/^_cell_/.test(key)) out.push(key.replace(/^_cell_/, '_cell.') + ' ' + String(single[key]).replace(/\(\d+\)$/, ''));
2652
+ });
2653
+ out.push('#');
2654
+ out.push(
2655
+ 'loop_', '_atom_site.group_PDB', '_atom_site.id', '_atom_site.type_symbol', '_atom_site.label_atom_id', '_atom_site.label_alt_id',
2656
+ '_atom_site.label_comp_id', '_atom_site.label_asym_id', '_atom_site.label_entity_id', '_atom_site.label_seq_id',
2657
+ '_atom_site.Cartn_x', '_atom_site.Cartn_y', '_atom_site.Cartn_z', '_atom_site.occupancy', '_atom_site.B_iso_or_equiv',
2658
+ '_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;
2660
+ for (r = 0; r < atoms.rows.length; r++) {
2661
+ var row = atoms.rows[r];
2662
+ if (get(row, '_atom_site_calc_flag') === 'dum') continue; // dummy atoms
2663
+ f = [coreToNumber(get(row, '_atom_site_fract_x')), coreToNumber(get(row, '_atom_site_fract_y')), coreToNumber(get(row, '_atom_site_fract_z'))];
2664
+ lab = get(row, '_atom_site_label');
2665
+ sym = get(row, '_atom_site_type_symbol'); if (sym === '?') sym = lab;
2666
+ el = (sym.match(/^[A-Za-z]{1,2}/) || ['X'])[0];
2667
+ el = el.charAt(0).toUpperCase() + el.substr(1).toLowerCase();
2668
+ var mySeen = [];
2669
+ for (s = 0; s < symops.length; s++) {
2670
+ g = symops[s](f).map(function (v) { return v - Math.floor(v + 1e-6); });
2671
+ dup = false;
2672
+ for (j = 0; j < mySeen.length; j++) {
2673
+ if (Math.abs(mySeen[j][0] - g[0]) < 1e-3 && Math.abs(mySeen[j][1] - g[1]) < 1e-3 && Math.abs(mySeen[j][2] - g[2]) < 1e-3) { dup = true; break; }
2674
+ }
2675
+ if (dup) continue;
2676
+ 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(' '));
2680
+ }
2681
+ }
2682
+ out.push('#');
2683
+ return out.join('\n') + '\n';
2684
+ }
2553
2685
  function parse(data) {
2686
+ if (isCoreCif(data)) {
2687
+ var converted = convertCoreCif(data);
2688
+ if (converted) data = converted;
2689
+ }
2690
+ else {
2691
+ // "_cell_angle_alpha" -> "_cell.angle_alpha"
2692
+ data = data.replace(/^(\s*_cell)_(?=\w)/gm, '$1.');
2693
+ }
2554
2694
  return parseInternal(data);
2555
2695
  }
2556
2696
  Text.parse = parse;
@@ -60275,6 +60415,16 @@ class ClickMenu {
60275
60415
  thisClass.setLogCmd('set axis off', true);
60276
60416
  });
60277
60417
 
60418
+ me.myEventCls.onIds("#" + me.pre + "mn6_showucYes", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
60419
+ ic.setOptionCls.setOption('unitcell', 'yes');
60420
+ thisClass.setLogCmd('set unitcell on', true);
60421
+ });
60422
+
60423
+ me.myEventCls.onIds("#" + me.pre + "mn6_showucNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
60424
+ ic.setOptionCls.setOption('unitcell', 'no');
60425
+ thisClass.setLogCmd('set unitcell off', true);
60426
+ });
60427
+
60278
60428
  me.myEventCls.onIds("#" + me.pre + "mn6_symmetry", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
60279
60429
  ic.bAxisOnly = false;
60280
60430
  await ic.symdCls.retrieveSymmetry(Object.keys(ic.structures)[0]);
@@ -61594,6 +61744,15 @@ class SetMenu {
61594
61744
  html += "</ul>";
61595
61745
  html += "</li>";
61596
61746
 
61747
+ // if(me.cfg.mmcifid !== undefined) {
61748
+ html += this.getMenuText('mn2_unitcell', 'Unit Cell', undefined, undefined, 1);
61749
+ html += "<ul>";
61750
+ html += this.getRadio('mn6_showuc', 'mn6_showucYes', 'Show', undefined, undefined, 2);
61751
+ html += this.getRadio('mn6_showuc', 'mn6_showucNo', 'Hide', true, undefined, 2);
61752
+ html += "</ul>";
61753
+ html += "</li>";
61754
+ // }
61755
+
61597
61756
  html += this.getMenuSep();
61598
61757
 
61599
61758
  html += this.getMenuText('mn2_resetwrap', 'Reset', undefined, 1, 1);
@@ -82557,6 +82716,57 @@ class Axes {
82557
82716
 
82558
82717
  return axisPos;
82559
82718
  }
82719
+
82720
+ buildUnitcell() { let ic = this.icn3d, me = ic.icn3dui;
82721
+ if(!ic.cell) {
82722
+ var aaa = 1; //alert("Unit cell information is available for structures from mmCIF files. Please load a structure with 'mmcifid=', 'bcifid=', or from a mmCIF file.");
82723
+ return;
82724
+ }
82725
+
82726
+ let a = ic.cell.length_a;
82727
+ let b = ic.cell.length_b;
82728
+ let c = ic.cell.length_c;
82729
+ let alpha = ic.cell.angle_alpha;
82730
+ let beta = ic.cell.angle_beta;
82731
+ let gamma = ic.cell.angle_gamma;
82732
+
82733
+ const rad = d => d * Math.PI / 180;
82734
+ const ca = Math.cos(rad(alpha));
82735
+ const cb = Math.cos(rad(beta));
82736
+ const cg = Math.cos(rad(gamma));
82737
+ const sg = Math.sin(rad(gamma));
82738
+
82739
+ // Lattice vectors
82740
+ const va = [a, 0, 0];
82741
+ const vb = [b * cg, b * sg, 0];
82742
+ const cx = c * cb;
82743
+ const cy = c * (ca - cb * cg) / sg;
82744
+ const cz = Math.sqrt(c * c - cx * cx - cy * cy);
82745
+ const vc = [cx, cy, cz];
82746
+
82747
+ // 8 corners, indexed by bits (i, j, k) -> i*va + j*vb + k*vc
82748
+ const corner = (i, j, k) => [0, 1, 2].map(n => i * va[n] + j * vb[n] + k * vc[n]);
82749
+
82750
+ let color = me.htmlCls.ORANGE, radius = 0.1;
82751
+ let atomColor = me.parasCls.thr(color);
82752
+
82753
+ for (let i = 0; i < 2; i++) {
82754
+ for (let j = 0; j < 2; j++) {
82755
+ ic.analysisCls.addLine(corner(0, i, j)[0], corner(0, i, j)[1], corner(0, i, j)[2], corner(1, i, j)[0], corner(1, i, j)[1], corner(1, i, j)[2], color, false, 'unitcell', radius); // edges along a
82756
+ ic.analysisCls.addLine(corner(i, 0, j)[0], corner(i, 0, j)[1], corner(i, 0, j)[2], corner(i, 1, j)[0], corner(i, 1, j)[1], corner(i, 1, j)[2], color, false, 'unitcell', radius); // edges along b
82757
+ ic.analysisCls.addLine(corner(i, j, 0)[0], corner(i, j, 0)[1], corner(i, j, 0)[2], corner(i, j, 1)[0], corner(i, j, 1)[1], corner(i, j, 1)[2], color, false, 'unitcell', radius); // edges along c
82758
+ }
82759
+ }
82760
+
82761
+ // add sphere at each corner
82762
+ for (let i = 0; i < 2; i++) {
82763
+ for (let j = 0; j < 2; j++) {
82764
+ for (let k = 0; k < 2; k++) {
82765
+ ic.sphereCls.createSphereBase(new Vector3$1(corner(i, j, k)[0], corner(i, j, k)[1], corner(i, j, k)[2]), atomColor, radius, 1, false, false, 1);
82766
+ }
82767
+ }
82768
+ }
82769
+ }
82560
82770
  }
82561
82771
 
82562
82772
  /**
@@ -86553,7 +86763,7 @@ class ApplyOther {
86553
86763
  ic.applyCenterCls.applyCenterOptions(options);
86554
86764
 
86555
86765
  ic.axesCls.buildAllAxes(undefined, true);
86556
-
86766
+
86557
86767
  switch (options.axis.toLowerCase()) {
86558
86768
  case 'yes':
86559
86769
  ic.axis = true;
@@ -86564,6 +86774,19 @@ class ApplyOther {
86564
86774
  ic.axis = false;
86565
86775
  break;
86566
86776
  }
86777
+
86778
+ ic.lines['unitcell'] = []; // reset
86779
+
86780
+ switch (options.unitcell.toLowerCase()) {
86781
+ case 'yes':
86782
+ ic.unitcell = true;
86783
+ ic.axesCls.buildUnitcell();
86784
+
86785
+ break;
86786
+ case 'no':
86787
+ ic.unitcell = false;
86788
+ break;
86789
+ }
86567
86790
  switch (options.pk.toLowerCase()) {
86568
86791
  case 'atom':
86569
86792
  ic.pk = 1;
@@ -116446,7 +116669,8 @@ class ShowAnno {
116446
116669
  }
116447
116670
 
116448
116671
  let nucleotide_chainid = {}, chemical_chainid = {}, chemical_set = {};
116449
- //ic.protein_chainid = {};
116672
+ // ic.protein_chainid = {};
116673
+
116450
116674
 
116451
116675
  if(ic.bAnnoShown === undefined || !ic.bAnnoShown || ic.bResetAnno) { // ic.bResetAnno when loading another structure
116452
116676
  ic.protein_chainid = {};
@@ -116473,7 +116697,7 @@ class ShowAnno {
116473
116697
  dialogWidth =(me.cfg.notebook) ? me.htmlCls.WIDTH / 2 : $("#" + ic.pre + "dl_selectannotations").dialog( "option", "width" );
116474
116698
  }
116475
116699
  ic.seqAnnWidth = dialogWidth - 120 - 30*2 - 50; // title: 120px, start and end resi: 30px, extra space on the left and right: 50px
116476
-
116700
+
116477
116701
  for(let i = 0, il = chainArray.length; i < il; ++i) {
116478
116702
  if(!ic.chainsSeq[chainArray[i]]) continue; // skip empty chain
116479
116703
 
@@ -116583,8 +116807,8 @@ class ShowAnno {
116583
116807
 
116584
116808
  await ic.mmcifParserCls.downloadMmcifSymmetry(id, 'mmtfid');
116585
116809
  }
116586
-
116587
- await this.showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set);
116810
+
116811
+ await this.showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set);
116588
116812
  }
116589
116813
  }
116590
116814
  else if(me.cfg.blast_rep_id !== undefined && !ic.bSmithwm && !ic.bLocalSmithwm) { // align sequence to structure
@@ -127084,7 +127308,10 @@ class PdbParser {
127084
127308
 
127085
127309
  ic.saveFileCls.showTitle();
127086
127310
 
127087
- if(me.cfg.rotate !== undefined) ic.resizeCanvasCls.rotStruc(me.cfg.rotate, true);
127311
+ // if(me.cfg.rotate !== undefined) {
127312
+ if(me.cfg.rotate !== undefined && !(me.cfg.url && me.cfg.url.indexOf('membranome') != -1)) {
127313
+ ic.resizeCanvasCls.rotStruc(me.cfg.rotate, true);
127314
+ }
127088
127315
 
127089
127316
  if(bAppend && Object.keys(ic.structures).length == 1 && !me.bNode) {
127090
127317
  // show all
@@ -131337,6 +131564,7 @@ class ParserUtils {
131337
131564
  let angle = -0.5 * Math.PI;
131338
131565
  ic.transformCls.setRotation(axis, angle);
131339
131566
  }
131567
+
131340
131568
  //if(Object.keys(ic.structures).length > 1) {
131341
131569
  // $("#" + ic.pre + "alternate").show();
131342
131570
  //}
@@ -135299,6 +135527,16 @@ class LoadCIF {
135299
135527
  = m24Array = m31Array = m32Array = m33Array = m34Array = [];
135300
135528
  }
135301
135529
 
135530
+ if(block.getCategory("_cell")) {
135531
+ ic.cell = {};
135532
+ ic.cell.length_a = parseFloat(block.getCategory("_cell").getColumn("length_a").getString(0));
135533
+ ic.cell.length_b = parseFloat(block.getCategory("_cell").getColumn("length_b").getString(0));
135534
+ ic.cell.length_c = parseFloat(block.getCategory("_cell").getColumn("length_c").getString(0));
135535
+ ic.cell.angle_alpha = parseFloat(block.getCategory("_cell").getColumn("angle_alpha").getString(0));
135536
+ ic.cell.angle_beta = parseFloat(block.getCategory("_cell").getColumn("angle_beta").getString(0));
135537
+ ic.cell.angle_gamma = parseFloat(block.getCategory("_cell").getColumn("angle_gamma").getString(0));
135538
+ }
135539
+
135302
135540
  // if (record === 'ENDMDL') {
135303
135541
  // ++moleculeNum;
135304
135542
  // id = ic.defaultPdbId;
@@ -135411,6 +135649,7 @@ class LoadCIF {
135411
135649
  let sChain = {};
135412
135650
  let prevModelNum = '';
135413
135651
  if(!ic.molid2chain) ic.molid2chain = {};
135652
+
135414
135653
  for (let i = 0; i < atomSize; ++i) {
135415
135654
  let modelNum = modelNumArray.getString(i);
135416
135655
  if(i > 0 && modelNum != prevModelNum) {
@@ -135641,7 +135880,7 @@ class LoadCIF {
135641
135880
  // if(oriResidueNum !== prevOriResidueNum) {
135642
135881
  if(oriResidueNum !== prevOriResidueNum || chain + "_" + resn != prevResn || prevAutochain != autochain) {
135643
135882
  let residue = me.utilsCls.residueName2Abbr(resn);
135644
-
135883
+
135645
135884
  ic.residueId2Name[residueNum] = residue;
135646
135885
 
135647
135886
  if(serial !== 1 && prevResidueNum !== '') {
@@ -135766,7 +136005,7 @@ class LoadCIF {
135766
136005
 
135767
136006
  resiArray = oriResiArray = resnArray = chainArray = [];
135768
136007
  }
135769
-
136008
+
135770
136009
  this.setSeq(structure, sChain, mChainSeq, ligSeqHash);
135771
136010
  }
135772
136011
 
@@ -135968,17 +136207,22 @@ class LoadCIF {
135968
136207
  }
135969
136208
 
135970
136209
  setSeq(structure, sChain, mChainSeq, ligSeqHash) { let ic = this.icn3d; ic.icn3dui;
136210
+ // sometimes a chain appears in both ligSeqHash and mChainSeq, e.g., mmcif data for 1TOP
136211
+ /*
135971
136212
  for(let chain in sChain) {
135972
136213
  let chainNum = structure + '_' + chain;
135973
136214
 
135974
- if(ligSeqHash.hasOwnProperty(chain)) {
136215
+ if(mChainSeq.hasOwnProperty(chain)) {
136216
+ ic.chainsSeq[chainNum] = mChainSeq[chain];
136217
+ }
136218
+ else if(ligSeqHash.hasOwnProperty(chain)) {
135975
136219
  ic.chainsSeq[chainNum] = ligSeqHash[chain];
135976
136220
  }
135977
136221
  else {
135978
136222
  ic.chainsSeq[chainNum] = mChainSeq[chain];
135979
136223
  }
135980
136224
  }
135981
-
136225
+ */
135982
136226
  ic.loadPDBCls.setResidMapping();
135983
136227
  }
135984
136228
  }
@@ -136917,6 +137161,14 @@ class ApplyCommand {
136917
137161
  ic.opts['axis'] = 'no';
136918
137162
  ic.pc1 = false;
136919
137163
  }
137164
+ else if(command == 'set unitcell on') {
137165
+ ic.opts['unitcell'] = 'yes';
137166
+ ic.drawCls.draw();
137167
+ }
137168
+ else if(command == 'set unitcell off') {
137169
+ ic.opts['unitcell'] = 'no';
137170
+ ic.drawCls.draw();
137171
+ }
136920
137172
  else if(command == 'set fog on') {
136921
137173
  ic.opts['fog'] = 'yes';
136922
137174
  ic.fogCls.setFog(true);
@@ -147399,9 +147651,10 @@ class Diagram2d {
147399
147651
  // get the residues in the selection
147400
147652
  let ncbiresid = data;
147401
147653
  let resid = ic.ncbi2resid[ncbiresid];
147402
- let resi = resid.substr(resid.lastIndexOf('_') + 1);
147403
147654
 
147404
- if(ic.ig2ddgm_chainid && ic.resid2refnum && ic.resid2refnum[resid]) {
147655
+ if(resid && ic.ig2ddgm_chainid && ic.resid2refnum && ic.resid2refnum[resid]) {
147656
+ let resi = resid.substr(resid.lastIndexOf('_') + 1);
147657
+
147405
147658
  let refnumLabel = ic.resid2refnum[resid];
147406
147659
  let refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
147407
147660
 
@@ -151174,7 +151427,8 @@ class SaveFile {
151174
151427
  idName = "PDB ID";
151175
151428
  }
151176
151429
  else if(bAlphaFold) {
151177
- idName = "AlphaFold ID";
151430
+ // idName = "AlphaFold ID";
151431
+ idName = "ID";
151178
151432
  }
151179
151433
 
151180
151434
  if(structureidArray.length > 1) {
@@ -154095,6 +154349,7 @@ class iCn3D {
154095
154349
  this.radiusArraySphere = new Array();
154096
154350
 
154097
154351
  this.axis = false; // used to turn on and off xyz axes
154352
+ this.unitcell = false; // used to turn on and off unit cell
154098
154353
 
154099
154354
  // pk
154100
154355
  //If its value is 1, selecting an atom will select the atom. If its value is 2, selecting an atom
@@ -154216,6 +154471,7 @@ class iCn3D {
154216
154471
  this.optsOri['clbonds'] = 'yes'; //yes, no
154217
154472
  this.optsOri['rotationcenter'] = 'molecule center'; //molecule center, pick center, display center
154218
154473
  this.optsOri['axis'] = 'no'; //yes, no
154474
+ this.optsOri['unitcell'] = 'no'; //yes, no
154219
154475
  this.optsOri['fog'] = 'no'; //yes, no
154220
154476
  this.optsOri['slab'] = 'no'; //yes, no
154221
154477
  this.optsOri['pk'] = 'residue'; //no, atom, residue, strand, chain
@@ -154633,7 +154889,7 @@ class iCn3DUI {
154633
154889
  //even when multiple iCn3D viewers are shown together.
154634
154890
  this.pre = this.cfg.divid + "_";
154635
154891
 
154636
- this.REVISION = '3.54.1';
154892
+ this.REVISION = '3.54.2';
154637
154893
 
154638
154894
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154639
154895
  this.bNode = (Object.keys(window).length < 3) ? true : false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icn3d",
3
- "version": "3.54.3",
3
+ "version": "3.54.5",
4
4
  "main": "./icn3d.js",
5
5
  "exports": {
6
6
  ".": {