/// <summary> /// Initializes a new instance of the <see cref="SearchSettingsViewModel"/> class. /// Initializes from <see cref="Models.MsPfParameters" />, MSPathFinder parameters. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from view model</param> /// <param name="mspfParameters">The MSPathFinder parameters.</param> public SearchSettingsViewModel(IMainDialogService dialogService, MsPfParameters mspfParameters) : this(dialogService) { if (mspfParameters == null) { return; } SearchModifications.AddRange( mspfParameters.Modifications.Select( searchMod => new SearchModificationViewModel(this.dialogService) { SearchModification = searchMod })); MinSequenceLength = mspfParameters.MinSequenceLength; MaxSequenceLength = mspfParameters.MaxSequenceLength; MinSequenceMass = mspfParameters.MinSequenceMass; MaxSequenceMass = mspfParameters.MaxSequenceMass; MinPrecursorIonCharge = mspfParameters.MinPrecursorIonCharge; MaxPrecursorIonCharge = mspfParameters.MaxPrecursorIonCharge; MinProductIonCharge = mspfParameters.MinProductIonCharge; MaxProductIonCharge = mspfParameters.MaxPrecursorIonCharge; PrecursorIonToleranceValue = mspfParameters.PrecursorTolerancePpm.GetValue(); ProductIonToleranceValue = mspfParameters.ProductIonTolerancePpm.GetValue(); MaxDynamicModificationsPerSequence = mspfParameters.MaxDynamicModificationsPerSequence; }
/// <summary> /// Initializes a new instance of the <see cref="ManageModificationsViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from the view model.</param> public ManageModificationsViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; Modifications = new ReactiveList <Modification>(); AddCommand = ReactiveCommand.Create(AddImplementation); EditCommand = ReactiveCommand.Create(EditImplementation, this.WhenAnyValue(x => x.SelectedModification).Select(m => m != null)); RemoveCommand = ReactiveCommand.Create(RemoveImplementation, this.WhenAnyValue(x => x.SelectedModification).Select(m => m != null)); }
/// <summary> /// Initializes new instance of <see cref="FragmentViewModel" />. /// </summary> /// <param name="aminoAcid">The selected amino acid.</param> /// <param name="index">The index of this fragment within the greater sequence that it is part of.</param> /// <param name="dialogService">Dialog service for opening LCMSSpectator dialogs.</param> public FragmentViewModel(AminoAcid aminoAcid, int index = 0, IMainDialogService dialogService = null) { AminoAcid = aminoAcid; Index = index; SetModSymbol(aminoAcid as ModifiedAminoAcid); this.dialogService = dialogService ?? new MainDialogService(); SelectModificationCommand = ReactiveCommand.Create(SelectModificationImpl); // Update the modification symbol when the amino acid changes. this.WhenAnyValue(x => x.AminoAcid).Subscribe(aa => SetModSymbol(aa as ModifiedAminoAcid)); }
/// <summary> /// Initializes a new instance of the <see cref="ManageModificationsViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from the view model.</param> public ManageModificationsViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; this.Modifications = new ReactiveList <Modification>(); var addCommand = ReactiveCommand.Create(); addCommand.Subscribe(_ => this.AddImplementation()); this.AddCommand = addCommand; var editCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.SelectedModification).Select(m => m != null)); editCommand.Subscribe(_ => this.EditImplementation()); this.EditCommand = editCommand; var removeCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.SelectedModification).Select(m => m != null)); removeCommand.Subscribe(_ => this.RemoveImplementation()); this.RemoveCommand = removeCommand; }
/// <summary> /// Initializes new instance of the <see cref="SequenceViewerViewModel" /> class. /// </summary> /// <param name="dialogService">Service for opening LCMSSpectator dialogs.</param> public SequenceViewerViewModel(IMainDialogService dialogService) { this.dialogService = dialogService ?? new MainDialogService(); SequenceFragments = new ReactiveList <FragmentViewModel> { ChangeTrackingEnabled = true }; IonColorDictionary = new IonColorDictionary(2); // Update the sequence displayed when the fragmentation sequence or spectrum changes. this.WhenAnyValue( x => x.SelectedSpectrum, x => x.FragmentationSequence, x => x.FragmentationSequence.LabeledIonViewModels) .Throttle(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => ParseFragmentationSequence()); SequenceFragments.ItemChanged.Where(x => x.PropertyName == "AminoAcid") .Subscribe(x => UpdateSequence(x.Sender.AminoAcid, x.Sender.Index)); }
/// <summary> /// Initializes a new instance of the <see cref="DataSetViewModel"/> class. /// </summary> /// <param name="dialogService">A dialog service for opening dialogs from the view model</param> public DataSetViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; this.ReadyToClose = false; this.IdFileOpen = false; this.SelectedPrSm = new PrSm(); this.ScanViewModel = new ScanViewModel(dialogService, new List <PrSm>()); this.CreateSequenceViewModel = new CreateSequenceViewModel(dialogService) { SelectedDataSetViewModel = this }; this.CreateSequenceViewModel.CreateAndAddPrSmCommand.Subscribe( _ => this.ScanViewModel.Data.Add(this.CreateSequenceViewModel.SelectedPrSm)); // Remove filter by raw file name from ScanViewModel filters this.ScanViewModel.Filters.Remove(this.ScanViewModel.Filters.FirstOrDefault(f => f.Name == "Raw File Name")); // When a PrSm is selected from the ScanViewModel, update the SelectedPrSm for this data set this.ScanViewModel.WhenAnyValue(x => x.SelectedPrSm).Where(prsm => prsm != null).Subscribe(x => this.SelectedPrSm = x); // When the scan number in the selected prsm changes, the selected scan in the xic plots should update this.WhenAnyValue(x => x.SelectedPrSm) .Where(_ => this.SelectedPrSm != null && this.SpectrumViewModel != null && this.XicViewModel != null) .Subscribe(prsm => { this.SpectrumViewModel.UpdateSpectra(prsm.Scan, this.SelectedPrSm.PrecursorMz); this.XicViewModel.SetSelectedScan(prsm.Scan); this.XicViewModel.ZoomToScan(prsm.Scan); }); var prsmObservable = this.WhenAnyValue(x => x.SelectedPrSm).Where(prsm => prsm != null); prsmObservable .Select(prsm => prsm.GetFragmentationSequence()).Where(fragSeq => fragSeq != null) .Subscribe(fragSeq => { this.SpectrumViewModel.FragmentationSequence = fragSeq; this.XicViewModel.FragmentationSequence = fragSeq; }); // When the prsm changes, update the Scan View Model. prsmObservable.Subscribe(prsm => this.ScanViewModel.SelectedPrSm = prsm); // When the prsm updates, update the prsm in the sequence creator prsmObservable.Subscribe(prsm => this.CreateSequenceViewModel.SelectedPrSm = prsm); // When the prsm updates, update the feature map prsmObservable.Where(_ => this.FeatureMapViewModel != null).Subscribe(prsm => this.FeatureMapViewModel.FeatureMapViewModel.SelectedPrSm = prsm); // When prsm updates, subscribe to scan updates prsmObservable.Subscribe(prsm => { prsm.WhenAnyValue(x => x.Scan, x => x.PrecursorMz) .Where(x => x.Item1 > 0 && x.Item2 > 0 && this.SpectrumViewModel != null) .Subscribe(x => this.SpectrumViewModel.UpdateSpectra(x.Item1, x.Item2)); prsm.WhenAnyValue(x => x.Scan).Where(scan => scan > 0 && this.XicViewModel != null) .Subscribe(scan => this.XicViewModel.SetSelectedScan(scan)); }); // When a new prsm is created by CreateSequenceViewModel, update SelectedPrSm this.CreateSequenceViewModel.WhenAnyValue(x => x.SelectedPrSm).Subscribe(prsm => this.SelectedPrSm = prsm); // When IDs are filtered in the ScanViewModel, update feature map with new IDs this.ScanViewModel.WhenAnyValue(x => x.FilteredData).Where(_ => this.FeatureMapViewModel != null).Subscribe(data => this.FeatureMapViewModel.UpdateIds(data)); // Toggle instrument data when ShowInstrumentData setting is changed. IcParameters.Instance.WhenAnyValue(x => x.ShowInstrumentData).Select(async x => await this.ScanViewModel.ToggleShowInstrumentDataAsync(x, (PbfLcMsRun)this.LcMs)).Subscribe(); // When product ion tolerance or ion correlation threshold change, update scorer factory IcParameters.Instance.WhenAnyValue(x => x.ProductIonTolerancePpm, x => x.IonCorrelationThreshold) .Subscribe( x => { var scorer = new ScorerFactory(x.Item1, Constants.MinCharge, Constants.MaxCharge, x.Item2); this.CreateSequenceViewModel.ScorerFactory = scorer; this.ScanViewModel.ScorerFactory = scorer; }); // When an ID file has been opened, turn on the unidentified scan filter this.WhenAnyValue(x => x.IdFileOpen) .Where(idFileOpen => idFileOpen) .Select(_ => this.ScanViewModel.Filters.FirstOrDefault(f => f.Name == "Hide Unidentified Scans")) .Where(f => f != null) .Subscribe(f => f.Selected = true); // Start MsPf Search Command var startMsPfSearchCommand = ReactiveCommand.Create(); startMsPfSearchCommand.Subscribe(_ => this.StartMsPfSearchImplementation()); this.StartMsPfSearchCommand = startMsPfSearchCommand; // Close command verifies that the user wants to close the dataset, then sets ReadyToClose to true if they are var closeCommand = ReactiveCommand.Create(); closeCommand.Subscribe(_ => { this.ReadyToClose = dialogService.ConfirmationBox( string.Format("Are you sure you would like to close {0}?", this.Title), string.Empty); }); this.CloseCommand = closeCommand; }
/// <summary> /// Initializes new instance of the <see cref="StableIsotopeViewModel"/> class. /// </summary> public StableIsotopeViewModel(IMainDialogService dialogService = null) { this.dialogService = dialogService ?? new MainDialogService(); // Initialize default values this.IsotopeProportions = new Dictionary <string, IsotopeProportionSelectorViewModel> { { "C", new IsotopeProportionSelectorViewModel(Atom.Get("C"), IsoProfilePredictor.Predictor.ProbC) }, { "H", new IsotopeProportionSelectorViewModel(Atom.Get("H"), IsoProfilePredictor.Predictor.ProbH) }, { "N", new IsotopeProportionSelectorViewModel(Atom.Get("N"), IsoProfilePredictor.Predictor.ProbN) }, { "O", new IsotopeProportionSelectorViewModel(Atom.Get("O"), IsoProfilePredictor.Predictor.ProbO) }, { "S", new IsotopeProportionSelectorViewModel(Atom.Get("S"), IsoProfilePredictor.Predictor.ProbS) } }; this.SelectedElement = this.IsotopeProportions["C"]; this.Mass = 0; this.Charge = 1; this.ToleranceUnits = new ReactiveList <ToleranceUnit> { ToleranceUnit.Ppm, ToleranceUnit.Th }; this.ToleranceValue = 10.0; this.ToleranceUnit = ToleranceUnit.Ppm; this.RelativeIntensityThreshold = 0.1; this.ObservedPeaks = new ReactiveList <ListItemViewModel <PeakDataPoint> > { ChangeTrackingEnabled = true }; // Add some empty peaks initialy to peak list for (int i = 0; i < DefaultNumberOfPeakFields; i++) { this.ObservedPeaks.Add(new ListItemViewModel <PeakDataPoint>(new PeakDataPoint(0, 0, 0, 0, string.Empty))); } this.IsotopicEnvelopePlotViewModel = new IsotopicEnvelopePlotViewModel(); // When selected element is changed, reset all values this.WhenAnyValue(x => x.SelectedElement).Subscribe( el => { foreach (var element in this.IsotopeProportions.Values) { element.Reset(); } }); // When a peak's ShouldBeRemoved flag is set, remove it this.ObservedPeaks.ItemChanged.Where(i => i.PropertyName == "ShouldBeRemoved") .Where(i => i.Sender.ShouldBeRemoved) .Subscribe(i => this.ObservedPeaks.Remove(i.Sender)); // Commands this.BuildPlotCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.Mass).Select(mass => mass > 0.0)); this.BuildPlotCommand.Subscribe(_ => this.BuildIsotopicProfilePlot()); this.ResetToDefaultProportionsCommand = ReactiveCommand.Create(); this.ResetToDefaultProportionsCommand .Where(_ => this.SelectedElement != null) .Subscribe(_ => this.SelectedElement.Reset()); this.TuneConcentrationCommand = ReactiveCommand.Create(); this.TuneConcentrationCommand.Subscribe(_ => this.TuneConcentration()); this.PastePeaksFromClipboardCommand = ReactiveCommand.Create(); this.PastePeaksFromClipboardCommand.Subscribe(_ => this.PastePeaksFromClipboard()); this.ClearObservedPeaksCommand = ReactiveCommand.Create(); this.ClearObservedPeaksCommand.Subscribe(_ => this.ObservedPeaks.Clear()); this.AddObservedPeakCommand = ReactiveCommand.Create(); this.AddObservedPeakCommand.Subscribe(_ => this.ObservedPeaks .Add(new ListItemViewModel <PeakDataPoint>( new PeakDataPoint(0.0, 0.0, 0.0, 0.0, string.Empty)))); }
/// <summary> /// Initializes a new instance of the MainWindowViewModel class. /// </summary> /// <param name="dialogService">Service for view model friendly dialogs</param> /// <param name="dataReader">Service for reading raw files, id files, and feature files</param> public MainWindowViewModel(IMainDialogService dialogService, IDataReader dataReader) { this.dialogService = dialogService; this.dataReader = dataReader; // Initialize child view models DataSets = new ReactiveList <DataSetViewModel> { ChangeTrackingEnabled = true }; CreateSequenceViewModel = new CreateSequenceViewModel(this.dialogService); ScanViewModel = new ScanViewModel(this.dialogService, new List <PrSm>()); // Remove filter by unidentified scans from ScanViewModel filters ScanViewModel.Filters.Remove(ScanViewModel.Filters.FirstOrDefault(f => f.Name == "Hide Unidentified Scans")); // Create commands for file operations OpenDataSetCommand = ReactiveCommand.CreateFromTask(async _ => await OpenDataSetImplementation()); OpenRawFileCommand = ReactiveCommand.CreateFromTask(async _ => await OpenRawFileImplementation()); OpenTsvFileCommand = ReactiveCommand.CreateFromTask(async _ => await OpenIdFileImplementation()); OpenFeatureFileCommand = ReactiveCommand.CreateFromTask(async _ => await OpenFeatureFileImplementation()); OpenFromDmsCommand = ReactiveCommand.CreateFromTask(async _ => await OpenFromDmsImplementation()); // Create command to open settings window OpenSettingsCommand = ReactiveCommand.Create(() => this.dialogService.OpenSettings(new SettingsViewModel(this.dialogService))); // Create command to open isotopic profile viewer OpenIsotopicProfileViewerCommand = ReactiveCommand.Create(OpenIsotopicProfileViewer); //this.OpenIsotopicProfileViewer(new object()); // Create command to open about box OpenAboutBoxCommand = ReactiveCommand.Create(() => this.dialogService.OpenAboutBox()); // Create command to open new modification management window OpenManageModificationsCommand = ReactiveCommand.Create(ManageModificationsImplementation); // Create MSPathFinder search command RunMsPathFinderSearchCommand = ReactiveCommand.Create(RunMsPathFinderSearchImplementation); // Create export command ExportResultsCommand = ReactiveCommand.Create(ExportResultsImplementation, DataSets.WhenAnyValue(x => x.Count).Select(count => count > 0)); // Create export command QuitProgramCommand = ReactiveCommand.Create(() => this.dialogService.QuitProgram()); ShowSplash = true; // When a data set sets its ReadyToClose property to true, remove it from dataset list DataSets.ItemChanged.Where(x => x.PropertyName == "ReadyToClose") .Select(x => x.Sender).Where(sender => sender.ReadyToClose) .Subscribe(dataSet => { ScanViewModel.RemovePrSmsFromRawFile(dataSet.Title); DataSets.Remove(dataSet); }); // If all datasets are closed, show splash screen DataSets.BeforeItemsRemoved.Subscribe(x => ShowSplash = DataSets.Count == 1); // If a dataset is opened, show splash screen DataSets.BeforeItemsAdded.Subscribe(x => ShowSplash = false); // When the data reader is reading an ID file, show the loading screen this.dataReader.WhenAnyValue(x => x.ReadingIdFiles) .Subscribe(readingIdFiles => IdFileLoading = readingIdFiles); // When a PrSm is selected in the Protein Tree, make all data sets show the PrSm ScanViewModel.WhenAnyValue(x => x.SelectedPrSm) .Where(selectedPrSm => selectedPrSm != null) .Subscribe(selectedPrSm => { foreach (var dataSet in DataSets) { dataSet.SelectedPrSm = selectedPrSm; } }); // Warm up InformedProteomics Averagine using arbitrary mass Task.Run(() => Averagine.GetIsotopomerEnvelopeFromNominalMass(50000)); }
/// <summary> /// Initializes a new instance of the <see cref="XicViewModel"/> class. /// </summary> /// <param name="dialogService">A dialog service for opening dialogs from the view model</param> /// <param name="lcms">the LCMSRun representing the raw file for this dataset.</param> public XicViewModel(IMainDialogService dialogService, ILcMsRun lcms) { this.dialogService = dialogService; this.lcms = lcms; this.fragmentXAxis = new LinearAxis { StringFormat = "0.###", Position = AxisPosition.Bottom, Title = "Retention Time", AbsoluteMinimum = lcms.MinLcScan, AbsoluteMaximum = lcms.MaxLcScan + 1 }; this.fragmentXAxis.AxisChanged += this.XAxisChanged; this.FragmentPlotViewModel = new XicPlotViewModel( this.dialogService, new FragmentationSequenceViewModel { AddPrecursorIons = false }, lcms, "Fragment XIC", this.fragmentXAxis, false); this.heavyFragmentXAxis = new LinearAxis { StringFormat = "0.###", Position = AxisPosition.Bottom, Title = "Retention Time", AbsoluteMinimum = lcms.MinLcScan, AbsoluteMaximum = lcms.MaxLcScan + 1 }; this.heavyFragmentXAxis.AxisChanged += this.XAxisChanged; this.HeavyFragmentPlotViewModel = new XicPlotViewModel( this.dialogService, new FragmentationSequenceViewModel { AddPrecursorIons = false }, lcms, "Heavy Fragment XIC", this.heavyFragmentXAxis, false, AxisPosition.Right); this.precursorXAxis = new LinearAxis { StringFormat = "0.###", Position = AxisPosition.Bottom, Title = "Retention Time", AbsoluteMinimum = lcms.MinLcScan, AbsoluteMaximum = lcms.MaxLcScan + 1 }; this.precursorXAxis.AxisChanged += this.XAxisChanged; this.PrecursorPlotViewModel = new XicPlotViewModel(this.dialogService, new PrecursorSequenceIonViewModel(), lcms, "Precursor XIC", this.precursorXAxis) { IsPlotUpdating = true, }; this.heavyPrecursorXAxis = new LinearAxis { StringFormat = "0.###", Position = AxisPosition.Bottom, Title = "Retention Time", AbsoluteMinimum = lcms.MinLcScan, AbsoluteMaximum = lcms.MaxLcScan + 1 }; this.heavyPrecursorXAxis.AxisChanged += this.XAxisChanged; this.HeavyPrecursorPlotViewModel = new XicPlotViewModel( this.dialogService, new PrecursorSequenceIonViewModel(), lcms, "Heavy Precursor XIC", this.heavyPrecursorXAxis, vertAxes: AxisPosition.Right); this.showHeavy = false; this.showFragmentXic = false; var openHeavyModificationsCommand = ReactiveCommand.Create(); openHeavyModificationsCommand.Subscribe(_ => this.OpenHeavyModificationsImplentation()); this.OpenHeavyModificationsCommand = openHeavyModificationsCommand; this.PrecursorPlotViewModel.FragmentationSequenceViewModel.HeavyModifications = IcParameters.Instance.LightModifications.ToArray(); this.FragmentPlotViewModel.FragmentationSequenceViewModel.HeavyModifications = IcParameters.Instance.LightModifications.ToArray(); this.HeavyPrecursorPlotViewModel.FragmentationSequenceViewModel.HeavyModifications = IcParameters.Instance.HeavyModifications.ToArray(); this.HeavyFragmentPlotViewModel.FragmentationSequenceViewModel.HeavyModifications = IcParameters.Instance.HeavyModifications.ToArray(); this.linkedAxes = new Dictionary <LinearAxis, List <LinearAxis> > { { this.precursorXAxis, new List <LinearAxis>() }, { this.fragmentXAxis, new List <LinearAxis>() }, { this.heavyPrecursorXAxis, new List <LinearAxis>() }, { this.heavyFragmentXAxis, new List <LinearAxis>() } }; this.plotLinkageTracker = new HashSet <Tuple <LinearAxis, LinearAxis> >(); this.TogglePlotLinks(this.fragmentXAxis, this.heavyFragmentXAxis); this.TogglePlotLinks(this.precursorXAxis, this.heavyPrecursorXAxis); this.TogglePlotLinks(this.precursorXAxis, this.fragmentXAxis); this.TogglePlotLinks(this.heavyPrecursorXAxis, this.heavyFragmentXAxis); // Update area ratios when the area of any of the plots changes this.WhenAny(x => x.FragmentPlotViewModel.Area, x => x.HeavyFragmentPlotViewModel.Area, (x, y) => x.Value / y.Value) .Select(this.FormatRatio) .ToProperty(this, x => x.FragmentAreaRatioLabel, out this.fragmentAreaRatioLabel); this.WhenAny(x => x.PrecursorPlotViewModel.Area, x => x.HeavyPrecursorPlotViewModel.Area, (x, y) => x.Value / y.Value) .Select(this.FormatRatio) .ToProperty(this, x => x.PrecursorAreaRatioLabel, out this.precursorAreaRatioLabel); this.WhenAnyValue(x => x.ShowFragmentXic, x => x.ShowHeavy) .Subscribe(x => { this.FragmentPlotViewModel.IsPlotUpdating = x.Item1; this.HeavyFragmentPlotViewModel.IsPlotUpdating = x.Item1 && x.Item2; this.HeavyPrecursorPlotViewModel.IsPlotUpdating = x.Item2; }); this.WhenAnyValue(x => x.FragmentationSequence) .Where(fragSeq => fragSeq != null) .Subscribe(fragSeq => { this.FragmentPlotViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; this.HeavyFragmentPlotViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; this.PrecursorPlotViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; this.HeavyPrecursorPlotViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; }); this.PrecursorToFragmentLinkLabel = "L"; this.LightToHeavyLinkLabel = "L"; this.LinkLightToHeavyCommand = ReactiveCommand.Create(); this.LinkLightToHeavyCommand.Subscribe( _ => { this.TogglePlotLinks(this.fragmentXAxis, this.heavyFragmentXAxis); this.TogglePlotLinks(this.precursorXAxis, this.heavyPrecursorXAxis); this.LightToHeavyLinkLabel = this.LightToHeavyLinkLabel == "L" ? "U" : "L"; }); this.LinkPrecursorToFragmentCommand = ReactiveCommand.Create(); this.LinkPrecursorToFragmentCommand.Subscribe( _ => { this.TogglePlotLinks(this.precursorXAxis, this.fragmentXAxis); this.TogglePlotLinks(this.heavyPrecursorXAxis, this.heavyFragmentXAxis); this.PrecursorToFragmentLinkLabel = this.PrecursorToFragmentLinkLabel == "L" ? "U" : "L"; }); }
/// <summary> /// Initializes a new instance of the SpectrumPlotViewModel class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from ViewModel.</param> /// <param name="fragSeqVm">Gets or sets the view model for the fragmentation sequence (fragment ion generator)</param> /// <param name="multiplier">How much padding should be before the lowest peak and after the highest peak?</param> /// <param name="autoZoomXAxis">Should this view model automatically zoom the plot?</param> public SpectrumPlotViewModel(IMainDialogService dialogService, IFragmentationSequenceViewModel fragSeqVm, double multiplier, bool autoZoomXAxis = true) { this.dialogService = dialogService; FragmentationSequenceViewModel = fragSeqVm; this.autoZoomXAxis = autoZoomXAxis; errorMapViewModel = new ErrorMapViewModel(dialogService); ShowUnexplainedPeaks = true; ShowFilteredSpectrum = false; ShowDeconvolutedSpectrum = false; AutoAdjustYAxis = true; Title = string.Empty; XAxis = new LinearAxis { Title = "m/z", StringFormat = "0.###", Position = AxisPosition.Bottom, }; PlotModel = new AutoAdjustedYPlotModel(XAxis, multiplier) { IsLegendVisible = false, YAxis = { Title = "Intensity", StringFormat = "0e0" } }; SequenceViewerViewModel = new SequenceViewerViewModel(); ions = new LabeledIonViewModel[0]; // When Spectrum updates, clear the filtered spectrum, deconvoluted spectrum, and filtered+deconvoluted spectrum this.WhenAnyValue(x => x.Spectrum) .Subscribe(spectrum => { spectrumDirty = true; filteredSpectrum = null; deconvolutedSpectrum = null; filteredDeconvolutedSpectrum = null; }); // If deconvolution option has changed, the X Axis should change. this.WhenAnyValue(x => x.ShowDeconvolutedSpectrum) .Subscribe(_ => spectrumDirty = true); // When Spectrum or ions change, or deconvoluted or filtered spectrum are selected, update spectrum plot this.WhenAnyValue( x => x.Spectrum, x => x.FragmentationSequenceViewModel.LabeledIonViewModels, x => x.ShowDeconvolutedSpectrum, x => x.ShowDeconvolutedIons, x => x.ShowFilteredSpectrum, x => x.ShowUnexplainedPeaks, x => x.ShowOnlyTop20Peaks) .Where(x => x.Item1 != null && x.Item2 != null) .Throttle(TimeSpan.FromMilliseconds(400), RxApp.TaskpoolScheduler) .SelectMany(async x => { var vms = await FragmentationSequenceViewModel.GetLabeledIonViewModels(); return(await Task.WhenAll( vms.Select( ion => ion.GetPeaksAsync(GetSpectrum(), ShowDeconvolutedSpectrum || ShowDeconvolutedIons)))); }) .Subscribe(dataPoints => { ions = FragmentationSequenceViewModel.LabeledIonViewModels; SetTerminalResidues(dataPoints); UpdatePlotModel(dataPoints); if (FragmentationSequenceViewModel is FragmentationSequenceViewModel model) { SequenceViewerViewModel.FragmentationSequence = model; SequenceViewerViewModel.SelectedSpectrum = Spectrum as ProductSpectrum; } }); // Update plot when data changes this.WhenAnyValue(x => x.Spectrum).Where(spectrum => spectrum == null).Subscribe( _ => { PlotModel.Annotations.Clear(); PlotModel.ClearSeries(); PlotModel.InvalidatePlot(true); }); // Update ions when relative intensity threshold changes. IcParameters.Instance.WhenAnyValue(x => x.PrecursorRelativeIntensityThreshold).Subscribe(precursorRelInt => { if (FragmentationSequenceViewModel is PrecursorSequenceIonViewModel precursorFragVm) { precursorFragVm.RelativeIntensityThreshold = precursorRelInt; } }); // Update plot when settings change IcParameters.Instance.WhenAnyValue(x => x.ProductIonTolerancePpm, x => x.IonCorrelationThreshold) .Throttle(TimeSpan.FromMilliseconds(400), RxApp.TaskpoolScheduler) .SelectMany(async x => await Task.WhenAll(ions.Select(ion => ion.GetPeaksAsync(GetSpectrum(), ShowDeconvolutedSpectrum, false)))) .Subscribe(UpdatePlotModel); // When AutoAdjustYAxis changes, update value in plot model. this.WhenAnyValue(x => x.AutoAdjustYAxis) .Subscribe(autoAdjust => { PlotModel.AutoAdjustYAxis = autoAdjust; PlotModel.YAxis.IsZoomEnabled = !autoAdjust; PlotModel.YAxis.IsPanEnabled = !autoAdjust; if (autoAdjust) { PlotModel.XAxis.Reset(); PlotModel.YAxis.Reset(); } }); // Update plot axes when FeaturePlotXMin, YMin, XMax, and YMax change this.WhenAnyValue(x => x.XMinimum, x => x.XMaximum) .Throttle(TimeSpan.FromSeconds(1), RxApp.TaskpoolScheduler) .Where(x => !xAxis.ActualMinimum.Equals(x.Item1) || !xAxis.ActualMaximum.Equals(x.Item2)) .Subscribe(x => { xAxis.Zoom(x.Item1, x.Item2); PlotModel.InvalidatePlot(false); }); this.WhenAnyValue(y => y.YMinimum, y => y.YMaximum) .Throttle(TimeSpan.FromSeconds(1), RxApp.TaskpoolScheduler) .Where(y => !PlotModel.YAxis.ActualMinimum.Equals(y.Item1) || !PlotModel.YAxis.ActualMaximum.Equals(y.Item2)) .Subscribe( y => { PlotModel.YAxis.Zoom(y.Item1, y.Item2); PlotModel.InvalidatePlot(false); }); // Update X min and max properties when x axis is panned or zoomed xAxis.AxisChanged += (o, e) => { XMinimum = Math.Round(xAxis.ActualMinimum, 3); XMaximum = Math.Round(xAxis.ActualMaximum, 3); }; // Update Y min and max properties when Y axis is panned or zoomed PlotModel.YAxis.AxisChanged += (o, e) => { YMinimum = Math.Round(PlotModel.YAxis.ActualMinimum, 3); YMaximum = Math.Round(PlotModel.YAxis.ActualMaximum, 3); }; // Save As Image Command requests a file path from the user and then saves the spectrum plot as an image SaveAsImageCommand = ReactiveCommand.Create(SaveAsImageImplementation); // Error map command opens a new error map window and passes it the most abundant isotope peak data points // and the current sequence. OpenErrorMapCommand = ReactiveCommand.Create(() => dialogService.OpenErrorMapWindow(errorMapViewModel)); OpenScanSelectionCommand = ReactiveCommand.Create(OpenScanSelectionImplementation); SaveAsTsvCommand = ReactiveCommand.Create(SaveAsTsvImplementation); SaveToClipboardCommand = ReactiveCommand.Create(SaveToClipboardImplementation); }
/// <summary> /// Initializes a new instance of the <see cref="SpectrumViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from view model.</param> /// <param name="lcms">LCMSRun for the data set that the spectrum plots are part of.</param> public SpectrumViewModel(IMainDialogService dialogService, ILcMsRun lcms) { this.lcms = lcms; Ms2SpectrumViewModel = new SpectrumPlotViewModel(dialogService, new FragmentationSequenceViewModel(), 1.05); PrevMs1SpectrumViewModel = new SpectrumPlotViewModel( dialogService, new PrecursorSequenceIonViewModel { PrecursorViewMode = PrecursorViewMode.Charges }, 1.25, false); NextMs1SpectrumViewModel = new SpectrumPlotViewModel( dialogService, new PrecursorSequenceIonViewModel { PrecursorViewMode = PrecursorViewMode.Charges }, 1.25, false); // When prev ms1 spectrum plot is zoomed/panned, next ms1 spectrum plot should zoom/pan isAxisInternalChange = false; PrevMs1SpectrumViewModel.XAxis.AxisChanged += (o, e) => { if (isAxisInternalChange) { return; } isAxisInternalChange = true; NextMs1SpectrumViewModel.XAxis.Zoom(PrevMs1SpectrumViewModel.XAxis.ActualMinimum, PrevMs1SpectrumViewModel.XAxis.ActualMaximum); isAxisInternalChange = false; }; // When next ms1 spectrum plot is zoomed/panned, prev ms1 spectrum plot should zoom/pan NextMs1SpectrumViewModel.XAxis.AxisChanged += (o, e) => { if (isAxisInternalChange) { return; } isAxisInternalChange = true; PrevMs1SpectrumViewModel.XAxis.Zoom(NextMs1SpectrumViewModel.XAxis.ActualMinimum, NextMs1SpectrumViewModel.XAxis.ActualMaximum); isAxisInternalChange = false; }; this.WhenAnyValue(x => x.FragmentationSequence) .Where(fragSeq => fragSeq != null) .Subscribe(fragSeq => { Ms2SpectrumViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; PrevMs1SpectrumViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; NextMs1SpectrumViewModel.FragmentationSequenceViewModel.FragmentationSequence = fragSeq; }); // By default, MS2 Spectrum is shown in the primary view PrimarySpectrumViewModel = Ms2SpectrumViewModel; Secondary1ViewModel = PrevMs1SpectrumViewModel; Secondary2ViewModel = NextMs1SpectrumViewModel; // Wire commands to swap the spectrum that is shown in the primary view SwapSecondary1Command = ReactiveCommand.Create(SwapSecondary1); SwapSecondary2Command = ReactiveCommand.Create(SwapSecondary2); }
/// <summary> /// Initializes a new instance of the <see cref="SettingsViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from a view model.</param> public SettingsViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; this.ToleranceUnits = new ReactiveList <ToleranceUnit> { ToleranceUnit.Ppm, ToleranceUnit.Th }; this.PrecursorIonTolerance = IcParameters.Instance.PrecursorTolerancePpm.GetValue(); this.PrecursorIonToleranceUnit = IcParameters.Instance.PrecursorTolerancePpm.GetUnit(); this.ProductIonTolerance = IcParameters.Instance.ProductIonTolerancePpm.GetValue(); this.ProductIonToleranceUnit = IcParameters.Instance.ProductIonTolerancePpm.GetUnit(); this.IonCorrelationThreshold = IcParameters.Instance.IonCorrelationThreshold; this.PointsToSmooth = IcParameters.Instance.PointsToSmooth; this.PrecursorRelativeIntensityThreshold = IcParameters.Instance.PrecursorRelativeIntensityThreshold; this.ShowInstrumentData = IcParameters.Instance.ShowInstrumentData; this.AutomaticallySelectIonTypes = IcParameters.Instance.AutomaticallySelectIonTypes; this.CidHcdIonTypes = IcParameters.Instance.GetCidHcdIonTypes(); this.EtdIonTypes = IcParameters.Instance.GetEtdIonTypes(); this.ExportImageDpi = IcParameters.Instance.ExportImageDpi; this.FeatureColors = new ColorListViewModel(); this.IdColors = new ColorListViewModel(); var oxyScanCol = IcParameters.Instance.Ms2ScanColor; this.Ms2ScanColor = new Color { A = oxyScanCol.A, R = oxyScanCol.R, G = oxyScanCol.G, B = oxyScanCol.B }; foreach (var color in IcParameters.Instance.FeatureColors) { this.FeatureColors.ColorViewModels.Add(new ColorViewModel { SelectedColor = new Color { A = color.A, R = color.R, B = color.B, G = color.G } }); } foreach (var color in IcParameters.Instance.IdColors) { this.IdColors.ColorViewModels.Add(new ColorViewModel { SelectedColor = new Color { A = color.A, R = color.R, B = color.B, G = color.G } }); } this.Modifications = new ReactiveList <SearchModificationViewModel>(); foreach (var searchModification in IcParameters.Instance.SearchModifications) { var modificationVm = new SearchModificationViewModel(searchModification, this.dialogService); ////modificationVm.RemoveModificationCommand.Subscribe(_ => this.RemoveModification(modificationVm)); this.Modifications.Add(modificationVm); } var addModificationCommand = ReactiveCommand.Create(); addModificationCommand.Subscribe(_ => this.AddModificationImplementation()); this.AddModificationCommand = addModificationCommand; var createNewModificationCommand = ReactiveCommand.Create(); createNewModificationCommand.Subscribe(_ => this.CreateNewModificationImplementation()); this.CreateNewModificationCommand = createNewModificationCommand; var saveCommand = ReactiveCommand.Create(); saveCommand.Subscribe(_ => this.SaveImplementation()); this.SaveCommand = saveCommand; var cancelCommand = ReactiveCommand.Create(); cancelCommand.Subscribe(_ => this.CancelImplementation()); this.CancelCommand = cancelCommand; HeavyModificationsViewModel = new HeavyModificationsViewModel(dialogService); this.Status = false; }
/// <summary> /// Initializes a new instance of the <see cref="ScanViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from the view model.</param> /// <param name="ids">The Protein-Spectrum-Match identifications to display.</param> public ScanViewModel(IMainDialogService dialogService, IEnumerable <PrSm> ids) { ClearFiltersCommand = ReactiveCommand.Create(ClearFilters); this.dialogService = dialogService; FilteredData = new PrSm[0]; FilteredProteins = new ReactiveList <ProteinId>(); Filters = new ReactiveList <IFilter> { ChangeTrackingEnabled = true }; Data = new ReactiveList <PrSm> { ChangeTrackingEnabled = true }; InitializeDefaultFilters(); Data.AddRange(ids); IdTree = new IdentificationTree(); // When a filter is selected/unselected, request a filter value if selected, then filter data Filters.ItemChanged.Where(x => x.PropertyName == "Selected") .Select(x => x.Sender) .Where(sender => !sender.Selected || sender.Name == "Hide Unidentified Scans" || this.dialogService.FilterBox(sender)) .SelectMany(async _ => await FilterDataAsync(Data)) .Subscribe(fd => FilteredData = fd); // Data changes when items are added or removed Data.CountChanged.Throttle(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler) .SelectMany(async _ => await FilterDataAsync(Data)) .Subscribe(fd => FilteredData = fd); // When data is filtered, group it by protein name this.WhenAnyValue(x => x.FilteredData).ObserveOn(RxApp.MainThreadScheduler) .Subscribe(async filteredData => { IdTree.ClearIds(); await IdTree.BuildIdTree(filteredData); FilteredProteins.Clear(); foreach (var protein in IdTree.ProteinIds) { FilteredProteins.Add(protein); } }); // When data is filtered and a PRSM has not been selected yet, select the first PRSM this.WhenAnyValue(x => x.FilteredData) .Where(fd => fd.Length > 0) .Where(_ => SelectedPrSm == null) .Subscribe(fd => SelectedPrSm = fd[0]); // When a tree object is selected and it is a PRSM, set the selected PRSM this.WhenAnyValue(x => x.TreeViewSelectedItem) .Select(x => x as PrSm) .Where(p => p != null) .Subscribe(p => SelectedPrSm = p); // When a tree object is selected and it is an IIdData, set the selected PRSM this.WhenAnyValue(x => x.TreeViewSelectedItem) .Select(x => x as IIdData) .Where(p => p != null) .Subscribe(p => SelectedPrSm = p.GetHighestScoringPrSm()); // When a PrSm's sequence changes, update its score. Data.ItemChanged.Where(x => x.PropertyName == "Sequence") .Select(x => x.Sender) .Where(sender => sender.Sequence.Count > 0) .Subscribe(UpdatePrSmScore); ExportSpectraCommand = ReactiveCommand.CreateFromTask(ExportSpectraImplementation); ExportPeaksCommand = ReactiveCommand.CreateFromTask(ExportPeaksImplementation); ExportProteinTreeCommand = ReactiveCommand.Create(ExportProteinTreeImplementation); ExportProteinTreeAsTsvCommand = ReactiveCommand.Create(ExportProteinTreeAsTsvImplementation); }
/// <summary> /// Initializes a new instance of the <see cref="SearchSettingsViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from view model.</param> public SearchSettingsViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; SearchModes = new[] { InternalCleavageType.MultipleInternalCleavages, InternalCleavageType.SingleInternalCleavage, InternalCleavageType.NoInternalCleavage }; ToleranceUnits = new[] { ToleranceUnit.Ppm, ToleranceUnit.Mz }; SelectedSequence = string.Empty; FastaEntries = new ReactiveList <FastaEntry>(); SequenceProteins = new FastaEntry[0]; SearchRunning = false; FromFastaEntry = true; FromSequence = false; // Browse Spectrum Files Command BrowseSpectrumFilesCommand = ReactiveCommand.Create(BrowseSpectrumFilesImplementation); // Browse Feature Files Command BrowseFeatureFilesCommand = ReactiveCommand.Create(BrowseFeatureFilesImplementation); // Browse Fasta DB Files Command BrowseFastaDbFilesCommand = ReactiveCommand.Create(BrowseFastaDbFilesImplementation); // Browse Output Directories Command BrowseOutputDirectoriesCommand = ReactiveCommand.Create(BrowseOutputDirectoriesImplementation); // Select All Proteins Command SelectAllProteinsCommand = ReactiveCommand.Create(() => SelectProteinsImplementation(true), FastaEntries.WhenAnyValue(x => x.Count).Select(count => count > 0)); // Select No Proteins Command SelectNoProteinsCommand = ReactiveCommand.Create(() => SelectProteinsImplementation(false), FastaEntries.WhenAnyValue(x => x.Count).Select(count => count > 0)); // Manage Modifications Command ManageModificationsCommand = ReactiveCommand.Create(ManageModificationsImplementation); // Add Modifications Command AddModificationCommand = ReactiveCommand.Create(AddModificationImplementation); // Run Command - Disabled when there is no SpectrumFilePath, FastaDbFilePath, or OutputFilePath selected RunCommand = ReactiveCommand.CreateFromTask(async _ => await RunImplementation(), this.WhenAnyValue( x => x.SpectrumFilePath, x => x.FastaDbFilePath, x => x.OutputFilePath) .Select(x => !string.IsNullOrWhiteSpace(x.Item1) && !string.IsNullOrWhiteSpace(x.Item2) && !string.IsNullOrWhiteSpace(x.Item3)) ); // Prev tab command PrevTabCommand = ReactiveCommand.Create(() => TabIndex--, Observable.Merge( new[] { this.WhenAnyValue(x => x.TabIndex).Select(tabIndex => tabIndex > 0), RunCommand.IsExecuting.Select(exec => !exec) })); // Next tab command NextTabCommand = ReactiveCommand.Create(() => TabIndex++, Observable.Merge( new[] { this.WhenAnyValue(x => x.TabIndex).Select(tabIndex => tabIndex < MaxTabIndex), RunCommand.IsExecuting.Select(exec => !exec) })); // Cancel Command CancelCommand = ReactiveCommand.Create(CancelImplementation); // Default values SelectedSearchMode = InternalCleavageType.SingleInternalCleavage; MinSequenceLength = 21; MaxSequenceLength = 300; MinPrecursorIonCharge = 2; MaxPrecursorIonCharge = 30; MinProductIonCharge = 1; MaxProductIonCharge = 15; MinSequenceMass = 3000.0; MaxSequenceMass = 50000.0; PrecursorIonToleranceValue = 10; PrecursorIonToleranceUnit = ToleranceUnit.Ppm; ProductIonToleranceValue = 10; PrecursorIonToleranceUnit = ToleranceUnit.Ppm; minScanNumber = 0; maxScanNumber = 0; maxDynamicModificationsPerSequence = 0; FixedNTerm = true; FixedCTerm = true; NumMatchesPerSpectrum = 1; // When search mode is selected, display correct search mode description this.WhenAnyValue(x => x.SelectedSearchMode) .Subscribe(searchMode => SearchModeDescription = searchModeDescriptions[(int)searchMode]); // When Spectrum file path is selected, use its directory for the output path by default if a output path // has not already been selected. this.WhenAnyValue(x => x.SpectrumFilePath) .Where(_ => string.IsNullOrWhiteSpace(OutputFilePath)) .Select(Path.GetDirectoryName) .Subscribe(specDir => OutputFilePath = specDir); SearchModifications = new ReactiveList <SearchModificationViewModel> { ChangeTrackingEnabled = true }; this.WhenAnyValue(x => x.FastaDbFilePath).Subscribe(_ => LoadFastaFile()); this.WhenAnyValue(x => x.FastaEntries.Count, x => x.SelectedSequence) .Select(x => FastaEntries.Where(entry => entry.ProteinSequenceText.Contains(x.Item2)).ToArray()) .Subscribe(entries => SequenceProteins = entries); // Remove search modification when its Remove property is set to true. SearchModifications.ItemChanged.Where(x => x.PropertyName == "Remove") .Select(x => x.Sender).Where(sender => sender.Remove) .Subscribe(searchMod => SearchModifications.Remove(searchMod)); ModificationsUpdated = false; }