icn3d 3.38.1 → 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.module.js CHANGED
@@ -15153,7 +15153,7 @@ class SetDialog {
15153
15153
  html += me.htmlCls.divStr + "dl_collectionsMenu'>";
15154
15154
  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>';
15155
15155
  html += me.htmlCls.divStr + "dl_collection_file' style=''>";
15156
- 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>";
15156
+ 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>";
15157
15157
  html += "Collection file: " + me.htmlCls.inputFileStr + "id='" + me.pre + "collectionfile'><br/>";
15158
15158
  html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
15159
15159
  html += "</div>";
@@ -15161,7 +15161,26 @@ class SetDialog {
15161
15161
  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>';
15162
15162
  html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
15163
15163
  html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
15164
+ html += '<br/>';
15165
+ html += me.htmlCls.buttonStr + "opendl_export_collections'>Export</button>";
15164
15166
  html += "</div>";
15167
+ html += '<br/>';
15168
+ html += "</div>";
15169
+
15170
+ html += me.htmlCls.divStr + "dl_export_collections' class='" + dialogClass + "'>";
15171
+ html += this.addNotebookTitle('dl_export_collections', 'Export Collections');
15172
+ html += "<label for='dl_collectionTitle'>Collection Title: </label>";
15173
+ html += "<input type='text' id='dl_collectionTitle' name='collectionTitle' placeholder='Enter collection title' />";
15174
+ html += '<br/>';
15175
+ html += "<label for='dl_collectionDescription'>Collection Description: </label>";
15176
+ html += "<input type='text' id='dl_collectionDescription' name='collectionDescription' placeholder='Enter collection description' />";
15177
+ html += '<br/>';
15178
+ html += "<input type='radio' id='dl_collectionExportSelected' name='exportOption' value='selected' />";
15179
+ html += "<label for='dl_collectionExportSelected'>Selected</label>";
15180
+ html += "<input type='radio' id='dl_collectionExportAll' name='exportOption' value='all' />";
15181
+ html += "<label for='dl_collectionExportAll'>All</label>";
15182
+ html += '<br/>';
15183
+ html += me.htmlCls.buttonStr + "export_collections'>Export</button>";
15165
15184
  html += "</div>";
15166
15185
 
15167
15186
  html += me.htmlCls.divStr + "dl_menuloadpref' class='" + dialogClass + "'>";
@@ -16492,8 +16511,8 @@ class Events {
16492
16511
 
16493
16512
  saveHtml(id) { let me = this.icn3dui, ic = me.icn3d;
16494
16513
  let html = '';
16495
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/lib/jquery-ui-1.13.2.min.css">\n';
16496
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/icn3d_full_ui.css">\n';
16514
+ html += '<link rel="stylesheet" href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/jquery-ui-1.13.2.min.css">\n';
16515
+ html += '<link rel="stylesheet" href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d_full_ui.css">\n';
16497
16516
  html += $("#" + id).html();
16498
16517
  let idArray = id.split('_');
16499
16518
  let idStr =(idArray.length > 2) ? idArray[2] : id;
@@ -17582,7 +17601,6 @@ class Events {
17582
17601
 
17583
17602
  urlTarget = '_blank';
17584
17603
 
17585
- console.log("smiles: " + $("#" + me.pre + "smiles").val() + " encode: " + encodeURIComponent($("#" + me.pre + "smiles").val()));
17586
17604
  window.open(hostUrl + '?smiles=' + encodeURIComponent($("#" + me.pre + "smiles").val()), urlTarget);
17587
17605
  });
17588
17606
 
@@ -17665,28 +17683,232 @@ class Events {
17665
17683
  $(".ui-dialog-content").dialog("close");
17666
17684
  } else {
17667
17685
  ic.resizeCanvasCls.closeDialogs();
17668
- }
17686
+ }
17687
+ ic.bInputfile = false;
17688
+ ic.pdbCollection = [];
17689
+ ic.allData = {};
17690
+ ic.allData['all'] = {
17691
+ 'atoms': {},
17692
+ 'proteins': {},
17693
+ 'nucleotides': {},
17694
+ 'chemicals': {},
17695
+ 'ions': {},
17696
+ 'water': {},
17697
+ 'structures': {}, // getSSExpandedAtoms
17698
+ 'ssbondpnts': {},
17699
+ 'residues': {}, // getSSExpandedAtoms
17700
+ 'chains': {},
17701
+ 'chainsSeq': {}, //Sequences and Annotation
17702
+ 'defNames2Atoms': {},
17703
+ 'defNames2Residues': {}
17704
+ };
17705
+ ic.allData['prev'] = {};
17706
+ ic.selectCollectionsCls.reset();
17707
+
17708
+ ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
17709
+ ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
17669
17710
  me.htmlCls.setHtmlCls.fileSupport();
17711
+
17712
+ let fileName = file.name;
17713
+ let fileExtension = fileName.split('.').pop().toLowerCase();
17714
+
17715
+ $("#" + ic.pre + "collections_menu").empty();
17716
+ $("#" + ic.pre + "collections_menu").off("change");
17717
+
17718
+ function parseJsonCollection(data) {
17719
+ let dataStr = JSON.parse(data);
17720
+ return dataStr["structures"].map(({ id, title, description, commands }) => {
17721
+ if (id && id.includes('.pdb')) {
17722
+ id = id.split('.pdb')[0];
17723
+ }
17724
+ return [id, title, description, commands, false];
17725
+ });
17726
+ }
17727
+
17728
+ function parsePdbCollection(data, description = '', commands = []) {
17729
+ let dataStr = data;
17730
+ let lines = dataStr.split('\n');
17731
+
17732
+ let sections = [];
17733
+ let currentSection = [];
17734
+
17735
+ lines.forEach(line => {
17736
+ if (line.startsWith('HEADER')) {
17737
+ currentSection = [];
17738
+ sections.push(currentSection);
17739
+ }
17740
+ currentSection.push(line);
17741
+ });
17742
+
17743
+ let ids = [];
17744
+ let titles = [];
17745
+
17746
+ sections.forEach((section) => {
17747
+ let headerLine = section[0];
17748
+ headerLine = headerLine.replace(/[\n\r]/g, '').trim();
17749
+ let header = headerLine.split(' ').filter(Boolean);
17750
+ let lastElement = header[header.length - 1];
17751
+ ids.push(lastElement);
17752
+ titles.push(section[1].startsWith('TITLE') ? section[1].split('TITLE').pop().trim() : lastElement);
17753
+ });
17754
+
17755
+ if (sections.length > 0) {
17756
+ ic.pdbCollection.push(...sections);
17757
+ }
17758
+
17759
+ return ids.map((id, index, description, commands) => [id, titles[index], description, commands, true]);
17760
+ }
17761
+
17762
+ let collection = [];
17763
+
17764
+ if (fileExtension === 'json' || fileExtension === 'pdb') {
17670
17765
  let reader = new FileReader();
17671
-
17672
17766
  reader.onload = async function (e) {
17673
- let dataStr = JSON.parse(e.target.result);
17674
- let collection = [dataStr["structures"].map(({ id }) => id), dataStr["structures"].map(({ title }) => title)];
17675
- let collectionHtml = ic.selectCollectionsCls.setAtomMenu(collection[0], collection[1]);
17767
+ if (fileExtension === 'json') {
17768
+ collection = parseJsonCollection(e.target.result);
17769
+ } else if (fileExtension === 'pdb') {
17770
+ ic.bInputfile = true;
17771
+ collection = parsePdbCollection(e.target.result);
17772
+ }
17676
17773
 
17677
- $("#" + ic.pre + "collections_menu").html(collectionHtml);
17678
- ic.selectCollectionsCls.clickStructure();
17679
-
17680
- $("#" + ic.pre + "collections_menu").trigger("change");
17681
-
17682
- me.htmlCls.clickMenuCls.setLogCmd(
17683
- "load collection file " +
17684
- $("#" + me.pre + "collectionfile").val(),
17685
- false
17686
- );
17687
-
17688
- };
17689
- reader.readAsText(file);
17774
+ let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
17775
+
17776
+ $("#" + ic.pre + "collections_menu").html(collectionHtml);
17777
+ await ic.selectCollectionsCls.clickStructure(collection);
17778
+ $("#" + ic.pre + "collections_menu").trigger("change");
17779
+
17780
+ me.htmlCls.clickMenuCls.setLogCmd(
17781
+ "load collection file " +
17782
+ $("#" + me.pre + "collectionfile").val(),
17783
+ false
17784
+ );
17785
+ };
17786
+
17787
+ reader.readAsText(file);
17788
+ } else if (fileExtension === 'zip' || fileExtension === 'gz') {
17789
+ ic.bInputfile = true;
17790
+ let reader2 = new FileReader();
17791
+ reader2.onload = async function (e) {
17792
+ if (fileExtension === 'zip') {
17793
+ let url = './script/jszip.js';
17794
+ await me.getAjaxPromise(url, 'script');
17795
+
17796
+ let jszip = new JSZip();
17797
+ try {
17798
+ let data = await jszip.loadAsync(e.target.result);
17799
+
17800
+ let hasJson = false;
17801
+ let hasPdb = false;
17802
+ let hasGz = false;
17803
+ let jsonFiles = [];
17804
+ let pdbFiles = [];
17805
+ let gzFiles = [];
17806
+
17807
+ for (let fileName in data.files) {
17808
+ let file = data.files[fileName];
17809
+ if (!file.dir) {
17810
+ if (fileName.endsWith('.json')) {
17811
+ hasJson = true;
17812
+ jsonFiles.push(file);
17813
+ } else if (fileName.endsWith('.pdb')) {
17814
+ hasPdb = true;
17815
+ pdbFiles.push(file);
17816
+ } else if (fileName.endsWith('.gz')) {
17817
+ hasGz = true;
17818
+ gzFiles.push(file);
17819
+ }
17820
+ }
17821
+ }
17822
+
17823
+ if (hasJson && hasPdb) {
17824
+ let jsonCollection = [];
17825
+ for (const file of jsonFiles) {
17826
+ let fileData = await file.async('text');
17827
+ parseJsonCollection(fileData).forEach(element => {
17828
+ jsonCollection.push(element);
17829
+ });
17830
+ }
17831
+
17832
+ // For each JSON object, check if a corresponding PDB file exists
17833
+ for (const [id, title, description, commands, _] of jsonCollection) {
17834
+ let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
17835
+ if (matchingPdbFile) {
17836
+ let pdbFileData = await matchingPdbFile.async('text');
17837
+ parsePdbCollection(pdbFileData, description, commands).forEach(element => {
17838
+ collection.push(element);
17839
+ });
17840
+ }
17841
+ }
17842
+
17843
+ } else if (hasJson) {
17844
+ // Do something if only JSON files are present
17845
+ jsonFiles.forEach(async file => {
17846
+ let fileData = await file.async('text');
17847
+ parseJsonCollection(fileData).forEach(element => {
17848
+ collection.push(element);
17849
+ });
17850
+ });
17851
+ } else if (hasPdb) {
17852
+ // Do something if only PDB files are present
17853
+ pdbFiles.forEach(async file => {
17854
+ let fileData = await file.async('text');
17855
+ parsePdbCollection(fileData).forEach(element => {
17856
+ collection.push(element);
17857
+ });
17858
+ });
17859
+ } else if (hasGz) {
17860
+ let url = './script/pako.js';
17861
+ await me.getAjaxPromise(url, 'script');
17862
+ try {
17863
+ for (const file of gzFiles) {
17864
+ let compressed = await file.async('uint8array');
17865
+ let decompressed = pako.inflate(compressed, { to: 'string' });
17866
+ parsePdbCollection(decompressed).forEach(element => {
17867
+ collection.push(element);
17868
+ });
17869
+ }
17870
+ } catch (error) {
17871
+ console.error('Error loading GZ file', error);
17872
+ }
17873
+ }
17874
+ } catch (error) {
17875
+ console.error('Error loading ZIP file', error);
17876
+ }
17877
+ } else if (fileExtension === 'gz') {
17878
+ let url = './script/pako.js';
17879
+ await me.getAjaxPromise(url, 'script');
17880
+
17881
+ try {
17882
+ const compressed = new Uint8Array(e.target.result);
17883
+ const decompressed = pako.inflate(compressed, { to: 'string' });
17884
+ collection = parsePdbCollection(decompressed);
17885
+ } catch (error) {
17886
+ console.error('Error loading GZ file', error);
17887
+ }
17888
+ }
17889
+
17890
+ let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
17891
+
17892
+ $("#" + ic.pre + "collections_menu").html(collectionHtml);
17893
+ await ic.selectCollectionsCls.clickStructure(collection);
17894
+
17895
+ $("#" + ic.pre + "collections_menu").trigger("change");
17896
+
17897
+ me.htmlCls.clickMenuCls.setLogCmd(
17898
+ "load collection file " +
17899
+ $("#" + me.pre + "collectionfile").val(),
17900
+ false
17901
+ );
17902
+ };
17903
+
17904
+ reader2.onerror = function(error) {
17905
+ console.error('Error reading file', error);
17906
+ };
17907
+
17908
+ reader2.readAsArrayBuffer(file);
17909
+ } else {
17910
+ throw new Error('Invalid file type');
17911
+ }
17690
17912
 
17691
17913
  if (Object.keys(me.utilsCls.getStructures(ic.dAtoms))){
17692
17914
  $("#" + me.pre + "dl_collection_file").hide();
@@ -17709,6 +17931,90 @@ class Events {
17709
17931
  }
17710
17932
  });
17711
17933
 
17934
+ me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
17935
+ me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
17936
+ });
17937
+
17938
+ me.myEventCls.onIds("#" + me.pre + "export_collections", "click", function (e) {
17939
+ let ic = me.icn3d;
17940
+
17941
+ const selectElement = document.getElementById(me.pre + 'collections_menu');
17942
+
17943
+ // Array to store parsed results
17944
+ const structures = [];
17945
+
17946
+ const dl_collectionExportSelected = document.getElementById('dl_collectionExportSelected');
17947
+ const dl_collectionExportAll = document.getElementById('dl_collectionExportAll');
17948
+
17949
+ if (dl_collectionExportSelected.checked) {
17950
+
17951
+ // Iterate over each <option> element
17952
+ Array.from(selectElement.options)
17953
+ .filter(option => option.selected)
17954
+ .forEach(option => {
17955
+ const name = option.value;
17956
+ const title = option.textContent.trim();
17957
+ const description = option.getAttribute('data-description');
17958
+
17959
+ // Push the extracted data into the array
17960
+ structures.push({
17961
+ id: name,
17962
+ title: title,
17963
+ description: description || '',
17964
+ commands: (ic.allData[name] && ic.allData[name].commands) ? ic.allData[name].commands : []
17965
+ });
17966
+ });
17967
+ } else if (dl_collectionExportAll.checked) {
17968
+ // Iterate over each <option> element
17969
+ Array.from(selectElement.options)
17970
+ .forEach(option => {
17971
+ const name = option.value;
17972
+ const title = option.textContent.trim();
17973
+ const description = option.getAttribute('data-description');
17974
+
17975
+ // Push the extracted data into the array
17976
+ structures.push({
17977
+ name: name,
17978
+ title: title,
17979
+ description: description || '',
17980
+ commands: (ic.allData[name] && ic.allData[name].commands) ? ic.allData[name].commands : []
17981
+ });
17982
+ });
17983
+ }
17984
+
17985
+
17986
+ const now = new Date();
17987
+ const month = now.getMonth() + 1; // Months are zero-based
17988
+ const day = now.getDate();
17989
+ const year = now.getFullYear();
17990
+ const formattedDate = `${month}_${day}_${year}`;
17991
+
17992
+ const collection = {
17993
+ collectionTitle: document.getElementById('dl_collectionTitle').value,
17994
+ collectionDescription: document.getElementById('dl_collectionDescription').value,
17995
+ structures: structures
17996
+ };
17997
+
17998
+ const filename = `${collection.collectionTitle.replace(/\s+/g, '_')}_${formattedDate}.json`;
17999
+
18000
+ const jsonString = JSON.stringify(collection, null, 2);
18001
+
18002
+ // Create a Blob with the JSON data
18003
+ const blob = new Blob([jsonString], { type: 'application/json' });
18004
+ const url = URL.createObjectURL(blob);
18005
+
18006
+ // Create a temporary link element to trigger download
18007
+ const a = document.createElement('a');
18008
+ a.href = url;
18009
+ a.download = filename;
18010
+ document.body.appendChild(a);
18011
+ a.click();
18012
+ document.body.removeChild(a);
18013
+
18014
+ // Revoke the object URL after download
18015
+ URL.revokeObjectURL(url);
18016
+ });
18017
+
17712
18018
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6file2fofc", "click", function(e) { let ic = me.icn3d;
17713
18019
  e.preventDefault();
17714
18020
  //if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -20548,7 +20854,7 @@ class Html {
20548
20854
  this.force = 4;
20549
20855
  this.simulation = undefined;
20550
20856
 
20551
- //this.baseUrl = "https://structure.ncbi.nlm.nih.gov/";
20857
+ //this.baseUrl = "https://www.ncbi.nlm.nih.gov/Structure/";
20552
20858
  this.baseUrl = (window && window.location && window.location.hostname == 'structure.ncbi.nlm.nih.gov')
20553
20859
  ? "https://structure.ncbi.nlm.nih.gov/Structure/" : "https://www.ncbi.nlm.nih.gov/Structure/";
20554
20860
 
@@ -45589,8 +45895,9 @@ class Domain3d {
45589
45895
 
45590
45896
  // if(fromPos >= start && toPos <= end) {
45591
45897
  if(ssCnt > 0) jsonStr += ', ';
45592
- jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ','
45593
- + substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
45898
+ jsonStr += '[' + sstype + ',' + fromPos + ',' + toPos + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
45899
+ // jsonStr += '[' + sstype + ',' + residFrom.split('_')[2] + ',' + residTo.split('_')[2] + ',' + substruct[k].x1.toFixed(2) + ',' + substruct[k].y1.toFixed(2) + ',';
45900
+ jsonStr += substruct[k].z1.toFixed(2) + ',' + substruct[k].x2.toFixed(2) + ',' + substruct[k].y2.toFixed(2) + ',' + substruct[k].z2.toFixed(2) + ']';
45594
45901
  ++ssCnt;
45595
45902
  // }
45596
45903
  }
@@ -45606,6 +45913,7 @@ class Domain3d {
45606
45913
  for(let j = startAll; j <= endAll; ++j) {
45607
45914
  let ncbiResid = chnid + '_' + j;
45608
45915
  let resid = ic.ncbi2resid[ncbiResid];
45916
+ resid.split('_')[2];
45609
45917
 
45610
45918
  let pos = j;
45611
45919
 
@@ -45613,6 +45921,7 @@ class Domain3d {
45613
45921
 
45614
45922
  if(!residueHash.hasOwnProperty(resid)) {
45615
45923
  jsonStr += '[' + pos + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
45924
+ // jsonStr += '[' + resi + ',' + 0 + ',' + fakeCoord + ',' + fakeCoord + ',' + fakeCoord + ']';
45616
45925
  }
45617
45926
  else {
45618
45927
  let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
@@ -45621,6 +45930,7 @@ class Domain3d {
45621
45930
  let restype = (me.parasCls.resn2restype[atom.resn]) ? me.parasCls.resn2restype[atom.resn] : 0;
45622
45931
 
45623
45932
  jsonStr += '[' + pos + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
45933
+ // jsonStr += '[' + resi + ',' + restype + ',' + atom.coord.x.toFixed(2) + ',' + atom.coord.y.toFixed(2) + ',' + atom.coord.z.toFixed(2) + ']';
45624
45934
  }
45625
45935
 
45626
45936
  ++domainCnt;
@@ -54274,7 +54584,7 @@ class ChainalignParser {
54274
54584
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
54275
54585
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
54276
54586
 
54277
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
54587
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
54278
54588
 
54279
54589
  for(let index in ic.afChainIndexHash) {
54280
54590
  let idArray = ic.afChainIndexHash[index].split('_');
@@ -54299,9 +54609,10 @@ class ChainalignParser {
54299
54609
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
54300
54610
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
54301
54611
 
54302
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
54612
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
54303
54613
 
54304
54614
  // dynamically align pairs in all chainids
54615
+ // the resrange from VASTSrv or VAST search uses NCBI residue numbers!!!
54305
54616
  let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
54306
54617
  for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
54307
54618
  let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
@@ -54476,7 +54787,8 @@ class ChainalignParser {
54476
54787
  if(!bFoundAlignment) {
54477
54788
  // sometimes VAST align works for the reversed pair
54478
54789
  if(!bReverse) {
54479
- ic.realignParserCls.realignOnStructAlign(true);
54790
+ let bVastsearch = true;
54791
+ ic.realignParserCls.realignOnStructAlign(true, bVastsearch);
54480
54792
  return;
54481
54793
  }
54482
54794
  else {
@@ -55232,7 +55544,8 @@ class ChainalignParser {
55232
55544
  // await ic.realignParserCls.realignChainOnSeqAlign(undefined, ic.chainidArray, bRealign, bPredefined);
55233
55545
 
55234
55546
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(ic.chainidArray);
55235
- await ic.realignParserCls.realignOnStructAlign();
55547
+ let bVastsearch = true;
55548
+ await ic.realignParserCls.realignOnStructAlign(undefined, bVastsearch);
55236
55549
 
55237
55550
  // reset annotations
55238
55551
  $("#" + ic.pre + "dl_annotations").html("");
@@ -58744,16 +59057,14 @@ class SdfParser {
58744
59057
  }
58745
59058
 
58746
59059
  async downloadSmiles(smiles) { let ic = this.icn3d, me = ic.icn3dui;
58747
- let urlSmiles = me.htmlCls.baseUrl + "openbabel/openbabel.cgi?smiles2pdb=" + smiles;
58748
- let pdbStr = await me.getAjaxPromise(urlSmiles, 'text');
59060
+ let urlSmiles = me.htmlCls.baseUrl + "openbabel/openbabel.cgi?smiles2sdf=" + smiles;
59061
+ let sdfStr = await me.getAjaxPromise(urlSmiles, 'text');
58749
59062
 
58750
59063
  ic.init();
58751
-
58752
59064
  ic.bInputfile = true;
58753
- ic.InputfileType = 'pdb';
58754
- ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + pdbStr : pdbStr;
58755
-
58756
- await ic.pdbParserCls.loadPdbData(pdbStr);
59065
+ ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + sdfStr : sdfStr;
59066
+ ic.InputfileType = 'sdf';
59067
+ await ic.sdfParserCls.loadSdfData(sdfStr);
58757
59068
  }
58758
59069
 
58759
59070
  async loadSdfData(data) { let ic = this.icn3d, me = ic.icn3dui;
@@ -59470,76 +59781,114 @@ class RealignParser {
59470
59781
  await this.realignChainOnSeqAlign(undefined, chainidArray, bRealign);
59471
59782
  }
59472
59783
 
59473
- async realignOnStructAlign(bReverse) { let ic = this.icn3d, me = ic.icn3dui;
59784
+ async realignOnStructAlign(bReverse, bVastsearch) { let ic = this.icn3d, me = ic.icn3dui;
59474
59785
  // each 3D domain should have at least 3 secondary structures
59475
59786
  let minSseCnt = (me.cfg.aligntool != 'tmalign') ? 3 : 0;
59476
59787
 
59477
- let struct2domain = {};
59478
- for(let struct in ic.structures) {
59479
- struct2domain[struct] = {};
59480
- let chainidArray = ic.structures[struct];
59481
- for(let i = 0, il = chainidArray.length; i < il; ++i) {
59482
- let chainid = chainidArray[i];
59483
- let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
59484
- let sseCnt = 0;
59485
- for(let serial in atoms) {
59486
- if(ic.atoms[serial].ssbegin) ++sseCnt;
59487
- if(sseCnt > minSseCnt) {
59488
- struct2domain[struct][chainid] = atoms;
59489
- break;
59490
- }
59491
- }
59492
- }
59493
- }
59788
+ /*
59789
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
59494
59790
 
59791
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
59792
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
59793
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
59794
+ // end of new version to be done for VASTsrv ==============
59795
+ */
59495
59796
  let ajaxArray = [], chainidPairArray = [];
59496
59797
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
59497
59798
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
59498
59799
 
59499
- //let cnt = 0;
59500
- let structArray = Object.keys(struct2domain);
59501
- if(bReverse) structArray = structArray.reverse();
59800
+ let struct2domain = {};
59801
+ if(bVastsearch && me.cfg.resrange) {
59802
+ let resRangeArray = decodeURIComponent(me.cfg.resrange).split(' | ');
59502
59803
 
59503
- for(let s = 0, sl = structArray.length; s < sl; ++s) {
59504
- let struct1 = structArray[s];
59804
+ let atomSet_t = ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms;
59805
+ for(let index = 1, indexl = ic.chainidArray.length; index < indexl; ++index) {
59806
+ let atomSet_q = ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms;
59505
59807
 
59506
- let chainidArray1 = Object.keys(struct2domain[struct1]);
59507
- if(chainidArray1.length == 0) continue;
59808
+ let alignAjax;
59809
+ if(me.cfg.aligntool != 'tmalign') {
59810
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
59811
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
59812
+
59813
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59814
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59815
+ }
59816
+ else {
59817
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
59818
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
59819
+
59820
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59821
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59822
+ }
59823
+
59824
+ ajaxArray.push(alignAjax);
59825
+
59826
+ chainidPairArray.push(ic.chainidArray[0] + ',' + ic.chainidArray[index]);
59827
+ }
59828
+ }
59829
+ else {
59830
+ for(let struct in ic.structures) {
59831
+ struct2domain[struct] = {};
59832
+ let chainidArray = ic.structures[struct];
59833
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
59834
+ let chainid = chainidArray[i];
59835
+ let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
59836
+ let sseCnt = 0;
59837
+ for(let serial in atoms) {
59838
+ if(ic.atoms[serial].ssbegin) ++sseCnt;
59839
+ if(sseCnt > minSseCnt) {
59840
+ struct2domain[struct][chainid] = atoms;
59841
+ break;
59842
+ }
59843
+ }
59844
+ }
59845
+ }
59508
59846
 
59509
- for(let i = 0, il = chainidArray1.length; i < il; ++i) {
59510
- let chainid1 = chainidArray1[i];
59511
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
59847
+ //let cnt = 0;
59848
+ let structArray = Object.keys(struct2domain);
59849
+ if(bReverse) structArray = structArray.reverse();
59512
59850
 
59513
- for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59514
- let struct2 = structArray[t];
59851
+ for(let s = 0, sl = structArray.length; s < sl; ++s) {
59852
+ let struct1 = structArray[s];
59515
59853
 
59516
- let chainidArray2 = Object.keys(struct2domain[struct2]);
59517
- if(chainidArray2.length == 0) continue;
59854
+ let chainidArray1 = Object.keys(struct2domain[struct1]);
59855
+ if(chainidArray1.length == 0) continue;
59518
59856
 
59519
- for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59520
- let chainid2 = chainidArray2[j];
59857
+ for(let i = 0, il = chainidArray1.length; i < il; ++i) {
59858
+ let chainid1 = chainidArray1[i];
59859
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
59521
59860
 
59522
- let alignAjax;
59523
- if(me.cfg.aligntool != 'tmalign') {
59524
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
59525
-
59526
- let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59527
- alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59528
- }
59529
- else {
59530
- let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
59531
- let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
59532
-
59533
- // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
59534
- // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
59861
+ for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59862
+ let struct2 = structArray[t];
59863
+
59864
+ let chainidArray2 = Object.keys(struct2domain[struct2]);
59865
+ if(chainidArray2.length == 0) continue;
59866
+
59867
+ for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59868
+ let chainid2 = chainidArray2[j];
59869
+
59870
+ let alignAjax;
59871
+ if(me.cfg.aligntool != 'tmalign') {
59872
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
59873
+
59874
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59875
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59876
+ }
59877
+ else {
59878
+ let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
59879
+ let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
59535
59880
 
59536
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59537
- alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59538
- }
59881
+ // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
59882
+ // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
59883
+
59884
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59885
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59886
+ }
59539
59887
 
59540
- ajaxArray.push(alignAjax);
59541
- chainidPairArray.push(chainid1 + ',' + chainid2);
59542
- //++cnt;
59888
+ ajaxArray.push(alignAjax);
59889
+ chainidPairArray.push(chainid1 + ',' + chainid2);
59890
+ //++cnt;
59891
+ }
59543
59892
  }
59544
59893
  }
59545
59894
  }
@@ -59655,7 +60004,7 @@ class RealignParser {
59655
60004
  let predefinedResArray, predefinedResPair;
59656
60005
 
59657
60006
  if(bPredefined) {
59658
- predefinedResArray = me.cfg.resdef.trim().replace(/\+/gi, ' ').split(': ');
60007
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
59659
60008
 
59660
60009
  if(predefinedResArray.length != chainidArray.length - 1) {
59661
60010
  alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -59844,7 +60193,7 @@ class RealignParser {
59844
60193
  }
59845
60194
  }
59846
60195
 
59847
- getSeqCoorResid(resiArray, chainid, bNCBI) { let ic = this.icn3d, me = ic.icn3dui;
60196
+ getSeqCoorResid(resiArray, chainid, bNCBIResi) { let ic = this.icn3d, me = ic.icn3dui;
59848
60197
  let seq = '', coorArray = [], residArray = [];
59849
60198
  let hAtoms = {};
59850
60199
 
@@ -59852,16 +60201,17 @@ class RealignParser {
59852
60201
  if(resiArray[j].indexOf('-') != -1) {
59853
60202
  let startEnd = resiArray[j].split('-');
59854
60203
  for(let k = parseInt(startEnd[0]); k <= parseInt(startEnd[1]); ++k) {
59855
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60204
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59856
60205
 
59857
60206
  // don't align solvent or chemicals
59858
60207
  if(!ic.chainsSeq[chainid] || !ic.chainsSeq[chainid][seqIndex] || me.parasCls.b62ResArray.indexOf(ic.chainsSeq[chainid][seqIndex].name.toUpperCase()) == -1) continue;
59859
60208
 
59860
60209
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59861
60210
 
59862
- coorArray = coorArray.concat(this.getResCoorArray(chainid + '_' + k));
60211
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60212
+ coorArray = coorArray.concat(this.getResCoorArray(resid));
59863
60213
 
59864
- residArray.push(chainid + '_' + k);
60214
+ residArray.push(resid);
59865
60215
  }
59866
60216
  }
59867
60217
  else if(resiArray[j] == 0) { // 0 means the whole chain
@@ -59871,18 +60221,19 @@ class RealignParser {
59871
60221
  else { // one residue
59872
60222
  let k = resiArray[j];
59873
60223
 
59874
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60224
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59875
60225
 
59876
60226
  if(!ic.chainsSeq[chainid][seqIndex]) continue;
59877
60227
 
59878
- let resCoorArray = this.getResCoorArray(chainid + '_' + k);
60228
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60229
+ let resCoorArray = this.getResCoorArray(resid);
59879
60230
  //if(resCoorArray.length == 1 && resCoorArray[0] === undefined) continue;
59880
60231
 
59881
60232
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59882
60233
 
59883
60234
  coorArray = coorArray.concat(resCoorArray);
59884
60235
 
59885
- residArray.push(chainid + '_' + k);
60236
+ residArray.push(resid);
59886
60237
  }
59887
60238
  }
59888
60239
 
@@ -64146,7 +64497,9 @@ class LoadPDB {
64146
64497
  structure = this.getStructureId(id, moleculeNum, bMutation, bNMR);
64147
64498
 
64148
64499
  ic.molTitle = '';
64149
- ic.molTitleHash = {};
64500
+ if (ic.allData === undefined) {
64501
+ ic.molTitleHash = {};
64502
+ }
64150
64503
 
64151
64504
  bHeader = true; // read the first header if there are multiple
64152
64505
  } else if (record === 'TITLE ') {
@@ -69170,15 +69523,15 @@ class SelectCollections {
69170
69523
  }
69171
69524
 
69172
69525
  //Set the menu of defined sets with an array of defined names "commandnameArray".
69173
- setAtomMenu(nameArray, titleArray) {
69526
+ setAtomMenu(nameArray) {
69174
69527
  let ic = this.icn3d;
69175
69528
  ic.icn3dui;
69176
69529
  let html = "";
69177
- let commandnameArray = [nameArray[0]];
69178
69530
  //for(let i in ic.defNames2Atoms) {
69179
69531
  for (let i = 0, il = nameArray.length; i < il; ++i) {
69180
- let name = nameArray[i];
69181
- let title = titleArray[i];
69532
+ let name = nameArray[i][0];
69533
+ let title = nameArray[i][1];
69534
+ let description = nameArray[i][2];
69182
69535
 
69183
69536
  let atomHash;
69184
69537
  if (
@@ -69201,16 +69554,11 @@ class SelectCollections {
69201
69554
  }
69202
69555
  }
69203
69556
 
69204
- if (commandnameArray.indexOf(name) != -1) {
69205
- html +=
69206
- "<option value='" +
69207
- name +
69208
- "' selected='selected'>" +
69209
- title +
69210
- "</option>";
69211
- } else {
69212
- html += "<option value='" + name + "'>" + title + "</option>";
69213
- }
69557
+ if (i == 0) {
69558
+ html += "<option value='" + nameArray[0][0] + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
69559
+ } else {
69560
+ html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
69561
+ }
69214
69562
  }
69215
69563
 
69216
69564
  return html;
@@ -69251,49 +69599,33 @@ class SelectCollections {
69251
69599
  }
69252
69600
 
69253
69601
  return difference;
69254
- }
69602
+ }
69255
69603
 
69256
- clickStructure() {
69604
+ clickStructure(collection) {
69257
69605
  let ic = this.icn3d,
69258
69606
  me = ic.icn3dui;
69259
69607
  let thisClass = this;
69260
69608
 
69261
- if (ic.allData == undefined) {
69262
- ic.allData = {};
69263
- ic.allData['all'] = {
69264
- 'atoms': {},
69265
- 'proteins': {},
69266
- 'nucleotides': {},
69267
- 'chemicals': {},
69268
- 'ions': {},
69269
- 'water': {},
69270
- 'structures': {},
69271
- 'ssbondpnts': {},
69272
- 'residues': {},
69273
- 'chains': {},
69274
- 'chainsSeq': {}, //Sequences and Annotation
69275
- 'defNames2Atoms': {},
69276
- 'defNames2Residues': {}
69277
- };
69278
- ic.allData['prev'] = {};
69279
- }
69280
-
69281
69609
  //me.myEventCls.onIds("#" + ic.pre + "atomsCustom", "change", function(e) { let ic = thisClass.icn3d;
69282
- $("#" + ic.pre + "collections_menu").change(async function (e) {
69610
+ $("#" + ic.pre + "collections_menu").on("change", async function (e) {
69283
69611
  let ic = thisClass.icn3d;
69284
69612
 
69285
69613
  let nameArray = $(this).val();
69286
69614
  let nameStructure = $(this).find("option:selected").text();
69615
+ let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
69616
+ let selectedIndicesMap = nameArray.reduce((map, name, i) => {
69617
+ map[name] = selectedIndices[i];
69618
+ return map;
69619
+ }, {});
69287
69620
 
69288
69621
  ic.nameArray = nameArray;
69289
- if (nameArray !== null) {
69290
- // let chainIdHash = {};
69291
69622
 
69623
+ if (nameArray !== null) {
69292
69624
  let bNoDuplicate = true;
69293
69625
  thisClass.reset();
69294
69626
  for (const name of nameArray) {
69295
69627
  if (!(name in ic.allData)) {
69296
- ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));//me.hashUtilsCls.cloneHash(ic.allData['all']);
69628
+ ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));
69297
69629
 
69298
69630
  ic.atoms = ic.allData['all']['atoms'];
69299
69631
 
@@ -69310,7 +69642,21 @@ class SelectCollections {
69310
69642
  ic.chainsSeq = ic.allData['all']['chainsSeq'];
69311
69643
  ic.defalls2Atoms = ic.allData['all']['defalls2Atoms'];
69312
69644
  ic.defalls2Residues = ic.allData['all']['defalls2Residues'];
69313
- await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate).then(() => {
69645
+
69646
+ async function loadStructure(pdb) {
69647
+ await ic.resetConfig();
69648
+ if (pdb) {
69649
+ let bAppend = true;
69650
+ if (Object.keys(ic.structures).length == 0) {
69651
+ bAppend = false;
69652
+ }
69653
+ await ic.pdbParserCls.loadPdbData(ic.pdbCollection[selectedIndicesMap[name]].join('\n'), undefined, undefined, bAppend);
69654
+ } else {
69655
+ await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
69656
+ }
69657
+ }
69658
+
69659
+ await loadStructure(collection[selectedIndicesMap[name]][4]).then(() => {
69314
69660
  ic.allData['all'] = {
69315
69661
  'atoms': ic.atoms,
69316
69662
  'proteins': ic.proteins,
@@ -69318,9 +69664,9 @@ class SelectCollections {
69318
69664
  'chemicals': ic.chemicals,
69319
69665
  'ions': ic.ions,
69320
69666
  'water': ic.water,
69321
- 'structures': ic.structures,
69667
+ 'structures': ic.structures, // getSSExpandedAtoms
69322
69668
  'ssbondpnts': ic.ssbondpnts,
69323
- 'residues': ic.residues,
69669
+ 'residues': ic.residues, // getSSExpandedAtoms
69324
69670
  'chains': ic.chains,
69325
69671
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
69326
69672
  'defNames2Atoms': ic.defNames2Atoms,
@@ -69328,26 +69674,27 @@ class SelectCollections {
69328
69674
  };
69329
69675
 
69330
69676
  ic.allData[name] = {
69677
+ 'title': ic.molTitle,
69331
69678
  'atoms': thisClass.dictionaryDifference(ic.allData['prev']['atoms'], ic.atoms),
69332
69679
  'proteins': thisClass.dictionaryDifference(ic.allData['prev']['proteins'], ic.proteins),
69333
69680
  'nucleotides': thisClass.dictionaryDifference(ic.allData['prev']['nucleotides'], ic.nucleotides),
69334
69681
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
69335
69682
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
69336
69683
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
69337
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
69684
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
69338
69685
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
69339
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
69686
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
69340
69687
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
69341
69688
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
69342
69689
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
69343
69690
  'defNames2Residues': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Residues'], ic.defNames2Residues)
69344
69691
  };
69345
69692
 
69346
- // ic.atoms = Object.assign(ic.atoms, ic.atomsTemp);
69347
69693
  thisClass.reset();
69348
69694
  });
69349
69695
  }
69350
69696
  }
69697
+
69351
69698
  for (const name of nameArray) {
69352
69699
  ic.atoms = Object.assign(ic.atoms, ic.allData[name]['atoms']);
69353
69700
 
@@ -69366,10 +69713,26 @@ class SelectCollections {
69366
69713
  ic.defNames2Residues = Object.assign(ic.defNames2Residues, ic.allData[name]['defNames2Residues']);
69367
69714
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69368
69715
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69369
- }
69716
+
69717
+ ic.molTitle = ic.allData[name]['title'];
69370
69718
 
69719
+ if (collection[selectedIndicesMap[name]][3] !== undefined && collection[selectedIndicesMap[name]][3].length > 0) {
69720
+ if (ic.allData[name]['commands'] == undefined) {
69721
+ let commands = collection[selectedIndicesMap[name]][3];
69722
+ ic.allData[name]['commands'] = commands;
69723
+ }
69724
+ }
69725
+
69726
+ if (ic.allData[name]['commands'] !== undefined) {
69727
+ for (const command of ic.allData[name]['commands']) {
69728
+ me.htmlCls.clickMenuCls.setLogCmd(command, true);
69729
+ await ic.applyCommandCls.applyCommand(command);
69730
+ }
69731
+ }
69732
+
69733
+ }
69734
+
69371
69735
  ic.opts["color"] = (Object.keys(ic.structures).length == 1) ? "chain" : "structure";
69372
- // ic.setStyleCls.setAtomStyleByOptions();
69373
69736
  ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
69374
69737
 
69375
69738
  ic.transformCls.zoominSelection();
@@ -69383,14 +69746,12 @@ class SelectCollections {
69383
69746
  // show selected chains in annotation window
69384
69747
  ic.annotationCls.showAnnoSelectedChains();
69385
69748
  }
69386
-
69749
+
69387
69750
  await ic.drawCls.draw();
69388
69751
  ic.saveFileCls.showTitle();
69389
69752
 
69390
- me.htmlCls.clickMenuCls.setLogCmd(
69391
- "select structure " + "[" + nameStructure + "]",
69392
- true
69393
- );
69753
+ me.htmlCls.clickMenuCls.setLogCmd("select structure " + "[" + nameStructure + "]", false);
69754
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf1 ' + nameArray, true);
69394
69755
  }
69395
69756
  });
69396
69757
 
@@ -70302,7 +70663,7 @@ class LoadScript {
70302
70663
  if(steps === 1
70303
70664
  || (ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length === Object.keys(ic.atoms).length)
70304
70665
  || (ic.optsHistory[steps - 1] !== undefined && ic.optsHistory[steps - 1].hasOwnProperty('hlatomcount') && ic.optsHistory[steps - 1].hlatomcount === Object.keys(ic.atoms).length) ) {
70305
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
70666
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
70306
70667
  // if(steps === 1) {
70307
70668
  // assign styles and color using the options at that stage
70308
70669
  // ic.setStyleCls.setAtomStyleByOptions(ic.optsHistory[steps - 1]);
@@ -70324,7 +70685,7 @@ class LoadScript {
70324
70685
  ic.pk = 3;
70325
70686
  }
70326
70687
 
70327
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
70688
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
70328
70689
  // if(steps === 1) {
70329
70690
  // ic.setColorCls.applyOriginalColor();
70330
70691
  // }
@@ -71390,6 +71751,10 @@ class Selection {
71390
71751
  selectOneResid(idStr, bUnchecked) {var ic = this.icn3d; ic.icn3dui;
71391
71752
  //var idStr = idArray[i]; // TYR $1KQ2.B:56@OH, $1KQ2.B:40 ASP
71392
71753
  //change to: let idStr = idArray[i]; // TYR $1KQ2.B:56@OH, or ASP $1KQ2.B:40
71754
+ //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
71755
+ let idArray = idStr.split(' ');
71756
+ idStr = idArray[1];
71757
+
71393
71758
  let posStructure = idStr.indexOf('$');
71394
71759
  let posChain = idStr.indexOf('.');
71395
71760
  let posRes = idStr.indexOf(':');
@@ -80202,7 +80567,7 @@ class ShareLink {
80202
80567
  let shortName = strArray[strArray.length - 1];
80203
80568
  ic.saveFileCls.saveFile(inputid + '-' + shortName + '.png', 'png');
80204
80569
  let text = '<div style="float:left; border: solid 1px #0000ff; padding: 5px; margin: 10px; text-align:center;">';
80205
- text += '<a href="https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + shortName + '" target="_blank">';
80570
+ text += '<a href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + shortName + '" target="_blank">';
80206
80571
  text += '<img style="height:300px" src ="' + inputid + '-' + shortName + '.png"><br>\n';
80207
80572
  text += '<!--Start of your comments==================-->\n';
80208
80573
  let yournote =(ic.yournote) ? ': ' + ic.yournote.replace(/\n/g, "<br>").replace(/; /g, ", ") : '';
@@ -80221,9 +80586,9 @@ class ShareLink {
80221
80586
  //shorturl: https://icn3d.page.link/NvbAh1Vmiwc4bgX87
80222
80587
  let urlArray = shorturl.split('page.link/');
80223
80588
  //if(urlArray.length == 2) shorturl = me.htmlCls.baseUrl + 'icn3d/share.html?' + urlArray[1];
80224
- // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to past posted data in Mac/iphone
80589
+ // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to pass posted data in Mac/iphone
80225
80590
  // So the base URL is still www.ncbi.nlm.nih.gov/Structure,just use short URL here
80226
- if(urlArray.length == 2) shorturl = 'https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + urlArray[1];
80591
+ if(urlArray.length == 2) shorturl = 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + urlArray[1];
80227
80592
 
80228
80593
  $("#" + ic.pre + "short_url").val(shorturl);
80229
80594
  $("#" + ic.pre + "short_url_title").val(shorturl + '&t=' + ic.yournote);
@@ -83380,7 +83745,7 @@ class iCn3DUI {
83380
83745
  //even when multiple iCn3D viewers are shown together.
83381
83746
  this.pre = this.cfg.divid + "_";
83382
83747
 
83383
- this.REVISION = '3.38.0';
83748
+ this.REVISION = '3.39.0';
83384
83749
 
83385
83750
  // In nodejs, iCn3D defines "window = {navigator: {}}"
83386
83751
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -83555,6 +83920,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83555
83920
 
83556
83921
  await ic.pdbParserCls.loadPdbData(pdbStr);
83557
83922
 
83923
+ // // use NCBI residue numbers if using VAST
83924
+ // me.icn3d.bUsePdbNum = 0;
83925
+
83558
83926
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
83559
83927
  let structureArray = Object.keys(ic.structures);
83560
83928
  let chainArray = me.cfg.chains.split(' | ');
@@ -83830,7 +84198,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83830
84198
 
83831
84199
  ic.bChainAlign = true;
83832
84200
  ic.inputid = me.cfg.chainalign;
83833
- let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
84201
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + decodeURIComponent(me.cfg.resrange) : '';
83834
84202
  let resdef = (me.cfg.resdef) ? me.cfg.resdef : '';
83835
84203
  ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
83836
84204
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);