icn3d 3.38.2 → 3.39.1

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;
@@ -52642,7 +52952,10 @@ class ViewInterPairs {
52642
52952
  cntHbond += result.cnt;
52643
52953
  svgHtmlNode += result.svgHtmlNode;
52644
52954
  svgHtmlLine += result.svgHtmlLine;
52645
- if(result.cnt > 0) residname2List += residname2 + ":hbond_" + result.cnt + " ";
52955
+ // if(result.cnt > 0) residname2List += residname2 + ":hbond_" + result.cnt + " ";
52956
+ // add hydrogen bond between main or side chains. result.mainside has value such as main,side,side,side
52957
+ // for two hydrogens between main and side, and side and side chains
52958
+ if(result.cnt > 0) residname2List += residname2 + ":hbond_" + result.cnt + ":type_" + result.mainside + " ";
52646
52959
 
52647
52960
  labels2dist = ic.resids2inter[resids]['ionic'];
52648
52961
  result = this.getInteractionPairDetails(labels2dist, type, 'ionic', index2xy, xlen, ylen, xcenter, ycenter);
@@ -52650,7 +52963,7 @@ class ViewInterPairs {
52650
52963
  cntIonic += result.cnt;
52651
52964
  svgHtmlNode += result.svgHtmlNode;
52652
52965
  svgHtmlLine += result.svgHtmlLine;
52653
- if(result.cnt > 0) residname2List += residname2 + ":ionic_" + result.cnt + " ";
52966
+ if(result.cnt > 0) residname2List += residname2 + ":ionic_" + result.cnt + ":type_" + result.mainside + " ";
52654
52967
 
52655
52968
  labels2dist = ic.resids2inter[resids]['halogen'];
52656
52969
  result = this.getInteractionPairDetails(labels2dist, type, 'halogen', index2xy, xlen, ylen, xcenter, ycenter);
@@ -52658,7 +52971,7 @@ class ViewInterPairs {
52658
52971
  cntHalegen += result.cnt;
52659
52972
  svgHtmlNode += result.svgHtmlNode;
52660
52973
  svgHtmlLine += result.svgHtmlLine;
52661
- if(result.cnt > 0) residname2List += residname2 + ":halogen_" + result.cnt + " ";
52974
+ if(result.cnt > 0) residname2List += residname2 + ":halogen_" + result.cnt + ":type_" + result.mainside + " ";
52662
52975
 
52663
52976
  labels2dist = ic.resids2inter[resids]['pi-cation'];
52664
52977
  result = this.getInteractionPairDetails(labels2dist, type, 'pi-cation', index2xy, xlen, ylen, xcenter, ycenter);
@@ -52666,7 +52979,7 @@ class ViewInterPairs {
52666
52979
  cntPication += result.cnt;
52667
52980
  svgHtmlNode += result.svgHtmlNode;
52668
52981
  svgHtmlLine += result.svgHtmlLine;
52669
- if(result.cnt > 0) residname2List += residname2 + ":pi-cation_" + result.cnt + " ";
52982
+ if(result.cnt > 0) residname2List += residname2 + ":pi-cation_" + result.cnt + ":type_" + result.mainside + " ";
52670
52983
 
52671
52984
  labels2dist = ic.resids2inter[resids]['pi-stacking'];
52672
52985
  result = this.getInteractionPairDetails(labels2dist, type, 'pi-stacking', index2xy, xlen, ylen, xcenter, ycenter);
@@ -52674,7 +52987,7 @@ class ViewInterPairs {
52674
52987
  cntPistacking += result.cnt;
52675
52988
  svgHtmlNode += result.svgHtmlNode;
52676
52989
  svgHtmlLine += result.svgHtmlLine;
52677
- if(result.cnt > 0) residname2List += residname2 + ":pi-stacking_" + result.cnt + " ";
52990
+ if(result.cnt > 0) residname2List += residname2 + ":pi-stacking_" + result.cnt + ":type_" + result.mainside + " ";
52678
52991
 
52679
52992
  // put contact as the last one since contact will use the same node as other interactions in ligand-protein interactoin
52680
52993
  labels2dist = ic.resids2inter[resids]['contact'];
@@ -52728,7 +53041,7 @@ class ViewInterPairs {
52728
53041
  return tmpText;
52729
53042
  }
52730
53043
  getInteractionPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
52731
- let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0;
53044
+ let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0, mainside= '';
52732
53045
  let colorText1 = ' <span style="background-color:#';
52733
53046
  let colorText2 = '">&nbsp;&nbsp;&nbsp;</span>';
52734
53047
  if(labels2dist !== undefined) {
@@ -52745,6 +53058,12 @@ class ViewInterPairs {
52745
53058
  let resid1 = resid1Ori.substr(0, pos1);
52746
53059
  let resid2 = resid2Ori.substr(0, pos2);
52747
53060
 
53061
+ let atomName1 = resid1.substr(resid1.indexOf('@') + 1);
53062
+ resid2.substr(resid2.indexOf('@') + 1);
53063
+ let atomType1 = (atomName1 === "N" || atomName1 === "C" || atomName1 === "O" || atomName1 === "CA") ? 'main' : 'side';
53064
+ if(mainside) mainside += ';';
53065
+ mainside += atomType1 + ',' + atomType1;
53066
+
52748
53067
  let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
52749
53068
  let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
52750
53069
  let color1 = (atom1.color) ? atom1.color.getHexString() : '';
@@ -52766,7 +53085,7 @@ class ViewInterPairs {
52766
53085
  }
52767
53086
  }
52768
53087
  }
52769
- return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine}
53088
+ return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine, mainside: mainside}
52770
53089
  }
52771
53090
 
52772
53091
  getContactPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
@@ -54274,7 +54593,7 @@ class ChainalignParser {
54274
54593
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
54275
54594
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
54276
54595
 
54277
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
54596
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
54278
54597
 
54279
54598
  for(let index in ic.afChainIndexHash) {
54280
54599
  let idArray = ic.afChainIndexHash[index].split('_');
@@ -54299,9 +54618,10 @@ class ChainalignParser {
54299
54618
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
54300
54619
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
54301
54620
 
54302
- let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(',') : [];
54621
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
54303
54622
 
54304
54623
  // dynamically align pairs in all chainids
54624
+ // the resrange from VASTSrv or VAST search uses NCBI residue numbers!!!
54305
54625
  let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
54306
54626
  for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
54307
54627
  let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
@@ -54476,7 +54796,8 @@ class ChainalignParser {
54476
54796
  if(!bFoundAlignment) {
54477
54797
  // sometimes VAST align works for the reversed pair
54478
54798
  if(!bReverse) {
54479
- ic.realignParserCls.realignOnStructAlign(true);
54799
+ let bVastsearch = true;
54800
+ ic.realignParserCls.realignOnStructAlign(true, bVastsearch);
54480
54801
  return;
54481
54802
  }
54482
54803
  else {
@@ -55232,7 +55553,8 @@ class ChainalignParser {
55232
55553
  // await ic.realignParserCls.realignChainOnSeqAlign(undefined, ic.chainidArray, bRealign, bPredefined);
55233
55554
 
55234
55555
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(ic.chainidArray);
55235
- await ic.realignParserCls.realignOnStructAlign();
55556
+ let bVastsearch = true;
55557
+ await ic.realignParserCls.realignOnStructAlign(undefined, bVastsearch);
55236
55558
 
55237
55559
  // reset annotations
55238
55560
  $("#" + ic.pre + "dl_annotations").html("");
@@ -59468,76 +59790,114 @@ class RealignParser {
59468
59790
  await this.realignChainOnSeqAlign(undefined, chainidArray, bRealign);
59469
59791
  }
59470
59792
 
59471
- async realignOnStructAlign(bReverse) { let ic = this.icn3d, me = ic.icn3dui;
59793
+ async realignOnStructAlign(bReverse, bVastsearch) { let ic = this.icn3d, me = ic.icn3dui;
59472
59794
  // each 3D domain should have at least 3 secondary structures
59473
59795
  let minSseCnt = (me.cfg.aligntool != 'tmalign') ? 3 : 0;
59474
59796
 
59475
- let struct2domain = {};
59476
- for(let struct in ic.structures) {
59477
- struct2domain[struct] = {};
59478
- let chainidArray = ic.structures[struct];
59479
- for(let i = 0, il = chainidArray.length; i < il; ++i) {
59480
- let chainid = chainidArray[i];
59481
- let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
59482
- let sseCnt = 0;
59483
- for(let serial in atoms) {
59484
- if(ic.atoms[serial].ssbegin) ++sseCnt;
59485
- if(sseCnt > minSseCnt) {
59486
- struct2domain[struct][chainid] = atoms;
59487
- break;
59488
- }
59489
- }
59490
- }
59491
- }
59797
+ /*
59798
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
59492
59799
 
59800
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms : ic.chains[chainidArray[0]];
59801
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
59802
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms : ic.chains[chainidArray[index]];
59803
+ // end of new version to be done for VASTsrv ==============
59804
+ */
59493
59805
  let ajaxArray = [], chainidPairArray = [];
59494
59806
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
59495
59807
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
59496
59808
 
59497
- //let cnt = 0;
59498
- let structArray = Object.keys(struct2domain);
59499
- if(bReverse) structArray = structArray.reverse();
59809
+ let struct2domain = {};
59810
+ if(bVastsearch && me.cfg.resrange) {
59811
+ let resRangeArray = decodeURIComponent(me.cfg.resrange).split(' | ');
59500
59812
 
59501
- for(let s = 0, sl = structArray.length; s < sl; ++s) {
59502
- let struct1 = structArray[s];
59813
+ let atomSet_t = ic.realignParserCls.getSeqCoorResid([resRangeArray[0]], ic.chainidArray[0], true).hAtoms;
59814
+ for(let index = 1, indexl = ic.chainidArray.length; index < indexl; ++index) {
59815
+ let atomSet_q = ic.realignParserCls.getSeqCoorResid([resRangeArray[index]], ic.chainidArray[index], true).hAtoms;
59503
59816
 
59504
- let chainidArray1 = Object.keys(struct2domain[struct1]);
59505
- if(chainidArray1.length == 0) continue;
59817
+ let alignAjax;
59818
+ if(me.cfg.aligntool != 'tmalign') {
59819
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
59820
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
59821
+
59822
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59823
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59824
+ }
59825
+ else {
59826
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
59827
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
59506
59828
 
59507
- for(let i = 0, il = chainidArray1.length; i < il; ++i) {
59508
- let chainid1 = chainidArray1[i];
59509
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
59829
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59830
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59831
+ }
59510
59832
 
59511
- for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59512
- let struct2 = structArray[t];
59833
+ ajaxArray.push(alignAjax);
59834
+
59835
+ chainidPairArray.push(ic.chainidArray[0] + ',' + ic.chainidArray[index]);
59836
+ }
59837
+ }
59838
+ else {
59839
+ for(let struct in ic.structures) {
59840
+ struct2domain[struct] = {};
59841
+ let chainidArray = ic.structures[struct];
59842
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
59843
+ let chainid = chainidArray[i];
59844
+ let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
59845
+ let sseCnt = 0;
59846
+ for(let serial in atoms) {
59847
+ if(ic.atoms[serial].ssbegin) ++sseCnt;
59848
+ if(sseCnt > minSseCnt) {
59849
+ struct2domain[struct][chainid] = atoms;
59850
+ break;
59851
+ }
59852
+ }
59853
+ }
59854
+ }
59513
59855
 
59514
- let chainidArray2 = Object.keys(struct2domain[struct2]);
59515
- if(chainidArray2.length == 0) continue;
59856
+ //let cnt = 0;
59857
+ let structArray = Object.keys(struct2domain);
59858
+ if(bReverse) structArray = structArray.reverse();
59516
59859
 
59517
- for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59518
- let chainid2 = chainidArray2[j];
59860
+ for(let s = 0, sl = structArray.length; s < sl; ++s) {
59861
+ let struct1 = structArray[s];
59519
59862
 
59520
- let alignAjax;
59521
- if(me.cfg.aligntool != 'tmalign') {
59522
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
59523
-
59524
- let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59525
- alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59526
- }
59527
- else {
59528
- let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
59529
- let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
59530
-
59531
- // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
59532
- // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
59863
+ let chainidArray1 = Object.keys(struct2domain[struct1]);
59864
+ if(chainidArray1.length == 0) continue;
59865
+
59866
+ for(let i = 0, il = chainidArray1.length; i < il; ++i) {
59867
+ let chainid1 = chainidArray1[i];
59868
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
59869
+
59870
+ for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59871
+ let struct2 = structArray[t];
59872
+
59873
+ let chainidArray2 = Object.keys(struct2domain[struct2]);
59874
+ if(chainidArray2.length == 0) continue;
59875
+
59876
+ for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59877
+ let chainid2 = chainidArray2[j];
59878
+
59879
+ let alignAjax;
59880
+ if(me.cfg.aligntool != 'tmalign') {
59881
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
59882
+
59883
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
59884
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
59885
+ }
59886
+ else {
59887
+ let pdb_target = ic.saveFileCls.getAtomPDB(struct2domain[struct1][chainid1], undefined, undefined, undefined, undefined, struct1);
59888
+ let pdb_query = ic.saveFileCls.getAtomPDB(struct2domain[struct2][chainid2], undefined, undefined, undefined, undefined, struct2);
59533
59889
 
59534
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59535
- alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59536
- }
59890
+ // let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
59891
+ // let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
59892
+
59893
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59894
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59895
+ }
59537
59896
 
59538
- ajaxArray.push(alignAjax);
59539
- chainidPairArray.push(chainid1 + ',' + chainid2);
59540
- //++cnt;
59897
+ ajaxArray.push(alignAjax);
59898
+ chainidPairArray.push(chainid1 + ',' + chainid2);
59899
+ //++cnt;
59900
+ }
59541
59901
  }
59542
59902
  }
59543
59903
  }
@@ -59653,7 +60013,7 @@ class RealignParser {
59653
60013
  let predefinedResArray, predefinedResPair;
59654
60014
 
59655
60015
  if(bPredefined) {
59656
- predefinedResArray = me.cfg.resdef.trim().replace(/\+/gi, ' ').split(': ');
60016
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
59657
60017
 
59658
60018
  if(predefinedResArray.length != chainidArray.length - 1) {
59659
60019
  alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -59842,7 +60202,7 @@ class RealignParser {
59842
60202
  }
59843
60203
  }
59844
60204
 
59845
- getSeqCoorResid(resiArray, chainid, bNCBI) { let ic = this.icn3d, me = ic.icn3dui;
60205
+ getSeqCoorResid(resiArray, chainid, bNCBIResi) { let ic = this.icn3d, me = ic.icn3dui;
59846
60206
  let seq = '', coorArray = [], residArray = [];
59847
60207
  let hAtoms = {};
59848
60208
 
@@ -59850,16 +60210,17 @@ class RealignParser {
59850
60210
  if(resiArray[j].indexOf('-') != -1) {
59851
60211
  let startEnd = resiArray[j].split('-');
59852
60212
  for(let k = parseInt(startEnd[0]); k <= parseInt(startEnd[1]); ++k) {
59853
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60213
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59854
60214
 
59855
60215
  // don't align solvent or chemicals
59856
60216
  if(!ic.chainsSeq[chainid] || !ic.chainsSeq[chainid][seqIndex] || me.parasCls.b62ResArray.indexOf(ic.chainsSeq[chainid][seqIndex].name.toUpperCase()) == -1) continue;
59857
60217
 
59858
60218
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59859
60219
 
59860
- coorArray = coorArray.concat(this.getResCoorArray(chainid + '_' + k));
60220
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60221
+ coorArray = coorArray.concat(this.getResCoorArray(resid));
59861
60222
 
59862
- residArray.push(chainid + '_' + k);
60223
+ residArray.push(resid);
59863
60224
  }
59864
60225
  }
59865
60226
  else if(resiArray[j] == 0) { // 0 means the whole chain
@@ -59869,18 +60230,19 @@ class RealignParser {
59869
60230
  else { // one residue
59870
60231
  let k = resiArray[j];
59871
60232
 
59872
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60233
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59873
60234
 
59874
60235
  if(!ic.chainsSeq[chainid][seqIndex]) continue;
59875
60236
 
59876
- let resCoorArray = this.getResCoorArray(chainid + '_' + k);
60237
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60238
+ let resCoorArray = this.getResCoorArray(resid);
59877
60239
  //if(resCoorArray.length == 1 && resCoorArray[0] === undefined) continue;
59878
60240
 
59879
60241
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59880
60242
 
59881
60243
  coorArray = coorArray.concat(resCoorArray);
59882
60244
 
59883
- residArray.push(chainid + '_' + k);
60245
+ residArray.push(resid);
59884
60246
  }
59885
60247
  }
59886
60248
 
@@ -64129,6 +64491,9 @@ class LoadPDB {
64129
64491
 
64130
64492
  ///id = line.substr(62, 4).trim();
64131
64493
  id = line.substr(62).trim();
64494
+ // remove "_" in the id
64495
+ id = id.replace(/_/g, '-');
64496
+
64132
64497
  oriId = id;
64133
64498
 
64134
64499
  if(id == '') {
@@ -64144,7 +64509,9 @@ class LoadPDB {
64144
64509
  structure = this.getStructureId(id, moleculeNum, bMutation, bNMR);
64145
64510
 
64146
64511
  ic.molTitle = '';
64147
- ic.molTitleHash = {};
64512
+ if (ic.allData === undefined) {
64513
+ ic.molTitleHash = {};
64514
+ }
64148
64515
 
64149
64516
  bHeader = true; // read the first header if there are multiple
64150
64517
  } else if (record === 'TITLE ') {
@@ -65037,6 +65404,8 @@ class LoadCIF {
65037
65404
 
65038
65405
  if(block.getCategory("_entry")) {
65039
65406
  id = block.getCategory("_entry").getColumn("id").getString(0);
65407
+ // remove "_" in the id
65408
+ id = id.replace(/_/g, '-');
65040
65409
 
65041
65410
  if(id == '') {
65042
65411
  if(bAppend) {
@@ -69168,15 +69537,15 @@ class SelectCollections {
69168
69537
  }
69169
69538
 
69170
69539
  //Set the menu of defined sets with an array of defined names "commandnameArray".
69171
- setAtomMenu(nameArray, titleArray) {
69540
+ setAtomMenu(nameArray) {
69172
69541
  let ic = this.icn3d;
69173
69542
  ic.icn3dui;
69174
69543
  let html = "";
69175
- let commandnameArray = [nameArray[0]];
69176
69544
  //for(let i in ic.defNames2Atoms) {
69177
69545
  for (let i = 0, il = nameArray.length; i < il; ++i) {
69178
- let name = nameArray[i];
69179
- let title = titleArray[i];
69546
+ let name = nameArray[i][0];
69547
+ let title = nameArray[i][1];
69548
+ let description = nameArray[i][2];
69180
69549
 
69181
69550
  let atomHash;
69182
69551
  if (
@@ -69199,16 +69568,11 @@ class SelectCollections {
69199
69568
  }
69200
69569
  }
69201
69570
 
69202
- if (commandnameArray.indexOf(name) != -1) {
69203
- html +=
69204
- "<option value='" +
69205
- name +
69206
- "' selected='selected'>" +
69207
- title +
69208
- "</option>";
69209
- } else {
69210
- html += "<option value='" + name + "'>" + title + "</option>";
69211
- }
69571
+ if (i == 0) {
69572
+ html += "<option value='" + nameArray[0][0] + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
69573
+ } else {
69574
+ html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
69575
+ }
69212
69576
  }
69213
69577
 
69214
69578
  return html;
@@ -69249,49 +69613,33 @@ class SelectCollections {
69249
69613
  }
69250
69614
 
69251
69615
  return difference;
69252
- }
69616
+ }
69253
69617
 
69254
- clickStructure() {
69618
+ clickStructure(collection) {
69255
69619
  let ic = this.icn3d,
69256
69620
  me = ic.icn3dui;
69257
69621
  let thisClass = this;
69258
69622
 
69259
- if (ic.allData == undefined) {
69260
- ic.allData = {};
69261
- ic.allData['all'] = {
69262
- 'atoms': {},
69263
- 'proteins': {},
69264
- 'nucleotides': {},
69265
- 'chemicals': {},
69266
- 'ions': {},
69267
- 'water': {},
69268
- 'structures': {},
69269
- 'ssbondpnts': {},
69270
- 'residues': {},
69271
- 'chains': {},
69272
- 'chainsSeq': {}, //Sequences and Annotation
69273
- 'defNames2Atoms': {},
69274
- 'defNames2Residues': {}
69275
- };
69276
- ic.allData['prev'] = {};
69277
- }
69278
-
69279
69623
  //me.myEventCls.onIds("#" + ic.pre + "atomsCustom", "change", function(e) { let ic = thisClass.icn3d;
69280
- $("#" + ic.pre + "collections_menu").change(async function (e) {
69624
+ $("#" + ic.pre + "collections_menu").on("change", async function (e) {
69281
69625
  let ic = thisClass.icn3d;
69282
69626
 
69283
69627
  let nameArray = $(this).val();
69284
69628
  let nameStructure = $(this).find("option:selected").text();
69629
+ let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
69630
+ let selectedIndicesMap = nameArray.reduce((map, name, i) => {
69631
+ map[name] = selectedIndices[i];
69632
+ return map;
69633
+ }, {});
69285
69634
 
69286
69635
  ic.nameArray = nameArray;
69287
- if (nameArray !== null) {
69288
- // let chainIdHash = {};
69289
69636
 
69637
+ if (nameArray !== null) {
69290
69638
  let bNoDuplicate = true;
69291
69639
  thisClass.reset();
69292
69640
  for (const name of nameArray) {
69293
69641
  if (!(name in ic.allData)) {
69294
- ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));//me.hashUtilsCls.cloneHash(ic.allData['all']);
69642
+ ic.allData['prev'] = JSON.parse(JSON.stringify(ic.allData['all']));
69295
69643
 
69296
69644
  ic.atoms = ic.allData['all']['atoms'];
69297
69645
 
@@ -69308,7 +69656,21 @@ class SelectCollections {
69308
69656
  ic.chainsSeq = ic.allData['all']['chainsSeq'];
69309
69657
  ic.defalls2Atoms = ic.allData['all']['defalls2Atoms'];
69310
69658
  ic.defalls2Residues = ic.allData['all']['defalls2Residues'];
69311
- await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate).then(() => {
69659
+
69660
+ async function loadStructure(pdb) {
69661
+ await ic.resetConfig();
69662
+ if (pdb) {
69663
+ let bAppend = true;
69664
+ if (Object.keys(ic.structures).length == 0) {
69665
+ bAppend = false;
69666
+ }
69667
+ await ic.pdbParserCls.loadPdbData(ic.pdbCollection[selectedIndicesMap[name]].join('\n'), undefined, undefined, bAppend);
69668
+ } else {
69669
+ await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
69670
+ }
69671
+ }
69672
+
69673
+ await loadStructure(collection[selectedIndicesMap[name]][4]).then(() => {
69312
69674
  ic.allData['all'] = {
69313
69675
  'atoms': ic.atoms,
69314
69676
  'proteins': ic.proteins,
@@ -69316,9 +69678,9 @@ class SelectCollections {
69316
69678
  'chemicals': ic.chemicals,
69317
69679
  'ions': ic.ions,
69318
69680
  'water': ic.water,
69319
- 'structures': ic.structures,
69681
+ 'structures': ic.structures, // getSSExpandedAtoms
69320
69682
  'ssbondpnts': ic.ssbondpnts,
69321
- 'residues': ic.residues,
69683
+ 'residues': ic.residues, // getSSExpandedAtoms
69322
69684
  'chains': ic.chains,
69323
69685
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
69324
69686
  'defNames2Atoms': ic.defNames2Atoms,
@@ -69326,26 +69688,27 @@ class SelectCollections {
69326
69688
  };
69327
69689
 
69328
69690
  ic.allData[name] = {
69691
+ 'title': ic.molTitle,
69329
69692
  'atoms': thisClass.dictionaryDifference(ic.allData['prev']['atoms'], ic.atoms),
69330
69693
  'proteins': thisClass.dictionaryDifference(ic.allData['prev']['proteins'], ic.proteins),
69331
69694
  'nucleotides': thisClass.dictionaryDifference(ic.allData['prev']['nucleotides'], ic.nucleotides),
69332
69695
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
69333
69696
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
69334
69697
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
69335
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
69698
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
69336
69699
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
69337
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
69700
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
69338
69701
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
69339
69702
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
69340
69703
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
69341
69704
  'defNames2Residues': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Residues'], ic.defNames2Residues)
69342
69705
  };
69343
69706
 
69344
- // ic.atoms = Object.assign(ic.atoms, ic.atomsTemp);
69345
69707
  thisClass.reset();
69346
69708
  });
69347
69709
  }
69348
69710
  }
69711
+
69349
69712
  for (const name of nameArray) {
69350
69713
  ic.atoms = Object.assign(ic.atoms, ic.allData[name]['atoms']);
69351
69714
 
@@ -69364,10 +69727,26 @@ class SelectCollections {
69364
69727
  ic.defNames2Residues = Object.assign(ic.defNames2Residues, ic.allData[name]['defNames2Residues']);
69365
69728
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69366
69729
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69367
- }
69730
+
69731
+ ic.molTitle = ic.allData[name]['title'];
69368
69732
 
69733
+ if (collection[selectedIndicesMap[name]][3] !== undefined && collection[selectedIndicesMap[name]][3].length > 0) {
69734
+ if (ic.allData[name]['commands'] == undefined) {
69735
+ let commands = collection[selectedIndicesMap[name]][3];
69736
+ ic.allData[name]['commands'] = commands;
69737
+ }
69738
+ }
69739
+
69740
+ if (ic.allData[name]['commands'] !== undefined) {
69741
+ for (const command of ic.allData[name]['commands']) {
69742
+ me.htmlCls.clickMenuCls.setLogCmd(command, true);
69743
+ await ic.applyCommandCls.applyCommand(command);
69744
+ }
69745
+ }
69746
+
69747
+ }
69748
+
69369
69749
  ic.opts["color"] = (Object.keys(ic.structures).length == 1) ? "chain" : "structure";
69370
- // ic.setStyleCls.setAtomStyleByOptions();
69371
69750
  ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
69372
69751
 
69373
69752
  ic.transformCls.zoominSelection();
@@ -69381,14 +69760,12 @@ class SelectCollections {
69381
69760
  // show selected chains in annotation window
69382
69761
  ic.annotationCls.showAnnoSelectedChains();
69383
69762
  }
69384
-
69763
+
69385
69764
  await ic.drawCls.draw();
69386
69765
  ic.saveFileCls.showTitle();
69387
69766
 
69388
- me.htmlCls.clickMenuCls.setLogCmd(
69389
- "select structure " + "[" + nameStructure + "]",
69390
- true
69391
- );
69767
+ me.htmlCls.clickMenuCls.setLogCmd("select structure " + "[" + nameStructure + "]", false);
69768
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf1 ' + nameArray, true);
69392
69769
  }
69393
69770
  });
69394
69771
 
@@ -70300,7 +70677,7 @@ class LoadScript {
70300
70677
  if(steps === 1
70301
70678
  || (ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length === Object.keys(ic.atoms).length)
70302
70679
  || (ic.optsHistory[steps - 1] !== undefined && ic.optsHistory[steps - 1].hasOwnProperty('hlatomcount') && ic.optsHistory[steps - 1].hlatomcount === Object.keys(ic.atoms).length) ) {
70303
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
70680
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
70304
70681
  // if(steps === 1) {
70305
70682
  // assign styles and color using the options at that stage
70306
70683
  // ic.setStyleCls.setAtomStyleByOptions(ic.optsHistory[steps - 1]);
@@ -70322,7 +70699,7 @@ class LoadScript {
70322
70699
  ic.pk = 3;
70323
70700
  }
70324
70701
 
70325
- // the following code caused problem for many links,e.g., https://structure.ncbi.nlm.nih.gov/icn3d/share.html?17g3r1JDvZ7ZL39e6
70702
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
70326
70703
  // if(steps === 1) {
70327
70704
  // ic.setColorCls.applyOriginalColor();
70328
70705
  // }
@@ -71388,6 +71765,10 @@ class Selection {
71388
71765
  selectOneResid(idStr, bUnchecked) {var ic = this.icn3d; ic.icn3dui;
71389
71766
  //var idStr = idArray[i]; // TYR $1KQ2.B:56@OH, $1KQ2.B:40 ASP
71390
71767
  //change to: let idStr = idArray[i]; // TYR $1KQ2.B:56@OH, or ASP $1KQ2.B:40
71768
+ //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
71769
+ let idArray = idStr.split(' ');
71770
+ idStr = idArray[1];
71771
+
71391
71772
  let posStructure = idStr.indexOf('$');
71392
71773
  let posChain = idStr.indexOf('.');
71393
71774
  let posRes = idStr.indexOf(':');
@@ -72747,7 +73128,6 @@ class Dssp {
72747
73128
  if(ssHash !== undefined && JSON.stringify(ssHash).indexOf('Oops there was a problem') === -1) {
72748
73129
  for(let chainNum in ic.chainsSeq) {
72749
73130
  let pos = chainNum.indexOf('_');
72750
-
72751
73131
  // one structure at a time
72752
73132
  if(chainNum.substr(0, pos) != struArray[index]) continue;
72753
73133
 
@@ -79959,6 +80339,11 @@ class SaveFile {
79959
80339
 
79960
80340
  $("#" + ic.pre + "title").html("PubChem CID <a id='" + ic.pre + "titlelink' href='" + url + "' style='color:" + titlelinkColor + "' target='_blank'>" + ic.inputid.toUpperCase() + "</a>: " + title);
79961
80341
  }
80342
+ else if(me.cfg.smiles !== undefined) {
80343
+ let text = decodeURIComponent(me.cfg.smiles);
80344
+ if(text.length > 60) text = text.substr(0, 60) + "...";
80345
+ $("#" + ic.pre + "title").html("SMILES: " + text);
80346
+ }
79962
80347
  else if(me.cfg.align !== undefined) {
79963
80348
  title = 'VAST+ alignment of ' + Object.keys(ic.structures);
79964
80349
 
@@ -80200,7 +80585,7 @@ class ShareLink {
80200
80585
  let shortName = strArray[strArray.length - 1];
80201
80586
  ic.saveFileCls.saveFile(inputid + '-' + shortName + '.png', 'png');
80202
80587
  let text = '<div style="float:left; border: solid 1px #0000ff; padding: 5px; margin: 10px; text-align:center;">';
80203
- text += '<a href="https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + shortName + '" target="_blank">';
80588
+ text += '<a href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + shortName + '" target="_blank">';
80204
80589
  text += '<img style="height:300px" src ="' + inputid + '-' + shortName + '.png"><br>\n';
80205
80590
  text += '<!--Start of your comments==================-->\n';
80206
80591
  let yournote =(ic.yournote) ? ': ' + ic.yournote.replace(/\n/g, "<br>").replace(/; /g, ", ") : '';
@@ -80219,9 +80604,9 @@ class ShareLink {
80219
80604
  //shorturl: https://icn3d.page.link/NvbAh1Vmiwc4bgX87
80220
80605
  let urlArray = shorturl.split('page.link/');
80221
80606
  //if(urlArray.length == 2) shorturl = me.htmlCls.baseUrl + 'icn3d/share.html?' + urlArray[1];
80222
- // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to past posted data in Mac/iphone
80607
+ // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to pass posted data in Mac/iphone
80223
80608
  // So the base URL is still www.ncbi.nlm.nih.gov/Structure,just use short URL here
80224
- if(urlArray.length == 2) shorturl = 'https://structure.ncbi.nlm.nih.gov/icn3d/share.html?' + urlArray[1];
80609
+ if(urlArray.length == 2) shorturl = 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + urlArray[1];
80225
80610
 
80226
80611
  $("#" + ic.pre + "short_url").val(shorturl);
80227
80612
  $("#" + ic.pre + "short_url_title").val(shorturl + '&t=' + ic.yournote);
@@ -83378,7 +83763,7 @@ class iCn3DUI {
83378
83763
  //even when multiple iCn3D viewers are shown together.
83379
83764
  this.pre = this.cfg.divid + "_";
83380
83765
 
83381
- this.REVISION = '3.38.1';
83766
+ this.REVISION = '3.39.0';
83382
83767
 
83383
83768
  // In nodejs, iCn3D defines "window = {navigator: {}}"
83384
83769
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -83553,6 +83938,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83553
83938
 
83554
83939
  await ic.pdbParserCls.loadPdbData(pdbStr);
83555
83940
 
83941
+ // // use NCBI residue numbers if using VAST
83942
+ // me.icn3d.bUsePdbNum = 0;
83943
+
83556
83944
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
83557
83945
  let structureArray = Object.keys(ic.structures);
83558
83946
  let chainArray = me.cfg.chains.split(' | ');
@@ -83828,7 +84216,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83828
84216
 
83829
84217
  ic.bChainAlign = true;
83830
84218
  ic.inputid = me.cfg.chainalign;
83831
- let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
84219
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + decodeURIComponent(me.cfg.resrange) : '';
83832
84220
  let resdef = (me.cfg.resdef) ? me.cfg.resdef : '';
83833
84221
  ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
83834
84222
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);