icn3d 3.38.2 → 3.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.js CHANGED
@@ -14252,7 +14252,7 @@ class SetDialog {
14252
14252
  html += me.htmlCls.divStr + "dl_collectionsMenu'>";
14253
14253
  html += '<b>Collection File</b>: <div style="width:20px; margin-top:6px; display:inline-block;"><span id="' + me.pre + 'dl_collection_file_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="display:none; width:15px;" title="Expand"></span><span id="' + me.pre + 'dl_collection_file_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="width:15px;" title="Shrink"></span></div><br>';
14254
14254
  html += me.htmlCls.divStr + "dl_collection_file' style=''>";
14255
- html += "You can load a collection of structures via a file. Here is <a href='https://github.com/ncbi/icn3d/blob/master/example/collection.json' target='_blank'>one example file</a><br><br>";
14255
+ html += "You can load a collection of structures via a file. Here are <a href='https://github.com/ncbi/icn3d/blob/master/example/collection/' target='_blank'>some example files</a><br><br>";
14256
14256
  html += "Collection file: " + me.htmlCls.inputFileStr + "id='" + me.pre + "collectionfile'><br/>";
14257
14257
  html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
14258
14258
  html += "</div>";
@@ -14260,7 +14260,26 @@ class SetDialog {
14260
14260
  html += '<br/><b>Structures</b>: <div style="width:20px; margin-top:6px; display:inline-block;"><span id="' + me.pre + 'dl_collection_structures_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="' + me.pre + 'dl_collection_structures_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="display:none; width:15px;" title="Shrink"></span></div><br>';
14261
14261
  html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
14262
14262
  html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
14263
+ html += '<br/>';
14264
+ html += me.htmlCls.buttonStr + "opendl_export_collections'>Export</button>";
14263
14265
  html += "</div>";
14266
+ html += '<br/>';
14267
+ html += "</div>";
14268
+
14269
+ html += me.htmlCls.divStr + "dl_export_collections' class='" + dialogClass + "'>";
14270
+ html += this.addNotebookTitle('dl_export_collections', 'Export Collections');
14271
+ html += "<label for='dl_collectionTitle'>Collection Title: </label>";
14272
+ html += "<input type='text' id='dl_collectionTitle' name='collectionTitle' placeholder='Enter collection title' />";
14273
+ html += '<br/>';
14274
+ html += "<label for='dl_collectionDescription'>Collection Description: </label>";
14275
+ html += "<input type='text' id='dl_collectionDescription' name='collectionDescription' placeholder='Enter collection description' />";
14276
+ html += '<br/>';
14277
+ html += "<input type='radio' id='dl_collectionExportSelected' name='exportOption' value='selected' />";
14278
+ html += "<label for='dl_collectionExportSelected'>Selected</label>";
14279
+ html += "<input type='radio' id='dl_collectionExportAll' name='exportOption' value='all' />";
14280
+ html += "<label for='dl_collectionExportAll'>All</label>";
14281
+ html += '<br/>';
14282
+ html += me.htmlCls.buttonStr + "export_collections'>Export</button>";
14264
14283
  html += "</div>";
14265
14284
 
14266
14285
  html += me.htmlCls.divStr + "dl_menuloadpref' class='" + dialogClass + "'>";
@@ -15591,8 +15610,8 @@ class Events {
15591
15610
 
15592
15611
  saveHtml(id) { let me = this.icn3dui, ic = me.icn3d;
15593
15612
  let html = '';
15594
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/lib/jquery-ui-1.13.2.min.css">\n';
15595
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/icn3d_full_ui.css">\n';
15613
+ html += '<link rel="stylesheet" href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/jquery-ui-1.13.2.min.css">\n';
15614
+ html += '<link rel="stylesheet" href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d_full_ui.css">\n';
15596
15615
  html += $("#" + id).html();
15597
15616
  let idArray = id.split('_');
15598
15617
  let idStr =(idArray.length > 2) ? idArray[2] : id;
@@ -16681,7 +16700,6 @@ class Events {
16681
16700
 
16682
16701
  urlTarget = '_blank';
16683
16702
 
16684
- console.log("smiles: " + $("#" + me.pre + "smiles").val() + " encode: " + encodeURIComponent($("#" + me.pre + "smiles").val()));
16685
16703
  window.open(hostUrl + '?smiles=' + encodeURIComponent($("#" + me.pre + "smiles").val()), urlTarget);
16686
16704
  });
16687
16705
 
@@ -16764,28 +16782,232 @@ class Events {
16764
16782
  $(".ui-dialog-content").dialog("close");
16765
16783
  } else {
16766
16784
  ic.resizeCanvasCls.closeDialogs();
16767
- }
16785
+ }
16786
+ ic.bInputfile = false;
16787
+ ic.pdbCollection = [];
16788
+ ic.allData = {};
16789
+ ic.allData['all'] = {
16790
+ 'atoms': {},
16791
+ 'proteins': {},
16792
+ 'nucleotides': {},
16793
+ 'chemicals': {},
16794
+ 'ions': {},
16795
+ 'water': {},
16796
+ 'structures': {}, // getSSExpandedAtoms
16797
+ 'ssbondpnts': {},
16798
+ 'residues': {}, // getSSExpandedAtoms
16799
+ 'chains': {},
16800
+ 'chainsSeq': {}, //Sequences and Annotation
16801
+ 'defNames2Atoms': {},
16802
+ 'defNames2Residues': {}
16803
+ };
16804
+ ic.allData['prev'] = {};
16805
+ ic.selectCollectionsCls.reset();
16806
+
16807
+ ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
16808
+ ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
16768
16809
  me.htmlCls.setHtmlCls.fileSupport();
16810
+
16811
+ let fileName = file.name;
16812
+ let fileExtension = fileName.split('.').pop().toLowerCase();
16813
+
16814
+ $("#" + ic.pre + "collections_menu").empty();
16815
+ $("#" + ic.pre + "collections_menu").off("change");
16816
+
16817
+ function parseJsonCollection(data) {
16818
+ let dataStr = JSON.parse(data);
16819
+ return dataStr["structures"].map(({ id, title, description, commands }) => {
16820
+ if (id && id.includes('.pdb')) {
16821
+ id = id.split('.pdb')[0];
16822
+ }
16823
+ return [id, title, description, commands, false];
16824
+ });
16825
+ }
16826
+
16827
+ function parsePdbCollection(data, description = '', commands = []) {
16828
+ let dataStr = data;
16829
+ let lines = dataStr.split('\n');
16830
+
16831
+ let sections = [];
16832
+ let currentSection = [];
16833
+
16834
+ lines.forEach(line => {
16835
+ if (line.startsWith('HEADER')) {
16836
+ currentSection = [];
16837
+ sections.push(currentSection);
16838
+ }
16839
+ currentSection.push(line);
16840
+ });
16841
+
16842
+ let ids = [];
16843
+ let titles = [];
16844
+
16845
+ sections.forEach((section) => {
16846
+ let headerLine = section[0];
16847
+ headerLine = headerLine.replace(/[\n\r]/g, '').trim();
16848
+ let header = headerLine.split(' ').filter(Boolean);
16849
+ let lastElement = header[header.length - 1];
16850
+ ids.push(lastElement);
16851
+ titles.push(section[1].startsWith('TITLE') ? section[1].split('TITLE').pop().trim() : lastElement);
16852
+ });
16853
+
16854
+ if (sections.length > 0) {
16855
+ ic.pdbCollection.push(...sections);
16856
+ }
16857
+
16858
+ return ids.map((id, index, description, commands) => [id, titles[index], description, commands, true]);
16859
+ }
16860
+
16861
+ let collection = [];
16862
+
16863
+ if (fileExtension === 'json' || fileExtension === 'pdb') {
16769
16864
  let reader = new FileReader();
16770
-
16771
16865
  reader.onload = async function (e) {
16772
- let dataStr = JSON.parse(e.target.result);
16773
- let collection = [dataStr["structures"].map(({ id }) => id), dataStr["structures"].map(({ title }) => title)];
16774
- let collectionHtml = ic.selectCollectionsCls.setAtomMenu(collection[0], collection[1]);
16866
+ if (fileExtension === 'json') {
16867
+ collection = parseJsonCollection(e.target.result);
16868
+ } else if (fileExtension === 'pdb') {
16869
+ ic.bInputfile = true;
16870
+ collection = parsePdbCollection(e.target.result);
16871
+ }
16775
16872
 
16776
- $("#" + ic.pre + "collections_menu").html(collectionHtml);
16777
- ic.selectCollectionsCls.clickStructure();
16778
-
16779
- $("#" + ic.pre + "collections_menu").trigger("change");
16780
-
16781
- me.htmlCls.clickMenuCls.setLogCmd(
16782
- "load collection file " +
16783
- $("#" + me.pre + "collectionfile").val(),
16784
- false
16785
- );
16786
-
16787
- };
16788
- reader.readAsText(file);
16873
+ let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
16874
+
16875
+ $("#" + ic.pre + "collections_menu").html(collectionHtml);
16876
+ await ic.selectCollectionsCls.clickStructure(collection);
16877
+ $("#" + ic.pre + "collections_menu").trigger("change");
16878
+
16879
+ me.htmlCls.clickMenuCls.setLogCmd(
16880
+ "load collection file " +
16881
+ $("#" + me.pre + "collectionfile").val(),
16882
+ false
16883
+ );
16884
+ };
16885
+
16886
+ reader.readAsText(file);
16887
+ } else if (fileExtension === 'zip' || fileExtension === 'gz') {
16888
+ ic.bInputfile = true;
16889
+ let reader2 = new FileReader();
16890
+ reader2.onload = async function (e) {
16891
+ if (fileExtension === 'zip') {
16892
+ let url = './script/jszip.js';
16893
+ await me.getAjaxPromise(url, 'script');
16894
+
16895
+ let jszip = new JSZip();
16896
+ try {
16897
+ let data = await jszip.loadAsync(e.target.result);
16898
+
16899
+ let hasJson = false;
16900
+ let hasPdb = false;
16901
+ let hasGz = false;
16902
+ let jsonFiles = [];
16903
+ let pdbFiles = [];
16904
+ let gzFiles = [];
16905
+
16906
+ for (let fileName in data.files) {
16907
+ let file = data.files[fileName];
16908
+ if (!file.dir) {
16909
+ if (fileName.endsWith('.json')) {
16910
+ hasJson = true;
16911
+ jsonFiles.push(file);
16912
+ } else if (fileName.endsWith('.pdb')) {
16913
+ hasPdb = true;
16914
+ pdbFiles.push(file);
16915
+ } else if (fileName.endsWith('.gz')) {
16916
+ hasGz = true;
16917
+ gzFiles.push(file);
16918
+ }
16919
+ }
16920
+ }
16921
+
16922
+ if (hasJson && hasPdb) {
16923
+ let jsonCollection = [];
16924
+ for (const file of jsonFiles) {
16925
+ let fileData = await file.async('text');
16926
+ parseJsonCollection(fileData).forEach(element => {
16927
+ jsonCollection.push(element);
16928
+ });
16929
+ }
16930
+
16931
+ // For each JSON object, check if a corresponding PDB file exists
16932
+ for (const [id, title, description, commands, _] of jsonCollection) {
16933
+ let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
16934
+ if (matchingPdbFile) {
16935
+ let pdbFileData = await matchingPdbFile.async('text');
16936
+ parsePdbCollection(pdbFileData, description, commands).forEach(element => {
16937
+ collection.push(element);
16938
+ });
16939
+ }
16940
+ }
16941
+
16942
+ } else if (hasJson) {
16943
+ // Do something if only JSON files are present
16944
+ jsonFiles.forEach(async file => {
16945
+ let fileData = await file.async('text');
16946
+ parseJsonCollection(fileData).forEach(element => {
16947
+ collection.push(element);
16948
+ });
16949
+ });
16950
+ } else if (hasPdb) {
16951
+ // Do something if only PDB files are present
16952
+ pdbFiles.forEach(async file => {
16953
+ let fileData = await file.async('text');
16954
+ parsePdbCollection(fileData).forEach(element => {
16955
+ collection.push(element);
16956
+ });
16957
+ });
16958
+ } else if (hasGz) {
16959
+ let url = './script/pako.js';
16960
+ await me.getAjaxPromise(url, 'script');
16961
+ try {
16962
+ for (const file of gzFiles) {
16963
+ let compressed = await file.async('uint8array');
16964
+ let decompressed = pako.inflate(compressed, { to: 'string' });
16965
+ parsePdbCollection(decompressed).forEach(element => {
16966
+ collection.push(element);
16967
+ });
16968
+ }
16969
+ } catch (error) {
16970
+ console.error('Error loading GZ file', error);
16971
+ }
16972
+ }
16973
+ } catch (error) {
16974
+ console.error('Error loading ZIP file', error);
16975
+ }
16976
+ } else if (fileExtension === 'gz') {
16977
+ let url = './script/pako.js';
16978
+ await me.getAjaxPromise(url, 'script');
16979
+
16980
+ try {
16981
+ const compressed = new Uint8Array(e.target.result);
16982
+ const decompressed = pako.inflate(compressed, { to: 'string' });
16983
+ collection = parsePdbCollection(decompressed);
16984
+ } catch (error) {
16985
+ console.error('Error loading GZ file', error);
16986
+ }
16987
+ }
16988
+
16989
+ let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
16990
+
16991
+ $("#" + ic.pre + "collections_menu").html(collectionHtml);
16992
+ await ic.selectCollectionsCls.clickStructure(collection);
16993
+
16994
+ $("#" + ic.pre + "collections_menu").trigger("change");
16995
+
16996
+ me.htmlCls.clickMenuCls.setLogCmd(
16997
+ "load collection file " +
16998
+ $("#" + me.pre + "collectionfile").val(),
16999
+ false
17000
+ );
17001
+ };
17002
+
17003
+ reader2.onerror = function(error) {
17004
+ console.error('Error reading file', error);
17005
+ };
17006
+
17007
+ reader2.readAsArrayBuffer(file);
17008
+ } else {
17009
+ throw new Error('Invalid file type');
17010
+ }
16789
17011
 
16790
17012
  if (Object.keys(me.utilsCls.getStructures(ic.dAtoms))){
16791
17013
  $("#" + me.pre + "dl_collection_file").hide();
@@ -16808,6 +17030,90 @@ class Events {
16808
17030
  }
16809
17031
  });
16810
17032
 
17033
+ me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
17034
+ me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
17035
+ });
17036
+
17037
+ me.myEventCls.onIds("#" + me.pre + "export_collections", "click", function (e) {
17038
+ let ic = me.icn3d;
17039
+
17040
+ const selectElement = document.getElementById(me.pre + 'collections_menu');
17041
+
17042
+ // Array to store parsed results
17043
+ const structures = [];
17044
+
17045
+ const dl_collectionExportSelected = document.getElementById('dl_collectionExportSelected');
17046
+ const dl_collectionExportAll = document.getElementById('dl_collectionExportAll');
17047
+
17048
+ if (dl_collectionExportSelected.checked) {
17049
+
17050
+ // Iterate over each <option> element
17051
+ Array.from(selectElement.options)
17052
+ .filter(option => option.selected)
17053
+ .forEach(option => {
17054
+ const name = option.value;
17055
+ const title = option.textContent.trim();
17056
+ const description = option.getAttribute('data-description');
17057
+
17058
+ // Push the extracted data into the array
17059
+ structures.push({
17060
+ id: name,
17061
+ title: title,
17062
+ description: description || '',
17063
+ commands: (ic.allData[name] && ic.allData[name].commands) ? ic.allData[name].commands : []
17064
+ });
17065
+ });
17066
+ } else if (dl_collectionExportAll.checked) {
17067
+ // Iterate over each <option> element
17068
+ Array.from(selectElement.options)
17069
+ .forEach(option => {
17070
+ const name = option.value;
17071
+ const title = option.textContent.trim();
17072
+ const description = option.getAttribute('data-description');
17073
+
17074
+ // Push the extracted data into the array
17075
+ structures.push({
17076
+ name: name,
17077
+ title: title,
17078
+ description: description || '',
17079
+ commands: (ic.allData[name] && ic.allData[name].commands) ? ic.allData[name].commands : []
17080
+ });
17081
+ });
17082
+ }
17083
+
17084
+
17085
+ const now = new Date();
17086
+ const month = now.getMonth() + 1; // Months are zero-based
17087
+ const day = now.getDate();
17088
+ const year = now.getFullYear();
17089
+ const formattedDate = `${month}_${day}_${year}`;
17090
+
17091
+ const collection = {
17092
+ collectionTitle: document.getElementById('dl_collectionTitle').value,
17093
+ collectionDescription: document.getElementById('dl_collectionDescription').value,
17094
+ structures: structures
17095
+ };
17096
+
17097
+ const filename = `${collection.collectionTitle.replace(/\s+/g, '_')}_${formattedDate}.json`;
17098
+
17099
+ const jsonString = JSON.stringify(collection, null, 2);
17100
+
17101
+ // Create a Blob with the JSON data
17102
+ const blob = new Blob([jsonString], { type: 'application/json' });
17103
+ const url = URL.createObjectURL(blob);
17104
+
17105
+ // Create a temporary link element to trigger download
17106
+ const a = document.createElement('a');
17107
+ a.href = url;
17108
+ a.download = filename;
17109
+ document.body.appendChild(a);
17110
+ a.click();
17111
+ document.body.removeChild(a);
17112
+
17113
+ // Revoke the object URL after download
17114
+ URL.revokeObjectURL(url);
17115
+ });
17116
+
16811
17117
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6file2fofc", "click", function(e) { let ic = me.icn3d;
16812
17118
  e.preventDefault();
16813
17119
  //if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -19647,7 +19953,7 @@ class Html {
19647
19953
  this.force = 4;
19648
19954
  this.simulation = undefined;
19649
19955
 
19650
- //this.baseUrl = "https://structure.ncbi.nlm.nih.gov/";
19956
+ //this.baseUrl = "https://www.ncbi.nlm.nih.gov/Structure/";
19651
19957
  this.baseUrl = (window && window.location && window.location.hostname == 'structure.ncbi.nlm.nih.gov')
19652
19958
  ? "https://structure.ncbi.nlm.nih.gov/Structure/" : "https://www.ncbi.nlm.nih.gov/Structure/";
19653
19959
 
@@ -44688,8 +44994,9 @@ class Domain3d {
44688
44994
 
44689
44995
  // if(fromPos >= start && toPos <= end) {
44690
44996
  if(ssCnt > 0) jsonStr += ', ';
44691
- jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ','
44692
- + substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
44997
+ jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
44998
+ // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
44999
+ jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
44693
45000
  ++ssCnt;
44694
45001
  // }
44695
45002
  }
@@ -44705,6 +45012,7 @@ class Domain3d {
44705
45012
  for(let j = startAll; j <= endAll; ++j) {
44706
45013
  let ncbiResid = chnid + '_' + j;
44707
45014
  let resid = ic.ncbi2resid[ncbiResid];
45015
+ resid.split('_')[2];
44708
45016
 
44709
45017
  let pos = j;
44710
45018
 
@@ -44712,6 +45020,7 @@ class Domain3d {
44712
45020
 
44713
45021
  if(!residueHash.hasOwnProperty(resid)) {
44714
45022
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
45023
+ // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
44715
45024
  }
44716
45025
  else {
44717
45026
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -44720,6 +45029,7 @@ class Domain3d {
44720
45029
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
44721
45030
 
44722
45031
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
45032
+ // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
44723
45033
  }
44724
45034
 
44725
45035
  ++domainCnt;
@@ -53373,7 +53683,7 @@ class ChainalignParser {
53373
53683
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53374
53684
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53375
53685
 
53376
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
53686
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
53377
53687
 
53378
53688
  for(let index in ic.afChainIndexHash) {
53379
53689
  let idArray = ic.afChainIndexHash[index].split('_');
@@ -53398,9 +53708,10 @@ class ChainalignParser {
53398
53708
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53399
53709
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53400
53710
 
53401
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
53711
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
53402
53712
 
53403
53713
  // dynamically align pairs in all chainids
53714
+ // the resrange from VASTSrv or VAST search uses NCBI residue numbers!!!
53404
53715
  let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
53405
53716
  for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
53406
53717
  let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
@@ -53575,7 +53886,8 @@ class ChainalignParser {
53575
53886
  if(!bFoundAlignment) {
53576
53887
  // sometimes VAST align works for the reversed pair
53577
53888
  if(!bReverse) {
53578
- ic.realignParserCls.realignOnStructAlign(true);
53889
+ let bVastsearch = true;
53890
+ ic.realignParserCls.realignOnStructAlign(true, bVastsearch);
53579
53891
  return;
53580
53892
  }
53581
53893
  else {
@@ -54331,7 +54643,8 @@ class ChainalignParser {
54331
54643
  // await ic.realignParserCls.realignChainOnSeqAlign(undefined, ic.chainidArray, bRealign, bPredefined);
54332
54644
 
54333
54645
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(ic.chainidArray);
54334
- await ic.realignParserCls.realignOnStructAlign();
54646
+ let bVastsearch = true;
54647
+ await ic.realignParserCls.realignOnStructAlign(undefined, bVastsearch);
54335
54648
 
54336
54649
  // reset annotations
54337
54650
  $("#" + ic.pre + "dl_annotations").html("");
@@ -58567,76 +58880,114 @@ class RealignParser {
58567
58880
  await this.realignChainOnSeqAlign(undefined, chainidArray, bRealign);
58568
58881
  }
58569
58882
 
58570
- async realignOnStructAlign(bReverse) { let ic = this.icn3d, me = ic.icn3dui;
58883
+ async realignOnStructAlign(bReverse, bVastsearch) { let ic = this.icn3d, me = ic.icn3dui;
58571
58884
  // each 3D domain should have at least 3 secondary structures
58572
58885
  let minSseCnt = (me.cfg.aligntool != 'tmalign') ? 3 : 0;
58573
58886
 
58574
- let struct2domain = {};
58575
- for(let struct in ic.structures) {
58576
- struct2domain[struct] = {};
58577
- let chainidArray = ic.structures[struct];
58578
- for(let i = 0, il = chainidArray.length; i < il; ++i) {
58579
- let chainid = chainidArray[i];
58580
- let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
58581
- let sseCnt = 0;
58582
- for(let serial in atoms) {
58583
- if(ic.atoms[serial].ssbegin) ++sseCnt;
58584
- if(sseCnt > minSseCnt) {
58585
- struct2domain[struct][chainid] = atoms;
58586
- break;
58587
- }
58588
- }
58589
- }
58590
- }
58887
+ /*
58888
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
58591
58889
 
58890
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
58891
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
58892
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
58893
+ // end of new version to be done for VASTsrv ==============
58894
+ */
58592
58895
  let ajaxArray = [], chainidPairArray = [];
58593
58896
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
58594
58897
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
58595
58898
 
58596
- //let cnt = 0;
58597
- let structArray = Object.keys(struct2domain);
58598
- if(bReverse) structArray = structArray.reverse();
58899
+ let struct2domain = {};
58900
+ if(bVastsearch && me.cfg.resrange) {
58901
+ let resRangeArray = decodeURIComponent(me.cfg.resrange).split(' | ');
58902
+
58903
+ let atomSet_t = ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms;
58904
+ for(let index = 1, indexl = ic.chainidArray.length; index < indexl; ++index) {
58905
+ let atomSet_q = ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms;
58906
+
58907
+ let alignAjax;
58908
+ if(me.cfg.aligntool != 'tmalign') {
58909
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
58910
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
58911
+
58912
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
58913
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
58914
+ }
58915
+ else {
58916
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
58917
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
58918
+
58919
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
58920
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
58921
+ }
58922
+
58923
+ ajaxArray.push(alignAjax);
58924
+
58925
+ chainidPairArray.push(ic.chainidArray[0] + ',' + ic.chainidArray[index]);
58926
+ }
58927
+ }
58928
+ else {
58929
+ for(let struct in ic.structures) {
58930
+ struct2domain[struct] = {};
58931
+ let chainidArray = ic.structures[struct];
58932
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
58933
+ let chainid = chainidArray[i];
58934
+ let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
58935
+ let sseCnt = 0;
58936
+ for(let serial in atoms) {
58937
+ if(ic.atoms[serial].ssbegin) ++sseCnt;
58938
+ if(sseCnt > minSseCnt) {
58939
+ struct2domain[struct][chainid] = atoms;
58940
+ break;
58941
+ }
58942
+ }
58943
+ }
58944
+ }
58599
58945
 
58600
- for(let s = 0, sl = structArray.length; s < sl; ++s) {
58601
- let struct1 = structArray[s];
58946
+ //let cnt = 0;
58947
+ let structArray = Object.keys(struct2domain);
58948
+ if(bReverse) structArray = structArray.reverse();
58602
58949
 
58603
- let chainidArray1 = Object.keys(struct2domain[struct1]);
58604
- if(chainidArray1.length == 0) continue;
58950
+ for(let s = 0, sl = structArray.length; s < sl; ++s) {
58951
+ let struct1 = structArray[s];
58605
58952
 
58606
- for(let i = 0, il = chainidArray1.length; i < il; ++i) {
58607
- let chainid1 = chainidArray1[i];
58608
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
58953
+ let chainidArray1 = Object.keys(struct2domain[struct1]);
58954
+ if(chainidArray1.length == 0) continue;
58609
58955
 
58610
- for(let t = s+1, tl = structArray.length; t < tl; ++t) {
58611
- let struct2 = structArray[t];
58956
+ for(let i = 0, il = chainidArray1.length; i < il; ++i) {
58957
+ let chainid1 = chainidArray1[i];
58958
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
58612
58959
 
58613
- let chainidArray2 = Object.keys(struct2domain[struct2]);
58614
- if(chainidArray2.length == 0) continue;
58960
+ for(let t = s+1, tl = structArray.length; t < tl; ++t) {
58961
+ let struct2 = structArray[t];
58615
58962
 
58616
- for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
58617
- let chainid2 = chainidArray2[j];
58963
+ let chainidArray2 = Object.keys(struct2domain[struct2]);
58964
+ if(chainidArray2.length == 0) continue;
58618
58965
 
58619
- let alignAjax;
58620
- if(me.cfg.aligntool != 'tmalign') {
58621
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
58622
-
58623
- let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
58624
- alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
58625
- }
58626
- else {
58627
- let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
58628
- let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
58629
-
58630
- // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
58631
- // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
58966
+ for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
58967
+ let chainid2 = chainidArray2[j];
58968
+
58969
+ let alignAjax;
58970
+ if(me.cfg.aligntool != 'tmalign') {
58971
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
58972
+
58973
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
58974
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
58975
+ }
58976
+ else {
58977
+ let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
58978
+ let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
58632
58979
 
58633
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
58634
- alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
58635
- }
58980
+ // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
58981
+ // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
58982
+
58983
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
58984
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
58985
+ }
58636
58986
 
58637
- ajaxArray.push(alignAjax);
58638
- chainidPairArray.push(chainid1 + ',' + chainid2);
58639
- //++cnt;
58987
+ ajaxArray.push(alignAjax);
58988
+ chainidPairArray.push(chainid1 + ',' + chainid2);
58989
+ //++cnt;
58990
+ }
58640
58991
  }
58641
58992
  }
58642
58993
  }
@@ -58752,7 +59103,7 @@ class RealignParser {
58752
59103
  let predefinedResArray, predefinedResPair;
58753
59104
 
58754
59105
  if(bPredefined) {
58755
- predefinedResArray = me.cfg.resdef.trim().replace(/\+/gi, ' ').split(': ');
59106
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
58756
59107
 
58757
59108
  if(predefinedResArray.length != chainidArray.length - 1) {
58758
59109
  var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -58941,7 +59292,7 @@ class RealignParser {
58941
59292
  }
58942
59293
  }
58943
59294
 
58944
- getSeqCoorResid(resiArray, chainid, bNCBI) { let ic = this.icn3d, me = ic.icn3dui;
59295
+ getSeqCoorResid(resiArray, chainid, bNCBIResi) { let ic = this.icn3d, me = ic.icn3dui;
58945
59296
  let seq = '', coorArray = [], residArray = [];
58946
59297
  let hAtoms = {};
58947
59298
 
@@ -58949,16 +59300,17 @@ class RealignParser {
58949
59300
  if(resiArray[j].indexOf('-') != -1) {
58950
59301
  let startEnd = resiArray[j].split('-');
58951
59302
  for(let k = parseInt(startEnd[0]); k <= parseInt(startEnd[1]); ++k) {
58952
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59303
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
58953
59304
 
58954
59305
  // don't align solvent or chemicals
58955
59306
  if(!ic.chainsSeq[chainid] || !ic.chainsSeq[chainid][seqIndex] || me.parasCls.b62ResArray.indexOf(ic.chainsSeq[chainid][seqIndex].name.toUpperCase()) == -1) continue;
58956
59307
 
58957
59308
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
58958
59309
 
58959
- coorArray = coorArray.concat(this.getResCoorArray(chainid + '_' + k));
59310
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
59311
+ coorArray = coorArray.concat(this.getResCoorArray(resid));
58960
59312
 
58961
- residArray.push(chainid + '_' + k);
59313
+ residArray.push(resid);
58962
59314
  }
58963
59315
  }
58964
59316
  else if(resiArray[j] == 0) { // 0 means the whole chain
@@ -58968,18 +59320,19 @@ class RealignParser {
58968
59320
  else { // one residue
58969
59321
  let k = resiArray[j];
58970
59322
 
58971
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59323
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
58972
59324
 
58973
59325
  if(!ic.chainsSeq[chainid][seqIndex]) continue;
58974
59326
 
58975
- let resCoorArray = this.getResCoorArray(chainid + '_' + k);
59327
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
59328
+ let resCoorArray = this.getResCoorArray(resid);
58976
59329
  //if(resCoorArray.length == 1 && resCoorArray[0] === undefined) continue;
58977
59330
 
58978
59331
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
58979
59332
 
58980
59333
  coorArray = coorArray.concat(resCoorArray);
58981
59334
 
58982
- residArray.push(chainid + '_' + k);
59335
+ residArray.push(resid);
58983
59336
  }
58984
59337
  }
58985
59338
 
@@ -63243,7 +63596,9 @@ class LoadPDB {
63243
63596
  structure = this.getStructureId(id, moleculeNum, bMutation, bNMR);
63244
63597
 
63245
63598
  ic.molTitle = '';
63246
- ic.molTitleHash = {};
63599
+ if (ic.allData === undefined) {
63600
+ ic.molTitleHash = {};
63601
+ }
63247
63602
 
63248
63603
  bHeader = true; // read the first header if there are multiple
63249
63604
  } else if (record === 'TITLE ') {
@@ -68267,15 +68622,15 @@ class SelectCollections {
68267
68622
  }
68268
68623
 
68269
68624
  //Set the menu of defined sets with an array of defined names "commandnameArray".
68270
- setAtomMenu(nameArray, titleArray) {
68625
+ setAtomMenu(nameArray) {
68271
68626
  let ic = this.icn3d;
68272
68627
  ic.icn3dui;
68273
68628
  let html = "";
68274
- let commandnameArray = [nameArray[0]];
68275
68629
  //for(let i in ic.defNames2Atoms) {
68276
68630
  for (let i = 0, il = nameArray.length; i < il; ++i) {
68277
- let name = nameArray[i];
68278
- let title = titleArray[i];
68631
+ let name = nameArray[i][0];
68632
+ let title = nameArray[i][1];
68633
+ let description = nameArray[i][2];
68279
68634
 
68280
68635
  let atomHash;
68281
68636
  if (
@@ -68298,16 +68653,11 @@ class SelectCollections {
68298
68653
  }
68299
68654
  }
68300
68655
 
68301
- if (commandnameArray.indexOf(name) != -1) {
68302
- html +=
68303
- "<option value='" +
68304
- name +
68305
- "' selected='selected'>" +
68306
- title +
68307
- "</option>";
68308
- } else {
68309
- html += "<option value='" + name + "'>" + title + "</option>";
68310
- }
68656
+ if (i == 0) {
68657
+ html += "<option value='" + nameArray[0][0] + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
68658
+ } else {
68659
+ html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
68660
+ }
68311
68661
  }
68312
68662
 
68313
68663
  return html;
@@ -68348,49 +68698,33 @@ class SelectCollections {
68348
68698
  }
68349
68699
 
68350
68700
  return difference;
68351
- }
68701
+ }
68352
68702
 
68353
- clickStructure() {
68703
+ clickStructure(collection) {
68354
68704
  let ic = this.icn3d,
68355
68705
  me = ic.icn3dui;
68356
68706
  let thisClass = this;
68357
68707
 
68358
- if (ic.allData == undefined) {
68359
- ic.allData = {};
68360
- ic.allData['all'] = {
68361
- 'atoms': {},
68362
- 'proteins': {},
68363
- 'nucleotides': {},
68364
- 'chemicals': {},
68365
- 'ions': {},
68366
- 'water': {},
68367
- 'structures': {},
68368
- 'ssbondpnts': {},
68369
- 'residues': {},
68370
- 'chains': {},
68371
- 'chainsSeq': {}, //Sequences and Annotation
68372
- 'defNames2Atoms': {},
68373
- 'defNames2Residues': {}
68374
- };
68375
- ic.allData['prev'] = {};
68376
- }
68377
-
68378
68708
  //me.myEventCls.onIds("#" + ic.pre + "atomsCustom", "change", function(e) { let ic = thisClass.icn3d;
68379
- $("#" + ic.pre + "collections_menu").change(async function (e) {
68709
+ $("#" + ic.pre + "collections_menu").on("change", async function (e) {
68380
68710
  let ic = thisClass.icn3d;
68381
68711
 
68382
68712
  let nameArray = $(this).val();
68383
68713
  let nameStructure = $(this).find("option:selected").text();
68714
+ let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
68715
+ let selectedIndicesMap = nameArray.reduce((map, name, i) => {
68716
+ map[name] = selectedIndices[i];
68717
+ return map;
68718
+ }, {});
68384
68719
 
68385
68720
  ic.nameArray = nameArray;
68386
- if (nameArray !== null) {
68387
- // let chainIdHash = {};
68388
68721
 
68722
+ if (nameArray !== null) {
68389
68723
  let bNoDuplicate = true;
68390
68724
  thisClass.reset();
68391
68725
  for (const name of nameArray) {
68392
68726
  if (!(name in ic.allData)) {
68393
- ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));//me.hashUtilsCls.cloneHash(ic.allData['all']);
68727
+ ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));
68394
68728
 
68395
68729
  ic.atoms = ic.allData['all']['atoms'];
68396
68730
 
@@ -68407,7 +68741,21 @@ class SelectCollections {
68407
68741
  ic.chainsSeq = ic.allData['all']['chainsSeq'];
68408
68742
  ic.defalls2Atoms = ic.allData['all']['defalls2Atoms'];
68409
68743
  ic.defalls2Residues = ic.allData['all']['defalls2Residues'];
68410
- await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate).then(() => {
68744
+
68745
+ async function loadStructure(pdb) {
68746
+ await ic.resetConfig();
68747
+ if (pdb) {
68748
+ let bAppend = true;
68749
+ if (Object.keys(ic.structures).length == 0) {
68750
+ bAppend = false;
68751
+ }
68752
+ await ic.pdbParserCls.loadPdbData(ic.pdbCollection[selectedIndicesMap[name]].join('\n'), undefined, undefined, bAppend);
68753
+ } else {
68754
+ await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
68755
+ }
68756
+ }
68757
+
68758
+ await loadStructure(collection[selectedIndicesMap[name]][4]).then(() => {
68411
68759
  ic.allData['all'] = {
68412
68760
  'atoms': ic.atoms,
68413
68761
  'proteins': ic.proteins,
@@ -68415,9 +68763,9 @@ class SelectCollections {
68415
68763
  'chemicals': ic.chemicals,
68416
68764
  'ions': ic.ions,
68417
68765
  'water': ic.water,
68418
- 'structures': ic.structures,
68766
+ 'structures': ic.structures, // getSSExpandedAtoms
68419
68767
  'ssbondpnts': ic.ssbondpnts,
68420
- 'residues': ic.residues,
68768
+ 'residues': ic.residues, // getSSExpandedAtoms
68421
68769
  'chains': ic.chains,
68422
68770
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
68423
68771
  'defNames2Atoms': ic.defNames2Atoms,
@@ -68425,26 +68773,27 @@ class SelectCollections {
68425
68773
  };
68426
68774
 
68427
68775
  ic.allData[name] = {
68776
+ 'title': ic.molTitle,
68428
68777
  'atoms': thisClass.dictionaryDifference(ic.allData['prev']['atoms'], ic.atoms),
68429
68778
  'proteins': thisClass.dictionaryDifference(ic.allData['prev']['proteins'], ic.proteins),
68430
68779
  'nucleotides': thisClass.dictionaryDifference(ic.allData['prev']['nucleotides'], ic.nucleotides),
68431
68780
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
68432
68781
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
68433
68782
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
68434
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
68783
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
68435
68784
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
68436
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
68785
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
68437
68786
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
68438
68787
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
68439
68788
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
68440
68789
  'defNames2Residues': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Residues'], ic.defNames2Residues)
68441
68790
  };
68442
68791
 
68443
- // ic.atoms = Object.assign(ic.atoms, ic.atomsTemp);
68444
68792
  thisClass.reset();
68445
68793
  });
68446
68794
  }
68447
68795
  }
68796
+
68448
68797
  for (const name of nameArray) {
68449
68798
  ic.atoms = Object.assign(ic.atoms, ic.allData[name]['atoms']);
68450
68799
 
@@ -68463,10 +68812,26 @@ class SelectCollections {
68463
68812
  ic.defNames2Residues = Object.assign(ic.defNames2Residues, ic.allData[name]['defNames2Residues']);
68464
68813
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
68465
68814
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
68466
- }
68815
+
68816
+ ic.molTitle = ic.allData[name]['title'];
68467
68817
 
68818
+ if (collection[selectedIndicesMap[name]][3] !== undefined && collection[selectedIndicesMap[name]][3].length > 0) {
68819
+ if (ic.allData[name]['commands'] == undefined) {
68820
+ let commands = collection[selectedIndicesMap[name]][3];
68821
+ ic.allData[name]['commands'] = commands;
68822
+ }
68823
+ }
68824
+
68825
+ if (ic.allData[name]['commands'] !== undefined) {
68826
+ for (const command of ic.allData[name]['commands']) {
68827
+ me.htmlCls.clickMenuCls.setLogCmd(command, true);
68828
+ await ic.applyCommandCls.applyCommand(command);
68829
+ }
68830
+ }
68831
+
68832
+ }
68833
+
68468
68834
  ic.opts["color"] = (Object.keys(ic.structures).length == 1) ? "chain" : "structure";
68469
- // ic.setStyleCls.setAtomStyleByOptions();
68470
68835
  ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
68471
68836
 
68472
68837
  ic.transformCls.zoominSelection();
@@ -68480,14 +68845,12 @@ class SelectCollections {
68480
68845
  // show selected chains in annotation window
68481
68846
  ic.annotationCls.showAnnoSelectedChains();
68482
68847
  }
68483
-
68848
+
68484
68849
  await ic.drawCls.draw();
68485
68850
  ic.saveFileCls.showTitle();
68486
68851
 
68487
- me.htmlCls.clickMenuCls.setLogCmd(
68488
- "select structure " + "[" + nameStructure + "]",
68489
- true
68490
- );
68852
+ me.htmlCls.clickMenuCls.setLogCmd("select structure " + "[" + nameStructure + "]", false);
68853
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf1 ' + nameArray, true);
68491
68854
  }
68492
68855
  });
68493
68856
 
@@ -69399,7 +69762,7 @@ class LoadScript {
69399
69762
  if(steps === 1
69400
69763
  || (ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length === Object.keys(ic.atoms).length)
69401
69764
  || (ic.optsHistory[steps - 1] !== undefined && ic.optsHistory[steps - 1].hasOwnProperty('hlatomcount') && ic.optsHistory[steps - 1].hlatomcount === Object.keys(ic.atoms).length) ) {
69402
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
69765
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
69403
69766
  // if(steps === 1) {
69404
69767
  // assign styles and color using the options at that stage
69405
69768
  // ic.setStyleCls.setAtomStyleByOptions(ic.optsHistory[steps - 1]);
@@ -69421,7 +69784,7 @@ class LoadScript {
69421
69784
  ic.pk = 3;
69422
69785
  }
69423
69786
 
69424
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
69787
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
69425
69788
  // if(steps === 1) {
69426
69789
  // ic.setColorCls.applyOriginalColor();
69427
69790
  // }
@@ -70487,6 +70850,10 @@ class Selection {
70487
70850
  selectOneResid(idStr, bUnchecked) {var ic = this.icn3d; ic.icn3dui;
70488
70851
  //var idStr = idArray[i]; // TYR $1KQ2.B:56@OH, $1KQ2.B:40 ASP
70489
70852
  //change to: let idStr = idArray[i]; // TYR $1KQ2.B:56@OH, or ASP $1KQ2.B:40
70853
+ //change to: let idStr = idArray[i]; // TYR $1KQ2.B:56@OH, or ASP $1KQ2.B:40, or $1KQ2.B:56@OH 130, or ASP $1KQ2.B:40 144
70854
+ let idArray = idStr.split(' ');
70855
+ idStr = idArray[1];
70856
+
70490
70857
  let posStructure = idStr.indexOf('$');
70491
70858
  let posChain = idStr.indexOf('.');
70492
70859
  let posRes = idStr.indexOf(':');
@@ -79299,7 +79666,7 @@ class ShareLink {
79299
79666
  let shortName = strArray[strArray.length - 1];
79300
79667
  ic.saveFileCls.saveFile(inputid + '-' + shortName + '.png', 'png');
79301
79668
  let text = '<div style="float:left; border: solid 1px #0000ff; padding: 5px; margin: 10px; text-align:center;">';
79302
- text += '<a href="https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + shortName + '" target="_blank">';
79669
+ text += '<a href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + shortName + '" target="_blank">';
79303
79670
  text += '<img style="height:300px" src ="' + inputid + '-' + shortName + '.png"><br>\n';
79304
79671
  text += '<!--Start of your comments==================-->\n';
79305
79672
  let yournote =(ic.yournote) ? ': ' + ic.yournote.replace(/\n/g, "<br>").replace(/; /g, ", ") : '';
@@ -79318,9 +79685,9 @@ class ShareLink {
79318
79685
  //shorturl: https://icn3d.page.link/NvbAh1Vmiwc4bgX87
79319
79686
  let urlArray = shorturl.split('page.link/');
79320
79687
  //if(urlArray.length == 2) shorturl = me.htmlCls.baseUrl + 'icn3d/share.html?' + urlArray[1];
79321
- // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to past posted data in Mac/iphone
79688
+ // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to pass posted data in Mac/iphone
79322
79689
  // So the base URL is still www.ncbi.nlm.nih.gov/Structure,just use short URL here
79323
- if(urlArray.length == 2) shorturl = 'https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + urlArray[1];
79690
+ if(urlArray.length == 2) shorturl = 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + urlArray[1];
79324
79691
 
79325
79692
  $("#" + ic.pre + "short_url").val(shorturl);
79326
79693
  $("#" + ic.pre + "short_url_title").val(shorturl + '&t=' + ic.yournote);
@@ -82477,7 +82844,7 @@ class iCn3DUI {
82477
82844
  //even when multiple iCn3D viewers are shown together.
82478
82845
  this.pre = this.cfg.divid + "_";
82479
82846
 
82480
- this.REVISION = '3.38.1';
82847
+ this.REVISION = '3.39.0';
82481
82848
 
82482
82849
  // In nodejs, iCn3D defines "window = {navigator: {}}"
82483
82850
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -82652,6 +83019,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82652
83019
 
82653
83020
  await ic.pdbParserCls.loadPdbData(pdbStr);
82654
83021
 
83022
+ // // use NCBI residue numbers if using VAST
83023
+ // me.icn3d.bUsePdbNum = 0;
83024
+
82655
83025
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
82656
83026
  let structureArray = Object.keys(ic.structures);
82657
83027
  let chainArray = me.cfg.chains.split(' | ');
@@ -82927,7 +83297,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82927
83297
 
82928
83298
  ic.bChainAlign = true;
82929
83299
  ic.inputid = me.cfg.chainalign;
82930
- let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
83300
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + decodeURIComponent(me.cfg.resrange) : '';
82931
83301
  let resdef = (me.cfg.resdef) ? me.cfg.resdef : '';
82932
83302
  ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
82933
83303
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);