icn3d 3.38.2 → 3.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.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("");
@@ -59468,76 +59781,114 @@ class RealignParser {
59468
59781
  await this.realignChainOnSeqAlign(undefined, chainidArray, bRealign);
59469
59782
  }
59470
59783
 
59471
- async realignOnStructAlign(bReverse) { let ic = this.icn3d, me = ic.icn3dui;
59784
+ async realignOnStructAlign(bReverse, bVastsearch) { let ic = this.icn3d, me = ic.icn3dui;
59472
59785
  // each 3D domain should have at least 3 secondary structures
59473
59786
  let minSseCnt = (me.cfg.aligntool != 'tmalign') ? 3 : 0;
59474
59787
 
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
- }
59788
+ /*
59789
+ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).split(' | ') : [];
59492
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
+ */
59493
59796
  let ajaxArray = [], chainidPairArray = [];
59494
59797
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
59495
59798
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
59496
59799
 
59497
- //let cnt = 0;
59498
- let structArray = Object.keys(struct2domain);
59499
- if(bReverse) structArray = structArray.reverse();
59800
+ let struct2domain = {};
59801
+ if(bVastsearch && me.cfg.resrange) {
59802
+ let resRangeArray = decodeURIComponent(me.cfg.resrange).split(' | ');
59803
+
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;
59807
+
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
+ }
59846
+
59847
+ //let cnt = 0;
59848
+ let structArray = Object.keys(struct2domain);
59849
+ if(bReverse) structArray = structArray.reverse();
59500
59850
 
59501
- for(let s = 0, sl = structArray.length; s < sl; ++s) {
59502
- let struct1 = structArray[s];
59851
+ for(let s = 0, sl = structArray.length; s < sl; ++s) {
59852
+ let struct1 = structArray[s];
59503
59853
 
59504
- let chainidArray1 = Object.keys(struct2domain[struct1]);
59505
- if(chainidArray1.length == 0) continue;
59854
+ let chainidArray1 = Object.keys(struct2domain[struct1]);
59855
+ if(chainidArray1.length == 0) continue;
59506
59856
 
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]);
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]);
59510
59860
 
59511
- for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59512
- let struct2 = structArray[t];
59861
+ for(let t = s+1, tl = structArray.length; t < tl; ++t) {
59862
+ let struct2 = structArray[t];
59513
59863
 
59514
- let chainidArray2 = Object.keys(struct2domain[struct2]);
59515
- if(chainidArray2.length == 0) continue;
59864
+ let chainidArray2 = Object.keys(struct2domain[struct2]);
59865
+ if(chainidArray2.length == 0) continue;
59516
59866
 
59517
- for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59518
- let chainid2 = chainidArray2[j];
59867
+ for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
59868
+ let chainid2 = chainidArray2[j];
59519
59869
 
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);
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);
59533
59880
 
59534
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
59535
- alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
59536
- }
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
+ }
59537
59887
 
59538
- ajaxArray.push(alignAjax);
59539
- chainidPairArray.push(chainid1 + ',' + chainid2);
59540
- //++cnt;
59888
+ ajaxArray.push(alignAjax);
59889
+ chainidPairArray.push(chainid1 + ',' + chainid2);
59890
+ //++cnt;
59891
+ }
59541
59892
  }
59542
59893
  }
59543
59894
  }
@@ -59653,7 +60004,7 @@ class RealignParser {
59653
60004
  let predefinedResArray, predefinedResPair;
59654
60005
 
59655
60006
  if(bPredefined) {
59656
- predefinedResArray = me.cfg.resdef.trim().replace(/\+/gi, ' ').split(': ');
60007
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
59657
60008
 
59658
60009
  if(predefinedResArray.length != chainidArray.length - 1) {
59659
60010
  alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -59842,7 +60193,7 @@ class RealignParser {
59842
60193
  }
59843
60194
  }
59844
60195
 
59845
- getSeqCoorResid(resiArray, chainid, bNCBI) { let ic = this.icn3d, me = ic.icn3dui;
60196
+ getSeqCoorResid(resiArray, chainid, bNCBIResi) { let ic = this.icn3d, me = ic.icn3dui;
59846
60197
  let seq = '', coorArray = [], residArray = [];
59847
60198
  let hAtoms = {};
59848
60199
 
@@ -59850,16 +60201,17 @@ class RealignParser {
59850
60201
  if(resiArray[j].indexOf('-') != -1) {
59851
60202
  let startEnd = resiArray[j].split('-');
59852
60203
  for(let k = parseInt(startEnd[0]); k <= parseInt(startEnd[1]); ++k) {
59853
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60204
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59854
60205
 
59855
60206
  // don't align solvent or chemicals
59856
60207
  if(!ic.chainsSeq[chainid] || !ic.chainsSeq[chainid][seqIndex] || me.parasCls.b62ResArray.indexOf(ic.chainsSeq[chainid][seqIndex].name.toUpperCase()) == -1) continue;
59857
60208
 
59858
60209
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59859
60210
 
59860
- coorArray = coorArray.concat(this.getResCoorArray(chainid + '_' + k));
60211
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60212
+ coorArray = coorArray.concat(this.getResCoorArray(resid));
59861
60213
 
59862
- residArray.push(chainid + '_' + k);
60214
+ residArray.push(resid);
59863
60215
  }
59864
60216
  }
59865
60217
  else if(resiArray[j] == 0) { // 0 means the whole chain
@@ -59869,18 +60221,19 @@ class RealignParser {
59869
60221
  else { // one residue
59870
60222
  let k = resiArray[j];
59871
60223
 
59872
- let seqIndex = (bNCBI) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
60224
+ let seqIndex = (bNCBIResi) ? k : ic.setSeqAlignCls.getPosFromResi(chainid, k);
59873
60225
 
59874
60226
  if(!ic.chainsSeq[chainid][seqIndex]) continue;
59875
60227
 
59876
- let resCoorArray = this.getResCoorArray(chainid + '_' + k);
60228
+ let resid = (bNCBIResi) ? ic.ncbi2resid[chainid + '_' + k] : chainid + '_' + k;
60229
+ let resCoorArray = this.getResCoorArray(resid);
59877
60230
  //if(resCoorArray.length == 1 && resCoorArray[0] === undefined) continue;
59878
60231
 
59879
60232
  seq += ic.chainsSeq[chainid][seqIndex].name.toUpperCase();
59880
60233
 
59881
60234
  coorArray = coorArray.concat(resCoorArray);
59882
60235
 
59883
- residArray.push(chainid + '_' + k);
60236
+ residArray.push(resid);
59884
60237
  }
59885
60238
  }
59886
60239
 
@@ -64144,7 +64497,9 @@ class LoadPDB {
64144
64497
  structure = this.getStructureId(id, moleculeNum, bMutation, bNMR);
64145
64498
 
64146
64499
  ic.molTitle = '';
64147
- ic.molTitleHash = {};
64500
+ if (ic.allData === undefined) {
64501
+ ic.molTitleHash = {};
64502
+ }
64148
64503
 
64149
64504
  bHeader = true; // read the first header if there are multiple
64150
64505
  } else if (record === 'TITLE ') {
@@ -69168,15 +69523,15 @@ class SelectCollections {
69168
69523
  }
69169
69524
 
69170
69525
  //Set the menu of defined sets with an array of defined names "commandnameArray".
69171
- setAtomMenu(nameArray, titleArray) {
69526
+ setAtomMenu(nameArray) {
69172
69527
  let ic = this.icn3d;
69173
69528
  ic.icn3dui;
69174
69529
  let html = "";
69175
- let commandnameArray = [nameArray[0]];
69176
69530
  //for(let i in ic.defNames2Atoms) {
69177
69531
  for (let i = 0, il = nameArray.length; i < il; ++i) {
69178
- let name = nameArray[i];
69179
- let title = titleArray[i];
69532
+ let name = nameArray[i][0];
69533
+ let title = nameArray[i][1];
69534
+ let description = nameArray[i][2];
69180
69535
 
69181
69536
  let atomHash;
69182
69537
  if (
@@ -69199,16 +69554,11 @@ class SelectCollections {
69199
69554
  }
69200
69555
  }
69201
69556
 
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
- }
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
+ }
69212
69562
  }
69213
69563
 
69214
69564
  return html;
@@ -69249,49 +69599,33 @@ class SelectCollections {
69249
69599
  }
69250
69600
 
69251
69601
  return difference;
69252
- }
69602
+ }
69253
69603
 
69254
- clickStructure() {
69604
+ clickStructure(collection) {
69255
69605
  let ic = this.icn3d,
69256
69606
  me = ic.icn3dui;
69257
69607
  let thisClass = this;
69258
69608
 
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
69609
  //me.myEventCls.onIds("#" + ic.pre + "atomsCustom", "change", function(e) { let ic = thisClass.icn3d;
69280
- $("#" + ic.pre + "collections_menu").change(async function (e) {
69610
+ $("#" + ic.pre + "collections_menu").on("change", async function (e) {
69281
69611
  let ic = thisClass.icn3d;
69282
69612
 
69283
69613
  let nameArray = $(this).val();
69284
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
+ }, {});
69285
69620
 
69286
69621
  ic.nameArray = nameArray;
69287
- if (nameArray !== null) {
69288
- // let chainIdHash = {};
69289
69622
 
69623
+ if (nameArray !== null) {
69290
69624
  let bNoDuplicate = true;
69291
69625
  thisClass.reset();
69292
69626
  for (const name of nameArray) {
69293
69627
  if (!(name in ic.allData)) {
69294
- 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']));
69295
69629
 
69296
69630
  ic.atoms = ic.allData['all']['atoms'];
69297
69631
 
@@ -69308,7 +69642,21 @@ class SelectCollections {
69308
69642
  ic.chainsSeq = ic.allData['all']['chainsSeq'];
69309
69643
  ic.defalls2Atoms = ic.allData['all']['defalls2Atoms'];
69310
69644
  ic.defalls2Residues = ic.allData['all']['defalls2Residues'];
69311
- 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(() => {
69312
69660
  ic.allData['all'] = {
69313
69661
  'atoms': ic.atoms,
69314
69662
  'proteins': ic.proteins,
@@ -69316,9 +69664,9 @@ class SelectCollections {
69316
69664
  'chemicals': ic.chemicals,
69317
69665
  'ions': ic.ions,
69318
69666
  'water': ic.water,
69319
- 'structures': ic.structures,
69667
+ 'structures': ic.structures, // getSSExpandedAtoms
69320
69668
  'ssbondpnts': ic.ssbondpnts,
69321
- 'residues': ic.residues,
69669
+ 'residues': ic.residues, // getSSExpandedAtoms
69322
69670
  'chains': ic.chains,
69323
69671
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
69324
69672
  'defNames2Atoms': ic.defNames2Atoms,
@@ -69326,26 +69674,27 @@ class SelectCollections {
69326
69674
  };
69327
69675
 
69328
69676
  ic.allData[name] = {
69677
+ 'title': ic.molTitle,
69329
69678
  'atoms': thisClass.dictionaryDifference(ic.allData['prev']['atoms'], ic.atoms),
69330
69679
  'proteins': thisClass.dictionaryDifference(ic.allData['prev']['proteins'], ic.proteins),
69331
69680
  'nucleotides': thisClass.dictionaryDifference(ic.allData['prev']['nucleotides'], ic.nucleotides),
69332
69681
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
69333
69682
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
69334
69683
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
69335
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
69684
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
69336
69685
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
69337
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
69686
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
69338
69687
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
69339
69688
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
69340
69689
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
69341
69690
  'defNames2Residues': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Residues'], ic.defNames2Residues)
69342
69691
  };
69343
69692
 
69344
- // ic.atoms = Object.assign(ic.atoms, ic.atomsTemp);
69345
69693
  thisClass.reset();
69346
69694
  });
69347
69695
  }
69348
69696
  }
69697
+
69349
69698
  for (const name of nameArray) {
69350
69699
  ic.atoms = Object.assign(ic.atoms, ic.allData[name]['atoms']);
69351
69700
 
@@ -69364,10 +69713,26 @@ class SelectCollections {
69364
69713
  ic.defNames2Residues = Object.assign(ic.defNames2Residues, ic.allData[name]['defNames2Residues']);
69365
69714
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69366
69715
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
69367
- }
69716
+
69717
+ ic.molTitle = ic.allData[name]['title'];
69368
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
+
69369
69735
  ic.opts["color"] = (Object.keys(ic.structures).length == 1) ? "chain" : "structure";
69370
- // ic.setStyleCls.setAtomStyleByOptions();
69371
69736
  ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
69372
69737
 
69373
69738
  ic.transformCls.zoominSelection();
@@ -69381,14 +69746,12 @@ class SelectCollections {
69381
69746
  // show selected chains in annotation window
69382
69747
  ic.annotationCls.showAnnoSelectedChains();
69383
69748
  }
69384
-
69749
+
69385
69750
  await ic.drawCls.draw();
69386
69751
  ic.saveFileCls.showTitle();
69387
69752
 
69388
- me.htmlCls.clickMenuCls.setLogCmd(
69389
- "select structure " + "[" + nameStructure + "]",
69390
- true
69391
- );
69753
+ me.htmlCls.clickMenuCls.setLogCmd("select structure " + "[" + nameStructure + "]", false);
69754
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf1 ' + nameArray, true);
69392
69755
  }
69393
69756
  });
69394
69757
 
@@ -70300,7 +70663,7 @@ class LoadScript {
70300
70663
  if(steps === 1
70301
70664
  || (ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length === Object.keys(ic.atoms).length)
70302
70665
  || (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
70666
+ // the following code caused problem for many links,e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?17g3r1JDvZ7ZL39e6
70304
70667
  // if(steps === 1) {
70305
70668
  // assign styles and color using the options at that stage
70306
70669
  // ic.setStyleCls.setAtomStyleByOptions(ic.optsHistory[steps - 1]);
@@ -70322,7 +70685,7 @@ class LoadScript {
70322
70685
  ic.pk = 3;
70323
70686
  }
70324
70687
 
70325
- // 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
70326
70689
  // if(steps === 1) {
70327
70690
  // ic.setColorCls.applyOriginalColor();
70328
70691
  // }
@@ -71388,6 +71751,10 @@ class Selection {
71388
71751
  selectOneResid(idStr, bUnchecked) {var ic = this.icn3d; ic.icn3dui;
71389
71752
  //var idStr = idArray[i]; // TYR $1KQ2.B:56@OH, $1KQ2.B:40 ASP
71390
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
+
71391
71758
  let posStructure = idStr.indexOf('$');
71392
71759
  let posChain = idStr.indexOf('.');
71393
71760
  let posRes = idStr.indexOf(':');
@@ -80200,7 +80567,7 @@ class ShareLink {
80200
80567
  let shortName = strArray[strArray.length - 1];
80201
80568
  ic.saveFileCls.saveFile(inputid + '-' + shortName + '.png', 'png');
80202
80569
  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">';
80570
+ text += '<a href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + shortName + '" target="_blank">';
80204
80571
  text += '<img style="height:300px" src ="' + inputid + '-' + shortName + '.png"><br>\n';
80205
80572
  text += '<!--Start of your comments==================-->\n';
80206
80573
  let yournote =(ic.yournote) ? ': ' + ic.yournote.replace(/\n/g, "<br>").replace(/; /g, ", ") : '';
@@ -80219,9 +80586,9 @@ class ShareLink {
80219
80586
  //shorturl: https://icn3d.page.link/NvbAh1Vmiwc4bgX87
80220
80587
  let urlArray = shorturl.split('page.link/');
80221
80588
  //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
80589
+ // When the baseURL is structure.ncbi.nlm.nih.gov, mmcifparser.cgi has a problem to pass posted data in Mac/iphone
80223
80590
  // 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];
80591
+ if(urlArray.length == 2) shorturl = 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/share.html?' + urlArray[1];
80225
80592
 
80226
80593
  $("#" + ic.pre + "short_url").val(shorturl);
80227
80594
  $("#" + ic.pre + "short_url_title").val(shorturl + '&t=' + ic.yournote);
@@ -83378,7 +83745,7 @@ class iCn3DUI {
83378
83745
  //even when multiple iCn3D viewers are shown together.
83379
83746
  this.pre = this.cfg.divid + "_";
83380
83747
 
83381
- this.REVISION = '3.38.1';
83748
+ this.REVISION = '3.39.0';
83382
83749
 
83383
83750
  // In nodejs, iCn3D defines "window = {navigator: {}}"
83384
83751
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -83553,6 +83920,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83553
83920
 
83554
83921
  await ic.pdbParserCls.loadPdbData(pdbStr);
83555
83922
 
83923
+ // // use NCBI residue numbers if using VAST
83924
+ // me.icn3d.bUsePdbNum = 0;
83925
+
83556
83926
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
83557
83927
  let structureArray = Object.keys(ic.structures);
83558
83928
  let chainArray = me.cfg.chains.split(' | ');
@@ -83828,7 +84198,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
83828
84198
 
83829
84199
  ic.bChainAlign = true;
83830
84200
  ic.inputid = me.cfg.chainalign;
83831
- let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
84201
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + decodeURIComponent(me.cfg.resrange) : '';
83832
84202
  let resdef = (me.cfg.resdef) ? me.cfg.resdef : '';
83833
84203
  ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
83834
84204
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);