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
29 changes: 29 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,7 @@
using Omics.Modifications;
using TopDownProteomics;
using UsefulProteomicsDatabases;
using Omics.Digestion;

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

public static void AddMods(IEnumerable<Modification> modifications, bool modsAreFromTheTopOfProteinXml)
Expand Down Expand Up @@ -202,6 +205,32 @@ 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 = 1; 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>
130 changes: 130 additions & 0 deletions MetaMorpheus/GUI/Views/CustomProteaseWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
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.IO;
using EngineLayer;
using Omics.Digestion;
using Proteomics.AminoAcidPolymer;

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;

CleavageSpecificity cleavageSpecificity;
if (Enum.TryParse(CleavageSpecComboBox.Text, out CleavageSpecificity _cleaveageSpec))
{
cleavageSpecificity = _cleaveageSpec;
}
else
{
MessageBox.Show("Please specify the digestion motif(s) of the protease");
return;
}

List<DigestionMotif> digestionMotifs;
var aminoAcidsInMotifString = motifString.Where(char.IsLetter).ToList();
foreach(var aa in aminoAcidsInMotifString)
{
if (!Residue.ResiduesDictionary.ContainsKey(aa.ToString()))
{
MessageBox.Show("Motif(s) contains invalid amino acids.");
return;
}
}
try
{
digestionMotifs = DigestionMotif.ParseDigestionMotifsFromString(motifString);
}
catch
{
MessageBox.Show("The motif(s) could not be parsed.");
return;
}

//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
{
if (ProteaseDictionary.Dictionary.TryAdd(proteaseName, proteaseToAdd))
{
MessageBox.Show("Success! Protease '" + proteaseName + "' has been added to the dictionary.");
}
else
{
MessageBox.Show("Failed to add Protease '" + proteaseName + "' 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);
}
}
}
Loading