diff --git a/THIRD-PARTY-LICENSE-README.md b/THIRD-PARTY-LICENSE-README.md index 263d6ece7..4e5b552b5 100644 --- a/THIRD-PARTY-LICENSE-README.md +++ b/THIRD-PARTY-LICENSE-README.md @@ -1602,3 +1602,36 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================================== + +R.NET (https://github.com/rdotnet/rdotnet) + +The MIT License (MIT) + +Copyright (c) 2014-2020 Jean-Michel Perraud +Copyright (c) 2019-2020 Luke Rasmussen +Copyright (c) 2018 David Pendray +Copyright (c) 2017 Guillaume Jamet +Copyright (c) 2016 Tomas Petricek, Wei Lu +Copyright (c) 2015 Nigel Delaney, Yuanhe Huang +Copyright (c) 2014 skuyguy94, David Charbonneau +Copyright (c) 2013 Kosei ABE, evolvedmicrobe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/MSDIAL4/LipidomicsRtManageProgram/MainWindow.xaml.cs b/src/MSDIAL4/LipidomicsRtManageProgram/MainWindow.xaml.cs index 4d4884a76..5dd38d2d8 100644 --- a/src/MSDIAL4/LipidomicsRtManageProgram/MainWindow.xaml.cs +++ b/src/MSDIAL4/LipidomicsRtManageProgram/MainWindow.xaml.cs @@ -108,7 +108,7 @@ public DelegateCommand SelectRLocationFolder { private void ShowRLocationSelectDialog(object obj) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { @@ -133,7 +133,7 @@ public DelegateCommand SelectOutputFolder { private void ShowOutputFolderSelectDialog(object obj) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/Export/AlignmentResultExportVM.cs b/src/MSDIAL4/MsDial/Export/AlignmentResultExportVM.cs index a74a65bdf..dcf2a8208 100644 --- a/src/MSDIAL4/MsDial/Export/AlignmentResultExportVM.cs +++ b/src/MSDIAL4/MsDial/Export/AlignmentResultExportVM.cs @@ -204,7 +204,7 @@ private void copyExportParametersToProjectProperty() { } #region properties - [Required(ErrorMessage = "Chose a folder path.")] + [Required(ErrorMessage = "Choose a folder path.")] public string ExportFolderPath { get { return exportFolderPath; } diff --git a/src/MSDIAL4/MsDial/Export/AlignmentResultExportWin.xaml.cs b/src/MSDIAL4/MsDial/Export/AlignmentResultExportWin.xaml.cs index a9c40febf..ddacab764 100644 --- a/src/MSDIAL4/MsDial/Export/AlignmentResultExportWin.xaml.cs +++ b/src/MSDIAL4/MsDial/Export/AlignmentResultExportWin.xaml.cs @@ -56,7 +56,7 @@ private void Button_ExportFolderPath_Click(object sender, RoutedEventArgs e) System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a project folder."; + fbd.Description = "Choose a project folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) diff --git a/src/MSDIAL4/MsDial/Export/LipoqualityDatabaseFormatExportVM.cs b/src/MSDIAL4/MsDial/Export/LipoqualityDatabaseFormatExportVM.cs index f953a6a82..ae0d91a38 100644 --- a/src/MSDIAL4/MsDial/Export/LipoqualityDatabaseFormatExportVM.cs +++ b/src/MSDIAL4/MsDial/Export/LipoqualityDatabaseFormatExportVM.cs @@ -15,7 +15,7 @@ public class LipoqualityDatabaseFormatExportVM : ViewModelBase private ObservableCollection alignmentFiles; #region - [Required(ErrorMessage = "Chose a folder for the exported file.")] + [Required(ErrorMessage = "Choose a folder for the exported file.")] public string ExportFolderPath { get { return exportFolderPath; } @@ -83,7 +83,7 @@ private void ShowFolderSelectionDialog(object obj) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/Export/MS2ExporterAsUserDefinedStyle.cs b/src/MSDIAL4/MsDial/Export/MS2ExporterAsUserDefinedStyle.cs index efa689cba..9cc96ee4e 100644 --- a/src/MSDIAL4/MsDial/Export/MS2ExporterAsUserDefinedStyle.cs +++ b/src/MSDIAL4/MsDial/Export/MS2ExporterAsUserDefinedStyle.cs @@ -15,7 +15,7 @@ public static void particular_settings_tada(object target, MainWindow mainWindow //var export_dir = mainWindow.ProjectProperty.ProjectFolderPath + "\\" + "Exported_Figures"; System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a save folder."; + fbd.Description = "Choose a save folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); var export_dir = string.Empty; if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/Export/MrmprobsExportVM.cs b/src/MSDIAL4/MsDial/Export/MrmprobsExportVM.cs index 965a1c63c..7afb2273d 100644 --- a/src/MSDIAL4/MsDial/Export/MrmprobsExportVM.cs +++ b/src/MSDIAL4/MsDial/Export/MrmprobsExportVM.cs @@ -35,7 +35,7 @@ public MrmprobsExportVM(bool isAlignmentView) /// /// Folder where the export function will export Mrmprobs library /// - [Required(ErrorMessage = "Chose a folder for the exported file.")] + [Required(ErrorMessage = "Choose a folder for the exported file.")] public string ExportFolderPath { get { return exportFolderPath; } @@ -266,7 +266,7 @@ private void ShowFolderSelectionDialog(object obj) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/Export/PeaklistExportVM.cs b/src/MSDIAL4/MsDial/Export/PeaklistExportVM.cs index 7f9dbf63d..342a4d7bd 100644 --- a/src/MSDIAL4/MsDial/Export/PeaklistExportVM.cs +++ b/src/MSDIAL4/MsDial/Export/PeaklistExportVM.cs @@ -30,7 +30,7 @@ public class PeaklistExportVM : ViewModelBase /// /// Folder where the export function will save the selected files /// - [Required(ErrorMessage = "Chose a folder for the exported files.")] + [Required(ErrorMessage = "Choose a folder for the exported files.")] public string ExportFolderPath { get { return exportFolderPath; } @@ -203,7 +203,7 @@ private void ShowFolderSelectionDialog(object obj) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) diff --git a/src/MSDIAL4/MsDial/Export/StoreMsAnnotationTagsWin.xaml.cs b/src/MSDIAL4/MsDial/Export/StoreMsAnnotationTagsWin.xaml.cs index 7f87ed261..875cb860b 100644 --- a/src/MSDIAL4/MsDial/Export/StoreMsAnnotationTagsWin.xaml.cs +++ b/src/MSDIAL4/MsDial/Export/StoreMsAnnotationTagsWin.xaml.cs @@ -85,7 +85,7 @@ private void Click_ExportFolderPathSelect(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose an export folder."; + fbd.Description = "Choose an export folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) @@ -137,7 +137,7 @@ private void ComboBox_MassSpecType_SelectionChanged(object sender, SelectionChan { if (mainWindow.ProjectProperty.MethodType == MethodType.ddMSMS && ((ComboBox)sender).SelectedIndex == 2) { - MessageBox.Show("In data depeondent mode, you cannot chose the deconvoluton output.", "Attention", MessageBoxButton.OK, MessageBoxImage.Information); + MessageBox.Show("In data depeondent mode, you cannot choose the deconvoluton output.", "Attention", MessageBoxButton.OK, MessageBoxImage.Information); return; } this.exportMsType = (ExportspectraType)((ComboBox)sender).SelectedIndex; diff --git a/src/MSDIAL4/MsDial/ForAIF/AifViewerControl.xaml.cs b/src/MSDIAL4/MsDial/ForAIF/AifViewerControl.xaml.cs index f548e0070..639cbc11b 100644 --- a/src/MSDIAL4/MsDial/ForAIF/AifViewerControl.xaml.cs +++ b/src/MSDIAL4/MsDial/ForAIF/AifViewerControl.xaml.cs @@ -1095,7 +1095,7 @@ private void message_exist(string txt) { } private void message_requestAlignment() { - MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } private void message_willBeAvailable() { diff --git a/src/MSDIAL4/MsDial/ForAIF/Export/ParticularAlignmentSpotExporterWindow.xaml.cs b/src/MSDIAL4/MsDial/ForAIF/Export/ParticularAlignmentSpotExporterWindow.xaml.cs index e4c147657..97cd808cf 100644 --- a/src/MSDIAL4/MsDial/ForAIF/Export/ParticularAlignmentSpotExporterWindow.xaml.cs +++ b/src/MSDIAL4/MsDial/ForAIF/Export/ParticularAlignmentSpotExporterWindow.xaml.cs @@ -49,7 +49,7 @@ public ParticularAlignmentSpotExporterWindow(MainWindow mainWindow) { private void Click_ExportFilePathSelect(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a project folder."; + fbd.Description = "Choose a project folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/MainWindow.xaml.cs b/src/MSDIAL4/MsDial/MainWindow.xaml.cs index 00acbb58b..f61392b98 100644 --- a/src/MSDIAL4/MsDial/MainWindow.xaml.cs +++ b/src/MSDIAL4/MsDial/MainWindow.xaml.cs @@ -1889,7 +1889,7 @@ private async void alignmetProcessing_Click(object sender, RoutedEventArgs e) private void normalizationMethod_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } var window = new NormalizationSetWin(this); window.Owner = this; @@ -1910,7 +1910,7 @@ private void normalizationMethod_Click(object sender, RoutedEventArgs e) private void principalComponentAnalysis_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } var window = new PcaSetWin(this); window.Owner = this; @@ -1926,7 +1926,7 @@ private void principalComponentAnalysis_Click(object sender, RoutedEventArgs e) } private void partialLeastSquares_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } var window = new PlsSetWin(this); window.Owner = this; @@ -1943,7 +1943,7 @@ private void partialLeastSquares_Click(object sender, RoutedEventArgs e) { } private void hierarchicalclusteringanalysis_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } var window = new HcaSetWin(this); window.Owner = this; @@ -1974,7 +1974,7 @@ private void MenuItem_MsmsMolecularNetwork_Click(object sender, RoutedEventArgs private void identificationSetting_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.projectProperty.Ionization == Ionization.ESI) @@ -2025,7 +2025,7 @@ private void ProjectPropertySetting_Click(object sender, RoutedEventArgs e) private void alignmentResultPropertySetting_Click(object sender, RoutedEventArgs e) { - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.projectProperty.Ionization == Ionization.ESI) @@ -2079,7 +2079,7 @@ private void menuItem_NormalizationResultExport_Click(object sender, RoutedEvent MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } //var filePath = @"C:\Users\tipputa\Desktop\test.pdf"; @@ -2256,7 +2256,7 @@ public void MenuItem_ShowAlignmentSampleTable_Click(object sender, RoutedEventAr MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.alignedDriftSpotBeanList != null && this.focusedAlignmentDriftID >= 0) { var target = ((e.Source as MenuItem).Parent as ContextMenu).PlacementTarget; @@ -2281,7 +2281,7 @@ private void MenuItem_AlignedChromatogramModification_Click(object sender, Route MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.alignedDriftSpotBeanList != null && this.focusedAlignmentDriftID >= 0) { var target = ((e.Source as MenuItem).Parent as ContextMenu).PlacementTarget; var uiName = ((ChromatogramAlignedEicUI)target).Name; @@ -2312,7 +2312,7 @@ private void MenuItem_AlignmentSpotTableViewer_Click(object sender, RoutedEventA MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } //new TableViewerHandler().StartUpAlignmentSpotTableViewer(this); // don't need to await; _ = new TableViewerTaskHandler().StartUpAlignmentSpotTableViewer(this); @@ -2322,7 +2322,7 @@ private void MenuItem_AlignmentSpotTableViewer_Click(object sender, RoutedEventA private void MenuItem_CorrelationBasedDeconvolution_ForAIF_SettingAndRun_Click(object sender, RoutedEventArgs e) { if (this.focusedAlignmentFileID < 0) { - MessageBox.Show("Chose an alignment file from the file navigator.", + MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.AnalysisFiles.Count <= 3) { @@ -2346,7 +2346,7 @@ private async void MenuItem_CorrelationBasedDeconvolution_ForAIF_Identification_ if (this.focusedAlignmentFileID < 0) { - MessageBox.Show("Chose an alignment file from the file navigator.", + MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.AnalysisFiles.Count <= 3) @@ -2370,7 +2370,7 @@ private async void MenuItem_CorrelationBasedDeconvolution_SingleSpot_Click(objec if (this.focusedAlignmentFileID < 0) { - MessageBox.Show("Chose an alignment file from the file navigator.", + MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.AnalysisFiles.Count <= 3) @@ -2393,7 +2393,7 @@ private void MenuItem_CorrelationBasedDeconvolution_ShowResult_Click(object send if (this.focusedAlignmentFileID < 0) { - MessageBox.Show("Chose an alignment file from the file navigator.", + MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.AnalysisFiles.Count <= 3) @@ -2506,7 +2506,7 @@ private void MenuItem_ParticularAlignmentSpotExport_Click(object sender, RoutedE MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } var window = new ForAIF.ParticularAlignmentSpotExporterWindow(this); window.Owner = this; window.WindowStartupLocation = WindowStartupLocation.CenterOwner; @@ -5993,7 +5993,7 @@ public void Reset_AlignmentTableViewer() { MessageBox.Show("You don't have any aligmnet result file.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } - if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Chose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } + if (this.focusedAlignmentFileID < 0) { MessageBox.Show("Choose an alignment file from the file navigator.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (this.alignmentSpotTableViewer != null) { this.alignmentSpotTableViewer.Close(); this.alignmentSpotTableViewer = null; diff --git a/src/MSDIAL4/MsDial/Molecular networking/MolecularNetworkExportWin.xaml.cs b/src/MSDIAL4/MsDial/Molecular networking/MolecularNetworkExportWin.xaml.cs index c65f43b9a..cf48d4e90 100644 --- a/src/MSDIAL4/MsDial/Molecular networking/MolecularNetworkExportWin.xaml.cs +++ b/src/MSDIAL4/MsDial/Molecular networking/MolecularNetworkExportWin.xaml.cs @@ -130,7 +130,7 @@ public DelegateCommand Browse { var fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a folder where to save the exported files."; + fbd.Description = "Choose a folder where to save the exported files."; fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { diff --git a/src/MSDIAL4/MsDial/Online database/DownloadOnlineMsMsRecordWin.xaml.cs b/src/MSDIAL4/MsDial/Online database/DownloadOnlineMsMsRecordWin.xaml.cs index f178fc42c..99060921d 100644 --- a/src/MSDIAL4/MsDial/Online database/DownloadOnlineMsMsRecordWin.xaml.cs +++ b/src/MSDIAL4/MsDial/Online database/DownloadOnlineMsMsRecordWin.xaml.cs @@ -72,7 +72,7 @@ private void Button_DownloadFolder_Click(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose an import folder."; + fbd.Description = "Choose an import folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK) diff --git a/src/MSDIAL4/MsDial/Property/AnalysisFilePropertySettingVM.cs b/src/MSDIAL4/MsDial/Property/AnalysisFilePropertySettingVM.cs index ebd69aaa4..a4e1ea156 100644 --- a/src/MSDIAL4/MsDial/Property/AnalysisFilePropertySettingVM.cs +++ b/src/MSDIAL4/MsDial/Property/AnalysisFilePropertySettingVM.cs @@ -38,7 +38,7 @@ public ObservableCollection AnalysisFilePropertyCollecti public static ValidationResult ValidateAnalysisFile(ObservableCollection test, ValidationContext context) { - if (test == null || test.Count == 0) return new ValidationResult("Chose the analysis files (abf, mzML, or netCDF format)."); + if (test == null || test.Count == 0) return new ValidationResult("Choose the analysis files (abf, mzML, or netCDF format)."); else return ValidationResult.Success; } #endregion diff --git a/src/MSDIAL4/MsDial/StartUp/StartUpProjectVM.cs b/src/MSDIAL4/MsDial/StartUp/StartUpProjectVM.cs index 78d699db1..4a65957f2 100644 --- a/src/MSDIAL4/MsDial/StartUp/StartUpProjectVM.cs +++ b/src/MSDIAL4/MsDial/StartUp/StartUpProjectVM.cs @@ -34,7 +34,7 @@ public string ProjectFolderPath set { this.projectProperty.ProjectFolderPath = value; } } - [Required(ErrorMessage = "Chose a project folder path.")] + [Required(ErrorMessage = "Choose a project folder path.")] public string ProjectFilePath { get { return this.projectProperty.ProjectFilePath; } diff --git a/src/MSDIAL4/MsDial/StartUp/StartUpWindow.xaml.cs b/src/MSDIAL4/MsDial/StartUp/StartUpWindow.xaml.cs index 430115de4..7f8e86bd9 100644 --- a/src/MSDIAL4/MsDial/StartUp/StartUpWindow.xaml.cs +++ b/src/MSDIAL4/MsDial/StartUp/StartUpWindow.xaml.cs @@ -36,7 +36,7 @@ private void Button_ProjectFilePathSelect_Click(object sender, RoutedEventArgs e { System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog(); fbd.RootFolder = Environment.SpecialFolder.Desktop; - fbd.Description = "Chose a project folder."; + fbd.Description = "Choose a project folder."; fbd.SelectedPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop); DateTime dt = DateTime.Now; diff --git a/src/MSDIAL5/MsdialCore/Export/AlignmentMetadataAccessorExtensions.cs b/src/MSDIAL5/MsdialCore/Export/AlignmentMetadataAccessorExtensions.cs new file mode 100644 index 000000000..5b4744b01 --- /dev/null +++ b/src/MSDIAL5/MsdialCore/Export/AlignmentMetadataAccessorExtensions.cs @@ -0,0 +1,12 @@ +using CompMs.Common.Interfaces; +using CompMs.MsdialCore.DataObj; +using CompMs.MsdialCore.Export.Internal; +using System; + +namespace CompMs.MsdialCore.Export; + +public static class AlignmentMetadataAccessorExtensions { + public static IMetadataAccessor Insert(this IMetadataAccessor accessor, string additionalColumn, int insertPosition, Func getter) { + return new InsertAlignmentMetadataAccessorDecorator(accessor, additionalColumn, insertPosition, getter); + } +} diff --git a/src/MSDIAL5/MsdialCore/Export/Internal/InsertAlignmentMetadataAccessorDecorator.cs b/src/MSDIAL5/MsdialCore/Export/Internal/InsertAlignmentMetadataAccessorDecorator.cs new file mode 100644 index 000000000..6120c447d --- /dev/null +++ b/src/MSDIAL5/MsdialCore/Export/Internal/InsertAlignmentMetadataAccessorDecorator.cs @@ -0,0 +1,47 @@ +using CompMs.Common.Interfaces; +using CompMs.MsdialCore.DataObj; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CompMs.MsdialCore.Export.Internal; + +internal sealed class InsertAlignmentMetadataAccessorDecorator : IMetadataAccessor +{ + public InsertAlignmentMetadataAccessorDecorator(IMetadataAccessor accessor, string additionalColumn, int insertPosition, Func getter) + { + Accessor = accessor; + AdditionalColumn = additionalColumn; + InsertPosition = insertPosition; + Getter = getter; + } + + public IMetadataAccessor Accessor { get; } + public string AdditionalColumn { get; } + public int InsertPosition { get; } + public Func Getter { get; } + + public IReadOnlyDictionary GetContent(AlignmentSpotProperty spot, IMSScanProperty msdec) { + var contents = Accessor.GetContent(spot, msdec); + if (contents is not IDictionary writable) { + var dict = contents.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + contents = dict; + writable = dict; + } + writable[AdditionalColumn] = Getter(spot, msdec); + return contents; + } + + public string[] GetHeaders() { + var header = Accessor.GetHeaders(); + var idx = InsertPosition; + if (idx == -1) { + idx = header.Length; + } + var result = new string[header.Length + 1]; + Array.Copy(header, 0, result, 0, idx); + result[idx] = AdditionalColumn; + Array.Copy(header, idx, result, idx + 1, header.Length - idx); + return result; + } +} \ No newline at end of file diff --git a/src/MSDIAL5/MsdialGuiApp/Model/Export/AlignmentExportGroupModel.cs b/src/MSDIAL5/MsdialGuiApp/Model/Export/AlignmentExportGroupModel.cs index 6785436fb..b7260ce2c 100644 --- a/src/MSDIAL5/MsdialGuiApp/Model/Export/AlignmentExportGroupModel.cs +++ b/src/MSDIAL5/MsdialGuiApp/Model/Export/AlignmentExportGroupModel.cs @@ -55,5 +55,11 @@ public void Export(AlignmentFileBeanModel alignmentFile, string exportDirectory, var lazyPeakSpot = new Lazy>(() => _peakSpotSupplyer.Supply(alignmentFile, default)); ExportMethod.Export(outNameTemplate, exportDirectory, lazyPeakSpot, msdecResults, notification, Types.Where(type => type.ShouldExport), AccessPeakMetaModel, AccessFileMeta); } + + public void Export(AlignmentFileBeanModel alignmentFile, string exportDirectory, string exportFileName, Action? notification) { + var msdecResults = alignmentFile.LoadMSDecResults(); + var lazyPeakSpot = new Lazy>(() => _peakSpotSupplyer.Supply(alignmentFile, default)); + ExportMethod.Export(exportFileName, exportDirectory, lazyPeakSpot, msdecResults, notification, new[] { Types.First(type => type.ShouldExport) }, AccessPeakMetaModel, AccessFileMeta); + } } } diff --git a/src/MSDIAL5/MsdialGuiApp/Model/Export/ExportMethod.cs b/src/MSDIAL5/MsdialGuiApp/Model/Export/ExportMethod.cs index 3342336c0..fb027e633 100644 --- a/src/MSDIAL5/MsdialGuiApp/Model/Export/ExportMethod.cs +++ b/src/MSDIAL5/MsdialGuiApp/Model/Export/ExportMethod.cs @@ -31,7 +31,7 @@ public bool IsLongFormat { } private bool _isLongFormat = false; - public void Export(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { + public void Export(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action? notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { if (IsLongFormat) { ExportLong(outNameTemplate, exportDirectory, lazySpots, msdecResults, notification, exportTypes, accessPeakMeta, accessFileMeta); } @@ -40,7 +40,7 @@ public void Export(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { + public void ExportLong(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action? notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { var outMetaName = string.Format(outNameTemplate, "PeakMaster"); var outMetaFile = Format.WithExtension(outMetaName); var outMetaPath = Path.Combine(exportDirectory, outMetaFile); @@ -78,7 +78,7 @@ public void ExportLong(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { + public void ExportWide(string outNameTemplate, string exportDirectory, Lazy> lazySpots, IReadOnlyList msdecResults, Action? notification, IEnumerable exportTypes, AccessPeakMetaModel accessPeakMeta, AccessFileMetaModel accessFileMeta) { var exporter = Format.CreateWideExporter(); var accessor = accessPeakMeta.GetAccessor(); MsdialCore.Export.MulticlassFileMetaAccessor fileMetaAccessor = accessFileMeta.GetAccessor(); diff --git a/src/MSDIAL5/MsdialGuiApp/Model/Export/IdentityAlignmentMetadataAccessorFactory.cs b/src/MSDIAL5/MsdialGuiApp/Model/Export/IdentityAlignmentMetadataAccessorFactory.cs new file mode 100644 index 000000000..f207dbc65 --- /dev/null +++ b/src/MSDIAL5/MsdialGuiApp/Model/Export/IdentityAlignmentMetadataAccessorFactory.cs @@ -0,0 +1,15 @@ +using CompMs.MsdialCore.Export; + +namespace CompMs.App.Msdial.Model.Export +{ + internal sealed class IdentityAlignmentMetadataAccessorFactory : IAlignmentMetadataAccessorFactory { + private readonly IMetadataAccessor _accessor; + + public IdentityAlignmentMetadataAccessorFactory(IMetadataAccessor accessor) + { + _accessor = accessor; + } + + public IMetadataAccessor CreateAccessor(bool trimSpectrumToExcelLimit) => _accessor; + } +} diff --git a/src/MSDIAL5/MsdialGuiApp/Model/Lcms/LcmsMethodModel.cs b/src/MSDIAL5/MsdialGuiApp/Model/Lcms/LcmsMethodModel.cs index 2db7881b2..b6dc33262 100644 --- a/src/MSDIAL5/MsdialGuiApp/Model/Lcms/LcmsMethodModel.cs +++ b/src/MSDIAL5/MsdialGuiApp/Model/Lcms/LcmsMethodModel.cs @@ -4,6 +4,7 @@ using CompMs.App.Msdial.Model.Export; using CompMs.App.Msdial.Model.Search; using CompMs.App.Msdial.Model.Setting; +using CompMs.App.Msdial.Model.Statistics; using CompMs.Common.Components; using CompMs.Common.Enum; using CompMs.Graphics.UI.ProgressBar; @@ -29,6 +30,7 @@ namespace CompMs.App.Msdial.Model.Lcms { + internal sealed class LcmsMethodModel : MethodModelBase { private static readonly ChromatogramSerializer CHROMATOGRAM_SPOT_SERIALIZER; @@ -77,7 +79,6 @@ public LcmsMethodModel( var isNormalized = alignmentFilesForExport.CanExportNormalizedData(currentAlignmentResult.Select(r => r?.NormalizationSetModel.IsNormalized ?? Observable.Return(false)).Switch()).ToReadOnlyReactivePropertySlim().AddTo(Disposables); AlignmentPeakSpotSupplyer peakSpotSupplyer = new AlignmentPeakSpotSupplyer(currentAlignmentResult, filter); var stats = new List { StatsValue.Average, StatsValue.Stdev, }; - var metadataAccessorFactory = new LcmsAlignmentMetadataAccessorFactory(storage.DataBaseMapper, storage.Parameter); var peakGroup = new AlignmentExportGroupModel( "Peaks", new ExportMethod( @@ -98,7 +99,7 @@ public LcmsMethodModel( new ExportType("MS/MS included", new LegacyQuantValueAccessor("MSMS", storage.Parameter), "MsmsIncluded"), new ExportType("Identification method", new AnnotationMethodAccessor(), "IdentificationMethod"), }, - new AccessPeakMetaModel(metadataAccessorFactory), + new AccessPeakMetaModel(new LcmsAlignmentMetadataAccessorFactory(storage.DataBaseMapper, storage.Parameter)), new AccessFileMetaModel(fileProperties).AddTo(Disposables), new[] { @@ -148,6 +149,32 @@ public LcmsMethodModel( var currentAlignmentFile = this.ObserveProperty(m => (IAlignmentModel)m.AlignmentModel).ToReadOnlyReactivePropertySlim().AddTo(Disposables); InternalMsfinderSettingModel = new InternalMsfinderSettingModel(storage.Parameter.ProjectParam, exportMatForMsfinder, currentAlignmentFile); + + var notameExportModel = new AlignmentExportGroupModel( + "Peaks", + new ExportMethod(analysisFiles, ExportFormat.Tsv) { IsLongFormat = false, }, + new[] { + new ExportType("Raw data (Height)", new LegacyQuantValueAccessor("Height", storage.Parameter), "Height", new List(0), true), + new ExportType("Raw data (Area)", new LegacyQuantValueAccessor("Area", storage.Parameter), "Area", new List(0)), + new ExportType("Normalized data (Height)", new LegacyQuantValueAccessor("Normalized height", storage.Parameter), "NormalizedHeight", new List(0), isNormalized), + new ExportType("Normalized data (Area)", new LegacyQuantValueAccessor("Normalized area", storage.Parameter), "NormalizedArea", new List(0), isNormalized), + }, + new AccessPeakMetaModel(new IdentityAlignmentMetadataAccessorFactory( + new LcmsMetadataAccessor(storage.DataBaseMapper, storage.Parameter, trimSpectrumToExcelLimit: true) + .Insert("Ion mode", 34, (p, _) => { + switch (p.IonMode) { + case IonMode.Positive: + return "RP_pos"; + case IonMode.Negative: + return "RP_neg"; + default: + return "null"; + } + }))), + new AccessFileMetaModel(fileProperties) { EnableMultiClass = true, NumberOfClasses = 2, }.AddTo(Disposables), + new[] { ExportspectraType.deconvoluted, }, + peakSpotSupplyer); + Notame = new Notame(alignmentFilesForExport, peakSpotSupplyer, notameExportModel, storage.Parameter.DataExportParam, storage.Parameter); } public InternalMsfinderSettingModel InternalMsfinderSettingModel { get; } @@ -399,6 +426,8 @@ public AnalysisResultExportModel ExportAnalysis() { } + public Notame Notame { get; } + public FragmentQuerySettingModel ShowShowFragmentSearchSettingView() { return new FragmentQuerySettingModel(_storage.Parameter.AdvancedProcessOptionBaseParam, AnalysisModel, AlignmentModel); } diff --git a/src/MSDIAL5/MsdialGuiApp/Model/Statistics/Notame.cs b/src/MSDIAL5/MsdialGuiApp/Model/Statistics/Notame.cs new file mode 100644 index 000000000..0f006a59a --- /dev/null +++ b/src/MSDIAL5/MsdialGuiApp/Model/Statistics/Notame.cs @@ -0,0 +1,211 @@ +using CompMs.App.Msdial.Model.Export; +using CompMs.App.Msdial.Properties; +using CompMs.App.Msdial.ViewModel.Service; +using CompMs.Common.Enum; +using CompMs.CommonMVVM; +using CompMs.MsdialCore.DataObj; +using CompMs.MsdialCore.Parameter; +using RDotNet; +using Reactive.Bindings.Notifiers; +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CompMs.App.Msdial.Model.Statistics { + internal sealed class Notame : DisposableModelBase { + public Notame(AlignmentFilesForExport alignmentFilesForExport, AlignmentPeakSpotSupplyer peakSpotSupplyer, AlignmentExportGroupModel exportModel, DataExportBaseParameter dataExportParameter, ParameterBase parameterBase) { + AlignmentFilesForExport = alignmentFilesForExport; + PeakSpotSupplyer = peakSpotSupplyer ?? throw new ArgumentNullException(nameof(peakSpotSupplyer)); + ExportModel = exportModel; + ExportDirectory = dataExportParameter.ExportFolderPath; + IonMode = parameterBase.IonMode; + RDirectory = Settings.Default.RHome; + } + + public string ExportDirectory { + get => _exportDirectory; + set => SetProperty(ref _exportDirectory, value); + } + private string _exportDirectory = string.Empty; + + public string RDirectory { + get => _rDirectory; + set => SetProperty(ref _rDirectory, value); + } + private string _rDirectory = string.Empty; + + public string GetExportFolder(string directory) { + var folder = directory.Replace("\\", "/"); + return folder; + } + + public AlignmentExportGroupModel ExportModel { get; } + + public AlignmentFilesForExport AlignmentFilesForExport { get; } + public AlignmentPeakSpotSupplyer PeakSpotSupplyer { get; } + public ExportMethod ExportMethod => ExportModel.ExportMethod; + public ReadOnlyObservableCollection ExportTypes => ExportModel.Types; + public bool exportReport; + + public Task ExportAlignmentResultAsync(IMessageBroker broker) { + return Task.Run(() => { + if (AlignmentFilesForExport.SelectedFile is null) { + return; + } + var publisher = new TaskProgressPublisher(broker, $"Exporting {AlignmentFilesForExport.SelectedFile.FileName}"); + using (publisher.Start()) { + var alignmentFile = AlignmentFilesForExport.SelectedFile; + if (ExportTypes.FirstOrDefault(type => type.IsSelected) is not { } type) { + throw new Exception("Export type (Height, Area, ...) is not selected."); + } + var fileName = $"{type.TargetLabel}_{((IFileBean)alignmentFile).FileID}_{DateTime.Now:yyyy_MM_dd_HH_mm_ss}"; + FileName = ExportMethod.Format.WithExtension(fileName); + ExportModel.Export(alignmentFile, ExportDirectory, fileName, null); + } + }); + } + + private readonly IonMode IonMode; + private REngine? engine; + private string originalDir; + + public string GetIonMode() { + if (IonMode == IonMode.Positive) { + return "pos"; + } + else if (IonMode == IonMode.Negative) { + return "neg"; + } + return string.Empty; + } + + private string NotameIonMode = string.Empty; + private string NotameExport = string.Empty; + private string FileName = string.Empty; + private string RPath = string.Empty; + + [STAThread] + public void Run() { + try { + NotameIonMode = GetIonMode(); + NotameExport = GetExportFolder(ExportDirectory); + RPath = GetExportFolder(RDirectory); + REngine.SetEnvironmentVariables(); + REngine.SetEnvironmentVariables($"{RPath}/bin/x64", RPath); + engine = REngine.GetInstance(); + engine.Evaluate($@"Sys.setenv(PATH = paste('{RPath}/bin/x64', Sys.getenv('PATH'), sep=';'))"); + + string[] libraries = ["BiocManager", "pcaMethods", "Biobase", "devtools", "notame", "remotes", "tinytex", "cowplot", "missForest", "ggpubr", "Cairo", "doParallel", "dplyr", "tidyr", "openxlsx", "MUVR"]; + var check = libraries.Select(lib => new { + Package = lib, + IsLoaded = engine.Evaluate($"require(\"{lib}\")").AsLogical().FirstOrDefault() + }); + if (check.Any(x => !x.IsLoaded)) { + foreach (var item in check.Where(x => !x.IsLoaded)) { + MessageBox.Show($"Some packages failed to load: {item.Package}"); + } + Packages(); + } + originalDir = engine.Evaluate("getwd()").AsCharacter().First(); + RunNotame(engine); + if (exportReport) { + ExportReport(engine); + } + MessageBox.Show("Output files are successfully created."); + if (Settings.Default.RHome != RDirectory) { + Settings.Default.RHome = RDirectory; + Settings.Default.Save(); + } + } catch (Exception ex) { + MessageBox.Show($"An error occurred on R: {ex.Message}"); + } finally { + if (Settings.Default.RHome != RDirectory) { + Settings.Default.RHome = RDirectory; + Settings.Default.Save(); + } + engine?.Evaluate($"setwd('{originalDir.Replace(@"\", @"\\")}')"); + } + } + + private bool Packages() { + string msgtext = "There is a package which has not installed yet. Please run this scripts on your local R Studio to install packages used in Notame preprocessing.\r\n\r\n" + + "###########################################\r\n\r\n" + + "if (!requireNamespace('BiocManager', quietly=TRUE)){\r\n " + + "install.packages('BiocManager')}\r\n" + + "BiocManager::install('pcaMethods')\r\n" + + "BiocManager::install('Biobase')\r\n\r\n" + + "if (!requireNamespace('devtools', quietly = TRUE)) {\r\n " + + "install.packages('devtools')}\r\n" + + "devtools::install_github('antonvsdata/notame')\r\n\r\n" + + "if (!requireNamespace('remotes', quietly=TRUE)){\r\n " + + "install.packages('remotes')}\r\n" + + "library(remotes)\r\n" + + "install_gitlab('CarlBrunius/MUVR')\r\n\r\n" + + "if (!requireNamespace('tinytex', quietly=TRUE)){\r\n " + + "install.packages('tinytex')}\r\n" + + "tinytex::install_tinytex()\r\n" + + "tinytex::tlmgr_install('grfext')\r\n\r\n" + + "required_packages <- c('doParallel', 'dplyr', 'openxlsx', 'cowplot', 'missForest', 'ggpubr', 'Cairo', 'tidyr')\r\n" + + "packages_to_install <- required_packages[!(required_packages %in% installed.packages()[,'Package'])]\r\n\r\n" + + "if(length(packages_to_install)) {\r\n " + + "install.packages(packages_to_install)}\r\n" + + "lapply(required_packages, library, character.only = TRUE)\r\n\r\n" + + "##########################################"; + var result = CustomPackageDialog.ShowDialog(msgtext); + if (MessageBox.Show("Click OK to run Notame (packages needed to be installed)", "Notame", + MessageBoxButtons.OKCancel) == DialogResult.Cancel) { + return false; + } else { + return true; + } + } + + private void RunNotame(REngine engine) { + string notameScriptPath = "Resources/Notame.R"; + string notameScript = System.IO.File.ReadAllText(notameScriptPath); + + engine.SetSymbol("path", engine.CreateCharacter(NotameExport)); + engine.SetSymbol("file_name", engine.CreateCharacter(FileName)); + engine.SetSymbol("ion_mod", engine.CreateCharacter(NotameIonMode)); + engine.Evaluate(notameScript); + } + + private void ExportReport(REngine engine) { + string reportScriptPath = "Resources/Report.R"; + string reportScript = System.IO.File.ReadAllText(reportScriptPath); + + engine.SetSymbol("path", engine.CreateCharacter(NotameExport)); + engine.Evaluate(reportScript); + } + } + public class CustomPackageDialog : Form { + private TextBox txtMessage; + private string message; + + public CustomPackageDialog(string message) { + this.message = message; + InitializeComponents(); + } + + private void InitializeComponents() { + this.Text = "Package Installation"; + this.Size = new System.Drawing.Size(600, 400); + + txtMessage = new TextBox(); + txtMessage.Multiline = true; + txtMessage.ReadOnly = true; + txtMessage.Text = message; + txtMessage.Dock = DockStyle.Top; + txtMessage.Height = 350; + this.Controls.Add(txtMessage); + } + + public static DialogResult ShowDialog(string message) { + using (var dialog = new CustomPackageDialog(message)) { + return dialog.ShowDialog(); + } + } + } +} diff --git a/src/MSDIAL5/MsdialGuiApp/MsdialGuiApp.csproj b/src/MSDIAL5/MsdialGuiApp/MsdialGuiApp.csproj index ca682e2e5..ff27e2439 100644 --- a/src/MSDIAL5/MsdialGuiApp/MsdialGuiApp.csproj +++ b/src/MSDIAL5/MsdialGuiApp/MsdialGuiApp.csproj @@ -50,10 +50,13 @@ + + + @@ -66,12 +69,19 @@ + + PreserveNewest + + + PreserveNewest + + @@ -113,6 +123,7 @@ Never + Never diff --git a/src/MSDIAL5/MsdialGuiApp/Properties/Resources.Designer.cs b/src/MSDIAL5/MsdialGuiApp/Properties/Resources.Designer.cs index 0eacef6d1..5d494d2df 100644 --- a/src/MSDIAL5/MsdialGuiApp/Properties/Resources.Designer.cs +++ b/src/MSDIAL5/MsdialGuiApp/Properties/Resources.Designer.cs @@ -88,7 +88,7 @@ public static string VDD_URI { } /// - /// Looks up a localized string similar to 5.3.240617. + /// Looks up a localized string similar to 5.4.240618-alpha. /// public static string VERSION { get { diff --git a/src/MSDIAL5/MsdialGuiApp/Properties/Resources.resx b/src/MSDIAL5/MsdialGuiApp/Properties/Resources.resx index cfb57e6f7..592668245 100644 --- a/src/MSDIAL5/MsdialGuiApp/Properties/Resources.resx +++ b/src/MSDIAL5/MsdialGuiApp/Properties/Resources.resx @@ -127,6 +127,6 @@ https://api.github.com/repos/systemsomicslab/MsdialWorkbench/releases?per_page=100 - 5.3.240617 + 5.4.240618-alpha \ No newline at end of file diff --git a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Designer.cs b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Designer.cs index f66f16549..c576d8fc6 100644 --- a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Designer.cs +++ b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace CompMs.App.Msdial.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Manual.cs b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Manual.cs index 8f481c9b5..a34b3df1e 100644 --- a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Manual.cs +++ b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.Manual.cs @@ -6,6 +6,7 @@ namespace CompMs.App.Msdial.Properties { internal sealed partial class Settings : System.Configuration.ApplicationSettingsBase { [System.Configuration.UserScopedSetting()] + [System.Configuration.DefaultSettingValue(null)] public List PreviousProjects { get { return (List)this["PreviousProjects"]; @@ -16,6 +17,7 @@ public List PreviousProjects { } [System.Configuration.UserScopedSetting()] + [System.Configuration.DefaultSettingValue(null)] public DockLayoutElement ChromatogramsViewLayoutTemplate { get { return (DockLayoutElement)this["ChromatogramsViewLayoutTemplate"]; @@ -26,6 +28,7 @@ public DockLayoutElement ChromatogramsViewLayoutTemplate { } [System.Configuration.UserScopedSetting()] + [System.Configuration.DefaultSettingValue(null)] public DockLayoutElement AccumulatedSpectrumViewLayoutTemplate { get { return (DockLayoutElement)this["AccumulatedSpectrumViewLayoutTemplate"]; @@ -34,5 +37,17 @@ public DockLayoutElement AccumulatedSpectrumViewLayoutTemplate { this["AccumulatedSpectrumViewLayoutTemplate"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(null)] + public string RHome { + get { + return ((string)(this["RHome"])); + } + set { + this["RHome"] = value; + } + } } } diff --git a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.settings b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.settings index 0046f2aab..338523f1d 100644 --- a/src/MSDIAL5/MsdialGuiApp/Properties/Settings.settings +++ b/src/MSDIAL5/MsdialGuiApp/Properties/Settings.settings @@ -5,5 +5,8 @@ True + + + \ No newline at end of file diff --git a/src/MSDIAL5/MsdialGuiApp/Resources/Notame.R b/src/MSDIAL5/MsdialGuiApp/Resources/Notame.R new file mode 100644 index 000000000..e32123af3 --- /dev/null +++ b/src/MSDIAL5/MsdialGuiApp/Resources/Notame.R @@ -0,0 +1,953 @@ +# RHaikonen +# 20240429 +# notame preprocessing, quality metrics, and MUVR selection +# Additional plotting with PCA and drift correction + +library(notame) +library(doParallel) +library(dplyr) +library(openxlsx) +library(pcaMethods) + +# Functions to import Ms-dial export +name_features <- function (feature_data) +{ + cols <- find_mz_rt_cols(feature_data) + mz_col <- cols$mz_col + rt_col <- cols$rt_col + round_mz <- as.numeric(feature_data[, mz_col]) %>% as.character() %>% + gsub("[.]", "_", .) + round_rt <- as.numeric(feature_data[, rt_col]) %>% as.character() %>% + gsub("[.]", "_", .) + feature_data$Feature_ID <- paste0(feature_data$Split, "_", + round_mz, "a", round_rt) + if (anyDuplicated(feature_data$Feature_ID)) { + duplicates <- paste0(feature_data$Feature_ID[duplicated(feature_data$Feature_ID)], + collapse = ", ") + stop(paste0("Could not create unique feature names from m/z and retention time columns. Duplicated values: ", + duplicates)) + } + feature_data +} + +find_mz_rt_cols <- function (feature_data) +{ + # Find mass and retention time columns + mz_tags <- c("mass", "m.?z$", "molecular.?weight", "average mz", "average.mz", "molecularweight", + "molecular weight", "average_mz") + rt_tags <- c("retention.?time", "^rt$", "(?=.*rt)(?=.*min)") + mz_col <- NULL + for (tag in mz_tags) { + hits <- grepl(tag, tolower(colnames(feature_data)), perl = T) + if (any(hits)) { + mz_col <- colnames(feature_data)[which(hits)[1]] + break + } + } + rt_col <- NULL + for (tag in rt_tags) { + hits <- grepl(tag, tolower(colnames(feature_data)), perl = T) + if (any(hits)) { + rt_col <- colnames(feature_data)[which(hits)[1]] + break + } + } + if (is.null(mz_col)) { + stop(paste0("No mass to charge ratio column found - should match one of:\n", + paste(mz_tags, collapse = ", "), " (not case-sensitive)")) + } + if (is.null(rt_col)) { + stop(paste0("No retention time column found - should match one of:\n", + paste(rt_tags, collapse = ", "), " (not case-sensitive)")) + } + return(list(mz_col = mz_col, rt_col = rt_col)) +} + +# helper fuctions: +best_class <- function(x) { + x <- type.convert(as.character(x), as.is = TRUE) + if (class(x) == "numeric") { + x <- x + } else if (length(unique(x)) < length(x) / 4) { + x <- as.factor(x) + } else if (is.integer(x)) { + x <- as.numeric(x) + } else { + x <- as.character(x) + } + x +} +best_classes <- function (x) +{ + as.data.frame(lapply(x, best_class), stringsAsFactors = FALSE) +} +correct_drift_temp <- function (object, log_transform = TRUE, spar = NULL, spar_lower = 0.5, + spar_upper = 1.5, check_quality = FALSE, condition = "RSD_r < 0 & D_ratio_r < 0", + plotting = FALSE, n_plotting = nrow(object), file = NULL, width = 16, height = 8, color = "QC", + shape = NULL, color_scale = getOption("notame.color_scale_dis"), + shape_scale = scale_shape_manual(values = c(15, 16))) +{ + corrected_list <- dc_cubic_spline(object, log_transform = log_transform, + spar = spar, spar_lower = spar_lower, spar_upper = spar_upper) + corrected <- corrected_list$object + inspected <- inspect_dc_temp(orig = object, dc = corrected, check_quality = check_quality, + condition = condition) + if (plotting) { + if (is.null(file)) { + stop("File must be specified") + } + save_dc_plots_temp(orig = object, dc = inspected, predicted = corrected_list$predicted, + file = file, log_transform = log_transform, width = width, + height = height, color = color, shape = shape, color_scale = color_scale, + shape_scale = shape_scale, n_plotting = n_plotting) + } + inspected +} + +################################################################################ +################################################################################ + +save_dc_plots_temp <- function (orig, dc, predicted, + file, log_transform = TRUE, width = 16, height = 8, color = "QC", + shape = color, color_scale = getOption("notame.color_scale_dis"), + shape_scale = scale_shape_manual(values = c(15, 16)), n_plotting = n_plotting) +{ + if (!requireNamespace("cowplot", quietly = TRUE)) { + stop("Package \"cowplot\" needed for this function to work. Please install it.", + call. = FALSE) + } + dc_plot_helper <- function(data, fname, title = NULL) { + tryCatch({ + p <- ggplot(mapping = aes_string(x = "Injection_order", + y = fname)) + theme_bw() + + theme(panel.grid = element_blank(), + legend.position = "bottom" + ) + + color_scale + shape_scale + + labs(title = title) + mean_qc <- finite_mean(data[data$QC == "QC", fname]) + sd_qc <- finite_sd(data[data$QC == "QC", fname]) + mean_sample <- finite_mean(data[data$QC != "QC", + fname]) + sd_sample <- finite_sd(data[data$QC != "QC", fname]) + y_intercepts <- sort(c(`-2 SD (Sample)` = mean_sample - + 2 * sd_sample, `-2 SD (QC)` = mean_qc - 2 * + sd_qc, `+2 SD (QC)` = mean_qc + 2 * sd_qc, `+2 SD (Sample)` = mean_sample + + 2 * sd_sample)) + for (yint in y_intercepts) { + p <- p + geom_hline(yintercept = yint, color = "grey", + linetype = "dashed") + } + p + scale_y_continuous(sec.axis = sec_axis(~., breaks = y_intercepts, + labels = names(y_intercepts))) + geom_point(data = data, + mapping = aes_string(color = color, shape = shape)) + }, error = function(cond) { + message(paste0("Problem with ", fname)) + message("Here's the original error message:") + message(conditionMessage(cond)) + print(fname) + }) + } + # Discard ones with missing QC as they cant be plotted! + orig <- orig[dc@featureData@data$DC_note != "Missing_QCS",] + predicted <- predicted[dc@featureData@data$DC_note != "Missing_QCS",] + dc <- dc[dc@featureData@data$DC_note != "Missing_QCS",] + + # also set some kind of threshold for abundance. + temp <- apply(exprs(dc),1, finite_median) + temp <- sort(temp, decreasing = T) + temp <- temp[1:(length(temp)/3)] + temp <- names(temp) + + orig <- orig[temp,] + predicted <- predicted[temp,] + dc <- dc[temp,] + + # select features based on n_plotting + # half best and half worse corrections based on D_ratio + + temp <- fData(dc) + # headilla ascendic + sel_feat_1 <- head(temp[order(temp$DC_delta_D_ratio_r, decreasing = T),], + n = 1)$Feature_ID + sel_feat <- head(temp[order(temp$DC_delta_D_ratio_r, decreasing = T),], + n = round(n_plotting/2))$Feature_ID + # descendic + sel_feat <- c(sel_feat, head(temp[order(temp$DC_delta_D_ratio_r, decreasing = F),], + n = round(n_plotting/2, digits = 0))$Feature_ID) + orig <- orig[sel_feat,] + predicted <- predicted[sel_feat,] + dc <- dc[sel_feat,] + + orig_data_log <- combined_data(log(orig)) + dc_data_log <- combined_data(log(dc)) + orig_data <- combined_data(orig) + dc_data <- combined_data(dc) + predictions <- as.data.frame(t(predicted)) + predictions$Injection_order <- orig_data$Injection_order + + pdf(paste0(file, "Drift_correction_",format(Sys.time(), "%Y%m%d"), ".pdf"), + width = width, height = height) + for (fname in Biobase::featureNames(dc)) { + p2 <- dc_plot_helper(data = dc_data, fname = fname, + title = "After") + if (log_transform) { + p1 <- dc_plot_helper(data = orig_data, fname = fname, + title = "Before") + p3 <- dc_plot_helper(data = orig_data_log, fname = fname, + title = "Drift correction in log space") + geom_line(data = predictions, + color = "grey") + p4 <- dc_plot_helper(data = dc_data_log, fname = fname, + title = "Corrected data in log space") + tryCatch(expr = { + p <- cowplot::plot_grid(p1, p3, p2, p4, nrow = 2) + }, error = function(e) { + message("Caught an error!") + print(fname) + print(e) + }) + } + else { + p1 <- dc_plot_helper(data = orig_data, fname = fname, + title = "Before (original values)") + geom_line(data = predictions, + color = "grey") + tryCatch(expr = { + p <- cowplot::plot_grid(p1, p2, nrow = 2) + }, error = function(e) { + message("Caught an error!") + print(fname) + print(e) + }) + } + plot(p) + } + dev.off() + + Cairo::Cairo(file = paste0(file, "drift_cor_report.png"), unit = "in", dpi = 72, width = 7, + height = 7, type = "png", bg = "white") + fname <- sel_feat_1 + p2 <- dc_plot_helper(data = dc_data, fname = fname, + title = "After") + if (log_transform) { + p1 <- dc_plot_helper(data = orig_data, fname = fname, + title = "Before") + p3 <- dc_plot_helper(data = orig_data_log, fname = fname, + title = "Drift correction in log space") + geom_line(data = predictions, + color = "grey") + p4 <- dc_plot_helper(data = dc_data_log, fname = fname, + title = "Corrected data in log space") + tryCatch(expr = { + p <- cowplot::plot_grid(p1, p3, p2, p4, nrow = 2) + }, error = function(e) { + message("Caught an error!") + print(fname) + print(e) + }) + } + else { + p1 <- dc_plot_helper(data = orig_data, fname = fname, + title = "Before (original values)") + geom_line(data = predictions, + color = "grey") + tryCatch(expr = { + p <- cowplot::plot_grid(p1, p2, nrow = 2) + }, error = function(e) { + message("Caught an error!") + print(fname) + print(e) + }) + } + plot(p) + dev.off() + log_text(paste("\nSaved drift correction plots to:", file)) +} + +############################################################################### +############################################################################### + +inspect_dc_temp <- function (orig, dc, check_quality, condition = "RSD_r < 0 & D_ratio_r < 0") +{ + if (is.null(quality(orig))) { + orig <- assess_quality(orig) + } + if (is.null(quality(dc))) { + dc <- assess_quality(dc) + } + orig_data <- exprs(orig) + dc_data <- exprs(dc) + fnames <- featureNames(orig) + qdiff <- quality(dc)[2:5] - quality(orig)[2:5] + log_text(paste("Inspecting drift correction results", Sys.time())) + inspected <- foreach::foreach(i = seq_len(nrow(orig_data)), + .combine = comb_temp, .export = c("%>%", "qdiff")) %dopar% + { + data <- orig_data[i, ] + if (all(is.na(dc_data[i, ]))) { + dc_note <- "Missing_QCS" + } + else if (any(dc_data[i, ] < 0, na.rm = TRUE)) { + dc_note <- "Negative_DC" + } + else if (check_quality) { + pass <- paste0("qdiff[i, ] %>% dplyr::filter(", + condition, ") %>% nrow() %>% as.logical()") %>% + parse(text = .) %>% eval() + if (!pass) { + dc_note <- "Low_quality" + } + else { + data <- dc_data[i, ] + dc_note <- "Drift_corrected" + } + } + else { + data <- dc_data[i, ] + dc_note <- "Drift_corrected" + } + list(data = matrix(data, nrow = 1, dimnames = list(fnames[i], + names(data))), dc_notes = data.frame(Feature_ID = fnames[i], + DC_note = dc_note, stringsAsFactors = FALSE)) + } + exprs(dc) <- inspected$data + dc <- assess_quality(dc) + dc <- join_fData(dc, inspected$dc_notes) + + # Join delta values + qdiff <- cbind(rownames(qdiff), qdiff) + colnames(qdiff) <- c("Feature_ID", "DC_delta_RSD", "DC_delta_RSD_r", "DC_delta_D_ratio", "DC_delta_D_ratio_r") + dc <- join_fData(dc, qdiff) + + log_text(paste("Drift correction results inspected at", + Sys.time())) + dc_note <- inspected$dc_notes$DC_note + note_counts <- table(dc_note) %>% unname() + note_percentage <- note_counts/sum(note_counts) + note_percentage <- scales::percent(as.numeric(note_percentage)) + note_labels <- table(dc_note) %>% names() + report <- paste(note_labels, note_percentage, sep = ": ", + collapse = ", ") + log_text(paste0("\nDrift correction results inspected, report:\n", + report)) + dc +} + +comb_temp <- function (x, ...) +{ + mapply(rbind, x, ..., SIMPLIFY = FALSE) +} + +############################################################## + +read_MSDIAL <- function(tablefile, ion_mod = ""){ + tbl <- read.delim(tablefile, header = F, quote = "") + + corner_row <- which(tbl[, 1] != "")[1] + corner_column <- which(tbl[1, ] != "")[1] + + # Featuredata + peakmetadata_cols <- tbl %>% + dplyr::select(1:(corner_column)) %>% + dplyr::slice(corner_row:dplyr::n()) + + colnames(peakmetadata_cols) <- as.character(unlist(peakmetadata_cols[1,])) + row_tbl <- peakmetadata_cols[-1,] + + if (ion_mod != ""){ + row_tbl$Split <- ion_mod + } else { + row_tbl$Split <- "Unknown" + } + + row_tbl <- name_features(as.data.frame(row_tbl)) + + row_tbl <- row_tbl %>% dplyr::select(Feature_ID, + Split, dplyr::everything()) %>% + best_classes() %>% + dplyr::mutate_if(is.factor, as.character) + + rownames(row_tbl) <- row_tbl$Feature_ID + fData <- as.data.frame(row_tbl) + + # extract the sample information (pData) and expression table + quantval_cols <- tbl %>% dplyr::select((corner_column+1):ncol(tbl)) + # select(all_of(corner_column)) + + # pData + pData <- as.data.frame(t(quantval_cols[c(1:corner_row),])) + + # colnames for pData + temp <- t(tbl[1:corner_row,corner_column]) + temp <- ifelse(temp == "Type", "QC", temp) + temp <- ifelse(temp == "File type", "QC", temp) + + temp[grepl("batch",temp, ignore.case = T)] <- "Batch" + + colnames(pData) <- temp # c("Class", "FileType","InjectionOrder", "BatchId", "SampleId") + pData <- as.data.frame(pData) + colnames(pData) <- gsub(" ", "_", colnames(pData)) + + pData$Sample_ID <- pData$Class + + # mark blanks + pData$QC[grepl("blank",pData$Sample_ID, ignore.case = T)]<-"Blank" + pData$Sample_ID[pData$Sample_ID == "Blank"] <- paste0("Blank_", seq_len(sum(pData$Sample_ID == "Blank", na.rm = T))) + + # mark QC + pData$QC[grepl("QC",pData$Sample_ID, ignore.case = T)] <- "QC" + subset <- pData$Sample_ID == "QC" & !is.na(pData$Sample_ID) + pData$Sample_ID[subset] <- paste0("QC_", seq_len(sum(pData$Sample_ID == "QC", na.rm = T))) + # pData$Sample_ID[grepl("QC",pData$Sample_ID, ignore.case = T)] <- "QC" + + # If averages and stdev still occure this will remove those + pData <- pData[!(pData$Batch %in% c("Average", "Stdev")),] + len_pdata <- nrow(pData) + + pData$Sample_ID <- paste0(make.unique(pData$Sample_ID, sep = "_")) + + # final pData + rownames(pData) <- pData$Sample_ID + + # Expression part + quantval_tbl <- as.matrix(quantval_cols[-c(1:corner_row),c(1:len_pdata)] %>% + dplyr::mutate(across(where(is.character), as.numeric))) + + rownames(quantval_tbl) <- rownames(fData) + colnames(quantval_tbl) <- rownames(pData) + + return(list(exprs = quantval_tbl, pheno_data = pData, feature_data = fData)) +} + +# set up path +path <- file.path(path, "/") +grouping_name <- "Class" + +set.seed(1234567) + +if (exists("ion_mod")){ + data <- read_MSDIAL(paste0(path, file_name), ion_mod = ion_mod) +} else { + data <- read_MSDIAL(paste0(path, file_name)) +} + +# # if data have more modes +# if(split_col =! ""){ +# data <- notame::read_from_excel(file = paste0(path, ""), sheet = 1, split_by = split_col) +# } + +if (exists("data")) { + # Replace spaces with underscores if necessary + rownames(data$exprs) <- gsub(" ", "_", rownames(data$exprs)) + rownames(data$feature_data) <- gsub(" ", "_", rownames(data$feature_data)) + data$feature_data$Feature_ID <- gsub(" ", "_", data$feature_data$Feature_ID) + + # Works with one or more modes + # Construct MetaboSet objects + # (note: assumption is that the dataset already contains group information) + + if ("Parameter1" %in% colnames(data$pheno_data) & "Parameter2" %in% colnames(data$pheno_data)){ + metaboset <- notame::construct_metabosets(exprs = data$exprs, pheno_data = data$pheno_data, + feature_data = data$feature_data, + group_col = "Parameter1", time_col = "Parameter2", split_data = F) + } else{ + metaboset <- notame::construct_metabosets(exprs = data$exprs, pheno_data = data$pheno_data, + feature_data = data$feature_data, + group_col = "Class", split_data = F) + } + + # Make sure that injection order is numeric + metaboset$Injection_order <- as.numeric(metaboset$Injection_order) + + # Plot PCA at the beginning and then after preprocessing at the end + metaboset_temp <- metaboset[,!metaboset$QC %in% "Blank"] + # metaboset_temp <- metaboset_temp[, metaboset_temp$QC != "QC"] + + PCA_start <- plot_pca(metaboset_temp, color = "Class", title = "Before preprocessing") + PCA_start_inj <- plot_pca(metaboset_temp, color = "Injection_order", title = "Before preprocessing") + + # Preprocessing of ONE mode + # (NB: visualizations disabled here for saving computational time, + # Also, create a folder called figures in the working folder if you create visualizations) + + # First, set all zero abundances to NA and asses the detection rate and flag based on that + metaboset <- notame::mark_nas(metaboset, value = 0) + metaboset <- notame::mark_nas(metaboset, value = 1) + metaboset <- notame::flag_detection(metaboset) + + # Then check that there is QC samples. + # The whole process is dependent on QC samples + if("QC" %in% metaboset$QC ){ + # Take several cores to speed up processing + num_cores <- parallel::detectCores() - 5 + cl <- parallel::makeCluster(num_cores) + doParallel::registerDoParallel(cl) + + # If lause. Jos alle 4 QC:ta + len_qc <- ncol(metaboset[, metaboset$QC == "QC"]) + + if (len_qc > 3){ + # Correct the possible drift + corrected <- correct_drift_temp(metaboset, check_quality = T, log_transform = T, + plotting = T, file = path, + n_plotting = 20) + } else{ + log_text(paste("\nNot enough QC samples. Only", len_qc, "QC samples and 4 needed.")) + log_text(paste("\nPreprocessing continues without drift correction.")) + corrected <- metaboset + } + + # flag based on quality + corrected <- notame::flag_quality(corrected) + # visualizations(corrected, prefix = paste0(path, "figures/", name, "_CLEANED")) + PCA_after_drift <- plot_pca(corrected, color = "Class", title = "After drift correction") + PCA_after_drift_inj <- plot_pca(corrected, color = "Injection_order", title = "After drift correction") + + # Remove the QCs for imputation + merged_no_qc <- notame::drop_qcs(corrected) + merged_no_qc <- merged_no_qc[,!merged_no_qc$QC %in% "Blank"] + + #visualizations(merged_no_qc, prefix = paste0(path, "figures/FULL_NO_QC")) + + # Imputation + # (note: may not be necessary especially if gap filling by compulsion was used in MS-DIAL) + + # Set seed number for reproducibility + set.seed(1234567) + imputed <- notame::impute_rf(merged_no_qc) + # Impute features with almost all NAs with 1 + imputed <- impute_simple(imputed, value = 1, na_limit = 0.8) + # Impute bad quality features + set.seed(1234567) + imputed <- impute_rf(imputed, all_features = TRUE) + + #Stop using several cores (releases them for other use) + parallel::stopCluster(cl) + + PCA_end <- plot_pca(imputed, color = "Class", title = "After preprocessing") + + # Plot the PCA for report + Cairo::Cairo(file = paste0(path,"PCA_for_report.png"), unit = "in", dpi = 72, width = 7, + height = 7, type = "png", bg = "white") + if(exists("PCA_after_drift")){ + plot(PCA_after_drift) + } else { + plot(PCA_end) + } + + dev.off() + + pdf(file = paste0(path, "PCA.pdf"), width = 16, height = 8) + if (length(unique(metaboset_temp$Batch))>1){ + plot(plot_pca(metaboset_temp, color = "Batch", title = "Before preprocessing")) + } + plot(PCA_start) + plot(PCA_start_inj) + plot(PCA_after_drift) + plot(PCA_after_drift_inj) + if (length(unique(imputed$Batch))>1){ + plot(plot_pca(imputed, color = "Batch", title = "After preprocessing")) + } + plot(PCA_end) + plot(plot_pca(imputed, color = "Injection_order", title = "After preprocessing")) + dev.off() + + # Save the merged and processed data + # options to save in rds format or to excel + print("Saving imputed files") + saveRDS(imputed, file = paste0(path, "full_data.RDS")) + write_to_excel(imputed, file = paste0(path, "full_data.xlsx")) + } else { + print("No QC samples so no drift correction nor imputation was done") + + print("Still saving the RDS and excel for further analysis.") + saveRDS(metaboset, file = paste0(path, "full_data.RDS")) + write_to_excel(metaboset, file = paste0(path, "full_data.xlsx")) + } +} else { + stop("Something went wrong in data reading.") +} + +######################################################################### + +# MUVR model to find most interesting ones +# Saves boxplot + +library(notame) +library(doParallel) +library(dplyr) +library(MUVR) +library(tidyr) + +notame_repeated_boxes <- function(file_path, file_name = "MUVR_plot.pdf", separate = group_col(object), + face = NULL, object, comp = T, name_col = NULL){ + pdf(file = paste0(file_path, file_name)) + + for (i in seq_len(nrow(object))) { + if (i%%500 == 0) { + cat(paste0("Iteration ", i, "/", nrow(object), "\n")) + } + + feat_name <- featureNames(object)[i] + p <- notame_boxplot(object = object, feat_name = feat_name, separate = separate, + face = face, comp = comp, name_col = name_col) + print(p) + } + dev.off() +} +# functions to produce the figures +notame_boxplot <- function(object, feat_name, name_col = NULL, + separate = group_col(object), + face = NULL, comp = NULL, free_y = T){ + metabolite <- as.data.frame(t(exprs(object[fData(object)$Feature_ID == feat_name]))) + metabolite <- cbind(metabolite, pData(object)[,separate]) + + # Add the group to facet + if(!is.null(face)){ + metabolite <- cbind(metabolite, pData(object)[,face]) + } + + colnames(metabolite) <- c("metabol", "sep") + # sep needs to be factor + metabolite$sep <- as.factor(metabolite$sep) + + # give the name for facet group + if(!is.null(face)){ + colnames(metabolite)[3] <- "face" + } + # add the title based on identification + if (!is.null(name_col)){ + if (!is.na(fData(object)[feat_name, name_col])){ + otsikko <- fData(object)[feat_name, name_col] + } + else{ + otsikko <- feat_name + } + } else{ + if (object@featureData@data[feat_name,"Metabolite.name"] != "Unknown"){ + otsikko <- paste0(object@featureData@data[feat_name,"Metabolite.name"], "\nFeat: ", feat_name) + } + else{ + otsikko <- feat_name + } + + } + + library(ggpubr) + + nutri_color <- c("#009FB8", "#BB0A21", "#9063CD", "#F6AE2D", "#3BC62F", "#DC7FA1", "#09715E", + "#747CC9", "#CB613F", "#65A74F", "#B1953F", "#B65CBF", "#48B1A7", "#C8577B") + Tissue_plot1 <- ggpubr::ggboxplot(metabolite, x = "sep", y = "metabol", + title = otsikko, fill = "sep", palette = nutri_color) + + theme_bw() + + theme(axis.text.x = element_text(angle = 90), + axis.title = element_blank(), + plot.title = element_text(hjust = 0.5)) + + if(!is.null(comp)){ + if(is.list(comp)){ + Tissue_plot1 <- Tissue_plot1 + + geom_signif(comparisons = comp, + map_signif_level=sigFunc, + margin_top = seq(-0.1, 0.1*length(comp), length.out = length(comp))) + + scale_y_continuous(expand = c(0.2,0)) + } + else{ + comp <- t(combn(levels(metabolite$sep),2)) + comp <- split(comp, 1:nrow(comp)) + Tissue_plot1 <- Tissue_plot1 + + geom_signif(comparisons = comp, + map_signif_level=sigFunc, + margin_top = seq(-0.1, 0.1*length(comp), length.out = length(comp)), + vjust = 0.6) + } + } + if(!is.null(face)){ + if(free_y){ + Tissue_plot1 + facet_wrap(.~face, scales = "free_y") + } + else{ + Tissue_plot1 + facet_wrap(.~face) + } + + } + else{ + Tissue_plot1 + } +} +# Help function to geom_signif +sigFunc = function(x){ + # browser() + if(x < 0.001){"***"} + else if(x < 0.01){"**"} + else if(x < 0.05){"*"} + else{NA}} + +plot_boxes_notame <- function(metaboset_figure, separate = "Class", ppath){ + temp <- combined_data(metaboset_figure) + feat_names <- featureNames(metaboset_figure) + # Make temp long + # - data: Data object + # - key: Name of new key column (made from names of data columns) + # - value: Name of new value column + data_long <- gather(data = temp, key = feature, value = abund, feat_names, factor_key=TRUE) + + comp <- t(combn(unique(metaboset_figure[[separate]]),2)) + comp <- split(comp, 1:nrow(comp)) + + # metabolite in all metabolites + p1 <- ggboxplot(data_long, x = separate, y = "abund", ggtheme = theme_bw()) + + theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + p2 <- facet(p = p1, facet.by = "feature", scales = "free") + + geom_signif(comparisons = comp, + map_signif_level=sigFunc, + margin_top = seq(-0.1, 0.1*length(comp), length.out = length(comp)), + vjust = 0.6) + + dpi <- 72 + format <- "png" + imgName <- "box_plot" + imgName = paste0(ppath, imgName, "dpi", dpi, ".", format) + Cairo::Cairo(file = imgName, unit = "in", dpi = 72, width = 9, + height = 9, type = "png", bg = "white") + plot(p2) + dev.off() +} + +# Add citations +add_cit <- function (name, ref) +{ + cites <- getOption("notame.citations") + if (!name %in% names(cites)) { + cites[[name]] <- ref + options(notame.citations = cites) + } +} + +# is numeric +looks_num <- function (x) +{ + stopifnot(is.atomic(x) || is.list(x)) + num_nas <- sum(is.na(x)) + num_nas_new <- suppressWarnings(sum(is.na(as.numeric(x)))) + return(num_nas_new == num_nas) +} + +# MUVR function +MUVR_run <- function (object, y = NULL, id = NULL, multi_level = FALSE, + multi_level_var = NULL, covariates = NULL, static_covariates = NULL, + all_features = FALSE, nRep = 5, nOuter = 6, nInner = nOuter - + 1, varRatio = 0.75, method = c("PLS", "RF"), ...) +{ + add_cit("MUVR package was used to fit multivariate models with variable selection:", + citation("MUVR")) + classes <- sapply(pData(object)[, c(covariates, static_covariates)], + class) + if (length(classes) && any(classes != "numeric")) { + stop("MUVR can only deal with numeric inputs, please transform all covariates to numeric", + call. = FALSE) + } + object <- drop_flagged(object, all_features = all_features) + if (any(!sapply(pData(object)[, covariates], looks_num))) { + stop("All covariates should be convertable to numeric") + } + pData(object)[covariates] <- lapply(pData(object)[covariates], + as.numeric) + if (!multi_level) { + if (is.null(y)) { + stop("y variable needs to be defined unless doing multi-level modeling") + } + predictors <- combined_data(object)[, c(featureNames(object), + covariates)] + outcome <- pData(object)[, y] + if (is.null(id)) { + muvr_model <- MUVR::MUVR(X = predictors, Y = outcome, + nRep = nRep, nOuter = nOuter, nInner = nInner, + varRatio = varRatio, method = method, ...) + } + else { + ID <- pData(object)[, id] + muvr_model <- MUVR::MUVR(X = predictors, Y = outcome, + ID = ID, nRep = nRep, nOuter = nOuter, nInner = nInner, + varRatio = varRatio, method = method, ...) + } + } + else { + if (is.null(id) || is.null(multi_level_var)) { + stop("id and multi_level_var needed for multi-level modeling") + } + ml_var <- pData(object)[, multi_level_var] <- as.factor(pData(object)[, + multi_level_var]) + if (length(levels(ml_var)) != 2) { + stop("The multilevel variable should have exactly 2 unique values") + } + else { + cat(paste("Computing effect matrix according to", + multi_level_var, ":", levels(ml_var)[2], "-", + levels(ml_var)[1])) + } + cd <- combined_data(object) + cd <- cd[order(cd[, id]), ] + x1 <- cd[cd[, multi_level_var] == levels(ml_var)[1], + c(featureNames(object), covariates)] + x2 <- cd[cd[, multi_level_var] == levels(ml_var)[2], + c(featureNames(object), covariates)] + predictors <- x2 - x1 + predictors[, static_covariates] <- cd[cd[, multi_level_var] == + levels(ml_var)[1], static_covariates] + rownames(predictors) <- unique(cd[, id]) + if (!is.null(y)) { + outcome <- cd[cd[, multi_level_var] == levels(ml_var)[1], + y] + muvr_model <- MUVR::MUVR(X = predictors, Y = outcome, + nRep = nRep, nOuter = nOuter, nInner = nInner, + varRatio = varRatio, method = method, ...) + } + else { + muvr_model <- MUVR::MUVR(X = predictors, ML = TRUE, + nRep = nRep, nOuter = nOuter, nInner = nInner, + varRatio = varRatio, method = method, ...) + } + } + muvr_model +} + +############################################### +############################################### + +ppath <- file.path(path, "/") +fig_comp <- TRUE +saveresults <- TRUE +report <- TRUE + +set.seed(1234567) + +# read the data +metaboset <- readRDS(file = paste0(ppath, "full_data.RDS")) + +# Take several cores to speed up processing +num_cores <- parallel::detectCores() - 5 +cl <- parallel::makeCluster(num_cores) +doParallel::registerDoParallel(cl) + +if (min(table(metaboset$Class)) < 2) { + num_outer <- 1 +} else if (min(table(metaboset$Class)) < 6){ + num_outer <- min(table(metaboset$Class)) +} else { + num_outer <- 6 +} + +# if () # modify it so that it gives warnings that there is no enough classes! +# # alternatively use parameters1 or two to do the MUVR + +if (min(table(metaboset$Class)) < 2){ + log_text("\nNumber of Class is too low! MUVR can not be performed!") +} else { + # Run the MUVR algorithm to take most interesting ones + MUVR_res <- MUVR_run(object = metaboset, y = "Class", + method = "RF", nOuter = num_outer) + parallel::stopCluster(cl) + + MUVR_vip <- MUVR::getVIP(MVObj = MUVR_res, model = "max") + + if (nrow(MUVR_vip) > 20) { + MUVR_vip <- MUVR::getVIP(MVObj = MUVR_res, model = "mid") + } + if (nrow(MUVR_vip) > 20 & nrow(getVIP(MVObj = MUVR_res, model = "min")) > 10 ) { + MUVR_vip <- MUVR::getVIP(MVObj = MUVR_res, model = "min") + } + if (nrow(MUVR_vip) > 20) { + MUVR_vip <- MUVR_vip[1:20,] + } + + metaboset_figure <- metaboset[MUVR_vip$name,] + + colnames <- colnames(pData(metaboset)) + if ("Parameter1" %in% colnames & "Parameter2" %in% colnames){ + notame_repeated_boxes(file_path = ppath, object = metaboset_figure, + comp = fig_comp, separate = "Parameter1", face = "Parameter2") + if(nrow(MUVR_vip) > 12){ + MUVR_vip <- MUVR_vip[1:12,] + metaboset_figure <- metaboset[MUVR_vip$name,] + } + + plot_boxes_notame(metaboset_figure, separate = "Parameter1", ppath = ppath) + + } else{ + notame_repeated_boxes(file_path = ppath, object = metaboset_figure, comp = fig_comp) + if(nrow(MUVR_vip) > 12){ + MUVR_vip <- MUVR_vip[1:12,] + metaboset_figure <- metaboset[MUVR_vip$name,] + } + plot_boxes_notame(metaboset_figure, ppath = ppath) + } + # Extract all VIP values and add to object + # MUVR_vip_all <- MUVR::getVIP(MVObj = MUVR_res, model = "max") + + nVar <- drop_flagged(metaboset) + nVar <- nrow(nVar) + VIPs = sort(MUVR_res$VIP[, "max"])[1:nVar] + VIPs = data.frame(order = 1:nVar, name = names(VIPs), rank = VIPs) + VIPs$name = as.character(VIPs$name) + + VIPs <- VIPs[,c(2,3)] + colnames(VIPs) <- c("Feature_ID", "VIP_score_MUVR") + metaboset <- notame::join_fData(metaboset, VIPs) + if (saveresults){ + saveRDS(metaboset, file = paste0(ppath, "MUVR_full_data.RDS")) + write_to_excel(metaboset, file = paste0(ppath, "MUVR_full_data.xlsx")) + } +} + +##### +# functions for reporting +metaboset_printer_temp <- function(x) { + temp <- paste("MetaboSet object with", nrow(x), "features and", ncol(x), "samples.\n") + temp <- paste(temp, sum(x$QC == "QC"), "QC samples included\n") + temp <- paste(temp, + sum(is.na(flag(x))), "non-flagged features,", + sum(!is.na(flag(x))), "flagged features.\n\n") + + if (!is.na(group_col(x))) { + temp <- paste0(temp, group_col(x), ":\n") + temp <- paste0(temp, print_levels_temp(pData(x)[, group_col(x)])) + } + if (!is.na(time_col(x))) { + temp <- paste0(temp, time_col(x), ":\n") + temp <- paste0(temp, print_levels_temp(pData(x)[, time_col(x)])) + } + if (!is.na(subject_col(x))) { + temp <- paste0(subject_col(x), ":\n") + subject <- as.character(pData(x)[, subject_col(x)]) + subject <- subject[!grepl("QC", subject)] + temp <- paste0(temp, + " ", length(unique(subject)), " distinct subjects\n min:", + min(table(subject)), ", max:", max(table(subject)), + " observations per subject.\n" + ) + } + + temp <- paste0(temp,"\nThe object has the following parts (splits):\n") + splits <- unique(fData(x)$Split) + t_splits <- table(fData(x)$Split) + for (split in splits) { + temp <- paste0(temp, " ", split, ": ", t_splits[split], " features\n") + } + temp <- paste0(temp, "\n") + return(temp) +} +print_levels_temp <- function(v) { + t_groups <- table(v) + if (is.factor(v)) { + groups <- levels(v) + } else { + groups <- unique(v) + } + output <- sapply(groups, function(y) { + obs <- t_groups[y] + paste0(y, ": ", obs) + }) + output <- paste(output, collapse = ", ") + return(paste(" ", output, "\n")) +} +desc_metaboset <- metaboset_printer_temp(metaboset) + +##################################################### \ No newline at end of file diff --git a/src/MSDIAL5/MsdialGuiApp/Resources/Report.R b/src/MSDIAL5/MsdialGuiApp/Resources/Report.R new file mode 100644 index 000000000..6b1c852f3 --- /dev/null +++ b/src/MSDIAL5/MsdialGuiApp/Resources/Report.R @@ -0,0 +1,142 @@ +# Reporting +if(report){ + setwd(ppath) + usrName <- "By Hanhineva Lab" + file.create("Notame_Report.Rnw") + rnwFile <- file("Notame_Report.Rnw", "w") + # fig.count <<- 0 + # table.count <<- 0 + header <- c("\\documentclass[a4paper]{article}", "\\usepackage[margin=1.0in]{geometry}", + "\\usepackage{longtable}", "\\usepackage{graphicx}", + "\\usepackage{grffile}", "<>=", "options(width=60);", + "@", "\\SweaveOpts{eps=FALSE,pdf=TRUE}", "\\title{Notame preprocessing report}", + paste("\\author{", usrName, "}", sep = ""), + "\\begin{document}", "\\parskip=.3cm", "\\maketitle") + cat(header, file = rnwFile, sep = "\n", append = TRUE) + + # Background information + + descr <- "\\section{About notame}\n + Notame (NOn-TArgeted MEtabolomics) is an R package designed to preprocess + LC-MS metabolomics data and provide quality metrics, statistics, and + results visualizations. The package was originally developed by Anton + Klåvus at the Kati Hanhineva lab, University of Eastern Finland, and + it utilizes several other R packages, such as MUVR, to perform the + data processing. The notame publication, including a description of a + complete LC-MS workflow, is freely available. + \\footnote{Klåvus A, Kokla M, Noerman S, et al. + \\textit{Notame: Workflow for Non-Targeted LC–MS Metabolic Profiling}, + Metabolites. 2020; 10(4):135.}\n" + + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + + # Drift correction + descr <- ("\\section{Drift correction}\n + Signal drift is a typical issue in LC-MS metabolomics, affecting sequences + with 30 to 50 injections or more. It causes a gradual change in the signal + intensity of the molecular features during the LC-MS analysis, which should + be corrected for optimal data quality. Notame utilizes information from the + QC samples to correct the drift. The QC samples are pooled from the biological + samples and injected before and after the samples as well as after every + 10 to 12 samples in the sequence. Notame performs drift correction by fitting + a smoothed cubic spline to the signal intensities of the QC samples, + separately for each molecular feature. The smoothing function prevents + overfitting the curve in case there are single deviating QC samples.\n + Please note that at least four QC samples are needed in the dataset to + perform this step. If your data has less, it is advisable to check the + PCA instead, where the QC samples should be tightly clustered.\n") + + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + if(file.exists("drift_cor_report.png")){ + fig <- c("\\begin{figure}[htbp]", "\\begin{center}", paste("\\includegraphics[width=1.0\\textwidth]{", + "drift_cor_report.png", "}", sep = ""), "\\caption{Most signigicant features}", + "\\end{center}", paste("\\label{", "drift_cor_report.png", + "}", sep = ""), "\\end{figure}", "\\clearpage\n\n") + cat(fig, file = rnwFile, append = TRUE, sep = "\n") + } else{ + descr <- "\\textbf{Selected peak file has less than 3 QC samples. Thus the drift correction was not made.}" + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + } + # Quality metrics + descr <- ("\\section{Quality metrics}\n + The quality of each molecular feature is determined by calculating + descriptive values according to the recommendations by Broadhurst et al. + \\footnote{Broadhurst D, Goodacre R, Reinke SN et al. + \\textit{Guidelines and considerations for the use of system suitability and + quality control samples in mass spectrometry assays applied in untargeted + clinical metabolomic studies.}, + Metabolomics 14, 72 (2018).} + . The following quality criteria should be met to consider the molecular + feature of good quality: the detection rate in the QC samples is atleast + 70%, relative standard deviation (RSD) in the QC samples is less than 0.2 + (20%), and the D-ratio is less than 0.4. D-ratio or dispersion ratio is + the sample standard deviation of the QC samples divided by the sample + standard deviation of the biological samples. The output data matrix from + Notame will include a column titled Flag that indicates whether the + molecular feature was flagged for bad quality and the reason (low QC detection + or low quality).\n + The flag for low QC detection or low quality is not intended for automatically + discarding all such peaks but rather be used as a warning signal to pay close + attention to the peak (e.g., peak shape, peak area integration, signal-to-noise + ratio) and to decide yourself whether the feature has sufficient quality for + reporting. For example, in highly variable sample sets, a true metabolite that + has detectable levels only in a few samples may dilute below the detection limit + in the pooled QC samples and result in a flag for low QC detection.\n\n") + + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + cat(desc_metaboset, file = rnwFile, append = TRUE, sep = "\n") + + # PCA + descr <- c("\\section{Overview of the data}\n", + "PCA can give brief overview of the data.") + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + + fig <- c("\\begin{figure}[htbp]", "\\begin{center}", paste("\\includegraphics[width=1.0\\textwidth]{", + "PCA_for_report.png", "}", sep = ""), "\\caption{PCA plot of classes in data}", + "\\end{center}", paste("\\label{", "PCA_for_report.png", + "}", sep = ""), "\\end{figure}", "\\clearpage\n\n") + cat(fig, file = rnwFile, append = TRUE, sep = "\n") + + + + # MUVR + descr <- ("\\section{Selection of differential molecular features with MUVR}\n + MUVR (Multivariate methods with Unbiased Variable selection in R) is an + algorithm developed by Lin Shi and Carl Brunius at the Chalmers University + of Technology + \\footnote{Shi L, Westerhuis JA, Rosén J, et al. + \\textit{Variable selection and validation in multivariate modelling.}, + Bioinformatics. 2019 Mar 15;35(6):972-980.} + . It chooses a limited number of molecular features, in this case maximum + 50, that differ between the study groups (given in the Class column in + MS-DIAL project). The algorithm uses a recursive variable selection procedure + with partial least squares (PLS) and random forest (RF) modelling.\n + The molecular features chosen by MUVR are accompanied with box plots and + can be used as a starting point for manual curation of the data and finding + the relevant metabolites for your study question.") + + cat(descr, file = rnwFile, append = TRUE, sep = "\n") + + fig <- c("\\begin{figure}[htbp]", "\\begin{center}", paste("\\includegraphics[width=1.0\\textwidth]{", + "box_plotdpi72.png", "}", sep = ""), "\\caption{12 most signigicant features}", + "\\end{center}", paste("\\label{", "box_plotdpi72.png", + "}", sep = ""), "\\end{figure}", "\\clearpage\n\n") + cat(fig, file = rnwFile, append = TRUE, sep = "\n") + + + # Finally close the file + + end <- c("\\vspace{5 mm}\n\n--------------------------------\n\n", + "The report was generated on \\Sexpr{date()}, OS system:", + "\\Sexpr{Sys.info()['sysname']}, version: \\Sexpr{gsub('#[0-9]+', '', Sys.info()['version'])} .\n", + "\\end{document}\n\n") + cat(end, file = rnwFile, append = TRUE) + + close(rnwFile) + + utils::Sweave(file = "Notame_Report.Rnw", encoding = "utf8") + res <- try(tools::latexmk("Notame_Report.tex", pdf = TRUE, + quiet = TRUE)) + tinytex::latexmk("Notame_Report.tex") +} +# END \ No newline at end of file diff --git a/src/MSDIAL5/MsdialGuiApp/Resources/notame.png b/src/MSDIAL5/MsdialGuiApp/Resources/notame.png new file mode 100644 index 000000000..10bcd0ac3 Binary files /dev/null and b/src/MSDIAL5/MsdialGuiApp/Resources/notame.png differ diff --git a/src/MSDIAL5/MsdialGuiApp/View/Core/MainWindow.xaml.cs b/src/MSDIAL5/MsdialGuiApp/View/Core/MainWindow.xaml.cs index cf0f80751..424873749 100644 --- a/src/MSDIAL5/MsdialGuiApp/View/Core/MainWindow.xaml.cs +++ b/src/MSDIAL5/MsdialGuiApp/View/Core/MainWindow.xaml.cs @@ -137,6 +137,8 @@ public MainWindow() { .Subscribe(ShowChildContent("Substructure Viewer", height: 600, width: 1000)); broker.ToObservable() .Subscribe(ShowChildContent("FSEA Result Viewer", height: 600, width: 1000)); + broker.ToObservable() + .Subscribe(ShowChildSettingDialog("Notame preprocessing", height: 500, width: 450, finishCommandContent: "Run")); /* broker.ToObservable() .Subscribe(ShowChildView); diff --git a/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialDataVisualizationTab.xaml b/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialDataVisualizationTab.xaml index 7e1c0486a..6de332ae5 100644 --- a/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialDataVisualizationTab.xaml +++ b/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialDataVisualizationTab.xaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:vm="clr-namespace:CompMs.App.Msdial.ViewModel.Core" + xmlns:stat="clr-namespace:CompMs.App.Msdial.ViewModel.Statistics" xmlns:common="clr-namespace:CompMs.CommonMVVM;assembly=CommonMVVM" xmlns:enum="clr-namespace:CompMs.Common.Enum;assembly=Common" mc:Ignorable="d" @@ -45,5 +46,8 @@ + diff --git a/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialProcessingTab.xaml b/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialProcessingTab.xaml index 1651d73fb..9e709b295 100644 --- a/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialProcessingTab.xaml +++ b/src/MSDIAL5/MsdialGuiApp/View/RibbonControl/MsdialProcessingTab.xaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:vm="clr-namespace:CompMs.App.Msdial.ViewModel.Core" + xmlns:commonmmvvm="clr-namespace:CompMs.CommonMVVM;assembly=CommonMVVM" mc:Ignorable="d" Header="Processing" KeyTip="P" d:DataContext="{d:DesignInstance Type={x:Type vm:MainWindowVM}}" > diff --git a/src/MSDIAL5/MsdialGuiApp/View/Setting/MolecularNetworkingExportSettingView.xaml.cs b/src/MSDIAL5/MsdialGuiApp/View/Setting/MolecularNetworkingExportSettingView.xaml.cs index 1e102736b..7afc792d9 100644 --- a/src/MSDIAL5/MsdialGuiApp/View/Setting/MolecularNetworkingExportSettingView.xaml.cs +++ b/src/MSDIAL5/MsdialGuiApp/View/Setting/MolecularNetworkingExportSettingView.xaml.cs @@ -19,7 +19,7 @@ public MolecularNetworkingExportSettingView() private void Browse_Click(object sender, RoutedEventArgs e) { var fbd = new Graphics.Window.SelectFolderDialog { - Title = "Chose a export folder.", + Title = "Choose a export folder.", }; if (fbd.ShowDialog() == Graphics.Window.DialogResult.OK) { diff --git a/src/MSDIAL5/MsdialGuiApp/View/Statistics/NotameView.xaml b/src/MSDIAL5/MsdialGuiApp/View/Statistics/NotameView.xaml new file mode 100644 index 000000000..e8145a278 --- /dev/null +++ b/src/MSDIAL5/MsdialGuiApp/View/Statistics/NotameView.xaml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + NOTAME ('NOn-TArgeted MEtabolomics') is an R-based tool to preprocess and clean metabolomics data. It will take 3-5 minutes. + In order to use Notame:1. You need to have a class property with 2 analysis parameters connected with underbar (ex. Food_Age, HighFat_2year). + 2. Quality control samples should be more than 3 (you can set QC's class as 'QC_QC' and blank's as just 'blank'). + For further information: + https://github.com/antonvsdata/notame + + + +