Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added custom protease window in GUI #2352

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
32 changes: 32 additions & 0 deletions MetaMorpheus/EngineLayer/GlobalVariables.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Chemistry;
using MassSpectrometry;
using MzLibUtil;
using Nett;
using Proteomics;
using Proteomics.AminoAcidPolymer;
Expand All @@ -14,6 +15,9 @@
using Omics.Modifications;
using TopDownProteomics;
using UsefulProteomicsDatabases;
using Omics.Digestion;
using static System.Net.Mime.MediaTypeNames;
using System.Collections;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all of these new namespaces necessary?


namespace EngineLayer
{
Expand Down Expand Up @@ -79,6 +83,7 @@ public static void SetUpGlobalVariables()
SetUpGlobalSettings();
LoadDissociationTypes();
LoadAvailableProteomes();
LoadCustomProtease();
}

public static void AddMods(IEnumerable<Modification> modifications, bool modsAreFromTheTopOfProteinXml)
Expand Down Expand Up @@ -202,6 +207,33 @@ public static void LoadCustomAminoAcids()
}
}

public static void LoadCustomProtease()
{
string ProtDirectory = Path.Combine(DataDir, @"ProteolyticDigestion");
string customProteasePath = Path.Combine(ProtDirectory, @"CustomProtease.tsv");
//load proteases from customProtease file or the original file to Protease dictionary
if (File.Exists(customProteasePath))
{
string[] proteaseToAdd = File.ReadAllLines(customProteasePath);
for (int i = 0; i < proteaseToAdd.Length; i++)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely need to start at i == 1 because the first row is the header

string[] array = proteaseToAdd[i].Split('\t');
List<DigestionMotif> motifList = DigestionMotif.ParseDigestionMotifsFromString(array[1]);
string name = array[0];
CleavageSpecificity cleavageSpecificity = (CleavageSpecificity)Enum.Parse(typeof(CleavageSpecificity), array[4], ignoreCase: true);
string psiMSAccessionNumber = array[5];
string psiMSName = array[6];
string proteaseModDetails = array[8];
Protease protease = new Protease(name, cleavageSpecificity, psiMSAccessionNumber, psiMSName, motifList);
if (!ProteaseDictionary.Dictionary.ContainsKey(protease.Name))
{
ProteaseDictionary.Dictionary.Add(protease.Name, protease);
}
}
}
}


public static void WriteAminoAcidsFile()
{
string directory = Path.Combine(DataDir, @"CustomAminoAcids");
Expand Down
11 changes: 7 additions & 4 deletions MetaMorpheus/GUI/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -732,16 +732,19 @@
<Button Grid.Row="2" Grid.Column="1" Content="Create new crosslinker"
HorizontalContentAlignment="Left" BorderThickness="0" Click="AddCustomCrosslinker_Click" />

<Button Grid.Row="4" Grid.Column="1" Content="Close program and open global settings"
<Button Grid.Row="3" Grid.Column="1" Content="Create new protease"
HorizontalContentAlignment="Left" BorderThickness="0" Click="AddCustomProtease_Click" />

<Button Grid.Row="5" Grid.Column="1" Content="Close program and open global settings"
HorizontalContentAlignment="Left" BorderThickness="0" Click="MenuItem_OpenSettings_Click" />

<Button Grid.Row="5" Grid.Column="1" Content="Close program and open GUI settings"
<Button Grid.Row="6" Grid.Column="1" Content="Close program and open GUI settings"
HorizontalContentAlignment="Left" BorderThickness="0" Click="MenuItem_GuiSettings_Click" />

<Button Grid.Row="6" Grid.Column="1" Content="Open mods/data folder"
<Button Grid.Row="7" Grid.Column="1" Content="Open mods/data folder"
HorizontalContentAlignment="Left" BorderThickness="0" Click="MenuItem_OpenDataDir_Click" />

<Button Grid.Row="7" Grid.Column="1" Content="Reset to factory defaults"
<Button Grid.Row="8" Grid.Column="1" Content="Reset to factory defaults"
HorizontalContentAlignment="Left" BorderThickness="0" Click="MenuItem_ResetDefaults_Click"
ToolTip="Reset saved tasks and MetaDraw Settings to default values"/>
</Grid>
Expand Down
6 changes: 6 additions & 0 deletions MetaMorpheus/GUI/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,12 @@ private void AddCustomCrosslinker_Click(object sender, RoutedEventArgs e)
dialog.ShowDialog();
}

private void AddCustomProtease_Click(object sender, RoutedEventArgs e)
{
var dialog = new Views.CustomProteaseWindow();
dialog.ShowDialog();
}

private void MoveTaskUp_Click(object sender, RoutedEventArgs e)
{
var item = GetItemDataContext(sender, e).FirstOrDefault();
Expand Down
84 changes: 84 additions & 0 deletions MetaMorpheus/GUI/Views/CustomProteaseWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<Window x:Class="MetaMorpheusGUI.Views.CustomProteaseWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MetaMorpheusGUI.Views"
mc:Ignorable="d"
Title="CustomProteaseWindow" Height="330" Width="380" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Grid>
<StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0,5,0,0" Height="300">
<!--protease name-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Name" Width="135" Margin=" 10,5,5,5" FontSize="13"></Label>
<Label Content="*" Foreground="Red" FontWeight="Bold" />
<TextBox x:Name="ProteaseNameTextBox" Width="155" Height="25">
</TextBox>
</StackPanel>
<!--Cleavage specificity-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Cleavage Specificity" Width="135" Margin=" 10,5,5,5" Height="33" FontSize="13"></Label>
<Label Content="*" Foreground="Red" FontWeight="Bold" />
<ComboBox Name ="CleavageSpecComboBox" SelectionChanged ="CleavageSpecComboBox_SelectionChanged" Width="155" Height="25">

</ComboBox>
</StackPanel>
<!--Psi-MS Acession Number-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Psi-MS Number" Width="145" Margin=" 10,5,10,10" Height="28" FontSize="13"></Label>
<TextBox Name="PsiMsAccessionNumTextBox" Width="155" Height="25">
</TextBox>
</StackPanel>
<!--Psi-MS Name-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Psi-MS Name" Width="145" Margin=" 10,5,10,10" FontSize="13"></Label>
<TextBox Name="PsiNameTextBox" Width="155" Height="25">
</TextBox>
</StackPanel>
<!--Digestion motif-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Digestion Motif" Width="135" Margin=" 10,5,5,5" Height="31" FontSize="13"></Label>
<Label Content="*" Foreground="Red" FontWeight="Bold" />
<TextBox Name="DigestionMotifTextBox" Width="155" Height="25">
<ToolTipService.ToolTip>
<ToolTip Content="Amino acid sequences or motifs recognized and cleaved by the protease"/>
</ToolTipService.ToolTip>
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="ex: 'A|', '|R', 'F[P]|'" Foreground="Gray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
<!--Cleavage Mod-->
<StackPanel Orientation="Horizontal" Height="40">
<Label Content="Cleavage Mod" Width="145" Margin=" 10,5,10,10" Height="36" FontSize="13"></Label>
<TextBox Name="CleavageModTextBox" Width="155" Height="25">
</TextBox>
</StackPanel>
<!--Save and cancel buttons-->
<StackPanel Orientation="Horizontal" Height="40" HorizontalAlignment="Center" Margin="8">
<Button Name="SaveProtease" Content="Save protease" FontSize="13" Margin="5" Width="100" Click="SaveProteaseButton_Click" />
<Button Name="CancelProtease" Content="Cancel" FontSize="13" Margin="5" Width="100" Click="CancelProteaseButton_Click" />
</StackPanel>

</StackPanel>
</Grid>
</Window>
127 changes: 127 additions & 0 deletions MetaMorpheus/GUI/Views/CustomProteaseWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using Proteomics.ProteolyticDigestion;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
using EngineLayer;
using System.Xml;
using Easy.Common.Extensions;
using System.Linq;
using MassSpectrometry;
using Omics.Digestion;

namespace MetaMorpheusGUI.Views
{
/// <summary>
/// Interaction logic for CustomProteaseWindow.xaml
/// </summary>
public partial class CustomProteaseWindow : Window
{
public CustomProteaseWindow()
{
InitializeComponent();

foreach (CleavageSpecificity c in Enum.GetValues(typeof(CleavageSpecificity)))
{
CleavageSpecComboBox.Items.Add(c);
}
}

private void SaveProteaseButton_Click(object sender, RoutedEventArgs e)
{
if (ProteaseNameTextBox.Text.Length == 0)
{
MessageBox.Show("Please specify the name of the protease");
return;
}
if (CleavageSpecComboBox.Text.Length == 0)
{
MessageBox.Show("Please specify the cleavage specificity of the protease");
return;
}
if (DigestionMotifTextBox.Text.Length == 0)
{
MessageBox.Show("Please specify the digestion motif(s) of the protease");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check to see if the digestion motiff is a valid amino acid?

return;
}
string proteaseName = ProteaseNameTextBox.Text;
string psiMsAccessionNum = PsiMsAccessionNumTextBox.Text;
string psiMsName = PsiNameTextBox.Text;
string motifString = DigestionMotifTextBox.Text;
Dictionary<string, CleavageSpecificity> CleavageSpecDic = new Dictionary<string, CleavageSpecificity>();
foreach (CleavageSpecificity c in Enum.GetValues(typeof(CleavageSpecificity))) {
CleavageSpecDic.Add(c.ToString(), c);
}
CleavageSpecificity cleavageSpecificity = CleavageSpecDic[CleavageSpecComboBox.Text];
List<DigestionMotif> digestionMotifs;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace this dictionary creation with
if (Enum.TryParse(CleavageSpecComboBox.Text, out _ cleaveageSpec)
{
set the value
}
else
{
message box error and return
}


try
{
digestionMotifs = DigestionMotif.ParseDigestionMotifsFromString(motifString);
}
catch
{
MessageBox.Show("The motif(s) could not be parsed.");
return;
}

//load the default ProteaseDictionary
//string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
//string path = ((!string.IsNullOrWhiteSpace(folderPath) && AppDomain.CurrentDomain.BaseDirectory.Contains(folderPath) && !AppDomain.CurrentDomain.BaseDirectory.Contains("Jenkins")) ? System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MetaMorpheus") : AppDomain.CurrentDomain.BaseDirectory);
//string path2 = System.IO.Path.Combine(path, "ProteolyticDigestion", "proteases.tsv");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments can be removed

//ProteaseDictionary.LoadProteaseDictionary(path2);

//create a new Protease and add to ProteaseDictionary
Protease proteaseToAdd = new Protease(proteaseName, cleavageSpecificity, psiMsAccessionNum, psiMsName, digestionMotifs);

if (ProteaseDictionary.Dictionary.ContainsKey(proteaseName))
{
MessageBox.Show("This protease already exists");
}
else
{
ProteaseDictionary.Dictionary.Add(proteaseName, proteaseToAdd);
}

if (!ProteaseDictionary.Dictionary.TryAdd(proteaseName, proteaseToAdd))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check seems redundant

{
MessageBox.Show("Success! Protease '" + proteaseName + "' has been added to the dictionary.");
}

//customProtease file path
string ProtDirectory = Path.Combine(GlobalVariables.DataDir, @"ProteolyticDigestion");
string customProteasePath = Path.Combine(ProtDirectory, @"CustomProtease.tsv");

//check if the customProtease file exists, create it if not
if (!File.Exists(customProteasePath))
{
File.Create(customProteasePath);
}

string lineToAdd = "\n" + proteaseName + "\t" + motifString + "\t\t\t" + CleavageSpecComboBox.Text + "\t" + psiMsAccessionNum + "\t" + psiMsName + "\t\t\t\t\t";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what pieces of information are being skipped over with all of the \t\t\t\t and is that information important here?

var lines = new List<string> { lineToAdd };
File.AppendAllLines(customProteasePath, lines);
DialogResult = true;
}

private void CancelProteaseButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}

private void CleavageSpecComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused method can be removed

{

}
}
}
35 changes: 35 additions & 0 deletions MetaMorpheus/Test/CustomProteaseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Proteomics.ProteolyticDigestion;
using System.IO;
using NUnit.Framework;
using EngineLayer;
using Omics.Digestion;
using MzLibUtil;


namespace Test
{
public static class CustomProteaseTest
{
[Test]
public static void TestAddCustomProtease ()
{
string ProtDirectory = Path.Combine(GlobalVariables.DataDir, @"ProteolyticDigestion");
string customProteasePath = Path.Combine(ProtDirectory, @"CustomProtease.tsv");

string[] pString = new string[] { "p\tA|\t\t\tfull\tcusPsiNum\tcusPsiName\t\t\t\t\t" };
File.WriteAllLines(customProteasePath, pString);

GlobalVariables.LoadCustomProtease();
var dictionary = ProteaseDictionary.Dictionary;
Assert.That(ProteaseDictionary.Dictionary.ContainsKey("p"));
Assert.That(ProteaseDictionary.Dictionary["p"].PsiMsName == "cusPsiName");

File.Delete(customProteasePath);
}
}
}