# HG changeset patch # User lain # Date 1677852624 0 # Node ID b58b229c4cbffbe5e2bccc1557f78e52b89cc378 planemo upload commit 523a9c8df173302ad38e9f15e7d82eab01736551-dirty diff -r 000000000000 -r b58b229c4cbf README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,56 @@ +# MS to Peakforest + + +Metadata +-------- + + * **@name**: MS2PF + * **@version**: 1.1.0 + * **@authors**: Lain Pavot (PFEM - INRAE - MetaboHUB) + * **@maintainers**: Lain Pavot (PFEM - INRAE - MetaboHUB) + * **@init date**: 2022, November + * **@main usage**: +Generates peakforest forms, auto-filled with data and metadata provided +with files or parametres. +Lets you check data and metadata, correct, and send them to the peakforest +instance of you choice. + +test +---- + +Test with FragNot data +```sh +input='Galaxy10-[Cmpd1-1__INCHIKEY___GIAZPLMMQOERPN-UHFFFAOYSA-N__RT___0..ABINITIOFRAGNOT_PForest.tabular].tabular' +input="test-data/${input}" +./server.py \ + --input ''${input}'',''${input}'',''${input}'' \ + --raw-metadata \'${input},${input},${input}\' \ + --method cf_pfem_urine_qtof \ + --peakforest-url https://metabohub.peakforest.org \ + --scan-type ms \ + --polarity positive \ + --name 'test1,test2,test3' +``` + +Test with MS2Snoop data +```sh +input='out-smol-base.tsv' +input="test-data/${input}" +./server.py \ + --input ''${input}'' \ + --method cf_pfem_urine_qtof \ + --pf_url https://nightly.peakforest.org \ + --scan_type ms \ + --polarity positive +``` + +Services provided +----------------- + + * Help and support: support@workflow4metabolomics.org + + +License +------- + + * Cea Cnrs Inria Logiciel Libre License, version 2.1 (CECILL-2.1) diff -r 000000000000 -r b58b229c4cbf add-one-spectrum-index.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/add-one-spectrum-index.js Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,2584 @@ + +var token = "{{ PF_TOKEN_PLACEHOLDER }}" ; +if ({{ TAB_INDEX_PLACEHOLDER }} == 1) { +} + +context_{{ TAB_INDEX_PLACEHOLDER }} = { + prefix: "#accordion-{{ TAB_INDEX_PLACEHOLDER }} ", + name: "Context[{{ TAB_INDEX_PLACEHOLDER }}]", + produce_json: {{ PRODUCE_JSON_PLACEHOLDER }}, + DEFAULT_MS_PEAK_VALUES: {{ MS_PEAK_VALUES_PLACEHOLDER }}, + DEFAULT_DATA: {{ DEFAULT_DATA }}, + modeEditSpectrum: false, + isSeparationFlowRateInit: false, + isMSpeaksInit: false, + isLC: false, + isGC: false, + isIC: false, + hot_LC_SFG: null , + hot_MS_Peaks: null, + hot_RCC_ADDED: null, + jsonSpectrumType: null, + isJsonSpectrumTypeComplete: false, + jsonSample: null, + isJsonSampleComplete: false, + isJsonRCCaddedComplete: false, + jsonChromato: null, + isJsonChromatoComplete: false, + jsonAnalyzer: null, + isJsonAnalyzerComplete: false, + jsonPeaksList: [], + isJsonPeaksListComplete: false, + jsonOtherMetadata: null, + isJsonOtherMetadataComplete: false, + jsonMolIonization: null, + jsonMolIonBeam: null, + cptPeakListTab: 0, + jsonAnalyzerAcquisition: [], + idMetadataMap: {}, + listOfViewableSpectra: [], + singlePick: true, + multiPickLine: -1, + subjects: [], + fitlerSearchLoadlCpd: 5, + inchikey: null, + initialized: false, + selected_ion_index: null, + lock: { + precursor_ion: false + }, + + sent_json: null, + + init: function() { + + var self = this ; + + $(document).ready(() => self.on_ready()); + $(document).ready(function() { + console.log("adding click on open_tab_{{ TAB_INDEX_PLACEHOLDER }}.") ; + var activate_tab = function() { + if (self.initialized) { + return ; + } + self.auto_set_spec_type() ; + } + if (self.is_ref()) { + $("#open_tab_{{ TAB_INDEX_PLACEHOLDER }}").click(activate_tab) ; + } + if ({{ TAB_INDEX_PLACEHOLDER }} == 1) { + activate_tab() ; + } + }) ; + + return (self) ; + + }, + + on_ready: function() { + var self = this ; + + $(self.prefix+".pickChemicalCompound").click(self.pickChemicalCompound); + $(self.prefix+".add1spectrum").change( + function(){self.add1spectrum_change_handler(this)} + ) + self.attach_search() ; + self.add_date_check() ; + self.populate_selects() ; + self.add_change_handlers() ; + }, + + populate_selects: function() { + var self = this ; + var choose_in_list ; + + choose_in_list = ` + + ` ; + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append(choose_in_list) ; + $("#add1spectrum-chromatoLC-colConstructor-{{ TAB_INDEX_PLACEHOLDER }}").append(choose_in_list) ; + $("#add1spectrum-chromatoLC-separationSolvA-{{ TAB_INDEX_PLACEHOLDER }}").append(choose_in_list) ; + $("#add1spectrum-chromatoLC-separationSolvB-{{ TAB_INDEX_PLACEHOLDER }}").append(choose_in_list) ; + $("#add1spectrum-sample-lcmsSolvent-{{ TAB_INDEX_PLACEHOLDER }}").append(choose_in_list) ; + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lc-methods.json", self.populate_lc_methods) ; + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lc-columns.json", self.populate_lc_columns) ; + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lc-solvents.json", self.populate_lc_solvents) ; + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-ms-ionization-methods.json", self.populate_ms_ionization) ; + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lcms-solvents.json", self.populate_lcms_solvents) ; + self.resetFromColors(); + }, + + attach_search: function() { + var self = this ; + + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").bind("keypress", function(e) { + var code = e.keyCode || e.which; + if (code == 13) { + self.searchLocalCompound(); + } + }); + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").typeahead({ + source: function(query, process) { + return self.searchAjax(); + } + }); + }, + + add_date_check: function() { + var self = this ; + + $("#add1spectrum-other-date-{{ TAB_INDEX_PLACEHOLDER }}").focusout(function() { + var element = $(this) ; + self.rm_warning(element); + self.rm_success(element) ; + if (element.val() == "") { + element.parent().addClass("has-warning"); + } else { + element.parent().addClass("has-success"); + } + }); + }, + + populate_lc_methods: function(data) { + // load data from json + $.each(data.methods,function() { + if (this.name !== undefined) { + if (this.value !== undefined) { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } else { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } + } + }); + }, + + populate_lc_columns: function(data) { + // load data from json + $.each(data.columns, function() { + $("#add1spectrum-chromatoLC-colConstructor-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + }); + $("#add1spectrum-chromatoLC-colConstructor-{{ TAB_INDEX_PLACEHOLDER }}").append( + '' + ); + }, + + populate_lc_solvents: function(data) { + // load data from json + $.each(data.solvents, function() { + $("#add1spectrum-chromatoLC-separationSolvA-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + $("#add1spectrum-chromatoLC-separationSolvB-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + }); + }, + + populate_ms_ionization: function(data) { + // load data from json + $.each(data.methods,function() { + if (this.name !==undefined) { + if (this.value !==undefined) { + $("#add1spectrum-analyzserMS-ionizationMethod-pos-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + $("#add1spectrum-analyzserMS-ionizationMethod-neg-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } else { + $("#add1spectrum-analyzserMS-ionizationMethod-pos-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + $("#add1spectrum-analyzserMS-ionizationMethod-neg-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } + } + }); + }, + + populate_lcms_solvents: function(data) { + // load data from json + $.each(data.solvents, function () { + $("#add1spectrum-sample-lcmsSolvent-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + }); + }, + + add_change_handlers: function() { + var self = this ; + + $("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").on("change", function() { + var v = $("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").val(); + $(self.prefix + ".add1spectrum-ionTrap").hide(); + if (v == "beam") { + } else if (v == "trap") { + $(self.prefix + ".add1spectrum-ionTrap").show(); + } + }) ; + $("#add1spectrum-peaksMS-msLevel-{{ TAB_INDEX_PLACEHOLDER }}").on("change", function() { + var v = $("#add1spectrum-peaksMS-msLevel-{{ TAB_INDEX_PLACEHOLDER }}").val(); + $(self.prefix + ".disabled-if-ms-in-msms").attr( + "disabled", + (v == "ms2" || v == "ms3") + ) ; + $(self.prefix + ".enabled-if-ms-in-msms").attr( + "disabled", + !(v == "ms2" || v == "ms3") + ) ; + $(self.prefix + ".hidden-if-ms-in-msms").css( + "display", + !(v == "ms2" || v == "ms3") ? "none" : "" + ) ; + }) ; + }, + + is_mix: function() { + return this.DEFAULT_DATA["sample_type"] == "compound-mix" ; + }, + + is_ref: function() { + return this.DEFAULT_DATA["sample_type"] == "compound-ref" ; + }, + + is_ms: function() { + return this.DEFAULT_DATA["spectrum_type"] == "LC_MS" ; + }, + + is_ms2: function() { + return this.DEFAULT_DATA["spectrum_type"] == "LC_MSMS" ; + }, + + is_other_in_mix() { + return this.is_mix() && {{ TAB_INDEX_PLACEHOLDER }} > 1 ; + }, + + hide: function(id) { + if (typeof id == Array) { + return (id.forEach(hide)) ; + } + $(id).hide() + }, + + rm_success: function(element) { + return (this.rm_parent_class(element, "has-success")) + }, + rm_error: function(element) { + return (this.rm_parent_class(element, "has-error")) + }, + rm_warning: function(element) { + return (this.rm_parent_class(element, "has-warning")) + }, + set_success: function(element) { + return (this.set_parent_class(element, "has-success")) + }, + set_error: function(element) { + return (this.set_parent_class(element, "has-error")) + }, + set_warning: function(element) { + return (this.set_parent_class(element, "has-warning")) + }, + rm_parent_class: function(element, cls) { + var parent ; + + if ((parent = element.parent()) == null) { + return false ; + } + return this.rm_class(parent, cls) ; + }, + set_parent_class: function(element, cls) { + var parent ; + + if ((parent = element.parent()) == null) { + return false ; + } + return this.set_class(parent, cls) ; + }, + rm_class: function(element, cls) { + if (element.hasClass(cls)) { + element.removeClass(cls) ; + return true ; + } + return false ; + }, + set_class: function(element, cls) { + if (element.hasClass(cls)) { + return false ; + } + element.addClass(cls) ; + return true ; + }, + is_success: function(element) { + return (this.parent_has_class(element, "has-success")) + }, + is_warning: function(element) { + return (this.parent_has_class(element, "has-warning")) + }, + is_error: function(element) { + return (this.parent_has_class(element, "has-error")) + }, + is_optional: function(element) { + return (element.hasClass("is-optional")) + }, + is_mandatory: function(element) { + return (element.hasClass("is-mandatory")) + }, + parent_has_class: function(element, cls) { + var parent ; + + if ((parent = element.parent()) == null) { + return false ; + } + return (parent.hasClass(cls)) ; + }, + + add1spectrum_change_handler: function(element) { + var self = this ; + var idElem ; + var valElem ; + var isSuccess ; + var isWarning ; + var isError ; + var isOptional ; + var isMandatory ; + + element = $(element) ; + idElem = element.attr("id") ; + valElem = element.val(); + console.log(`Change handler called for [${idElem}]=${valElem}`) ; + if (idElem.split("-").slice(0, -1).join("-") == "add1spectrum-peaksMS-msPrecursorIon") { + var index = idElem.split("-")[3] - 1 ; + all_contexts[index].sync_precursor_ion() ; + if (all_contexts[index].hot_MS_Peaks != null) { + all_contexts[index].hot_MS_Peaks.render() + } + } + isSuccess = self.is_success(element); + isWarning = self.is_warning(element); + isError = self.is_error(element); + isOptional = self.is_optional(element); + isMandatory = self.is_mandatory(element); + + switch(idElem) { + case "add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}": + if (valElem == "compound-ref") { + $("#add1spectrum-sample-type-compound-ref-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#add1spectrum-sample-type-compound-mix-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-sample-type-rcc-added-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + } else if (valElem == "compound-mix") { + $("#add1spectrum-sample-type-compound-mix-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#add1spectrum-sample-type-compound-ref-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-sample-type-rcc-added-{{ TAB_INDEX_PLACEHOLDER }}").show(); + self.handsontableRefChemCpdAdded(null); + } + break; + case "add1spectrum-chromatoLC-colConstructor-{{ TAB_INDEX_PLACEHOLDER }}": + self.resetElemColor("add1spectrum-chromatoLC-colConstructorOther-{{ TAB_INDEX_PLACEHOLDER }}"); + if (valElem == "" || valElem == null || valElem != "other" ) { + self.disableElem("add1spectrum-chromatoLC-colConstructorOther-{{ TAB_INDEX_PLACEHOLDER }}"); + } else { + self.enableElem("add1spectrum-chromatoLC-colConstructorOther-{{ TAB_INDEX_PLACEHOLDER }}"); + } + break; + case "add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}": + self.fulfillLCdata(valElem); + break; + case "add1spectrum-analyzserMS-ionizationMethod-pos-{{ TAB_INDEX_PLACEHOLDER }}": + if ($("#add1spectrum-analyzserMS-ionizationMethod-pos-{{ TAB_INDEX_PLACEHOLDER }}").val() != null) { + $($("#add1spectrum-peaksMS-polarity-{{ TAB_INDEX_PLACEHOLDER }} option")[1]).attr("disabled", false); + } + break; + case "add1spectrum-analyzserMS-ionizationMethod-neg-{{ TAB_INDEX_PLACEHOLDER }}": + if ($("#add1spectrum-analyzserMS-ionizationMethod-neg-{{ TAB_INDEX_PLACEHOLDER }}").val() != null) { + $($("#add1spectrum-peaksMS-polarity-{{ TAB_INDEX_PLACEHOLDER }} option")[2]).attr("disabled", false); + } + break; + } + if ((isMandatory || isOptional) && (valElem == "" || valElem == null)) { + if (isSuccess) { + self.rm_success(element) ; + } else if (isWarning) { + self.rm_warning(element) ; + } else if (isError) { + self.rm_error(element) ; + } + if (isMandatory) { + self.set_error(element) ; + } else { + self.set_warning(element) ; + } + } + if (isMandatory && (valElem != "" && valElem != null)) { + if (isError) { + self.rm_error(element) ; + } + self.set_success(element) ; + } else if (isOptional && valElem != "") { + if (isWarning) { + self.rm_warning(element) ; + } + self.set_success(element) ; + } + if (element.parent().children("input").size() == 2) { + if (isMandatory) { + if (isSuccess) { + self.rm_success(element) ; + } else if (isWarning) { + self.rm_warning(element) ; + } else if (isError) { + self.rm_error(element) ; + } + if (element.parent().children("input").toArray().some( + (el) => $(el).val() === null || $(el).val() === "" + )) { + self.set_error(element) ; + } else { + eslf.set_success(element) ; + } + } else if (isOptional) { + isSuccess = self.is_success(element); + isWarning = self.is_warning(element); + isError = self.is_error(element); + if (isSuccess) { + self.rm_success(element) + } else if (isWarning) { + self.rm_warning(element) ; + } else if (isError) { + self.rm_error(element) ; + } + if (element.parent().children("input").toArray().some( + (el) => ($(el).val() == null || $(el).val() == "") + )) { + self.set_warning(element) ; + } else { + self.set_success(element) ; + } + } + } + if (element.hasClass("one-or-more")) { + // get parent class + isSuccess = self.is_success(element); + isWarning = self.is_warning(element); + isError = self.is_error(element); + // reset class + if (isSuccess) { + self.rm_success(element) ; + } else if (isWarning) { + self.rm_warning(element) ; + } else if (isError) { + self.rm_error(element) ; + } + isTmpSuccess = false; + $.each(element.parent().children("input"), function(id, child){ + if ($(child).val() != null && $(child).val() != "") { + isTmpSuccess = true; + } + }); + $.each(element.parent().children("select"), function(id, child){ + if ($(child).val() != null && $(child).val() != "") { + isTmpSuccess = true; + } + }); + // end parkour + element.parent().addClass( + isTmpSuccess ? "has-success" : "has-error" + ); + } + // CHECK IF OK STEP 2 + if (element.hasClass("add1spectrum-sampleForm")) { + var isBtnStep2OK = true; + $.each($(self.prefix + ".add1spectrum-sampleForm"), (id, elem) => { + if (self.is_error($(elem)) && $(elem).is(":visible")) { + isBtnStep2OK = false; + } + }); + if (isBtnStep2OK) { + self.rm_class($("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + } else { + self.set_class($("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.rm_class($("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + } + } + // CHECK IF OK STEP 3 - LC + if ( + element.hasClass("add1spectrum-chromatoLCForm") + && $("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}").is(":visible") + ) { + var isBtnStep3OK = true; + $.each($(self.prefix+".add1spectrum-chromatoLCForm"), (id, elem) => { + if (self.is_error($(elem)) && $(elem).is(":visible")) + isBtnStep3OK = false; + }); + if (isBtnStep3OK) { + self.rm_class($("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + } else { + self.set_class($("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.rm_class($("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + } + } + // TODO CHECK IF OK STEP 3 - GC + // CHECK IF OK STEP 4 - MS ANALYZER + if ( + element.hasClass("add1spectrum-analyzerMSForm") + && $("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").is(":visible") + ) { + var isBtnStep4OK = true; + $.each($(self.prefix+".add1spectrum-analyzerMSForm"), (id, elem) => { + if (self.is_error($(elem)) && $(elem).is(":visible")) + isBtnStep4OK = false; + }); + if (isBtnStep4OK) { + self.rm_class($("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + } else { + self.set_class($("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.rm_class($("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + } + } + // CHECK IF OK STEP 5 - PEAKS + if ( + element.hasClass("add1spectrum-peaksMSForm-peaklist") + && $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").is(":visible") + ) { + var isBtnStep5OK = true; + $.each($(self.prefix+".add1spectrum-peaksMSForm-peaklist"), (id, elem) => { + if (self.is_error($(elem)) && $(elem).is(":visible")) + isBtnStep5OK = false; + }); + if (isBtnStep5OK && (self.is_ms() || self.a_ion_parent_is_selected())) { + self.rm_class($("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + } else { + self.set_class($("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.rm_class($("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + } + } + // CHECK IF OK STEP 6 - OTHER DATA + if ( + element.hasClass("add1spectrum-otherForm") + && $("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").is(":visible") + ) { + self.checkIfEnableSubmit() ; + } + }, + + a_ion_parent_is_selected: function() { + return (this.get_selected_parent_ion_index() !== null) ; + }, + + get_selected_parent_ion_index: function() { + if (this.hot_MS_Peaks == undefined) { + return null ; + } + var data = this.hot_MS_Peaks.getData() ; + for (var i = 0 ; i < data.length ; i += 1) { + if (data[i][7] === "true" || data[i][7] === true) { + return i ; + } + } + return null ; + }, + + auto_set_spec_type: function() { + console.log("auto_set_spec_type...") ; + var self = this ; + var id = `#set_${self.DEFAULT_DATA["spectrum_type"]}_spectrum_button` ; + var element = $(self.prefix + id) ; + if (element.length) { + element.click() ; + console.log(`auto_set_spec_type to ${self.DEFAULT_DATA["spectrum_type"]} ok.`) + } else { + console.log(element) + console.log("Failed!") + } + if (self.DEFAULT_DATA["sample_type"]) { + self.auto_set_sample_type(self) ; + } + }, + + auto_set_sample_type: function() { + console.log("auto_set_sample_type...") ; + var self = this ; + var id = "#add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}" ; + var element = $(id) ; + if (element.length) { + element.val(self.DEFAULT_DATA["sample_type"]).change() ; + console.log(`auto_set_sample_type to ${self.DEFAULT_DATA["sample_type"]} ok.`) ; + if (self.DEFAULT_DATA["sample_type"] == "compound-ref") { + $("#add1spectrum-sample-mixSolvent-{{ TAB_INDEX_PLACEHOLDER }}").val( + "H2O/ethanol (75/25)" + ).change() ; + } + } else { + console.log(element) + console.log("Failed!") + } + if (self.DEFAULT_DATA["inchikey"]) { + setTimeout(() => self.auto_set_inchikey(self), 1000) ; + } + }, + + auto_set_inchikey: function() { + console.log("auto_set_inchikey...") ; + var self = this ; + var id ; + var element ; + if (self.is_ref()) { + id = "#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}:text" ; + element = $(id) ; + if (element.length) { + console.log(`auto_set_inchikey to ${self.DEFAULT_DATA["inchikey"]} ok.`) + element.val(self.DEFAULT_DATA["inchikey"]).change() ; + console.log(`Inchikey set!`) ; + } else { + console.log(element) + console.log("Failed!") + } + } else { + for (var index = 0 ; index < all_contexts.length ; index += 1) { + var inchikey = all_contexts[index].DEFAULT_DATA["inchikey"] ; + id = `#container_RCC_ADDED-1 tbody:nth(0) tr:nth(${index}) td:nth(1)` ; + element = $(id) ; + if (element.length) { + console.log(`auto_set_inchikey to ${inchikey} ok.`) + self.hot_RCC_ADDED.setDataAtCell(index, 1, inchikey) ; + element.innerHTML = inchikey ; + element.change() ; + console.log(element) ; + console.log(`Inchikey set!`) ; + } else { + console.log(element) + console.log("Failed!") + } + } + console.log(self.hot_RCC_ADDED) + self.hot_RCC_ADDED.render() ; + } + $("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}").click() ; + if (self.DEFAULT_DATA["method"]) { + setTimeout(() => self.auto_set_method(self), 1000) ; + } + }, + + auto_set_method: function() { + console.log("auto_set_method...") ; + var self = this ; + var id = "#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}" ; + var element = $(id) ; + element.length && element.val(self.DEFAULT_DATA["method"]).change() ; + $("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}").click() ; + setTimeout(() => { + (() => { + $("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").click() ; + console.log(`auto_set_method to ${self.DEFAULT_DATA["method"]} ok.`) + if (self.DEFAULT_DATA["scan_type"]) { + setTimeout(() => self.auto_set_scan_type(self), 1000) ; + } + })(self) + }, 1000) ; + }, + + auto_set_scan_type: function() { + console.log("auto_set_scan_type...") ; + var self = this ; + var id = "#add1spectrum-peaksMS-msLevel-{{ TAB_INDEX_PLACEHOLDER }}" ; + var element = $(id) ; + if (element.length) { + element.val(self.DEFAULT_DATA["scan_type"]).change() ; + console.log(`auto_set_scan_type to ${self.DEFAULT_DATA["scan_type"]} ok.`) + } else { + console.log("Failed!") + } + if (self.DEFAULT_DATA["polarity"]) { + self.auto_set_polarity(self) ; + } + }, + + auto_set_polarity: function() { + console.log("auto_set_polarity...") ; + var self = this ; + var id = "#add1spectrum-peaksMS-polarity-{{ TAB_INDEX_PLACEHOLDER }}" ; + var element = $(id) ; + if (element.length) { + element.val(self.DEFAULT_DATA["polarity"]).change() ; + console.log(`auto_set_polarity to ${self.DEFAULT_DATA["polarity"]} ok.`) + } else { + console.log("Failed!") + } + if (self.DEFAULT_DATA["resolution"]) { + self.auto_set_resolution(self) ; + } + }, + + auto_set_resolution: function() { + console.log("auto_set_resolution...") ; + var self = this ; + var id = "#add1spectrum-peaksMS-resolution-{{ TAB_INDEX_PLACEHOLDER }}" ; + var element = $(id) ; + if (element.length) { + element.val(self.DEFAULT_DATA["resolution"]).change() ; + console.log(`auto_set_resolution to ${self.DEFAULT_DATA["resolution"]} ok.`) + } else { + console.log("Failed!") + } + if (self.DEFAULT_DATA["next"] || true) { + setTimeout(() => self.finish_initialized(self), 1000) ; + } + }, + + finish_initialized: function() { + var self = this ; + if (ctx() === self) { + self.initialized = true ; + } + }, + + //USED IN HTML + updateLCMSspectraViewer: function() { + var self = this ; + var tab_no ; + console.log(`Updating spectral view for tab {{ TAB_INDEX_PLACEHOLDER }}`) ; + // reset current viewer + $("#containter-lcms-spectrum-preview-{{ TAB_INDEX_PLACEHOLDER }}").empty(); + // reset data. + + if (self.is_mix()) { + tab_no = 1 ; + } else { + tab_no = {{ TAB_INDEX_PLACEHOLDER }} ; + } + var range_from = $(`#add1spectrum-peaksMS-rangeFrom-${tab_no}`) ; + if ((spectrumMinPPM = Number(range_from.val())) == "") { + spectrumMinPPM = 10000; + } + var range_to = $(`#add1spectrum-peaksMS-rangeTo-${tab_no}`) ; + if ((spectrumMaxPPM = Number(range_to.val())) == "") { + spectrumMaxPPM = 0; + } + maxGraph = 0; + var localData = []; + var localDataAnnot = []; + // gather new data + // TODO switch tab in function of technic + $.each(self.hot_MS_Peaks.getData(), function() { + if(this[0] != undefined && this[0] != "") { + var x = (Number(this[0])); + var y = Number(this[2]); + var a = this[6]; + localData.push([(x-0.000001),-150]); + localData.push([(x+0.000001),-150]); + localData.push([x,y]); + localDataAnnot[x] = a; + if (x < spectrumMinPPM) { + spectrumMinPPM = x; + } + if (x > spectrumMaxPPM) { + spectrumMaxPPM = x; + } + if (y > maxGraph) { + maxGraph = y; + } + } + }); + + // build new one + spectrumMinPPM = spectrumMinPPM - (0.1 * spectrumMinPPM); + spectrumMaxPPM = spectrumMaxPPM + (0.1 * spectrumMaxPPM); + maxGraph = maxGraph + (0.1 * maxGraph); + localData.sort(); + console.log(localData) + // build graph + $("#containter-lcms-spectrum-preview-{{ TAB_INDEX_PLACEHOLDER }}").highcharts({ + chart: { + zoomType: "x", + spacingRight: 10, + spacingLeft: 10, + type: "scatter" + }, + title: { + text: "Spectrum Preview", + useHTML: true + }, + subtitle: { + text: ( + document.ontouchstart === undefined + ? "Select area" + : "Pinch the chart to zoom in" + ) + }, + xAxis: { + type: "number", + title: {text: "m/z"}, + min: spectrumMinPPM, + max: spectrumMaxPPM, + labels: { + formatter: function() { + return (Math.abs(this.value) + ""); + } + } + }, + yAxis: { + title: {text: "Relative Intensity (%)"}, + min: 0, + max: maxGraph + }, + tooltip: { + crosshairs: true, + formatter: function() { + var compo = ""; + return ( + "" + this.series.name + + "
m/z:" + Math.abs(this.x) + "" + + ";
Relative Intensity: " + this.y + + "%;
Annotation: " + localDataAnnot[ this.x] + + "" + ); + } + }, + legend: {enabled: false}, + plotOptions: {scatter: {}}, + series: [{ + name: "preview", + showInLegend: true, + color: "#f00", + lineColor: "#f00", + pointInterval: 10, + pointStart: 100, + lineWidth : 2, + marker: { + enabled: true, + radius: 2, + lineColor: "#f00" + }, + data: localData, + zIndex: 10 + }] + }); + }, + + //USED HERE + fulfillLCdata: function(jsonFileName) { + var self = this ; + var url = `{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/lc-methods/${jsonFileName}.json` ; + $.getJSON(url, function(json) { + // $.POST + console.log(json); + // lc chromato + if (json.lc_chromatography != null) { + [ + ["colConstructor", "column_constructor"], + ["colConstructorOther", "column_constructor_other"], + ["colName", "column_name"], + ["colLength", "column_length"], + ["colDiameter", "column_diameter"], + ["colParticuleSize", "particule_size"], + ["colTemperature", "column_temperature"], + ["separationFlowRate", "separation_flow_rate"], + ["separationSolvA", "separation_solvent_a"], + ["separationSolvApH", "ph_solvent_a"], + ["separationSolvB", "separation_solvent_b"], + ["separationSolvBpH", "ph_solvent_b"] + ].forEach((arr) => { + var el ; + console.log(arr) + el = $(`#add1spectrum-chromatoLC-${arr[0]}-{{ TAB_INDEX_PLACEHOLDER }}`) + el.val(json.lc_chromatography[arr[1]]) ; + el.change() + }) + try { + $("#add1spectrum-chromatoLC-LCMode-{{ TAB_INDEX_PLACEHOLDER }}").val(json.lc_chromatography.LC_mode); + $("#add1spectrum-chromatoLC-LCMode-{{ TAB_INDEX_PLACEHOLDER }}").change(); + } catch (e) {} + var handsontableSeparationFlowRateData = []; + if (json.lc_chromatography.separation_flow_gradient != null) { + $.each(json.lc_chromatography.separation_flow_gradient, function() { + var e = [ + "" + this.time, + "" + this.solvA, + "" + this.solvB + ]; + handsontableSeparationFlowRateData.push(e); + }); + } else { + handsontableSeparationFlowRateData = null; + } + self.handsontableSeparationFlowRate(handsontableSeparationFlowRateData); + } + // ms_analyzer + if (json.ms_analyzer != null) { + $("#add1spectrum-analyzer-ms-instrument-{{ TAB_INDEX_PLACEHOLDER }}").val(json.ms_analyzer.instrument); + $("#add1spectrum-analyzer-ms-instrument-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-analyzer-ms-model-{{ TAB_INDEX_PLACEHOLDER }}").val(json.ms_analyzer.model); + $("#add1spectrum-analyzer-ms-model-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-analyzer-ms-resolutionFWHM-{{ TAB_INDEX_PLACEHOLDER }}").val(json.ms_analyzer.resolution_FWHM); + $("#add1spectrum-analyzer-ms-resolutionFWHM-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-analyzer-ms-ionAnalyzerType-{{ TAB_INDEX_PLACEHOLDER }}").val(json.ms_analyzer.ion_analyzer_type); + $("#add1spectrum-analyzer-ms-ionAnalyzerType-{{ TAB_INDEX_PLACEHOLDER }}").change(); + } + if (json.molecule_ionization != null) { + ["pos", "neg"].forEach((mode) => { + if (json.molecule_ionization[`mode_${mode}`] != null) { + [ + ["ionizationMethod", "ionisation_method"], + ["sprayGazFlow", "spray_gaz_flow"], + ["vaporizerGazFlow", "vaporizer_gaz_flow"], + ["vaporizerTemperature", "vaporizer_temperature"], + ["sourceGazFlow", "source_gaz_flow"], + ["ionTransferTubeTemperatureOrTransferCapillaryTemperature", "transfer_tube_or_capillary_temperature"], + ["highVoltageOrCoronaVoltage", "voltage"], + ].forEach((tuple) => { + var el ; + var id = tuple[0] ; + var key = tuple[1] ; + el = $(`#add1spectrum-analyzserMS-${id}-${mode}-{{ TAB_INDEX_PLACEHOLDER }}`) ; + console.log(el) + el.val(json.molecule_ionization[`mode_${mode}`][key]); + el.change() ; + }) + } + }) + } + + if (json.molecule_beamOrTrap != null) { + if (json.molecule_beamOrTrap.ion_beam != null) { + $("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").val("beam").change(); + $("#add1spectrum-ionTrapBeam-ionGas-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_beam.ion_gas).change(); + $("#add1spectrum-ionTrapBeam-ionGasPressureValue-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_beam.ion_pressure_value).change(); + $("#add1spectrum-ionTrapBeam-ionGasPressureUnit-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_beam.ion_pressure_unit).change(); + } + if (json.molecule_beamOrTrap.ion_trap != null) { + $("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").val("trap").change(); + $("#add1spectrum-ionTrapBeam-ionGas-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_trap.ion_gas).change(); + $("#add1spectrum-ionTrapBeam-ionGasPressureValue-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_trap.ion_pressure_value).change(); + $("#add1spectrum-ionTrapBeam-ionGasPressureUnit-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_trap.ion_pressure_unit).change(); + $("#add1spectrum-ionTrapBeam-ionNumber-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_trap.ion_number).change(); + $("#add1spectrum-ionTrapBeam-ionFrequencyShift-{{ TAB_INDEX_PLACEHOLDER }}").val(json.molecule_beamOrTrap.ion_trap.ion_freq_shift).change(); + } + } + // other + if (json.other != null) { + $("#add1spectrum-other-author-{{ TAB_INDEX_PLACEHOLDER }}").val(json.other.data_authors); + $("#add1spectrum-other-author-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-other-validator-{{ TAB_INDEX_PLACEHOLDER }}").val(json.other.data_validator); + $("#add1spectrum-other-validator-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-other-date-{{ TAB_INDEX_PLACEHOLDER }}").val(json.other.acquisition_date); + $("#add1spectrum-other-date-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-other-owner-{{ TAB_INDEX_PLACEHOLDER }}").val(json.other.data_ownership); + $("#add1spectrum-other-owner-{{ TAB_INDEX_PLACEHOLDER }}").change(); + } + }).error(function(event, jqxhr, exception) { + if (event.status == 404) { + $("#alertBoxSelectTemplate-{{ TAB_INDEX_PLACEHOLDER }}").html(` + + `); + } + }); + }, + + //USED HERE + resetFromColors: function() { + + var self = this ; + $.each($(self.prefix+".add1spectrum"), function(id, elem) { + element = $(elem) + self.rm_success(element) ; + self.rm_warning(element) ; + self.rm_error(element) ; + if ($(elem).hasClass("is-mandatory") && ($(elem).val() == "" || $(elem).val() == null)) { + self.set_error($(elem)) ; + } + if ($(elem).hasClass("is-optional") && ($(elem).val() == "" || $(elem).val() == null)) { + self.set_warning($(elem)) ; + } + if ($(elem).val() != "" && $(elem).val() != null) { + self.set_success($(elem)) ; + } + }); + $.each($(self.prefix+"button.switchStep"), function(id, elem) { + if (!$(this).hasClass("btn-disabled")) { + $(this).addClass("btn-disabled"); + } + if ($(this).hasClass("btn-primary")) { + $(this).removeClass("btn-primary"); + } + $(this).prop("disabled", true); + }); + + // peak list: no data to check + $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("btn-disabled"); + $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").addClass("btn-primary"); + $("#btnSwitch-gotoStep5-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + + $("#add1spectrum-other-author-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + $("#add1spectrum-other-validator-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + $("#add1spectrum-other-date-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + $("#add1spectrum-other-owner-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + $("#add1spectrum-other-fileName-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + $("#add1spectrum-other-fileSize-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + }, + + //USED IN HTML + switchToStep: function(step) { + + var self = this ; + switch(step) { + case 2: + // hide after step 2 / alt step 2 + $("#add1spectrum-chromatographyData-LC-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-chromatographyData-GC-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-analyserData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-peaksData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + if ($("#step1sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step1sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + if (self.is_ms()) { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").empty(); + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + '' + ); + $.getJSON("{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lc-methods.json", function(data) { + // load data from json + $.each(data.methods,function() { + if (this.name !== undefined) { + if (this.value !== undefined) { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } else { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } + } + }); + }); + } else if (self.is_ms2()) { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").empty(); + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + '' + ); + $.getJSON( + "{{ PF_URL_PLACEHOLDER }}/webapp/resources/json/list-lc-msms-methods.json", + function(data) { + // load data from json + $.each(data.methods, function() { + if (this.name !== undefined) { + if (this.value !== undefined) { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } else { + $("#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}").append( + `` + ); + } + } + }); + } + ); + } + // check panel to show + if (self.isLC) { + $("#add1spectrum-chromatographyData-LC-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep2-lc-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + var sign = $("#step2-lc-sign-{{ TAB_INDEX_PLACEHOLDER }}") ; + self.rm_class(sign, "fa-check-circle") && self.set_class(sign, "fa-question-circle") ; + if (!self.isSeparationFlowRateInit) { + self.handsontableSeparationFlowRate(null); + self.isSeparationFlowRateInit = true; + } + } else if (self.isGC) { + $("#add1spectrum-chromatographyData-GC-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep2-gc-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + var sign = $("#step2-gc-sign-{{ TAB_INDEX_PLACEHOLDER }}") ; + sign.removeClass("fa-check-circle").addClass("fa-question-circle"); + if ($("#step2-gc-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + } + } else if (self.isIC) { + $("#add1spectrum-chromatographyData-IC-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep2-ic-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + if ($("#step2-ic-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + $("#step2-ic-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-check-circle").addClass("fa-question-circle"); + } + } + break; + case 3: + // hide after step 3 / alt step 3 + $("#add1spectrum-analyserData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-peaksData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // step 2 ok + if ($("#step2-lc-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step2-lc-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + if ($("#step2-gc-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step2-gc-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + // check panel to show + if (self.is_ms() || self.is_ms2()) { + $("#add1spectrum-analyserData-MS-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep3-ms-{{ TAB_INDEX_PLACEHOLDER }}").trigger('click'); + // debug display + [ + "add1spectrum-analyzserMS-sprayGazFlow-pos", + "add1spectrum-analyzserMS-sprayGazFlow-neg", + "add1spectrum-analyzserMS-vaporizerGazFlow-pos", + "add1spectrum-analyzserMS-vaporizerGazFlow-neg", + "add1spectrum-analyzserMS-vaporizerTemperature-pos", + "add1spectrum-analyzserMS-vaporizerTemperature-neg", + "add1spectrum-analyzserMS-sourceGazFlow-pos", + "add1spectrum-analyzserMS-sourceGazFlow-neg", + "add1spectrum-analyzserMS-ionTransferTubeTemperatureOrTransferCapillaryTemperature-pos", + "add1spectrum-analyzserMS-ionTransferTubeTemperatureOrTransferCapillaryTemperature-neg", + "add1spectrum-analyzserMS-highVoltageOrCoronaVoltage-pos", + "add1spectrum-analyzserMS-highVoltageOrCoronaVoltage-neg" + ].forEach((id) => { + var element = $(`#id-{{ TAB_INDEX_PLACEHOLDER }}`) + element.height(element.parent().children("span").height()) + }) + if ($("#step3-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + $("#step3-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-check-circle").addClass("fa-question-circle"); + } + // MSMS only + $(self.prefix+".enable-if-ms").attr("disabled", !self.is_ms()); + $(self.prefix+".enable-if-msms").attr("disabled", !self.is_ms2()); + } + // avoid display bug + $("#add1spectrum-analyzer-ms-instrument-{{ TAB_INDEX_PLACEHOLDER }}").change(); + break; + case 4: + // hide after step 4 / alt step 4 + $("#add1spectrum-peaksData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // step 3 ok + if ($("#step3-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step3-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + if (self.is_ms() || self.is_ms2()) { + $("#add1spectrum-peaksData-MS-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + if ($("#step4-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + $("#step4-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-check-circle").addClass("fa-question-circle"); + } + // LC MS + if (!self.isMSpeaksInit) { + console.log(`self.is_mix(): ${self.is_mix()}`) + if (self.is_mix()) { + all_contexts.forEach((context, index) => { + context.handsontableMSpeaks(null) ; + context.updateLCMSspectraViewer() ; + context.isMSpeaksInit = true; + $(context.prefix+".add1spectrum-peaksMSForm-peaklist-reset").val("").change(); + }) + } else { + self.handsontableMSpeaks(null); + self.isMSpeaksInit = true; + $(self.prefix+".add1spectrum-peaksMSForm-peaklist-reset").val("").change(); + } + } + } + // show ms tab + setTimeout(() => $("#container_MS_Peaks-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"), 250); + $("#add1spectrum-peaksMS-msLevel-{{ TAB_INDEX_PLACEHOLDER }}").change(); + break; + case 5: + // hide after step 5 / alt step 5 + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // step 4 ok + if ($("#step4-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step4-ms-sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + if ($("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + $("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-check-circle").addClass("fa-question-circle"); + } + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $("#linkActivateStep5-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + // reset step 6 button + self.checkIfEnableSubmit(); + $("#import1SpectrumLoadingBare-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#import1SpectrumResults-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + break; + case 6: + self.postOneSpectrumFrom(); + self.cptPeakListTab++; + break; + case 7: + self.dumpOneSpectrumFrom(); + break; + } + }, + + //USED HERE + resetElemColor: function(idElem) { + + var self = this ; + if ($(`#${idElem}`).parent().hasClass("has-success")) { + $(`#${idElem}`).parent().removeClass("has-success") ; + } + if ($(`#${idElem}`).parent().hasClass("has-warning")) { + $(`#${idElem}`).parent().removeClass("has-warning") ; + } + if ($(`#${idElem}`).parent().hasClass("has-error")) { + $(`#${idElem}`).parent().removeClass("has-error") ; + } + }, + + //USED HERE + disableElem: function(idElem) { + + var self = this ; + $(`#${idElem}`).prop("disabled", true) ; + $(`#${idElem}`).val("") ; + if ($(`#${idElem}`).hasClass("is-mandatory")) { + $(`#${idElem}`).removeClass("is-mandatory") ; + } + }, + + //USED HERE + enableElem: function(idElem) { + + var self = this ; + $(`#${idElem}`).prop("disabled", false) ; + $(`#${idElem}`).parent().addClass("has-error") ; + if (!$(`#${idElem}`).hasClass("is-mandatory")) { + $(`#${idElem}`).addClass("is-mandatory") ; + } + }, + + //USED HERE + checkIfEnableSubmit: function() { + + var self = this ; + var isBtnStep6OK = true; + $.each($(self.prefix+".add1spectrum-otherForm"), (id, elem) => { + if (self.is_error($(elem)) && $(elem).is(":visible")) { + isBtnStep6OK = false; + } + }); + if (isBtnStep6OK) { + self.rm_class($("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + self.rm_class($("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-disabled") ; + self.set_class($("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}"), "btn-primary") ; + $("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", false); + } else { + if (!$("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("btn-disabled")) { + $("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").addClass("btn-disabled"); + } + if ($("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("btn-primary")) { + $("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("btn-primary"); + } + $("#btnSwitch-gotoStep6-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + if (!$("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("btn-disabled")) { + $("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").addClass("btn-disabled"); + } + if ($("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("btn-primary")) { + $("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("btn-primary"); + } + $("#btnSwitch-gotoStep7-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + } + }, + + //USED IN HTML + addOneSpectrum: function(type) { + + var self = this ; + // unlock + $(self.prefix+".add1spectrum-sampleForm").prop("disabled", false); + $(self.prefix+".add1spectrum-chromatoLCForm").prop("disabled", false); + $(self.prefix+".add1spectrum-analyzerMSForm").prop("disabled", false); + $(self.prefix+".add1spectrum-otherForm").prop("disabled", false); + $("#add1spectrum-chromatoLC-colConstructor-{{ TAB_INDEX_PLACEHOLDER }}").change(); + // reset + self.isLC = false; + self.isGC = false; + self.isIC = false; + $("#alertBoxSubmitSpectrum-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + // hide in all steps + $(self.prefix+".opt-ms").hide(); + $(self.prefix+".opt-msms").hide(); + // hide step 2 + $("#add1spectrum-chromatographyData-LC-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#add1spectrum-chromatographyData-GC-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // hide step 3 + $("#add1spectrum-analyserData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $(self.prefix+".add1spectrum-ionTrap").hide(); + // hide step 4 + $("#add1spectrum-peaksData-MS-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // hide step 5 + $("#add1spectrum-otherData-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + // reset field step 1 + $("#add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $(self.prefix+".add1spectrum-sample-type-panel").hide(); + $(self.prefix+".add1spectrum-sampleForm").val(""); + $("#sample-bonus-display-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + // reset field step 2 + $(self.prefix+".add1spectrum-chromatoLCForm").val(""); + // reset field step 3 + $(self.prefix+".add1spectrum-analyzerMSForm").val(""); + // reset field step 4 + // reset peak lists / all tabs + self.isSeparationFlowRateInit = false; + self.isMSpeaksInit = false; + $(self.prefix+".handsontable").html(""); + // reset field step 5 => NO! + // set icon + $("#step0sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + if ($("#step1sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-check-circle")) { + $("#step1sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-check-circle").addClass("fa-question-circle"); + } + // collapse step 0 / uncollaspe step 1 + $("#linkActivateStep1-{{ TAB_INDEX_PLACEHOLDER }}").trigger("click"); + // show step 1 content + $("#add1spectrum-sampleData-{{ TAB_INDEX_PLACEHOLDER }}").show(); + switch(type) { + case 1: + // TODO GC-MS stuff + self.isGC = true; + break; + case 2: + // LC-MS stuff + self.isLC = true; + $(self.prefix+".opt-ms").show(); + break; + case 5: + // LC-MSMS stuff + self.isLC = true; + $(self.prefix+".opt-ms").show(); + $(self.prefix+".opt-msms").show(); + break; + case 6: + // IC-MS stuff + self.isIC = true; + $(self.prefix+".opt-ms").show(); + break; + case 7: + // IC-MSMS stuff + self.isIC = true; + $(self.prefix+".opt-ms").show(); + $(self.prefix+".opt-msms").show(); + break; + } + self.resetFromColors(); + // reset json obj to submit form + self.jsonSpectrumType = null; + self.isJsonSpectrumTypeComplete = false; + self.jsonSample = null; + self.isJsonSampleComplete = false; + self.isJsonRCCaddedComplete = false; + self.jsonChromato = null; + self.isJsonChromatoComplete = false; + self.jsonAnalyzer = null; + self.isJsonAnalyzerComplete = false; + self.jsonPeaksList = []; + self.isJsonPeaksListComplete = false; + self.jsonOtherMetadata = null; + self.isJsonOtherMetadataComplete = false; + + self.cptPeakListTab = 0; + self.jsonAnalyzerAcquisition = []; + self.idMetadataMap = {} + self.listOfViewableSpectra = []; + + // spec MS + self.jsonMolIonization = null; + + // spec MSMS + self.jsonMolIonBeam = null; + + // try load cpd + if (self.inchikey !== null) { + self.loadJSCompound(self.inchikey); + } + }, + + //USED HERE + loadJSCompound: function(inchikey) { + var self = this ; + + $("#add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}").val("compound-ref"); + $("#add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val(inchikey); + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").change(); + if (inchidata[inchikey] !== null) { + return (set_inchi_data(inchidata[inchikey]), {{ TAB_INDEX_PLACEHOLDER }}) ; + } + $.ajax({ + type: "get", + url: "{{ PF_URL_PLACEHOLDER }}/webapp/get-cpd-data", + data: "inchikey="+inchikey, + dataType: "json", + success: function(data) { + if (data.success) { + set_inchi_data(data) ; + } + }, + error : function(data) { + } + }).always(function() { + }); + }, + + //USED HERE + handsontableSeparationFlowRate: function(data) { + var self = this ; + + // reset + $("#container_LC_SFG-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + // init + var data_LC_SFG; + if (data==null) { + data_LC_SFG = [ + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + [ "", "", "" ], + ]; + } else { + data_LC_SFG = data; + } + + var container_LC_SFG = document.getElementById("container_LC_SFG-{{ TAB_INDEX_PLACEHOLDER }}"); + self.hot_LC_SFG = new Handsontable(container_LC_SFG, { + data : data_LC_SFG, + minSpareRows : 1, + colHeaders : true, + colHeaders: ["time (min)", "solv. A (%)", "solv. B (%)"], + contextMenu : false + }); + Handsontable.Dom.addEvent(document.body, "click", function(e) { + var element = e.target || e.srcElement; + if (element.nodeName == "BUTTON"&& element.name == "dump") { + var name = element.getAttribute("data-dump"); + var instance = element.getAttribute("data-instance"); + self.hot_LC_SFG = window[instance]; + console.log("data of " + name, self.hot_LC_SFG.getData()); + } + }); + $("#container_LC_SFG table.htCore-{{ TAB_INDEX_PLACEHOLDER }}").css("width","100%"); + }, + + //USED HERE + handsontableMSpeaks: function(data) { + console.log("handsontableMSpeaks") + console.log(data) + var self = this ; + var data_MS_Peaks ; + var container_MS_Peaks ; + + if (data != null) { + data_MS_Peaks = data; + } else { + data_MS_Peaks = JSON.parse(JSON.stringify(self.DEFAULT_MS_PEAK_VALUES)); + } + $("#container_MS_Peaks-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + container_MS_Peaks = document.getElementById( + "container_MS_Peaks-{{ TAB_INDEX_PLACEHOLDER }}" + ); + var colHeaders = [ + "m/z", "absolute intensity", "relative intensity (%)", "delta (ppm)", + "composition", "attribution", "Validated" + ] + var columns = [ + {type: "numeric", format: "0.0000"}, + {type: "numeric", format: "0.00"}, + {type: "numeric", format: "0.00"}, + {type: "numeric", format: "0.0000"}, + {type: "text"}, + {type: "text"}, + {type: "checkbox"} + ] ; + if (self.is_ms2()) { + colHeaders.push("Parent ion") ; + columns.push({type: "checkbox"}) ; + } + self.hot_MS_Peaks = new Handsontable(container_MS_Peaks, { + data: data_MS_Peaks, + minSpareRows: 1, + colHeaders: true, + colHeaders: colHeaders, + contextMenu: false, + maxRows: data_MS_Peaks.length, + minRows: data_MS_Peaks.length, + columns: columns, + afterChange: function(changes) { + if (self.lock.precursor_ion) { + return ; + } + self.lock.precursor_ion = true ; + try { + changes?.forEach(([row, prop, old, value]) => { + var data ; + var precursor_ion ; + + var data = self.hot_MS_Peaks.getData() ; + if (prop !== 7 || value !== true || data === undefined) { + return ; + } + for (var i = 0; i < data.length ; i += 1) { + data[i][7] = false ; + } + data[row][7] = true ; + precursor_ion = $(`#add1spectrum-peaksMS-msPrecursorIon-{{ TAB_INDEX_PLACEHOLDER }}`) ; + console.log(`setting preco ion to ${data[row][0]}`) ; + precursor_ion.val(data[row][0]) ; + precursor_ion.change() ; + self.hot_MS_Peaks.render() ; + }) + } finally { + self.lock.precursor_ion = false ; + } + } + }); + Handsontable.Dom.addEvent(document.body, "click", (e) => { + var element ; + var name ; + var instance ; + + element = e.target || e.srcElement ; + if (element.nodeName == "BUTTON" && element.name == "dump") { + name = element.getAttribute("data-dump") ; + instance = element.getAttribute("data-instance") ; + self.hot_MS_Peaks = window[instance] ; + console.log("data of " + name, self.hot_MS_Peaks.getData()) ; + } + }) ; + + $("#container_MS_Peaks-{{ TAB_INDEX_PLACEHOLDER }} table.htCore").css( + "width","100%" + ) ; + if (self.is_ms2()) { + setTimeout(() => self.select_precursor_ion(), 200) ; + } + }, + + change_tab: function() { + var self = this ; + setTimeout(() => self.auto_select_ion_parent(), 1000) ; + }, + + auto_select_ion_parent: function() { + var self = this ; + if (!self.a_ion_parent_is_selected()) { + setTimeout(() => self.select_precursor_ion(), 1000) ; + } + }, + + select_precursor_ion: function() { + var self = this ; + var data ; + var precuirsor_ion ; + + if (self.hot_MS_Peaks == null) { + return setTimeout(() => self.select_precursor_ion(), 200) ; + } + console.log("Selecting ion preco for tab {{ TAB_INDEX_PLACEHOLDER }}") + data = self.hot_MS_Peaks.getData() ; + for (var i = 0 ; i < data.length ; i += 1) { + if (data[i][5] === "[M+H]+" || data[i][5] === "[M+H]-") { + precursor_ion = $("#add1spectrum-peaksMS-msPrecursorIon-{{ TAB_INDEX_PLACEHOLDER }}") ; + console.log(precursor_ion) + precursor_ion.val(data[i][0]) ; + precursor_ion.change() ; + return ; + } + } + }, + + sync_precursor_ion: function() { + var self = this ; + var data ; + + if (self.lock.precursor_ion || self.hot_MS_Peaks == undefined) { + return ; + } + self.lock.precursor_ion = true ; + console.log("Syncing precursor ion") + var val = $("#add1spectrum-peaksMS-msPrecursorIon-{{ TAB_INDEX_PLACEHOLDER }}").val() ; + var data = self.hot_MS_Peaks.getData() ; + for (var i = 0; i < data.length ; i += 1) { + if (Math.abs(data[i][0] - val) < 0.0001) { + for (var j = 0; j < data.length ; j += 1) { + data[j][7] = false ; + } + data[i][7] = true ; + self.hot_MS_Peaks.render() ; + return ; + } + } + self.lock.precursor_ion = false ; + }, + + // USED HERE + handsontableRefChemCpdAdded: function(data) { + var self = this ; + // reset + $("#container_RCC_ADDED-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + $("#sample-bonus-display-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + // init + var data_RCC_ADDED, colHeaderData, container_RCC_ADDED; + + colHeaderData = [ + {data: "common name", type: "text"}, + {data: "InChIKey", type: "text"}, + {data: "composition", renderer: lightgrayRenderer}, + {data: "concentration (µg/ml)", type: "text"}, + {data: "exact mass", renderer: lightgrayRenderer}, + {data: "(M+H)+ or (M-H)-", renderer: lightgrayRenderer} + ] ; + + if (data == null) { + data_RCC_ADDED = [ + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + [ "", "", "","", "", "" ], + ]; + } else { + container_RCC_ADDED = data; + } + + container_RCC_ADDED = document.getElementById("container_RCC_ADDED-{{ TAB_INDEX_PLACEHOLDER }}"); + self.hot_RCC_ADDED = new Handsontable(container_RCC_ADDED, { + data: data_RCC_ADDED, + minSpareRows : 1, + colHeaders : true, + colHeaders: [ + "common name", + "InChIKey", + "composition", + "concentration (µg/ml)", + "exact mass", + "(M+H)+ or (M-H)-" + ], + contextMenu : false, + columns: colHeaderData + }); + function bindDumpButton_RCC_ADDED() { + Handsontable.Dom.addEvent(document.body, "click", (e) => { + var element = e.target || e.srcElement; + if (element.nodeName == "BUTTON"&& element.name == "dump") { + var name = element.getAttribute("data-dump"); + var instance = element.getAttribute("data-instance"); + self.hot_RCC_ADDED = window[instance]; + console.log("data of " + name, self.hot_RCC_ADDED.getData()); + } + }); + } + bindDumpButton_RCC_ADDED(); + $("#container_RCC_ADDED-{{ TAB_INDEX_PLACEHOLDER }} table.htCore").css("width","100%"); + // celect cell + self.hot_RCC_ADDED.selectCell(0, 0); + // add select listener + self.hot_RCC_ADDED.addHook("afterSelection", (r, c) => self.hookSelection(r, c)); + }, + + //USED HERE + hookSelection: function(r, c) { + var self = this ; + if (c == 0 || c == 1 || c == 2) + self.pickChemicalCompound4Mix(r); + }, + + //USED HERE + postOneSpectrumFrom: function() { + var self = this ; + $("#import1SpectrumLoadingBare-{{ TAB_INDEX_PLACEHOLDER }}").show(); + + // II - form data -> json object + self.loadFomDataIntoJsonObjects(); + // II.A - check if json object complete + var alertMsg = self.getFormErrorMessage(); + + if (alertMsg != "") { + $("#alertBoxSubmitSpectrum-{{ TAB_INDEX_PLACEHOLDER }}").html(alertMsg); + $("#import1SpectrumLoadingBare-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + return false; + } + // all OK: lock! + // lock sample + $(self.prefix+".add1spectrum-sampleForm").prop("disabled", true); + // lock chromato + $(self.prefix+".add1spectrum-chromatoLCForm").prop("disabled", true); + if (!$("#container_LC_SFG-{{ TAB_INDEX_PLACEHOLDER }}").is(":empty")) { + self.hot_LC_SFG.updateSettings({ + cells: function(row, col, prop) { + var cellProperties = {}; + cellProperties.readOnly = true; + return cellProperties; + } + }); + } + if (!$("#container_MS_Peaks-{{ TAB_INDEX_PLACEHOLDER }}").is(":empty")) { + self.hot_MS_Peaks.updateSettings({ + cells: function(row, col, prop) { + var cellProperties = {}; + cellProperties.readOnly = true; + return cellProperties; + } + }); + } + if (!$("#container_RCC_ADDED-{{ TAB_INDEX_PLACEHOLDER }}").is(":empty")) { + self.hot_RCC_ADDED.updateSettings({ + cells: function(row, col, prop) { + var cellProperties = {}; + cellProperties.readOnly = true; + return cellProperties; + } + }); + self.hot_RCC_ADDED.removeHook( + "afterSelection", + (r, c) => self.hookSelection(r, c) + ); + } + + // lock analyzer + $(self.prefix+".add1spectrum-analyzerMSForm").prop("disabled", true); + // lock other metadata field + $(self.prefix+".add1spectrum-otherForm").prop("disabled", true); + // lock switch btn + $("#btnSwitch-gotoStep2-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + $("#btnSwitch-gotoStep3-lc-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + $("#btnSwitch-gotoStep4-ms-{{ TAB_INDEX_PLACEHOLDER }}").prop("disabled", true); + self.postSpectrumToServer() ; + }, + + postSpectrumToServer: function(jsonData, tab_index) { + var self = this ; + var base_peakdata ; + var new_peakdata ; + var is_ms2 = self.is_ms2() ; + + if (self.is_mix()) { + if ({{ TAB_INDEX_PLACEHOLDER }} != 1) { + return ; + } + jsonData = self.gatherJsonObjects() ; + all_mix_data = Object.assign({}, jsonData) ; + all_mix_data["peaklists"] = [] ; + base_peakdata = Object.assign({}, jsonData["peaklists"][0]) ; + base_peakdata["msms_ms_precursor_ion"] = undefined ; + all_contexts.forEach((context, index) => { + new_peakdata = Object.assign({}, base_peakdata) ; + context.loadFomDataIntoJsonObjects() + if (is_ms2) { + new_peakdata["precursor_ion"] = context.jsonPeaksList["msms_ms_precursor_ion"]["m/z"] ; + } + new_peakdata["peaklist"] = context.jsonPeaksList["peaklist"] ; + all_mix_data["peaklists"].push(new_peakdata) + }) + } + // II.B - rebuild json full object (with all metadata or just id if already in base) + if (jsonData == null) { + jsonData = self.gatherJsonObjects(); + } + // II.C - add id metadata (if exist) + var json_array = [] ; + if (!tab_index) { + tab_index = {{ TAB_INDEX_PLACEHOLDER }} ; + } + json_array[tab_index-1] = jsonData ; + + // III - post json object + // III.A - success + self.sent_json = jsonData ; + console.warn( + "This data has been validated without going through the internal server!" + ) + if ($("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-question-circle")) { + $("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-question-circle").addClass("fa-check-circle"); + } + if ($("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").hasClass("fa-spinner")) { + $("#step5sign-{{ TAB_INDEX_PLACEHOLDER }}").removeClass("fa-spinner fa-spin").addClass("fa-check-circle"); + } + $("#import1SpectrumLoadingBare-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + $("#alertBoxSubmitSpectrum-{{ TAB_INDEX_PLACEHOLDER }}").html(` + + `); + return true; + }, + + //USED HERE + loadFomDataIntoJsonObjects: function() { + var self = this ; + // I - Spectrum type + self.isJsonSpectrumTypeComplete = false ; + if (self.isGC && self.is_ms()) { + self.jsonSpectrumType = "gc-ms" ; + } else if (self.isLC && self.is_ms()) { + self.jsonSpectrumType = "lc-ms" ; + } else if (self.isLC && self.is_ms2()) { + self.jsonSpectrumType = "lc-msms" ; + } else if (self.isGC && self.is_ms()) { + self.jsonSpectrumType = "ic-ms" ; + } else if (self.isLC && self.is_ms()) { + self.jsonSpectrumType = "ic-msms" ; + } + if (self.jsonSpectrumType != null && self.jsonSpectrumType != "") { + self.isJsonSpectrumTypeComplete = true; + } + + // II - Sample + self.isJsonSampleComplete = true; + self.isJsonRCCaddedComplete = true; + self.jsonSample = {}; + + switch($("#add1spectrum-sample-type-{{ TAB_INDEX_PLACEHOLDER }}").val()) { + // II.A - chemical lib. compound + case "compound-ref": + if ($("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val() == "") { + return false; + } + self.jsonSample["sample_type"] = "reference-chemical-compound"; + self.jsonSample["inchikey"] = $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonSample["concentration"] = $("#add1spectrum-sample-concentration-{{ TAB_INDEX_PLACEHOLDER }}").val(); + if (self.is_ms()) { + self.jsonSample["solvent"] = $("#add1spectrum-sample-lcmsSolvent-{{ TAB_INDEX_PLACEHOLDER }}").val(); + } + self.isJsonSampleComplete = true; + break; + // II.B - chemical lib. compound mix + case "compound-mix": + // solvent + self.jsonSample["solvent"] = $("#add1spectrum-sample-mixSolvent-{{ TAB_INDEX_PLACEHOLDER }}").val(); + // cpd added + self.jsonSample.inchikeys_list = self.getRCCADDED(); + self.jsonSample.concentrations_list = self.getRCCADDEDConcentration(); + if (self.jsonSample.inchikeys_list.length == 0 && !self.is_other_in_mix()) { + self.isJsonRCCaddedComplete = false; + console.log(`isJsonRCCaddedComplete: false`) + return false; + } + self.isJsonSampleComplete = true; + break; + default: + if (!self.is_other_in_mix()) { + return false; + } + } + + // III - Chromato + self.isJsonChromatoComplete = true; + self.jsonChromato = {}; + + // III.A - no chromato + // nope? + + // III.B - GC + if (self.isGC) { + self.isJsonChromatoComplete = false; + // TODO + } + + // III.C - LC + if (self.isLC) { + self.isJsonChromatoComplete = true; + self.jsonChromato = {}; + // check error + $.each($(self.prefix+".add1spectrum-chromatoLCForm").parent(), function() { + if ($(this).hasClass("has-error")) + self.isJsonChromatoComplete = false; + }); + if ( + !self.isJsonChromatoComplete + && !self.is_other_in_mix() + ) { + console.log(`isJsonChromatoComplete: false`) + return false; + } + var id = `#add1spectrum-chromatoLC-method-{{ TAB_INDEX_PLACEHOLDER }}` ; + self.jsonChromato["method"] = $(`${id} option:selected`).text(); + [ + ["column_constructor", "colConstructor"], + ["column_constructor_other", "colConstructorOther"], + ["column_name", "colName"], + ["column_length", "colLength"], + ["column_diameter", "colDiameter"], + ["particule_size", "colParticuleSize"], + ["column_temperature", "colTemperature"], + ["mode", "LCMode"], + ["separation_flow_rate", "separationFlowRate"], + ["solvent_a", "separationSolvA"], + ["solvent_a_ph", "separationSolvApH"], + ["solvent_b", "separationSolvB"], + ["solvent_b_ph", "separationSolvBApH"] + ].forEach((field) => { + id = `#add1spectrum-chromatoLC-${field[1]}-{{ TAB_INDEX_PLACEHOLDER }}` ; + self.jsonChromato[field[0]] = $(id).val(); + }) + // fulfill json object + + jsonSFG = []; + var formatData = { + time: [], + solvent_a_percent: [], + solvent_b_percent: [] + }; + $.each(self.hot_LC_SFG.getData(), function(){ + if (this[0]!="") { + if (!isNaN(this[0]) && !isNaN(this[1]) && !isNaN(this[2])) { + formatData["time"].push(Number(this[0])); + formatData["solvent_a_percent"].push(Number(this[1])); + formatData["solvent_b_percent"].push(Number(this[2])); + } + } + }); + self.jsonChromato.separation_flow_gradient = formatData; + } + + // III.D - IC + if (self.isIC) { + self.isJsonChromatoComplete = false; + // TODO + } + + // IV - Analyzer + self.isJsonAnalyzerComplete = true; + self.isJsonAnalyzer = {}; + // IV.A - MS + if (self.is_ms() || self.is_ms2()) { + self.isJsonAnalyzerComplete = true; + self.jsonAnalyzer = {}; + // check error + $.each($(self.prefix+".add1spectrum-analyzerMSForm").parent(), function(){ + if ($(this).hasClass("has-error")) + self.isJsonAnalyzerComplete = false; + }); + if ( + !self.isJsonAnalyzerComplete + && !self.is_other_in_mix() + ) { + console.log(`isJsonAnalyzerComplete: false`) + return false; + } + + // fulfill json object + self.jsonAnalyzer["instrument_name"] = $("#add1spectrum-analyzer-ms-instrument-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonAnalyzer["instrument_model"] = $("#add1spectrum-analyzer-ms-model-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonAnalyzer["instrument_brand"] = $("#add1spectrum-analyzer-ms-model-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonAnalyzer["ion_analyzer_type"] = $("#add1spectrum-analyzer-ms-ionAnalyzerType-{{ TAB_INDEX_PLACEHOLDER }}").val(); + + if (self.is_ms2()) { + // MSMS ion BEAM or TRAP + self.jsonMolIonBeam = {} + var jsonIonTrapBeam = { + ion_gas: $("#add1spectrum-ionTrapBeam-ionGas-{{ TAB_INDEX_PLACEHOLDER }}").val(), + ion_pressure_value: $("#add1spectrum-ionTrapBeam-ionGasPressureValue-{{ TAB_INDEX_PLACEHOLDER }}").val(), + ion_pressure_unit: $("#add1spectrum-ionTrapBeam-ionGasPressureUnit-{{ TAB_INDEX_PLACEHOLDER }}").val() + } ; + var key = null ; + if ($("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").val() == "trap") { + // sp + jsonIonTrapBeam["ion_freq_shift"] = $("#add1spectrum-ionTrapBeam-ionFrequencyShift-{{ TAB_INDEX_PLACEHOLDER }}").val(); + jsonIonTrapBeam["ion_number"] = $("#add1spectrum-ionTrapBeam-ionNumber-{{ TAB_INDEX_PLACEHOLDER }}").val(); + key = "ion_trap" ; + } else if ($("#add1spectrum-ionTrapBeam-type-{{ TAB_INDEX_PLACEHOLDER }}").val() == "beam") { + key = "ion_beam_storage" ; + } + if (key !== null) { + self.jsonMolIonBeam[key] = jsonIonTrapBeam; + } + } + + self.jsonMolIonization = {}; + var json_mode ; + ["pos", "neg"].forEach((kind) => { + json_mode = {} ; + [ + ["ionisation_method", "ionizationMethod"], + ["spray_gaz_flow", "sprayGazFlow"], + ["vaporizer_gaz_flow", "vaporizerGazFlow"], + ["vaporizer_temperature", "vaporizerTemperature"], + ["source_gaz_flow", "sourceGazFlow"], + ["transfer_tube_or_capillary_temperature", "ionTransferTubeTemperatureOrTransferCapillaryTemperature"], + ["high_voltage", "highVoltageOrCoronaVoltage"] + ].forEach((field) => { + var id = `#add1spectrum-analyzserMS-${field[1]}-${kind}-{{ TAB_INDEX_PLACEHOLDER }}` ; + json_mode[field[0]] = $(id).val() ; + }) + self.jsonMolIonization[`mode_${kind}`] = json_mode ; + }) + } + + // IV.B - NMR + if (self.is_ms() || self.is_ms2()) { + self.isJsonPeaksListComplete = false; + // init + var peaklist = []; + var peakdata = {}; + var spectrumData = {}; + // peaklist + var ms_peak_data = self.hot_MS_Peaks.getData(); + $.each(ms_peak_data, function(index) { + var data = ms_peak_data[index] ; + var formatData = {}; + if ( + data[0] != "" + && !isNaN(data[0]) + // && !isNaN(data[2]) + && (data[6] === "true" || data[6] === true) + ) { + peaklist.push({ + mz: Number(data[0]), + RI: Number(data[2]), + deltaPPM: Number(data[3]), + composition: (data[4]), + attribution: (data[5]) + }); + self.isJsonPeaksListComplete = true; + } + }); + // peak list data + peakdata["ms_lvl"] = $("#add1spectrum-peaksMS-msLevel-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["polarity"] = $("#add1spectrum-peaksMS-polarity-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["resolution"] = $("#add1spectrum-peaksMS-resolution-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["curation"] = $("#add1spectrum-peaksMS-curation-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["mz_range_from"] = $("#add1spectrum-peaksMS-rangeFrom-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["mz_range_to"] = $("#add1spectrum-peaksMS-rangeTo-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["rt_abs_from"] = $("#add1spectrum-peaksMS-rtMinFrom-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["rt_abs_to"] = $("#add1spectrum-peaksMS-rtMinTo-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["rt_solv_from"] = $("#add1spectrum-peaksMS-rtSolvFrom-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["rt_solv_to"] = $("#add1spectrum-peaksMS-rtSolvTo-{{ TAB_INDEX_PLACEHOLDER }}").val(); + peakdata["resolution_FWHM"] = $("#add1spectrum-analyzer-ms-resolutionFWHM-{{ TAB_INDEX_PLACEHOLDER }}").val(); + if (self.is_ms2()) { + var data = self.hot_MS_Peaks.getData() ; + if (data.length != 0) { + var selected_ion = self.get_selected_parent_ion_index() ; + peakdata["msms_ms_precursor_ion"] = { + "m/z": data[selected_ion][0], + "abs_intensity": data[selected_ion][1], + "rel_intensity": data[selected_ion][2], + "attribution": data[selected_ion][5] + } ; + } + } + peakdata["peaklist"] = peaklist; + self.jsonPeaksList = peakdata; + } + + self.isJsonOtherMetadataComplete = true; + self.jsonOtherMetadata = {}; + // check error + $.each($(self.prefix+".add1spectrum-otherForm").parent(), function(){ + if ($(this).hasClass("has-error")) + self.isJsonOtherMetadataComplete = false; + }); + if (!self.isJsonOtherMetadataComplete && !self.is_other_in_mix()) { + console.log(`isJsonOtherMetadataComplete: false`) + return false; + } + self.jsonOtherMetadata["data_authors"] = $("#add1spectrum-other-author-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonOtherMetadata["data_validator"] = $("#add1spectrum-other-validator-{{ TAB_INDEX_PLACEHOLDER }}").val();; + self.jsonOtherMetadata["acquisition_date"] = $("#add1spectrum-other-date-{{ TAB_INDEX_PLACEHOLDER }}").val(); + if (!self.jsonOtherMetadata["acquisition_date"]) { + self.jsonOtherMetadata["acquisition_date"] = null ; + } + self.jsonOtherMetadata["data_ownership"] = $("#add1spectrum-other-owner-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonOtherMetadata["raw_file_name"] = $("#add1spectrum-other-fileName-{{ TAB_INDEX_PLACEHOLDER }}").val(); + self.jsonOtherMetadata["raw_file_size"] = $("#add1spectrum-other-fileSize-{{ TAB_INDEX_PLACEHOLDER }}").val(); + return true; + }, + + //USED HERE + getFormErrorMessage: function() { + var self = this ; + var alertMsg = ""; + if (!self.isJsonSpectrumTypeComplete) { + alertMsg = ` + ` ; + } else if (!self.isJsonSampleComplete) { + alertMsg = ` + ` ; + } else if (!self.isJsonRCCaddedComplete) { + alertMsg = ` + `; + } else if (!self.isJsonChromatoComplete) { + alertMsg = ` + '; + } else if (!self.isJsonPeaksListComplete) { + alertMsg = ` + '; + } else if (self.is_mix() && self.is_ms2()) { + for (var i = 0 ; i < all_contexts.length ; i += 1) { + if (all_contexts[i].get_selected_parent_ion_index() === null) { + return alertMsg + ` + + ` + } + } + } + // TODO other + return alertMsg; + }, + + //USED HERE + gatherJsonObjects: function() { + var self = this ; + var jsonData = {}; + if (self.is_mix()) { + jsonData["sample_type"] = "mix_of_reference_chemical_compounds" ; + } else { + jsonData["sample_type"] = "reference_chemical_compound" ; + } + jsonData["spectrum_type"] = self.jsonSpectrumType.toUpperCase().replaceAll("-", ""); + jsonData["sample"] = self.jsonSample; + if (self.isLC) { + jsonData["chromatography"] = self.jsonChromato; + } else if (self.isGC) { + jsonData["chromatography"] = self.jsonChromato; + } else if (self.isIC) { + jsonData["chromatography"] = self.jsonChromato; + } + if (self.is_ms()) { + jsonData["analyzer"] = self.jsonAnalyzer; + var molecule_ionization = self.jsonMolIonization; + jsonData["ionization_mode_positive"] = molecule_ionization["mode_pos"] ; + jsonData["ionization_mode_negative"] = molecule_ionization["mode_neg"] ; + jsonData["peaklists"] = [self.jsonPeaksList] ; + } else if (self.is_ms2()) { + jsonData["analyzer"] = self.jsonAnalyzer; + var molecule_ionization = self.jsonMolIonization; + jsonData["ionization_mode_positive"] = molecule_ionization["mode_pos"] ; + jsonData["ionization_mode_negative"] = molecule_ionization["mode_neg"] ; + if (self.jsonMolIonBeam != null) { + jsonData["ion_beam_storage"] = self.jsonMolIonBeam["ion_beam_storage"]; + } + jsonData["peaklists"] = [self.jsonPeaksList] ; + } + jsonData["other_metadata"] = self.jsonOtherMetadata; + return jsonData; + }, + + //USED IN HTML + pickChemicalCompound: function() { + var self = this ; + self.singlePick = true; + $("#modalPickCompound-{{ TAB_INDEX_PLACEHOLDER }}").modal("show"); + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").focus(); + }, + + //USED HERE + pickChemicalCompound4Mix: function(rowNumber) { + var self = this ; + self.singlePick = false; + self.multiPickLine = rowNumber; + $("#modalPickCompound-{{ TAB_INDEX_PLACEHOLDER }}").modal("show"); + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").focus(); + }, + + //USED HERE + searchAjax: function() { + var self = this ; + var results ; + var rawQuery = $('#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}').val(); + if (rawQuery.length > 2) { + return [] ; + } + results = [] ; + $.ajax({ + type: "post", + url: "{{ PF_URL_PLACEHOLDER }}/webapp/search", + dataType: "json", + async: false, + data: "query=" + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").val(), + success: function(json) { + if (json.success) { + $.each(json.compoundNames, function(){ + results.push(this.name) ; + }) ; + $.each(json.compounds, function(){ + if (this.inChIKey.indexOf(rawQuery)) { + results.push(this.inChIKey) ; + } + }) ; + } + }, + error : function(xhr) { + self.subjects = [] ; + console.log(xhr) ; + } + }) ; + return results ; + }, + + //USED HERE + searchLocalCompound: function() { + var self = this ; + $("#load-step-1-{{ TAB_INDEX_PLACEHOLDER }}").show(); + $.ajax({ + type: "get", + url: "{{ PF_URL_PLACEHOLDER }}/rest/v2/compounds", + async: true, + data: "limit=1&query=" + $('#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}').val() + "&query_filter=" + self.fitlerSearchLoadlCpd+"&token={{ PF_TOKEN_PLACEHOLDER }}", + success: function(data) { + data = data[0] ; + var id = parseInt(data["id"]) ; + var name = data["name"] ; + var inchikey = data["inchikey"] ; + var inchi = data["inchi"] ; + data = ` +
+ + + + + + + + + + + + + + + + + +
Chemical Name Monoisotopic Mass Formula Structure
+ ${name} +
${inchikey} +
${data["exactMass"]}${data["formula"]} + ${name} + +
+ *: Generic Compounds (abstract "flat" compound without (+) or (-) center). + <` + "script" + ` type="text/javascript"> + $("#tabPickCpd-{{ TAB_INDEX_PLACEHOLDER }}").tablesorter(); + $.each($(self.prefix+".compoundFormula"), function(id, elem) { + var rawFromula = $(elem).text(); + var formatedFormula = rawFromula; + try { + $.each($.unique( rawFromula.match(/\d+/g)), function(keyF, valF) { + var re = new RegExp(valF,"g"); + formatedFormula = formatedFormula.replace(re, "" + valF + ""); + }); + } catch (e){} + formatedFormula = formatedFormula.replace("", ""); + $(elem).html(formatedFormula); + }); + $.each($(self.prefix+".compoundMass"), function(id, elem) { + var exactMass = parseFloat( $(elem).text()); + exactMass = roundNumber(exactMass,7) + $(elem).html(exactMass); + }); + + +
+ <` + "script" + ` type="text/javascript"> + var listOfRefCompoundsMatch = null; + + loadCompoundInForm = function(id, inchikey, inchi, composition, exactMass, type) { + if (ctx().modeEditSpectrum) { + var name = $("#cpt-load-name-" + id + "-{{ TAB_INDEX_PLACEHOLDER }}").html(); + if (ctx().multiPickLine >= 0) { + ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 0, name); + // ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 1, inchikey); + + // restet form + setTimeout(function(){ + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#ok-step-1-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + }, 200); + // img + var typeS = "chemical"; + if (type == 100) + typeS = "generic"; + else if (type == 101) + typeS = "chemical"; + // ''+name+'' + var currentCpt = { + "name": name, + "type": typeS, + "concentration": "?", + "inchikey": inchikey + }; + updatedCpdMixData[name] = currentCpt; + } + // display + $("#modalPickCompound-{{ TAB_INDEX_PLACEHOLDER }}").modal("hide"); + $("#modalEditSpectrum-{{ TAB_INDEX_PLACEHOLDER }} .modal-dialog").show(); + return; + } // else: add one spectrum + var name = $("#cpt-load-name-" + id + "-{{ TAB_INDEX_PLACEHOLDER }}").html(); + if (ctx().singlePick) { + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val(inchikey); + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-sample-inchi-{{ TAB_INDEX_PLACEHOLDER }}").val(inchi); + $("#add1spectrum-sample-inchi-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-sample-commonName-{{ TAB_INDEX_PLACEHOLDER }}").val(name); + $("#add1spectrum-sample-commonName-{{ TAB_INDEX_PLACEHOLDER }}").change(); + + $("#importspectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val(inchikey); + $("#importspectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").change(); + } else if (ctx().multiPickLine >= 0) { + ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 0, name); + ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 1, inchikey); + ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 2, composition); + ctx().hot_RCC_ADDED.setDataAtCell(ctx().multiPickLine, 4, exactMass); + // restet form + setTimeout(function(){ + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#ok-step-1-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + }, 200); + } + var typeS = "chemical"; + if (type == 100) + typeS = "generic"; + else if (type == 101) + typeS = "chemical"; + if (ctx().singlePick) + $("#sample-bonus-display-{{ TAB_INDEX_PLACEHOLDER }}").html(''+name+''); + else { + // delete + $(ctx().prefix+"img.mixRCCadd"+ctx().multiPickLine).remove(); + // add + $("#sample-bonus-display-{{ TAB_INDEX_PLACEHOLDER }}").append(''+name+''); + $(ctx().prefix+"img.mixRCCadd"+ctx().multiPickLine+"").mouseenter(function() { + $(this).removeClass("compoundSVGZoom"); + }).mouseleave(function() { + $(this).addClass("compoundSVGZoom"); + }); + } + $("#modalPickCompound-{{ TAB_INDEX_PLACEHOLDER }}").modal("hide"); + } + ` ; + $("#ok-step-1-{{ TAB_INDEX_PLACEHOLDER }}").html(data); + }, + error : function(xhr) { + // log + console.log(xhr); + // error + $("#ok-step-1-{{ TAB_INDEX_PLACEHOLDER }}").html("Error: could not process request."); + } + }).always(function() { + $("#load-step-1-{{ TAB_INDEX_PLACEHOLDER }}").hide(); + }); + }, + + //USED HERE + getRCCADDED: function() { + var self = this ; + jsonRCC_ADDED = []; + $.each(self.hot_RCC_ADDED.getData(), function(){ + var formatData = {}; + if ("InChIKey" in this && this["InChIKey"]!= undefined && this["InChIKey"] != "") { + jsonRCC_ADDED.push(this["InChIKey"]); + } + }); + return jsonRCC_ADDED; + }, + + //USED HERE + getRCCADDEDConcentration: function() { + var self = this ; + jsonRCC_ADDED = []; + $.each(self.hot_RCC_ADDED.getData(), function(){ + var formatData = {}; + if ("InChIKey" in this && this["InChIKey"]!= undefined && this["InChIKey"] != "") { + jsonRCC_ADDED.push(this["concentration (µg/ml)"]); + } + }); + return jsonRCC_ADDED; + }, + + //USED IN HTML + clearLine: function() { + var self = this ; + // restet form + setTimeout(function(){ + $("#add-one-cc-s1-value-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#ok-step-1-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + }, 200); + $(self.prefix+"img.mixRCCadd"+self.multiPickLine).remove(); + if (self.singlePick) { + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#add1spectrum-sample-inchikey-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-sample-inchi-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#add1spectrum-sample-inchi-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#add1spectrum-sample-commonName-{{ TAB_INDEX_PLACEHOLDER }}").val(""); + $("#add1spectrum-sample-commonName-{{ TAB_INDEX_PLACEHOLDER }}").change(); + $("#sample-bonus-display-{{ TAB_INDEX_PLACEHOLDER }}").html(""); + } else if (self.multiPickLine >= 0) { + for(var i = 0 ; i < 6 ; i += 1) { + self.hot_RCC_ADDED.setDataAtCell(self.multiPickLine, i, ""); + } + } + }, + + exit: function() { + $.ajax({type: "get", url: "/quit", async: true, success: ()=>window.close()}); + }, + +} ; + +$.ajax({ + type: "get", + url: "{{ PF_URL_PLACEHOLDER }}/webapp/get-cpd-data?token={{ PF_TOKEN_PLACEHOLDER }}", + data: "inchikey=" + "{{ INCHIKEY_PLACEHOLDER }}", + dataType: "json", + success: function(data) { + if (data.success) { + var self = context_{{ TAB_INDEX_PLACEHOLDER }} ; + console.log(`inchikey {{ INCHIKEY_PLACEHOLDER }} found!!`) + inchidata["{{ INCHIKEY_PLACEHOLDER }}"] = data ; + self.init() ; + self.fitlerSearchLoadlCpd = 5; + self.inchikey = null; + all_contexts.push(self) ; + } else { + no_success( + {{ TAB_INDEX_PLACEHOLDER }}, + "{{ INCHIKEY_PLACEHOLDER }}", + {{ DEFAULT_DATA }}["name"] + ) ; + } + }, + error : function(data) { + no_success( + {{ TAB_INDEX_PLACEHOLDER }}, + "{{ INCHIKEY_PLACEHOLDER }}", + {{ DEFAULT_DATA }}["name"] + ) ; + } +}).always(() => null); diff -r 000000000000 -r b58b229c4cbf common.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common.js Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,195 @@ + +this.ctx = () => context; +var all_contexts = [] ; +var inchidata = {} ; +var all_mix_data = {} ; +function no_success(tab_index, inchi, data) { + console.log(`inchikey ${inchi} not found...`) ; + console.log(`disabling ${data} ...`) + disable_tab( + tab_index, + "red", + "This compound has not been found on peakforest" + ) ; +} + +function disable_tab(tab_index, color, title) { + var element = $(`#open_tab_${tab_index}`) ; + element.attr("disabled", "disabled").off("click"); + element.attr("onclick", null) ; + element.attr("title", title) ; + element.attr("data-toggle", null) ; + element.attr("href", null) ; + element.css("color", color) ; + element.css("cursor", "not-allowed") ; +} + +function send_everything_to_peakforest(url, token) { + var bundles ; + if (context.is_mix()) { + bundles = [all_mix_data] ; + } else { + bundles = create_dataset_bundles() ; + } + bundles.forEach((bundle, index) => { + console.log(bundle) + $.ajax({ + type: "post", + url: `${url}/rest/v2/spectrum?token=${token}`, + data: JSON.stringify(bundle), + contentType: "application/json" + }) + }) + // console.log(bundles) +} + +function create_dataset_bundles() { + var bundles = [] ; + var data ; + all_contexts.forEach((context, index) => { + if ((data = context.sent_json) === null) { + return ; + } + if (bundles.length === 0) { + // console.log("First metadata!") + return bundles.push(data) ; + } + if (merge_in_bundle(bundles, data)) { + // console.log("Merged!") + } else { + // console.log("New metadata!") + } + }) ; + return bundles ; +} + +function merge_in_bundle(bundles, data) { + for(var i = 0 ; i < bundles.length ; i += 1) { + if ( + identical(bundles[i]["sample"], data["sample"]) + && identical(bundles[i]["chromatography"], data["chromatography"]) + && identical(bundles[i]["analyzer"], data["analyzer"]) + && identical(bundles[i]["ionization_mode_positive"], data["ionization_mode_positive"]) + && identical(bundles[i]["ionization_mode_negative"], data["ionization_mode_negative"]) + && identical(bundles[i]["other_metadata"], data["other_metadata"]) + ) { + bundles[i]["peaklists"].push(data["peaklists"][0]) ; + return true ; + } else { + continue ; + console.log( + "sample: " + + identical(bundles[i]["sample"], data["sample"]) + ) + console.log( + "chromatography: " + + identical(bundles[i]["chromatography"], data["chromatography"]) + ) + console.log( + "analyzer: " + + identical(bundles[i]["analyzer"], data["analyzer"]) + ) + console.log( + "ionization_mode_positive: " + + identical(bundles[i]["ionization_mode_positive"], data["ionization_mode_positive"]) + ) + console.log( + "ionization_mode_negative: " + + identical(bundles[i]["ionization_mode_negative"], data["ionization_mode_negative"]) + ) + console.log( + "other_metadata: " + + identical(bundles[i]["other_metadata"], data["other_metadata"]) + ) + } + } + bundles.push(data) ; + return false ; +} + +function identical(left, right) { + if (typeof left !== typeof right) { + return false ; + } + if (left === null) { + return right === null ; + } + if (right === null) { + return left === null ; + } + switch (typeof left) { + case "array": + return identical_array(left, right) ; + break ; + case "object": + return identical_object(left, right) ; + break ; + default: + break ; + } + return (left === right) +} + +function identical_array(left, right) { + if (right.length !== left.length) { + return false ; + } + for(var i = 0 ; i < left.length ; i += 1) { + if (!identical(left[i], right[i])) { + return false ; + } + } + return true ; +} + +function identical_object(left, right) { + var left_keys ; + + if (!( + share_keys(left, right) + && share_keys(right, left) + )) { + return true ; + } + left_keys = Object.keys(left) ; + for (var i = 0 ; i < left_keys.length ; i += 1){ + if (!identical(left[left_keys[i]], right[left_keys[i]])) { + return false ; + } + } + return true ; +} + +function share_keys(left, right) { + var left_keys ; + var right_keys ; + + left_keys = Object.keys(left) ; + right_keys = Object.keys(right) ; + for(var i = 0 ; i < left_keys.length ; i += 1) { + if (!right_keys.includes(left_keys[i])) { + return false ; + } + } + return true ; +} + +var set_inchi_data = function(data, tab_index) { + inchidata[data.inchikey] = data ; + $(`#add1spectrum-sample-inchi-${tab_index}`).val(data.inchi); + $(`#add1spectrum-sample-inchi-${tab_index}`).change(); + $(`#add1spectrum-sample-commonName-${tab_index}`).val(data.name); + $(`#add1spectrum-sample-commonName-${tab_index}`).change(); + $(`#sample-bonus-display-${tab_index}`).html( + `${data.name}` + ); +} + +var lightgrayRenderer = function(instance, td, row, col, prop, value, cellProperties) { + Handsontable.renderers.TextRenderer.apply(this, arguments); + td.style.backgroundColor = "#EEE"; +} diff -r 000000000000 -r b58b229c4cbf compound-mix.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compound-mix.html Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,36 @@ +
+
+
+
+
+ +
+
+
+ + Precursor ion (M/Z) + + + +
+
+
+
+
+
\ No newline at end of file diff -r 000000000000 -r b58b229c4cbf compound-ref.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compound-ref.html Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,660 @@ +
+
+
+ +
+
+ + + +
+
+
+ + + + + + +
+ + + +
+ + diff -r 000000000000 -r b58b229c4cbf config.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config.yml Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,250 @@ +## +## when you see {{ something }} in a string, this means the string is +## a template, and the "{{ something }}" will be replaced by its value +## at runtime. +## This is usefull to build strings from other strings. +## to reference an item in a tree, you can use dots as branches: +## {{ parameters.flags.help }} +## will be extrapolated to "Show this help" +## +## But beware: +## {{ parameters.mandatory }} +## will be extrapolated to +## "{'input': 'input file path'}" +## + +## this config is used for debug. +## it allows to define debug options before everything else is parsed +__meta_config__: + __debug__: False + __debug_stream__: stderr + __only_root_debug__: False + + +## the cli parameters +parameters: + mandatory: + ## input is mandatory + input: input file path + flags: + ## help, verbose and version can be provided with no parameter. + help: Show this help + verbose: More verbose outputs + version: Show this tool's version + debug: show debug outputs + do_run_dry: Runs the whole process, without the server. Usefull for tests. + embed_js: Embed js in html file instead of using a separated js file. + firefox: Open firefox on the web page. + chromium: Open chromium or chrome on the web page. + optional: + ## these optional parameters need a value "--opt value --opt2 value2" + method: "default is {{ defaults.method }}" + spectrum_type: "default is {{ defaults.spectrum_type }}" + sample_type: "default is {{ defaults.sample_type }}" + resolution: "default is {{ defaults.resolution }}" + resolution: "default is {{ defaults.resolution }}" + name: The precursor name + peakforest.url: "default={{ defaults.peakforest.url }}" + peakforest.token: The token to comunicate with peakforest api + polarity: positive|negative + raw_metadata: example - 1-1__INCHIKEY__=QNAYBMKLOCPYGJ-REOHCLBHSA-N_L-Alanine_MS_POS_plasma_RT__=0.84_filtree.csv + scan_type: ms|msms|rmn + run_dry_html: when "--run-dry", provides the output directory for {{ generated.html }} + run_dry_js: when "--run-dry", provides the output directory for {{ generated.js }} + raw_metadata_sep: "raw metadata separator" + logging.std: "Either out, err, or anything else to not output" + logging.file.path: "The file path to output logs to" + validation: "Set the default validation to the provided value, TRUE or FALSE." + output_json: "Provide a path to output a JSON file." + meta: + ## meta info about the tool itself + author: Lain Pavot + version: 1.1.0 + shortcuts: + ## to define things like: "we can use -p instead of --polarity" + peakforest.token: t + polarity: p + help: h + version: v + verbose: V + debug: d + logging.std: l + +## some default parameters +## logging defines two elements: std and file. +## std should be either empty, err or out. +## it tells where to outputs logs: +## - nowhere (empty value) +## - in sterr (err) +## - in stdout (out) +## and file. Id a path is provided, add outputs to this file. +## if append is true, outputs are appended to the file. +## otherwise, the file is emptied each time the app runs. +defaults: + peakforest: + url: https://nightly.peakforest.org + token: '' + spectrum_type: LC_MSMS + method: cf_pfem_urine_method1_qtof-msms + # api-msms-fia__idf-cea + # cf_pfem_plasma_method1_qtof-msms + # cf_pfem_urine_method1_qtof-msms + # lc-msms__test + scan_type: ms2 + resolution: high + sample_type: compound-ref + # sample_type: compound-mix + polarity: positive + raw_metadata: '' + name: '' + run_dry_html: + run_dry_js: + raw_metadata_sep: ',' + validation: "TRUE" + verbose: false + debug: true + logging: + std: out ## out || err + file: + path: + append: False + output_json: '' + +## token related info +token: + ## do you use a file to store your token? + use_file: false + ## if so, what path the file is located at? + file_path: .token + ## if not, you can provide you token here + value: + +network: + ip: 0.0.0.0 + port: 8000 + +workdir: + ## create a tmp directory + create_tmp: true + ## works in the created tmp directory, or if not created, in /tmp + work_in_tmp: true + ## generate outputs in the created tmp directory, or if not created, in /tmp + generate_in_tmp: true + +## the templates paths +templates: + ## meta is what wrapps the whole page. + main: meta.html + main_mix: meta-compound-mix.html + main_ref: meta-compound-ref.html + ## form is one instance of a pf form + # form: form.html + # form: compound-ref.html + form: form.html + form_mix: compound-mix.html + form_ref: compound-ref.html + ## one item of the tab list + tab_list: tab_list.html + ## the js for one form + js: add-one-spectrum-index.js + ## placeholders for the html templates. + ## this will not change the placeholders syntax for this file. + placeholders: + start: "{{ " + stop: " }}" + +generated: + ## what filename to give to the whole html file + html: pf.html + ## what filename to give to js files + js: add-one-spectrum-{{ index }}.js + +regex: + values: + ## reuse these smol regex in bigger regex! + spectrum_type: "NMR|LC_MS|LC_MSMS|MRM(_\\d+)?" + matrix: "[Uu]rine|[Pp]lasma|[Pp]las" + mode: "POS|NEG" + energy: "\\d+ev" + pool: "[Pp]ool\\d+" + rt: "\\d+\\.\\d+" + runs: "\\d+-\\d+" + inchikey: "[A-Z]{14}-[A-Z]{10}-[A-Z]" + + ## the "INCHIKEY" word + ## one or more underscores + ## may be followed by a equal sign + ## captures in the "inchikey" variable: + ## 14, 10 and 1 letters + ## in caps + ## separated by a hyphen + inchikey: "INCHIKEY_+=?(?P{{ regex.values.inchikey }})" + + ## method is one of values defined bellow, between underscores + spectrum_type: "_(?P{{ regex.values.method }})_" + + ## matrix is one of values defined bellow, between underscores + matrix: "_(?P{{ regex.values.matrix }})_" + + ## pool is one of values defined bellow, between underscores + pool: "_(?P{{ regex.values.pool }})_" + + ## molecule everything between inchikey and method. + molecule: "{{ regex.inchikey }}_(?P.*?){{ regex.method }}" + + ## mode is one of values defined bellow, between underscores + mode: "_(?P{{ regex.values.mode }})_" + + ## energy is one of values defined bellow, between underscores + energy: "_(?P{{ regex.values.energy }})_" + + ## - A underscore, + ## - the "RT" word, + ## - some underscore(s), + ## - an optional interrogation mark, + ## - the actual RT value is captured here, + ## - there is a underscore at the end + rt: "_RT_+=?(?P{{ regex.values.rt }})_" + + ## "runs" is at the beginning, and ends with an underscore. + runs: "^(?P{{ regex.values.runs }})_" + + + ## BEGIN + ## anything + ## the inchikey + ## anything else can follow + ## END + # fragnot: ^.*{{ regex.inchikey }}.*$ + + + ## This is the most exhaustive regex I came with to extract info from + ## fragnot files name. + # fragnot: + # ^ + # .* (?# there may be anything at the begining) + # (?P\d+-\d+) (?# the run numbers) + # _+ (?# followed by anything - underscores usualy) + # INCHIKEY_+=?(?P{{ regex.inchikey }}) (?# we insert inchikey regex here - see above) + # _+ (?# there is one or more underscores) + # (?P.*?) (?# the molecule name follows the inchikey) + # _+ (?# there is one or more underscores) + # (?P{{ regex.method }}) (?# then, there is the method - nmr, ms or mrm???) + # _+ (?# there may be some underscores to separate) + # (?P{{ regex.matrix }})? (?# the matrix - urine or plasma) + # _* (?# there may be some underscores to separate) + # (?PPOS|NEG) (?# the acq mode - pos or neg) + # _+ (?# there may be some underscores to separate) + # (?P{{ regex.pool }})? (?# the pool - "Pool"+numbers, optional) + # _* (?# there may be some underscores to separate) + # (?P\d+ev)? (?# the energy - only for nmr, so it's optional) + # _* (?# there may be some underscores to separate) + # (?P{{ regex.pool }})? (?# the pool - sometimes the pool if *after* the energy...) + # _* (?# there may be some underscores to separate) + # (?P{{ regex.matrix }})? (?# the matrix is here, sometimes) + # _* (?# there may be anything here) + # RT_+=?(?P\d+\.\d+) (?# the retension time is a decimal number) + # _* (?# there may be anything at the end) + # (?P[fF]iltree)? (?# sometimes, "Filtree" appears, lets capture it) + # \.[ct]sv (?# the extension) + # $ \ No newline at end of file diff -r 000000000000 -r b58b229c4cbf macros.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/macros.xml Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,202 @@ + + 1.1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + +
\ No newline at end of file diff -r 000000000000 -r b58b229c4cbf meta-compound-mix.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/meta-compound-mix.html Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,1272 @@ + + + + + + + + PeakForest MetaboHub + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +
+
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+
+
+ + +
+ + +
+ + + + {{ EMBED_JS }} + + + \ No newline at end of file diff -r 000000000000 -r b58b229c4cbf meta-compound-ref.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/meta-compound-ref.html Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,112 @@ + + + + + + + + PeakForest MetaboHub + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ +
+ {{ ADD_SPECTRUM_FORM }} +
+
+
+ + +
+ + +
+ + + + + {{ EMBED_JS }} + + + \ No newline at end of file diff -r 000000000000 -r b58b229c4cbf ms2pf_it.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ms2pf_it.xml Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,144 @@ + + + adds you MS spectrum to peakforest. + + + 0 + macros.xml + + + python + pyyaml + + + + 8000 + / + + + + + + +@MS2PF_COMMON_CMD@ + + + + + + + + do_output_json + + + + + + + + diff -r 000000000000 -r b58b229c4cbf server.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server.py Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,1120 @@ +#!/usr/bin/env python3 + +import atexit +import csv +import http.server +import json +import logging +import os +import re +import shutil +import socketserver +import sys +import tempfile +import yaml + +TAB_LIST_PLACEHOLDER = "TAB_LIST_PLACEHOLDER" +MS_PEAK_VALUES_PLACEHOLDER = "MS_PEAK_VALUES_PLACEHOLDER" +COMPOUND_NAME_PLACEHOLDER = "COMPOUND_NAME_PLACEHOLDER" +TAB_INDEX_PLACEHOLDER = "TAB_INDEX_PLACEHOLDER" +EMBED_JS_PLACEHOLDER = "EMBED_JS" +ACTIVE_TAB_PLACEHOLDER = "ACTIVE_TAB_PLACEHOLDER" +ADD_SPECTRUM_FORM = "ADD_SPECTRUM_FORM" +PRODUCE_JSON_PLACEHOLDER = "PRODUCE_JSON_PLACEHOLDER" + +COMPOUND_REF = "compound-ref" +COMPOUND_MIX = "compound-mix" + +END_MS_PEAK_VALUES_PLACEHOLDER = " ]" +MS_DATA_COLUMN_NUMBER = 9 +DEFAULT_MS_PEAK_VALUES = ( + "[\n" + + (" [" + ','.join([' ""'] * MS_DATA_COLUMN_NUMBER) + "],\n") * 17 + + END_MS_PEAK_VALUES_PLACEHOLDER +) + +FRAGNOT_HEADER = { + "m/z": "fragment_mz", + "absolute_intensity": "abs_intensity", + "relative_intensity": "rel_intensity", + "theo_mass": "", + "delta_ppm": "ppm", + "rdbequiv": "", + "composition": "", + "attribution": "fragment", +} + +MS_2_SNOOP_HEADER = { + "name": str, + "inchikey": str, + "composition": str, + "fragment": str, + "fragment_mz": str, + "ppm": str, + "fileid": str, + "correlation": str, + "abs_intensity": lambda x:float(x) * 100, + "rel_intensity": lambda x:float(x) * 100, + "valid_corelation": str +} + + +class ConfigException(ValueError): + """ + An exception raised when something went wrong in the config and we + cannot continue - i.e: when there's no token for peakforest + """ + +class YAMLConfig(dict): + + """ + Dictionary that handles key with dot in them: + test["truc.chose"] + is equivalant to + test["truc"]["chose"] + Assignation works too. + Add the possibility to use placeholders: + --- yaml + test: {{ truc.chose }} + truc: + chose: bidule + --- + here, test's value is "bidule" + """ + + def __init__(self, *args, **kwargs): + meta_conf = kwargs.pop("__meta_config__", {}) + self._debug = meta_conf.get("__debug__", False) + self._stream_name = meta_conf.get("__debug_stream__", "stdout") + self._debug_stream = getattr(sys, self._stream_name) + self._only_root_debug = meta_conf.get("__only_root_debug__", False) + if "__root__" in kwargs: + if self._only_root_debug: + self._debug = False + self._name = kwargs.pop("__name__") + self._debugger("Is not root config.") + self._root = kwargs.pop("__root__") + else: + self._name = "root" + self._debugger("Is root config.") + self._root = self + super().__init__(*args, **kwargs) + for key, value in self.copy().items(): + if isinstance(value, dict) and not isinstance(value, YAMLConfig): + self._debugger(f"Parsing sub-config for {key}") + self[key] = self._propagate(value, key) + self._replace_placeholders(self) + self._extract_defaults() + + def _propagate(self, sub_dict, name): + if isinstance(sub_dict, dict) and not isinstance(sub_dict, self.__class__): + return YAMLConfig( + **sub_dict, + __name__=name, + __root__=self._root, + __meta_config__={ + "__debug__": self._debug, + "__debug_stream__": self._stream_name, + "__only_root_debug__": self._only_root_debug, + } + ) + return sub_dict + + def _debugger(self, message): + if self._debug: + self._debug_stream.write(f"[{self._name}]: {message}\n") + self._debug_stream.flush() + + def __getattr__(self, attr): + if attr in self: + return self[attr] + if '.' in attr: + attr, sub = attr.split('.', 1) + return getattr(getattr(self, attr), sub) + return super().__getattribute__(attr) + + def _replace_placeholders(self, subpart): + self._debugger("Replacing placeholders...") + for sub_key, sub_item in subpart.copy().items(): + if isinstance(sub_item, str): + for placeholder in re.findall("{{ (?P.*?) }}", sub_item): + if placeholder not in self._root: + self._debugger(f"Could not fine replacement for {placeholder}") + continue + replacement = self._root[placeholder] + if isinstance(replacement, str): + self._debugger(f"Found placeholder: {placeholder} -> {replacement}") + sub_item = sub_item.replace( + "{{ " + placeholder + " }}", + replacement + ) + else: + self._debugger(f"Found placeholder: {placeholder} -> {replacement.__class__.__name__}") + sub_item = self._propagate(replacement, placeholder) + dict.__setitem__(subpart, sub_key, sub_item) + elif isinstance(sub_item, dict): + super().__setitem__(sub_key, self._propagate(sub_item, sub_key)) + + def _extract_defaults(self): + if self._root is not self: + return + if "defaults" not in self: + self._debugger("No defaults here.") + return + if "arguments" not in self: + self._debugger("Arguments creation...") + self["arguments"] = self._propagate({}, "arguments") + self._debugger("Populating arguments with defaults values") + for key, value in self.defaults.items(): + if key not in self: + if isinstance(value, dict): + value = self._propagate(value, key) + self.arguments[key] = value + self._debugger(f"Default {key} = {value}") + + def __setitem__(self, key, value): + if isinstance(value, dict): + value = self._propagate(value, key) + if "." not in key: + return super().__setitem__(key, value) + curent = self + key, subkey = key.rsplit(".", 1) + self[key][subkey] = value + + def __getitem__(self, key): + if super().__contains__(key): + return super().__getitem__(key) + if "." not in key: + return super().__getitem__(key) + curent = self + while "." in key: + key, subkey = key.split(".", 1) + curent = curent[key] + key = subkey + if subkey not in curent: + curent[subkey] = self._propagate({}, subkey) + result = curent[subkey] + return result + + def __contains__(self, key): + if "." not in key: + return super().__contains__(key) + key, subkey = key.split(".", 1) + if not super().__contains__(key): + return False + return subkey in self[key] + + def copy(self): + return { + key: ( + value if not isinstance(value, dict) + else value.copy() + ) for key, value in self.items() + } + +class YAMLParameters(YAMLConfig): + + """ + Parses parameters from the command line and put them + in the config. + Uses the config to know which parameter is recognized, or not, + to know the metadata (author, version), + which command is a flag, is optional, the help strings, etc... + Assigns default small parameter if not defined in the "shortcut" + section of the config file. + CLI config must be in the root section "parameters": + --- + parameters: + mandatory: + input: input file path + flags: + help: Show this help + optional: + method: "default is {{ defaults.method }}" + meta: + author: Lain Pavot + version: 1.1.0 + shortcuts: + help: h + ## will autogenerate -i for input and -m for method + --- + default parameters are searched in the "default" root section. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._errors = list() + if not self.parameters.shortcuts: + self.parameters["shortcuts"] = YAMLConfig() + self._mandatory = self.parameters.mandatory + self._optional = self.parameters.optional + self._flags = { + flag: False + for flag in self.parameters.flags + } + self._all_params = self._optional.copy() + self._all_params.update(self._mandatory) + self._all_params.update(self._flags) + self._small_params = dict() + self._determine_small_params() + + @property + def in_error(self): + return bool(self._errors) + + @property + def sorted_keys(self): + return sorted(self._all_params.keys()) + + @property + def sorted_items(self): + return sorted(self._all_params.items()) + + def _determine_small_params(self, verbose=False): + self._small_params = (self.parameters.shortcuts or {}).copy() + chars = list(map(chr, range(97, 123))) + list(map(chr, range(65, 91))) + all_params = self._all_params.copy() + for long, short in self._small_params.items(): + chars.remove(short) + del all_params[long] + for param in all_params.copy().keys(): + for operation in ( + lambda x:x[0], ## select first char + lambda x:x.split('-', 1)[-1][0], ## first char after - + lambda x:x.split('_', 1)[-1][0], ## first char after _ + lambda x:x.split('.', 1)[-1][0], ## first char after . + lambda x:x[0].upper(), ## select first char + lambda x:x.split('-', 1)[-1][0].upper(), ## first char after - + lambda x:x.split('_', 1)[-1][0].upper(), ## first char after _ + lambda x:x.split('.', 1)[-1][0].upper(), ## first char after . + lambda x: chars[0], ## first letter in the alphabet + ): + char = operation(param) + if char not in self._small_params.values(): + self._small_params[param] = char + chars.remove(char) + del all_params[param] + break + + def _get_parameter_index(self, parameter, original): + if f"--{parameter}" in sys.argv: + return sys.argv.index(f"--{parameter}") + parameter = self._small_params[original] + if f"-{parameter}" in sys.argv: + return sys.argv.index(f"-{parameter}") + return None + + def as_parameter(self, string): + return ( + string + .replace('.', '-') + .replace('_', '-') + ) + + def show_version(self): + print(self.parameters.meta.version) + + def show_help(self): + parameters = [ + f"-{self._small_params[arg]}|--{self.as_parameter(arg)} {arg}" + for arg in self._mandatory + ] + [ + f"[-{self._small_params[arg]}|--{self.as_parameter(arg)} {arg}]" + for arg in self._optional + ] + [ + f"[-{self._small_params[arg]}|--{self.as_parameter(arg)}]" + for arg in self._flags + ] + print( + f"Usage: {__file__} " + ' '.join(parameters) + + "\n\n" + + '\n'.join( + f" -{self._small_params[args]}|--{self.as_parameter(args)}: {help_str}" + for args, help_str in self.sorted_items + ) + + "\n\n" + + '\n'.join( + f"{key}: {value}" + for key, value in self.parameters.meta.items() + ) + ) + sys.exit(0) + + def parse_args(self): + errors = list() + for kind in ("mandatory", "optional", "flags"): + keys = list(sorted(getattr(self, f"_{kind}").keys())) + for original_param, actual_param in zip( + keys, + map(self.as_parameter, keys), + ): + if original_param in self.defaults: + self.arguments[original_param] = self.defaults[original_param] + elif kind == "flags": + self.arguments[original_param] = False + parser = getattr(self, f"parse_{kind}") + if (error := parser(original_param, actual_param)): + errors.append(error) + self._errors = errors + return self + + def parse_mandatory(self, original, actual): + if (index := self._get_parameter_index(actual, original)) is None: + return f"The parameter --{actual} is mandatory." + if index == len(sys.argv) - 1: + return f"The parameter --{actual} needs a value." + self.arguments[original] = sys.argv[index + 1] + + def parse_optional(self, original, actual): + if (index := self._get_parameter_index(actual, original)) is None: + return + if index == len(sys.argv) - 1: + return f"The parameter --{actual} needs a value." + self.arguments[original] = sys.argv[index + 1] + + def parse_flags(self, original, actual): + if (index := self._get_parameter_index(actual, original)) is None: + return + self.arguments[original] = True + +def parse_config(**kwargs): + """ + opens the config file, extract it using pyyaml's safe loader + and tries to extract and apply a maximum of informations/directives + from the config: + - token retrieval + - workdir management + - tempfile management + """ + root_dir = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(root_dir, "config.yml")) as config_file: + config = YAMLConfig( + **yaml.load(config_file.read(), Loader=yaml.SafeLoader), + **kwargs + ) + + if not config.token.value: + if config.token.use_file: + if (not os.path.exists(path := config.token.file_path)): + raise ConfigException("Missing token value or token file.") + with open(path) as token_file: + config.token["value"] = token_file.read() + elif config.defaults.peakforest.token: + config.token["value"] = config.defaults.peakforest.token + + if config.workdir.create_tmp: + tmp_dir = tempfile.mkdtemp() + atexit.register(lambda:shutil.rmtree(tmp_dir)) + else: + tmp_dir = tempfile.gettempdir() + config.workdir["tmp_dir"] = tmp_dir + + config["root_dir"] = root_dir + config["tab_list"] = [] + config["form_template"] = os.path.join(root_dir, config.templates.form) + config["meta_template"] = os.path.join(root_dir, config.templates.main) + config["js_template"] = os.path.join(root_dir, config.templates.js) + config["tab_list_template"] = os.path.join(root_dir, config.templates.tab_list) + config["placeholders"] = dict() + config.placeholders[MS_PEAK_VALUES_PLACEHOLDER] = DEFAULT_MS_PEAK_VALUES + config.placeholders[TAB_INDEX_PLACEHOLDER] = "1" + config.placeholders[ACTIVE_TAB_PLACEHOLDER] = "active" + config.placeholders[ADD_SPECTRUM_FORM] = "" + config.placeholders[EMBED_JS_PLACEHOLDER] = "" + config.placeholders[TAB_LIST_PLACEHOLDER] = "" + config.placeholders["DEFAULT_MIN_MZ"] = "50" + config.placeholders["DEFAULT_MAX_MZ"] = "500" + config.placeholders["DEFAULT_RESOLUTION_LOW"] = "" + config.placeholders["DEFAULT_RESOLUTION_HIGH"] = "selected=\"selected\"" + config.placeholders["DEFAULT_RESOLUTION_UNSET"] = "" + config.placeholders["DEFAULT_MIN_RT"] = "0.9" + config.placeholders["DEFAULT_MAX_RT"] = "1.4" + return config + +def parse_parameters(config): + """ + parses command line and checks provided values are acceptable/usable. + Raises some error if not. + """ + parameters = YAMLParameters(**config) + parameters.parse_args() + + parameters["json_result"] = [] + + get_logger(parameters) + + arguments = parameters.arguments + if arguments.help: + parameters.show_help() + sys.exit(0) + + if arguments.version: + parameters.show_version() + sys.exit(0) + + if parameters.in_error: + raise ValueError( + "Some errors occured during parameters extraction: \n" + + '\n'.join(parameters.errors) + ) + + if arguments.sample_type == COMPOUND_MIX: + parameters["form_template"] = os.path.join( + parameters["root_dir"], + parameters.templates.form_mix + ) + parameters["meta_template"] = os.path.join( + parameters["root_dir"], + parameters.templates.main_mix + ) + elif arguments.sample_type == COMPOUND_REF: + parameters["form_template"] = os.path.join( + parameters["root_dir"], + parameters.templates.form_ref + ) + parameters["meta_template"] = os.path.join( + parameters["root_dir"], + parameters.templates.main_ref + ) + + arguments["produce_json"] = ( + "output_json" in arguments + and arguments["output_json"] != "" + ) + if arguments.produce_json: + parameters.placeholders[PRODUCE_JSON_PLACEHOLDER] = "true" + parameters.json_result = [] + arguments["output_json"] = os.path.abspath(arguments["output_json"]) + atexit.register(save_json, parameters) + else: + parameters.placeholders[PRODUCE_JSON_PLACEHOLDER] = "false" + + if arguments.run_dry_html: + arguments["do_run_dry"] = True + parameters.generated["html"] = os.path.abspath(arguments.run_dry_html) + + if arguments.run_dry_js: + arguments["do_run_dry"] = True + parameters.generated["js"] = os.path.abspath(arguments.run_dry_js) + + if arguments.do_run_dry: + parameters.logger.info("Dry run. Server will ne be run.") + if arguments.run_dry_html: + parameters.logger.info(f"HTML file will be put in {arguments.run_dry_html}") + if arguments.run_dry_js: + parameters.logger.info(f"JS file will be put in {arguments.run_dry_js}") + + if arguments.peakforest.token: + config.token["value"] = arguments.peakforest.token + if not config.token.value: + raise ConfigException( + "No token provided. We will not be able to connect to peakforest." + ) + + if os.path.exists(arguments.input): + single_file = True + file_paths = [arguments.input] + else: + path_list = arguments.input.split(',') + if all(map(os.path.exists, path_list)): + single_file = False + file_paths = path_list + else: + raise ValueError( + f"Some files cannot be found: " + + ', '.join( + path for path in path_list + if not os.path.exists(path) + ) + ) + arguments["input"] = list(map(os.path.abspath, file_paths)) + + if single_file: + arguments["name"] = [arguments.name] + arguments["raw_metadata"] = [arguments.raw_metadata] + parameters.logger.info(f"Single file processing: {arguments.input}") + else: + parameters.logger.info(f"Multiple file processing:") + arguments["raw_metadata"] = arguments.raw_metadata.split( + arguments.raw_metadata_sep + ) + if not arguments.name: + arguments["name"] = arguments["raw_metadata"] + else: + arguments["name"] = arguments.name.split(',') + for i in range(len(arguments.name)): + parameters.logger.info(f" - file: {arguments.input[i]}") + parameters.logger.info(f" - name: {arguments.name[i]}") + parameters.logger.info(f" - metadata: {arguments.raw_metadata[i]}") + parameters.logger.info(f" ") + if ( + len(arguments.name) != len(arguments.raw_metadata) + or len(arguments.name) != len(arguments.input) + ): + raise ValueError( + "name, raw_metadata and input parameters have different lengths: \n" + f"input is {len(arguments.input)} elements long, " + f"raw_metadata is {len(arguments.raw_metadata)} elements long " + f"and name is {len(arguments.name)} elements long." + ) + if arguments.spectrum_type == "LC_MS": + arguments["scan_type"] = "ms" + elif arguments.spectrum_type == "LC_MSMS": + arguments["scan_type"] = "ms2" + if arguments.method == "test": + if arguments.spectrum_type == "LC_MS": + arguments["method"] = "cf_pfem_urine_qtof" + else: + arguments["method"] = "cf_pfem_urine_method1_qtof-msms" + if arguments["sample_type"] == COMPOUND_MIX: + check_mix_compound_files(parameters) + more_info_in_logs(parameters) + return parameters + +def check_mix_compound_files(parameters): + arguments = parameters.arguments + try: + numbarz = [ + list(map(int, os.path.basename(metadata).split("_", 1)[0].split("-"))) + for metadata in arguments.raw_metadata + ] + except ValueError: + parameters.logger.error( + "Metadata/file names does not start with `[0-9]+-[0-9]+_.*` . " + "This is necessary in the case of compounds mix." + ) + sys.exit(-1) + runs, samples = zip(*numbarz) + if not all(runs[0] == i for i in runs[1:]): + parameters.logger.error( + "Run numbers in metadata/file names are not identical. " + "You mixed some files." + ) + sys.exit(-1) + length = len(samples) + if list(sorted(samples)) != list(range(1, length+1)): + if not all(samples.count(i) == 1 for i in samples): + parameters.logger.error("Some samples are duplicated. ") + else: + parameters.logger.error("Some samples files are missing. ") + sys.exit(-1) + +def more_info_in_logs(config): + arguments = config.arguments + if arguments.embed_js: + config.logger.info(f"JS will be embed in HTML page to form a HTML bundle.") + else: + config.logger.info(f"JS are separated files, needed to be served.") + config.logger.info(f"Choosen parameters:") + config.logger.info(f" - method: {arguments.method}") + config.logger.info(f" - peakforest instance: {arguments.peakforest.url}") + config.logger.info(f" - polarity instance: {arguments.polarity}") + config.logger.info(f" - spectrum type: {arguments.spectrum_type}") + config.logger.info(f" - scan type: {arguments.scan_type}") + config.logger.info(f" - produce JSON: {arguments.produce_json}") + config.logger.info(f" - sample type: {arguments.sample_type}") + +def process_all_files(config): + """ + for each file and its metadata, read and process them, + then fills the meta html template file with the whole result. + """ + arguments = config.arguments + extra_defaults = [ + process_fragnot_metadata(metadata, config) + for metadata in arguments.raw_metadata + ] + for i, name in enumerate(arguments.name): + extra_defaults[i]["name"] = name + + if not extra_defaults: + extra_defaults = [{}] * len(arguments.input) + + index = 0 + for input_path, extra_default in zip(arguments.input, extra_defaults): + config.logger.info(f"Processing file at {input_path}...") + curent_defaults = arguments.copy() + curent_defaults.update(extra_default) + if config.arguments.verbose: + config.logger.info( + "[VERBOSE] Defaults for curent file: " + + ';'.join(f"{key}={value}" for key, value in curent_defaults.items()) + ) + tsv_content, tsv_data_extractor = read_input(input_path, config) + index = process_tsv( + tsv_content, + tsv_data_extractor, + config, + defaults_data = curent_defaults, + index = index+1, + ) + if arguments.embed_js: + config.logger.info(f"Embeding JS in HTML file... ") + for index in range(len(config.tab_list)): + config.placeholders[EMBED_JS_PLACEHOLDER] += "" + config.placeholders[EMBED_JS_PLACEHOLDER] += "\n" + config.logger.info(f" - add-one-spectrum-{index+1}.js embed.") + config.placeholders[TAB_LIST_PLACEHOLDER] = "\n".join(config.tab_list) + else: + config.placeholders[EMBED_JS_PLACEHOLDER] += "" + config.placeholders[EMBED_JS_PLACEHOLDER] += "\n".join( + [""] + [ + " "*12 + f"" + for index in range(len(config.tab_list)) + ] + ) + config.placeholders[EMBED_JS_PLACEHOLDER] += "\n" + config.placeholders[TAB_LIST_PLACEHOLDER] = "\n".join(config.tab_list) + + fill_template("meta_template", "pf_path", config) + +def fill_template( + template_name, + output_name, + config, + additional_placeholders=dict() +): + """ + Fills a template, replaces the placeholders. + Either outputs the result in a given file, or returns it if path is none. + """ + template_path = config[template_name] + config.logger.debug(f"Filling template {template_name} at {template_path}...") + with open(template_path) as template_file: + template_content = template_file.read() + placeholders = config.placeholders.copy() + placeholders.update(additional_placeholders) + for placeholder, replacement in placeholders.items(): + if not placeholder.startswith(config.templates.placeholders.start): + placeholder = placeholder.join(( + config.templates.placeholders.start, + config.templates.placeholders.stop + )) + template_content = template_content.replace(placeholder, replacement) + if output_name is None: + config.logger.debug(f"Returning template content") + return template_content + output_path = config[output_name] + if "{{ index }}" in output_path: + index_value = additional_placeholders["{{ index }}"] + config.logger.debug(f"Changing index value for {index_value}") + output_path = output_path.replace("{{ index }}", index_value) + config.logger.debug(f"Full output path {output_path}") + with open(output_path, "w") as output_file: + output_file.write(template_content) + +def read_input(input_path, config): + """ + reads a tsv file and determin its processor, based on its header. + """ + with open(input_path) as input_file: + config.logger.info(f"Reading {input_path}...") + tsv_file = csv.reader(input_file, delimiter='\t') + header = next(tsv_file) + tsv_file = list(tsv_file) + config.logger.info(f"Header is: {', '.join(header)}") + if header == list(FRAGNOT_HEADER): + config.logger.info(f"Fragnot recognized.") + processor = fragnot_extractor + return uniformize_fragnot(tsv_file, header), processor + else: + config.logger.info(f"MS2Snoop recognized.") + processor = ms2snoop_extractor + return uniformize_ms2snoop(tsv_file, header), processor + +def uniformize_fragnot(content, header): + """ + sorts fragnot data so they appear always in the same order + """ + return sorted(content, key=lambda x:(float(x[0]), float(x[4]))) + +def uniformize_ms2snoop(content, header): + """ + sorts ms2snoop data so they appear always in the same order + """ + return sorted(content, key=lambda x:(x[0], float(x[4]))) + +def process_fragnot_metadata(raw_metadata, config): + """ + Tries to extract informations from the metadata provided by fragnot + files names. + Heavily based on regex defined in conf file. + """ + regex = config.regex.copy() + del regex["values"] + result = {} + config.logger.info(f"Extracting info from {raw_metadata}...") + count = 0 + for name, expression in regex.items(): + if (match := re.search(expression, raw_metadata)): + result[name] = match[name] + count += 1 + did = "+ did" + else: + did = "- did not" + if config.arguments.verbose: + config.logger.info(f" {did} match {expression}") + config.logger.info(f"{count} useful informations extracted.") + return result + +def process_tsv( + tsv_content, + tsv_data_extractor, + config, + defaults_data={}, + index=1 +): + """ + processes one tsv file, containing one or multiple compounds. + Creation of the peak table for each compound + """ + tsv_content = list(tsv_content) + curent_name, ms_data = get_ms_data( + tsv_content[0], + tsv_data_extractor, + defaults_data, + config + ) + _, second_ms_data = get_ms_data( + tsv_content[1], + tsv_data_extractor, + defaults_data, + config + ) + ms_peak_table = [] + config.logger.info(f"Processing compound {curent_name}...") + + for line in tsv_content: + name, new_ms_data = get_ms_data(line, tsv_data_extractor, defaults_data, config) + if name != curent_name: + new_compound(curent_name, index, ms_data, config, ms_peak_table) + curent_name = name + index += 1 + config.logger.info(f"Processing compound {curent_name}...") + ms_peak_table = [] + ms_data = new_ms_data + ms_peak_table.append( + ", ".join( + f'"{value}"' if value not in ("na", "NA") + else '""' + for value in ( + ms_data["fragment_mz"], + ms_data["abs_intensity"], + ms_data["rel_intensity"], + ms_data["ppm"], + ms_data["composition"], + ms_data["fragment"], + str(ms_data["valid_corelation"] == "TRUE").lower(), + "true" if ms_data.get("correlation") == "1" else "false" + ) + ) + ) + new_compound(curent_name, index, ms_data, config, ms_peak_table) + return index + +def get_ms_data(line, extractor, defaults, config): + ms_data = defaults.copy() + ms_data.update(extractor(config, *line)) + return ms_data["name"], ms_data + +def new_compound(name, index, ms_data, config, ms_peak_table): + """ + aggregates informations to form the peak table, + adds the compound to the tab list, + creates the js file for this tab + """ + if len([x for x in ms_peak_table if x.split(", ")[7] == "\"true\""]) > 1: + for i in range(len(ms_peak_table)): + ms_peak_table[i] = ", ".join( + ms_peak_table[i].split(", ")[:-1] + [", \"false\""] + ) + config.placeholders[MS_PEAK_VALUES_PLACEHOLDER] = f"""[ + {','.join('['+line+']' for line in ms_peak_table)} + ]""" + tab_list = fill_template( + "tab_list_template", + None, + config, { + COMPOUND_NAME_PLACEHOLDER: name, + TAB_INDEX_PLACEHOLDER: str(index), + }) + config.tab_list.append(tab_list) + create_js_file(index, ms_data, config) + config.placeholders[ADD_SPECTRUM_FORM] += fill_template( + "form_template", + None, + config, + {TAB_INDEX_PLACEHOLDER: str(index)}, + ) + if index == 1: + config.placeholders[ACTIVE_TAB_PLACEHOLDER] = "" + +def fragnot_extractor(config, *line): + """ + Fragnot processor - extracts one fragnot line of content and + produces a uniformised output. + """ + fragnot_data = { + FRAGNOT_HEADER[header]: line[i].strip() + for i, header in enumerate(FRAGNOT_HEADER) + } + fragnot_data["composition"] = "unknown" + fragnot_data["valid_corelation"] = config.arguments.validation + return fragnot_data + +def ms2snoop_extractor(config, *line): + """ + Fragnot processor - extracts one ms2snoop line of content and + produces a uniformised output. + """ + ms2snoop_data = { + header: MS_2_SNOOP_HEADER[header](line[i]) + for i, header in enumerate(MS_2_SNOOP_HEADER) + } + return ms2snoop_data + +def create_js_file(index, ms_data, config): + """ + fills the js template file for one tab (compound) + """ + if (method := ms_data["method"]): + method = f'"{method}"' + else: + method = "null" + if config.arguments.verbose: + config.logger.info( + "[VERBOSE] " + + ';'.join(f"{key}={value}" for key, value in ms_data.items()) + ) + fill_template( + "js_template", + "js_file", + config, + { + TAB_INDEX_PLACEHOLDER: str(index), + "INCHIKEY_PLACEHOLDER": ms_data["inchikey"], + "DEFAULT_DATA": f"""{{ + name: "{ms_data["name"]}", + inchikey: "{ms_data["inchikey"]}", + method: {method}, + spectrum_type: "{ms_data["spectrum_type"]}", + scan_type: "{ms_data["scan_type"]}", + polarity: "{ms_data["polarity"]}", + resolution: "{ms_data["resolution"]}", + sample_type: "{ms_data["sample_type"]}", + }}""", + "{{ index }}": str(index) + }, + ) + +def prepare_workplace(config): + """ + prepares the directory we will work in. + """ + if config.workdir.work_in_tmp: + os.chdir(config.workdir.tmp_dir) + config.logger.info(f"Moving to {os.getcwd()}") + if config.workdir.generate_in_tmp: + gen_dir = config.workdir.tmp_dir + else: + gen_dir = tempfile.gettempdir() + config.workdir.tmp_dir = gen_dir + shutil.copy(os.path.join(config["root_dir"], "common.js"), gen_dir) + config.logger.info(f"Outputs will be generated in {config.workdir.tmp_dir}") + return gen_dir + +def get_hander_for(directory, config): + """ + generates the handler class for the directory we provide. + """ + config["json_result"] = [{}] * len(config.tab_list) + + class HTTPHandler(http.server.SimpleHTTPRequestHandler): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs, directory=directory) + + def do_POST(self): + content_length = int(self.headers.get("Content-Length")) + json_bytes = self.rfile.read(content_length).decode("utf-8") + json_list = json.loads(json_bytes) + for i, obj in enumerate(json_list): + print(obj) + if obj: + config["json_result"][i] = obj + save_json(config) + self.send_head() + self.wfile.write(json_bytes.encode("utf-8")) + return + + def do_GET(self): + if self.path == "/quit": + self.path = "/" + super().do_GET() + exit(0) + self.path = os.path.join(directory, self.path) + if self.path == "/": + self.path = config.generated.html + return super().do_GET() + + return HTTPHandler + + +def save_json(config): + json_string = json.dumps(config["json_result"]) + print(json_string) + with open(config.arguments.output_json, "w") as json_file: + json_file.write(json_string) + +def run_server(config): + """ + prepare and runs the server, with the handler for the given directory + """ + ip, port = config.network.ip, config.network.port + config.logger.debug(f"IP and port: {ip}:{port}") + socketserver.TCPServer.allow_reuse_address = True + config.logger.debug(f"Allow reuse adress.") + handler = get_hander_for(config.workdir.tmp_dir, config) + config.logger.debug(f"Created server handler for {config.workdir.tmp_dir}") + config.logger.debug( + f"Content of directory {config.workdir.tmp_dir}: " + + "\n" + + '\n'.join(sorted( + f" - {path}"for path in os.listdir(config.workdir.tmp_dir) + )) + ) + config.logger.debug(f"Creating TCP server...") + server = socketserver.TCPServer((ip, port), handler) + if ip == "0.0.0.0": + displayed_ip = "localhost" + else: + displayed_ip = ip + config.logger.debug(f"Serving...") + print() + print(f"http://{displayed_ip}:{port}") + server.serve_forever() + +def get_logger(config, dummy=False): + dummy_log = lambda msg:dummy and config.logger.info(msg) + arguments = config.arguments + if not dummy: + logger = logging.getLogger(__file__) + if arguments.debug: + dummy_log(f"Output debug info.") + level = logging.DEBUG + else: + level = logging.INFO + if not dummy: + logger.setLevel(level) + formatter = logging.Formatter( + "%(asctime)s - %(levelname)s - %(message)s" + ) + if arguments.logging.std == "err": + dummy_log(f"Handler added to output logs in stderr.") + if not dummy: + handler = logging.StreamHandler(sys.stderr) + handler.setLevel(level) + handler.setFormatter(formatter) + logger.addHandler(handler) + elif arguments.logging.std == "out": + dummy_log(f"Handler added to output logs in stdout.") + if not dummy: + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(level) + handler.setFormatter(formatter) + logger.addHandler(handler) + else: + dummy_log(f"Logs will not be output in stderr not stdout.") + if (path := arguments.logging.file.path): + dummy_log(f"Add log file: {arguments.logging.file.path}.") + if not arguments.logging.file.append: + dummy_log(f"Log file content cleaned.") + with open(path, "w"):pass + else: + dummy_log(f"Logs appended to log file.") + if not dummy: + file_handler = logging.FileHandler(filename=path) + file_handler.setLevel(level) + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + if not dummy: + config["logger"] = logger + starting_sequence(logger) + get_logger(config, dummy=True) + return logger + +def starting_sequence(logger): + logger.info("*bip* *bop*") + logger.info("starting...") + logger.info("program...") + logger.info("MS2PF is running...") + logger.info("*bip* *bop* am a robot") + atexit.register(stoping_sequence, logger) + +def stoping_sequence(logger): + logger.info("*bip* *bop*") + logger.info("ending...") + logger.info("program...") + logger.info("MS2PF is shuting down...") + logger.info("...robot") + logger.info("*bip* *bop*") + logger.info("shutdown") + logger.info("...") + +if __name__ == "__main__": + + base_config = parse_config() + config = parse_parameters(base_config) + + """ + The config contains result of the parsed config file. + """ + arguments = config.arguments + + config.logger.info(f"Starting MS2PF from {os.getcwd()}") + + gen_dir = prepare_workplace(config) + + config["pf_path"] = os.path.join(gen_dir, config.generated.html) + config.logger.info(f"HTML output file will be {config.pf_path}") + config["js_file"] = os.path.join(gen_dir, config.generated.js) + config.logger.info(f"JS output files will like {config.js_file}") + config.placeholders["PF_URL_PLACEHOLDER"] = arguments.peakforest.url + config.placeholders["PF_TOKEN_PLACEHOLDER"] = ( + arguments.peakforest.token + or config.token.value + ) + if (token := config.placeholders.PF_TOKEN_PLACEHOLDER): + config.logger.info(f"Using a token for authentification - length: {len(token)}") + else: + config.logger.info(f"No token provided for peakforest authentification.") + + process_all_files(config) + + if not arguments.do_run_dry: + config.logger.debug(f"Running the server.") + if arguments.firefox or arguments.chromium: + config.logger.debug(f"Running the server.") + import threading + import time + if arguments.firefox: + browser = "firefox" + else: + browser = "chromium" + if (ip := config.network.ip) == "0.0.0.0": + ip = "localhost" + adress = f"http://{ip}:{config.network.port}" + threading.Thread( + target=lambda:( + time.sleep(1), + os.system(f"{browser} {adress}") + ), + daemon=True + ).start() + run_server(config) + else: + config.logger.debug(f"Server not run.") diff -r 000000000000 -r b58b229c4cbf tab_list.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tab_list.html Fri Mar 03 14:10:24 2023 +0000 @@ -0,0 +1,14 @@ +
  • + + + {{ COMPOUND_NAME_PLACEHOLDER }} + +