diff --git a/LipidCreator/CreatorGUI.Designer.cs b/LipidCreator/CreatorGUI.Designer.cs index de8fdc4..c22e464 100644 --- a/LipidCreator/CreatorGUI.Designer.cs +++ b/LipidCreator/CreatorGUI.Designer.cs @@ -27,6 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE using System; using System.Drawing; using System.Windows.Forms; +using System.Data; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -120,6 +121,17 @@ protected override void OnPaint(PaintEventArgs e) } + + public class FMenuItem : MenuItem + { + public DataGridView view; + public FMenuItem(string s, EventHandler e, DataGridView v) : base(s, e) + { + view = v; + } + } + + public class TutorialWindow : Control { public Tutorial tutorial; @@ -336,8 +348,8 @@ partial class CreatorGUI public Image addImage; public bool initialCall = true; - List stHgList = new List(); - List stEsterHgList = new List(); + List stHgList = new List(); + List stEsterHgList = new List(); [NonSerialized] public System.Timers.Timer timerEasterEgg; @@ -896,6 +908,17 @@ partial class CreatorGUI [NonSerialized] public System.Windows.Forms.Button openReviewFormButton; + + + [NonSerialized] + DataGridView glFA1FuncGroups; + + + + + + + public ArrayList controlElements; @@ -1364,6 +1387,8 @@ private void InitializeComponent() stNegativeAdduct = new GroupBox(); medNegativeAdduct = new GroupBox(); + glFA1FuncGroups = new DataGridView(); + glStep1 = new GroupBox(); plStep1 = new GroupBox(); slStep1 = new GroupBox(); @@ -1846,6 +1871,7 @@ private void InitializeComponent() glContainsSugar.CheckedChanged += new EventHandler(glContainsSugarCheckedChanged); glContainsSugar.BringToFront(); + glRepresentativeFA.Location = new Point(glHydroxyl1Textbox.Left + glHydroxyl1Textbox.Width + sep, glHydroxyl1Textbox.Top); glRepresentativeFA.Width = 150; glRepresentativeFA.Text = "First FA representative"; @@ -1854,6 +1880,52 @@ private void InitializeComponent() glRepresentativeFA.SendToBack(); + + + + + + + + DataGridViewComboBoxColumn funcGroupCol = new DataGridViewComboBoxColumn(); + funcGroupCol.DataSource = Lipid.FUNCTIONAL_GROUP_NAMES; + funcGroupCol.HeaderText = "Func. group"; + funcGroupCol.DataPropertyName = "Func. group"; + + DataGridViewTextBoxColumn rangeCol = new DataGridViewTextBoxColumn(); + rangeCol.HeaderText = "Range"; + rangeCol.DataPropertyName = "Range"; + + + glStep1.Controls.Add(glFA1FuncGroups); + glFA1FuncGroups.Location = new Point(glFA1Combobox.Left + glFA1Combobox.Width + 2 * sep + glDB1Textbox.Width, glFA1Combobox.Top); + glFA1FuncGroups.Size = new Size(340, 360); + glFA1FuncGroups.BringToFront(); + glFA1FuncGroups.Columns.AddRange(funcGroupCol, rangeCol); + glFA1FuncGroups.DefaultCellStyle.WrapMode = DataGridViewTriState.True; + glFA1FuncGroups.AllowUserToResizeColumns = false; + glFA1FuncGroups.AllowUserToAddRows = false; + glFA1FuncGroups.AllowUserToResizeRows = false; + glFA1FuncGroups.MultiSelect = false; + glFA1FuncGroups.RowTemplate.Height = 20; + glFA1FuncGroups.SelectionMode = DataGridViewSelectionMode.FullRowSelect; + glFA1FuncGroups.RowHeadersVisible = false; + glFA1FuncGroups.ScrollBars = ScrollBars.Vertical; + glFA1FuncGroups.DefaultCellStyle.Font = new Font("Arial", 8); + glFA1FuncGroups.RowHeadersWidthSizeMode = + DataGridViewRowHeadersWidthSizeMode.DisableResizing; + glFA1FuncGroups.EnableHeadersVisualStyles = false; + glFA1FuncGroups.ColumnHeadersHeight = 20; + glFA1FuncGroups.DataBindingComplete += functionalGroupComplete; + glFA1FuncGroups.CellValueChanged += functionalGroupCellValueChanged; + + ContextMenu cm = new ContextMenu(); + cm.MenuItems.Add(new FMenuItem("Add functional group", new EventHandler(addFunctionalGroup), glFA1FuncGroups)); + cm.MenuItems.Add(new FMenuItem("Remove functional group", new EventHandler(removeFunctionalGroup), glFA1FuncGroups)); + glFA1FuncGroups.ContextMenu = cm; + + + // tab for phospholipids diff --git a/LipidCreator/CreatorGUI.cs b/LipidCreator/CreatorGUI.cs index e6b5d4a..a2bf5a7 100644 --- a/LipidCreator/CreatorGUI.cs +++ b/LipidCreator/CreatorGUI.cs @@ -324,7 +324,7 @@ public CreatorGUI(string _inputParameters) int key = (c << 20) + ((db + 1) << 5) + (oh + 1); if (long_chain_bases.ContainsKey(key)) continue; - Dictionary > oh_fg = new Dictionary >(){{"O", new List(){csgoslin.KnownFunctionalGroups.get_functional_group("O")}}}; + Dictionary > oh_fg = new Dictionary >(){{"O", new List(){csgoslin.KnownFunctionalGroups.get_functional_group("O")}}}; oh_fg["O"][0].count = oh; csgoslin.FattyAcid lcb = new csgoslin.FattyAcid("FA", c, new csgoslin.DoubleBonds(db), oh_fg, csgoslin.LipidFaBondType.LCB_REGULAR); @@ -650,10 +650,10 @@ public void lipidNameSearch(Object sender, EventArgs e) } } - catch(Exception ex) { Console.WriteLine(ex); } + catch {} } } - catch(Exception) + catch { translatedLipidName.Text = ""; lipidMassLabel.Text = "m/z: "; @@ -687,6 +687,46 @@ private void searchLipidsComplete(object sender, DataGridViewBindingCompleteEven + + private void functionalGroupComplete(object sender, DataGridViewBindingCompleteEventArgs e) + { + if (!(sender is DataGridView)) return; + DataGridView view = (DataGridView)sender; + view.Columns[0].Width = (int)Math.Floor(view.Size.Width * 0.45); + view.Columns[1].Width = (int)Math.Floor(view.Size.Width * 0.55); + } + + + + public void addFunctionalGroup(Object sender, EventArgs e) + { + DataTable dt = (DataTable)(((FMenuItem)sender).view.DataSource); + DataRow dr = dt.NewRow(); + dr[0] = Lipid.FUNCTIONAL_GROUP_NAMES[0]; + dr[1] = "0-1"; + dt.Rows.Add(dr); + } + + + + public void removeFunctionalGroup(Object sender, EventArgs e) + { + + DataGridView view = ((FMenuItem)sender).view; + var dt = view.DataSource as DataTable; + + List selRows = new List(); + foreach (DataGridViewRow row in view.SelectedRows) selRows.Add(row.Index); + view.DataSource = null; + + for (int i = selRows.Count - 1; i >= 0; --i) dt.Rows.RemoveAt(selRows[i]); + view.DataSource = dt; + } + + + + + public void statisticsMenu(Object sender, EventArgs e) { menuStatistics.Checked = !menuStatistics.Checked; @@ -1082,6 +1122,7 @@ public void changeTabElements(int index) glFA1Checkbox1.Checked = currentGlycerolipid.fag1.faTypes[FattyAcidType.Ester]; glFA1Checkbox2.Checked = currentGlycerolipid.fag1.faTypes[FattyAcidType.Plasmenyl]; glFA1Checkbox3.Checked = currentGlycerolipid.fag1.faTypes[FattyAcidType.Plasmanyl]; + glFA1FuncGroups.DataSource = currentGlycerolipid.fag1.functionalGroups; glFA2Textbox.Text = currentGlycerolipid.fag2.lengthInfo; glDB2Textbox.Text = currentGlycerolipid.fag2.dbInfo; @@ -1114,6 +1155,7 @@ public void changeTabElements(int index) updateRanges(currentGlycerolipid.fag1, glFA1Textbox, glFA1Combobox.SelectedIndex); updateRanges(currentGlycerolipid.fag1, glDB1Textbox, 3); updateRanges(currentGlycerolipid.fag1, glHydroxyl1Textbox, 4); + updateFunctionalGroupGridView(currentGlycerolipid.fag1, glFA1FuncGroups); updateRanges(currentGlycerolipid.fag2, glFA2Textbox, glFA2Combobox.SelectedIndex); updateRanges(currentGlycerolipid.fag2, glDB2Textbox, 3); updateRanges(currentGlycerolipid.fag2, glHydroxyl2Textbox, 4); @@ -1554,7 +1596,6 @@ public void updateRanges(FattyAcidGroup fag, TextBox tb, int objectTypeI, bool i fag.hydroxylCounts = new HashSet(); } } - tb.BackColor = incorrectParsing ? alertColor : Color.White; } @@ -1563,6 +1604,9 @@ public void updateRanges(FattyAcidGroup fag, TextBox tb, int objectTypeI, bool i + + + private void homeText3LinkClicked(Object sender, EventArgs e) { string url = "https://www.nature.com/articles/s41467-020-15960-z"; @@ -1571,6 +1615,27 @@ private void homeText3LinkClicked(Object sender, EventArgs e) + private void functionalGroupCellValueChanged(object sender, DataGridViewCellEventArgs e) + { + int minRange = LipidCreator.MIN_HYDROXY_LENGTH; + int maxRange = LipidCreator.MAX_HYDROXY_LENGTH; + var parsed = LipidCreator.parseRange((string)(((DataGridView)sender).Rows[e.RowIndex].Cells[1].Value), minRange, maxRange, (ChainType)4); + ((DataGridView)sender).Rows[e.RowIndex].DefaultCellStyle.BackColor = (parsed == null) ? alertColor : Color.White; + } + + + + private void updateFunctionalGroupGridView(FattyAcidGroup fag, DataGridView view) + { + foreach (DataGridViewRow row in view.Rows) + { + int minRange = LipidCreator.MIN_HYDROXY_LENGTH; + int maxRange = LipidCreator.MAX_HYDROXY_LENGTH; + var parsed = LipidCreator.parseRange((string)(row.Cells[1].Value), minRange, maxRange, (ChainType)4); + row.DefaultCellStyle.BackColor = (parsed == null) ? alertColor : Color.White; + } + fag.createFunctionalGroupCount(); + } @@ -2586,86 +2651,105 @@ public LipidCategory checkPropertiesValid() if (cntActiveAdducts < 1) { MessageBox.Show("No adduct selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (currentLipid is Glycerolipid) { + ((Glycerolipid)currentLipid).fag1.createFunctionalGroupCount(); + ((Glycerolipid)currentLipid).fag2.createFunctionalGroupCount(); if (((Glycerolipid)currentLipid).fag1.faTypes[FattyAcidType.NoType]) { MessageBox.Show("Please always select the top fatty acyl!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } else if (((Glycerolipid)currentLipid).fag2.faTypes[FattyAcidType.NoType] && !((Glycerolipid)currentLipid).fag3.faTypes[FattyAcidType.NoType]) { MessageBox.Show("Please select the middle fatty acyl for DG!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glFA1Textbox.BackColor == alertColor) { MessageBox.Show("First fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glFA2Textbox.BackColor == alertColor) { MessageBox.Show("Second fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glDB1Textbox.BackColor == alertColor) { MessageBox.Show("First double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glDB2Textbox.BackColor == alertColor) { MessageBox.Show("Second double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glHydroxyl1Textbox.BackColor == alertColor) { MessageBox.Show("First hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glHydroxyl2Textbox.BackColor == alertColor) { MessageBox.Show("Second hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; + } + if (((Glycerolipid)currentLipid).fag1.functionalGroupCounts == null) + { + MessageBox.Show("A functional group content in first fatty acid is not valid!", "Not registrable"); + return LipidCategory.NoLipid; } + if (((Glycerolipid)currentLipid).fag2.functionalGroupCounts == null) + { + MessageBox.Show("A functional group content in second fatty acid is not valid!", "Not registrable"); + return LipidCategory.NoLipid; + } + if (((Glycerolipid)currentLipid).containsSugar) { if (currentLipid.headGroupNames.Count == 0) { MessageBox.Show("No head group selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (((Glycerolipid)currentLipid).fag1.faTypes[FattyAcidType.NoType] || ((Glycerolipid)currentLipid).fag2.faTypes[FattyAcidType.NoType]) { MessageBox.Show("Both fatty acyls must be selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } } else { + ((Glycerolipid)currentLipid).fag3.createFunctionalGroupCount(); if (((Glycerolipid)currentLipid).fag1.faTypes[FattyAcidType.NoType] && ((Glycerolipid)currentLipid).fag2.faTypes[FattyAcidType.NoType] && ((Glycerolipid)currentLipid).fag3.faTypes[FattyAcidType.NoType]) { MessageBox.Show("No fatty acyl selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glFA3Textbox.BackColor == alertColor) { MessageBox.Show("Third fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glDB3Textbox.BackColor == alertColor) { MessageBox.Show("Third double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (glHydroxyl3Textbox.BackColor == alertColor) { MessageBox.Show("Third hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; + } + if (((Glycerolipid)currentLipid).fag3.functionalGroupCounts == null) + { + MessageBox.Show("A functional group content in third fatty acid is not valid!", "Not registrable"); + return LipidCategory.NoLipid; } } return LipidCategory.Glycerolipid; @@ -2679,68 +2763,68 @@ public LipidCategory checkPropertiesValid() if (((Phospholipid)currentLipid).fag1.faTypes[FattyAcidType.NoType] || ((Phospholipid)currentLipid).fag2.faTypes[FattyAcidType.NoType] || ((Phospholipid)currentLipid).fag3.faTypes[FattyAcidType.NoType]) { MessageBox.Show("At least the top three fatty acyls must be selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plFA1Textbox.BackColor == alertColor) { MessageBox.Show("First fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plFA2Textbox.BackColor == alertColor) { MessageBox.Show("Second fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clFA3Textbox.BackColor == alertColor) { MessageBox.Show("Third fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clFA4Textbox.BackColor == alertColor) { MessageBox.Show("Fourth fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plDB1Textbox.BackColor == alertColor) { MessageBox.Show("First double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plDB2Textbox.BackColor == alertColor) { MessageBox.Show("Second double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clDB3Textbox.BackColor == alertColor) { MessageBox.Show("Third double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clDB4Textbox.BackColor == alertColor) { MessageBox.Show("Fourth double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plHydroxyl1Textbox.BackColor == alertColor) { MessageBox.Show("First hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plHydroxyl2Textbox.BackColor == alertColor) { MessageBox.Show("Second hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clHydroxyl3Textbox.BackColor == alertColor) { MessageBox.Show("Third hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (clHydroxyl4Textbox.BackColor == alertColor) { MessageBox.Show("Fourth hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } } else @@ -2748,7 +2832,7 @@ public LipidCategory checkPropertiesValid() if (currentLipid.headGroupNames.Count == 0) { MessageBox.Show("No head group selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } @@ -2768,7 +2852,7 @@ public LipidCategory checkPropertiesValid() if (!hasOneHG) { MessageBox.Show("No head group selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } } else if (!((Phospholipid)currentLipid).isCL) @@ -2787,7 +2871,7 @@ public LipidCategory checkPropertiesValid() if (!hasOneHG) { MessageBox.Show("No head group selected!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } } @@ -2797,24 +2881,24 @@ public LipidCategory checkPropertiesValid() if (((Phospholipid)currentLipid).fag1.faTypes[FattyAcidType.NoType]) { MessageBox.Show("Please select at least the top fatty acyl!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plFA1Textbox.BackColor == alertColor) { MessageBox.Show("First fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plDB1Textbox.BackColor == alertColor) { MessageBox.Show("First double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plHydroxyl1Textbox.BackColor == alertColor) { MessageBox.Show("First hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } @@ -2823,19 +2907,19 @@ public LipidCategory checkPropertiesValid() if (plFA2Textbox.BackColor == alertColor) { MessageBox.Show("Second fatty acyl length content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plDB2Textbox.BackColor == alertColor) { MessageBox.Show("Second double bond content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } if (plHydroxyl2Textbox.BackColor == alertColor) { MessageBox.Show("Second hydroxyl content not valid!", "Not registrable"); - return LipidCategory.NoLipid; + return LipidCategory.NoLipid; } } diff --git a/LipidCreator/FattyAcid.cs b/LipidCreator/FattyAcid.cs index 3315d75..aa55d0a 100644 --- a/LipidCreator/FattyAcid.cs +++ b/LipidCreator/FattyAcid.cs @@ -39,7 +39,7 @@ public class FattyAcid : IComparable public FattyAcidType fattyAcidType; public ElementDictionary atomsCount; public bool isLCB; - + public Dictionary functionalGroups = new Dictionary(); public override string ToString() { @@ -47,12 +47,7 @@ public override string ToString() return String.Format("{0} with length {1}, double bond(s) {2}, hydroxylations {3}, and fatty acid type {4}.", faLCB, length, db, hydroxyl, fattyAcidType); } - public FattyAcid(int l, int db, int hydro) - { - - } - - public FattyAcid(int l, int db, int hydro, FattyAcidType fattyAcidType = FattyAcidType.Ester, bool _isLCB = false) + public FattyAcid(int l, int db, int hydro, FattyAcidType fattyAcidType = FattyAcidType.Ester, bool _isLCB = false, Dictionary funcGroups = null) { length = l; this.db = db; @@ -60,6 +55,10 @@ public FattyAcid(int l, int db, int hydro, FattyAcidType fattyAcidType = FattyAc isLCB = _isLCB; atomsCount = MS2Fragment.createEmptyElementDict(); this.fattyAcidType = fattyAcidType; + if (funcGroups != null) + { + foreach (KeyValuePair kvp in funcGroups) functionalGroups.Add(kvp.Key, kvp.Value); + } if (!isLCB) { if (length > 0 || db > 0) @@ -95,6 +94,11 @@ public FattyAcid(int l, int db, int hydro, FattyAcidType fattyAcidType = FattyAc atomsCount[(int)Molecule.O] = hydroxyl; // O atomsCount[(int)Molecule.N] = 1; // N } + foreach (KeyValuePair kvp in functionalGroups) + { + if (kvp.Value <= 0) continue; + MS2Fragment.addCounts(atomsCount, Lipid.ALL_FUNCTIONAL_GROUPS[kvp.Key].elements); + } } public FattyAcid(FattyAcid copy) @@ -138,6 +142,7 @@ public string ToString(bool fullFormat = true) if (hydroxyl > 0) key += ";O" + Convert.ToString(hydroxyl); } } + foreach (KeyValuePair kvp in functionalGroups) key += ";(" + Lipid.ALL_FUNCTIONAL_GROUPS[kvp.Key].abbreviation + ")" + Convert.ToString(kvp.Value); key += LipidCreator.computeHeavyIsotopeLabel(atomsCount); return key; } diff --git a/LipidCreator/FattyAcidGroup.cs b/LipidCreator/FattyAcidGroup.cs index f637f40..e3bbcec 100644 --- a/LipidCreator/FattyAcidGroup.cs +++ b/LipidCreator/FattyAcidGroup.cs @@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ using System; +using System.Data; using System.Collections; using System.Collections.Generic; using System.Xml.Linq; @@ -78,6 +79,8 @@ public class FattyAcidGroup public HashSet carbonCounts; public HashSet doubleBondCounts; public HashSet hydroxylCounts; + public DataTable functionalGroups = new DataTable(); + public Dictionary> functionalGroupCounts = null; public FattyAcidGroup(bool isLCB = false, bool dummy = false) { @@ -94,6 +97,8 @@ public FattyAcidGroup(bool isLCB = false, bool dummy = false) carbonCounts = new HashSet(); doubleBondCounts = new HashSet(); hydroxylCounts = new HashSet(); + functionalGroups.Columns.Add("Func. group", typeof(string)); + functionalGroups.Columns.Add("Range", typeof(string)); } public FattyAcidGroup(FattyAcidGroup copy) @@ -123,6 +128,46 @@ public FattyAcidGroup(FattyAcidGroup copy) { hydroxylCounts.Add(d); } + + functionalGroups.Columns.Add("Func. group", typeof(string)); + functionalGroups.Columns.Add("Range", typeof(string)); + + foreach (DataRow copyDataRow in copy.functionalGroups.Rows) + { + DataRow dr = functionalGroups.NewRow(); + dr[0] = copyDataRow[0]; + dr[1] = copyDataRow[1]; + functionalGroups.Rows.Add(dr); + } + createFunctionalGroupCount(); + } + + + public void createFunctionalGroupCount() + { + if (functionalGroupCounts == null) functionalGroupCounts = new Dictionary>(); + else functionalGroupCounts.Clear(); + + foreach (DataRow dataRow in functionalGroups.Rows) + { + string key = (string)dataRow[0]; + FunctionalGroupType fgt = Lipid.FUNCTIONAL_GROUP_POSITIONS[key]; + string value = (string)dataRow[1]; + + int minRange = LipidCreator.MIN_HYDROXY_LENGTH; + int maxRange = LipidCreator.MAX_HYDROXY_LENGTH; + var parsed = LipidCreator.parseRange(value, minRange, maxRange, (ChainType)4); + if (parsed == null) + { + functionalGroupCounts = null; + break; + } + else + { + if (!functionalGroupCounts.ContainsKey(fgt)) functionalGroupCounts.Add(fgt, new HashSet()); + functionalGroupCounts[fgt].UnionWith(parsed); + } + } } @@ -176,6 +221,11 @@ public ulong getHashCode() hashCode += Lipid.FAHashCode[faType]; } + foreach (DataRow dataRow in functionalGroups.Rows) + { + hashCode += LipidCreator.HashCode((string)dataRow[0]) + LipidCreator.HashCode((string)dataRow[1]); + } + return hashCode; } } @@ -267,6 +317,13 @@ public bool anyFAChecked() return faTypes[FattyAcidType.Ester] || faTypes[FattyAcidType.Plasmanyl] || faTypes[FattyAcidType.Plasmenyl]; } + + + + + + + // generator function for providing all possible carbon length / double bond / // hydroxyl / (ether / ester) bonding combinations for a fatty acid public System.Collections.Generic.IEnumerable getFattyAcids() @@ -288,9 +345,37 @@ public System.Collections.Generic.IEnumerable getFattyAcids() if (fattyAcidLength <= fattyAcidHydroxyl) continue; foreach (KeyValuePair fattyAcidKeyValuePair in faTypes) { - // in old nomenclature, we denied plasmenyls with zero double bonds, since the number of double bonds were expliticely written. In the new nomenclature, it is again implicit - //if (fattyAcidKeyValuePair.Value && !(fattyAcidKeyValuePair.Key.Equals("FAp") && fattyAcidDoubleBond == 0)) yield return new FattyAcid(fattyAcidLength, fattyAcidDoubleBond, fattyAcidHydroxyl, fattyAcidKeyValuePair.Key, isLCB); - if (fattyAcidKeyValuePair.Value) yield return new FattyAcid(fattyAcidLength, fattyAcidDoubleBond, fattyAcidHydroxyl, fattyAcidKeyValuePair.Key, isLCB); + if (!fattyAcidKeyValuePair.Value) continue; + + if (functionalGroupCounts == null || functionalGroupCounts.Count == 0) + { + yield return new FattyAcid(fattyAcidLength, fattyAcidDoubleBond, fattyAcidHydroxyl, fattyAcidKeyValuePair.Key, isLCB); + } + else + { + Dictionary funcGroups = new Dictionary(); + Dictionary> funcGroupsPossibilities = new Dictionary>(); + Dictionary divisors = new Dictionary(); + + int combinations = 1; + foreach(KeyValuePair> kvp in functionalGroupCounts) + { + funcGroupsPossibilities.Add(kvp.Key, new List(kvp.Value)); + int tmp = combinations; + combinations *= kvp.Value.Count; + funcGroups.Add(kvp.Key, 0); + divisors.Add(kvp.Key, new int[]{combinations, tmp}); + } + for (int i = 0; i < combinations; ++i) + { + foreach (KeyValuePair> kvp in functionalGroupCounts) + { + int pos = (i % divisors[kvp.Key][0]) / divisors[kvp.Key][1]; + funcGroups[kvp.Key] = funcGroupsPossibilities[kvp.Key][pos]; + } + yield return new FattyAcid(fattyAcidLength, fattyAcidDoubleBond, fattyAcidHydroxyl, fattyAcidKeyValuePair.Key, isLCB, funcGroups); + } + } } } } diff --git a/LipidCreator/FunctionalGroup.cs b/LipidCreator/FunctionalGroup.cs new file mode 100644 index 0000000..e050114 --- /dev/null +++ b/LipidCreator/FunctionalGroup.cs @@ -0,0 +1,54 @@ +/* +MIT License + +Copyright (c) 2018 Dominik Kopczynski - dominik.kopczynski {at} isas.de + Bing Peng - bing.peng {at} isas.de + Nils Hoffmann - nils.hoffmann {at} isas.de + +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. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; + + +namespace LipidCreator +{ + + public enum FunctionalGroupType {Alkoxy, Amino, Carboxyl, Cyano, Epoxy, Ethyl, Hydroperoxy, Hydroxy, Methoxy, Methyl, Nitro, Oxo, Peroxy, Phosphate, Sulfanyl, Sulfate}; + + [Serializable] + public partial class FunctionalGroup + { + public FunctionalGroupType type; + public string name; + public string abbreviation; + public ElementDictionary elements; + + public FunctionalGroup(FunctionalGroupType _type, string _name, string abbrev, ElementDictionary _elements) + { + type = _type; + name = _name; + abbreviation = abbrev; + elements = _elements; + } + } +} diff --git a/LipidCreator/Lipid.cs b/LipidCreator/Lipid.cs index 56f8642..b3c4fa6 100644 --- a/LipidCreator/Lipid.cs +++ b/LipidCreator/Lipid.cs @@ -98,10 +98,6 @@ public LipidException(Molecule _molecule, int _counts, string message = "") : ba } - - - - [Serializable] public abstract class Lipid { @@ -126,6 +122,10 @@ public abstract class Lipid public static Dictionary FARepresentationString = new Dictionary(){{FattyAcidType.Ester, "FA"}, {FattyAcidType.Plasmanyl, "FA O"}, {FattyAcidType.Plasmenyl, "FA P"}, {FattyAcidType.NoType, "FAx"}}; public static Dictionary FAHashCode = new Dictionary(){{FattyAcidType.Ester, 35146310681585UL}, {FattyAcidType.Plasmanyl, 230776207451746402UL}, {FattyAcidType.Plasmenyl, 723018610604835218UL}, {FattyAcidType.NoType, 165630315668861088UL}}; + + public static Dictionary FunctionalGroupCodes = new Dictionary(){{"Hydroxy", "OH"}, {"Epoxy", "Ep"}, {"Oxo/Keto", "oxo"}, {"Amino", "NH2"}}; + + public static Dictionary LipidCategoryNames = new Dictionary(){ @@ -150,8 +150,35 @@ public abstract class Lipid {AdductType.CHHHCOOm, new Adduct("+CH3COO", "+CH3COO⁻", -1, MS2Fragment.initializeElementDict(new Dictionary(){{"H", 3}, {"C", 2}, {"O", 2}}))} }; + + + public static Dictionary ALL_FUNCTIONAL_GROUPS = new Dictionary() + { + {FunctionalGroupType.Alkoxy, new FunctionalGroup(FunctionalGroupType.Alkoxy, "Alkoxy", "oxy", MS2Fragment.initializeElementDict(new Dictionary(){{"O", 1}}))}, + {FunctionalGroupType.Amino, new FunctionalGroup(FunctionalGroupType.Amino, "Amino", "NH2", MS2Fragment.initializeElementDict(new Dictionary(){{"N", 1}, {"H", 1}}))}, + {FunctionalGroupType.Carboxyl, new FunctionalGroup(FunctionalGroupType.Carboxyl, "Carboxyl", "COOH", MS2Fragment.initializeElementDict(new Dictionary(){{"C", 1}, {"O", 2}}))}, + {FunctionalGroupType.Cyano, new FunctionalGroup(FunctionalGroupType.Cyano, "Cyano", "CN", MS2Fragment.initializeElementDict(new Dictionary(){{"C", 1}, {"N", 1}, {"H", -1}}))}, + {FunctionalGroupType.Epoxy, new FunctionalGroup(FunctionalGroupType.Epoxy, "Epoxy", "Ep", MS2Fragment.initializeElementDict(new Dictionary(){{"O", 1}, {"H", -2}}))}, + {FunctionalGroupType.Ethyl, new FunctionalGroup(FunctionalGroupType.Ethyl, "Ethyl", "Et", MS2Fragment.initializeElementDict(new Dictionary(){{"C", 2}, {"H", 4}}))}, + {FunctionalGroupType.Hydroperoxy, new FunctionalGroup(FunctionalGroupType.Hydroperoxy, "Hydroperoxy", "OOH", MS2Fragment.initializeElementDict(new Dictionary(){{"O", 2}}))}, + {FunctionalGroupType.Hydroxy, new FunctionalGroup(FunctionalGroupType.Hydroxy, "Hydroxy", "OH", MS2Fragment.initializeElementDict(new Dictionary(){{"O", 1}}))}, + {FunctionalGroupType.Methoxy, new FunctionalGroup(FunctionalGroupType.Methoxy, "Methoxy", "OMe", MS2Fragment.initializeElementDict(new Dictionary(){{"C", 1}, {"H", 2}, {"O", 1}}))}, + {FunctionalGroupType.Methyl, new FunctionalGroup(FunctionalGroupType.Methyl, "Methyl", "Me", MS2Fragment.initializeElementDict(new Dictionary(){{"C", 1}, {"H", 2}}))}, + {FunctionalGroupType.Nitro, new FunctionalGroup(FunctionalGroupType.Nitro, "Nitro", "NO2", MS2Fragment.initializeElementDict(new Dictionary(){{"N", 1}, {"O", 2}, {"H", -1}}))}, + {FunctionalGroupType.Oxo, new FunctionalGroup(FunctionalGroupType.Oxo, "Oxo/Keto", "oxo", MS2Fragment.initializeElementDict(new Dictionary(){{"H", -2}, {"O", 1}}))}, + {FunctionalGroupType.Peroxy, new FunctionalGroup(FunctionalGroupType.Peroxy, "Peroxy", "OO", MS2Fragment.initializeElementDict(new Dictionary(){{"O", 2}}))}, + {FunctionalGroupType.Phosphate, new FunctionalGroup(FunctionalGroupType.Phosphate, "Phosphate", "Ph", MS2Fragment.initializeElementDict(new Dictionary(){{"P", 1}, {"O", 4}, {"H", 1}}))}, + {FunctionalGroupType.Sulfanyl, new FunctionalGroup(FunctionalGroupType.Sulfanyl, "Sulfanyl", "SH", MS2Fragment.initializeElementDict(new Dictionary(){{"S", 1}}))}, + {FunctionalGroupType.Sulfate, new FunctionalGroup(FunctionalGroupType.Sulfate, "Sulfate", "Su", MS2Fragment.initializeElementDict(new Dictionary(){{"S", 1}, {"O", 4}}))} + }; + + + public static Dictionary FUNCTIONAL_GROUP_POSITIONS = ALL_FUNCTIONAL_GROUPS.Values.ToDictionary(k => k.name, k => k.type); + public static Dictionary ADDUCT_POSITIONS = ALL_ADDUCTS.Keys.ToDictionary(k=>ALL_ADDUCTS[k].name, k=>k); + public static readonly List FUNCTIONAL_GROUP_NAMES = ALL_FUNCTIONAL_GROUPS.Values.Select(f => f.name).ToList(); + public static Dictionary chargeToAdduct = new Dictionary{{1, ALL_ADDUCTS[AdductType.Hp]}, {2, ALL_ADDUCTS[AdductType.HHp]}, {-1, ALL_ADDUCTS[AdductType.Hm]}, {-2, ALL_ADDUCTS[AdductType.HHm]}}; @@ -161,12 +188,24 @@ public csgoslin.FattyAcid convertFA(FattyAcid fa, int num, bool sp_exception = f { Dictionary > functionalGroups = new Dictionary >(); csgoslin.DoubleBonds db = new csgoslin.DoubleBonds(fa.db); + if (fa.hydroxyl > 0) { csgoslin.FunctionalGroup fg = csgoslin.KnownFunctionalGroups.get_functional_group("OH"); fg.count = fa.hydroxyl; functionalGroups.Add("OH", new List{fg}); } + + foreach (KeyValuePair kvp in fa.functionalGroups) + { + if (!ALL_FUNCTIONAL_GROUPS.ContainsKey(kvp.Key) || kvp.Value == 0) continue; + string goslinFG = ALL_FUNCTIONAL_GROUPS[kvp.Key].abbreviation; + csgoslin.FunctionalGroup fg = csgoslin.KnownFunctionalGroups.get_functional_group(goslinFG); + fg.count = kvp.Value; + functionalGroups.Add(goslinFG, new List{fg}); + } + + csgoslin.LipidFaBondType faType = csgoslin.LipidFaBondType.ESTER; if (fa.fattyAcidType == FattyAcidType.Plasmanyl) faType = csgoslin.LipidFaBondType.ETHER_PLASMANYL; else if (fa.fattyAcidType == FattyAcidType.Plasmenyl) faType = csgoslin.LipidFaBondType.ETHER_PLASMENYL; @@ -178,22 +217,23 @@ public csgoslin.FattyAcid convertFA(FattyAcid fa, int num, bool sp_exception = f - public csgoslin.LipidMolecularSpecies convertLipid(string hg, List fa_list) + public csgoslin.LipidSpecies convertLipid(string hg, List fa_list) { - // goslin - csgoslin.Headgroup cshg = new csgoslin.Headgroup(hg); - List csFAs = new List(); - for (int i = 0; i < fa_list.Count; ++i) csFAs.Add(convertFA(fa_list[i], i + 1, cshg.sp_exception)); - return new csgoslin.LipidMolecularSpecies(cshg, csFAs); + return convertLipid(new csgoslin.Headgroup(hg), fa_list); } - public csgoslin.LipidMolecularSpecies convertLipid(csgoslin.Headgroup cshg, List fa_list) - { - // goslin + public csgoslin.LipidSpecies convertLipid(csgoslin.Headgroup cshg, List fa_list) + { List csFAs = new List(); - for (int i = 0; i < fa_list.Count; ++i) csFAs.Add(convertFA(fa_list[i], i + 1, cshg.sp_exception)); + bool doStructureDefined = false; + for (int i = 0; i < fa_list.Count; ++i){ + csgoslin.FattyAcid fa = convertFA(fa_list[i], i + 1, cshg.sp_exception); + csFAs.Add(fa); + if (fa.functional_groups.Count > 0) doStructureDefined = true; + } + if (doStructureDefined) return new csgoslin.LipidStructureDefined(cshg, csFAs); return new csgoslin.LipidMolecularSpecies(cshg, csFAs); } diff --git a/LipidCreator/LipidCreator.csproj b/LipidCreator/LipidCreator.csproj index 89bbcbd..117545f 100644 --- a/LipidCreator/LipidCreator.csproj +++ b/LipidCreator/LipidCreator.csproj @@ -41,6 +41,8 @@ + + diff --git a/LipidCreator/StructureEditor/LipidStructure.cs b/LipidCreator/StructureEditor/LipidStructure.cs index 5862f40..2ca6c7b 100644 --- a/LipidCreator/StructureEditor/LipidStructure.cs +++ b/LipidCreator/StructureEditor/LipidStructure.cs @@ -163,6 +163,27 @@ public void toggleState() + public class LipidStructureFragment { + public int id; + public string fragmentName; + public int charge; + public const int minCharge = -1; + public const int maxCharge = 1; + + public LipidStructureFragment(int i, string f, int c = 0) + { + id = i; + fragmentName = f; + charge = c; + } + + public void toggleCharge() + { + charge = (charge >= maxCharge) ? minCharge : charge + 1; + } + } + + public class LipidStructure { @@ -187,8 +208,9 @@ public class LipidStructure public Font decoratorFont; public Graphics graphics; public int currentProjection; - public Dictionary positiveFragments = new Dictionary(); - public Dictionary negativeFragments = new Dictionary(); + public LipidStructureFragment currentFragment = null; + public Dictionary positiveFragments = new Dictionary(); + public Dictionary negativeFragments = new Dictionary(); public Dictionary nodeConnectionsCount = new Dictionary(); public Dictionary nodeConnectionsHiddenCount = new Dictionary(); public HashSet specialAtoms = new HashSet(){"N", "O", "P", "S"}; @@ -430,8 +452,8 @@ public LipidStructure(string file_name, Form form) public void addFragment(string fragmentName, bool isPositive) { int newProjectionId = projectionIds++; - if (isPositive) positiveFragments.Add(fragmentName, newProjectionId); - else negativeFragments.Add(fragmentName, newProjectionId); + if (isPositive) positiveFragments.Add(fragmentName, new LipidStructureFragment(newProjectionId, fragmentName)); + else negativeFragments.Add(fragmentName, new LipidStructureFragment(newProjectionId, fragmentName)); foreach (var node in nodes) { @@ -455,13 +477,13 @@ public void removeFragment(string fragmentName, bool isPositive) if (isPositive) { if (!positiveFragments.ContainsKey(fragmentName)) return; - projectionId = positiveFragments[fragmentName]; + projectionId = positiveFragments[fragmentName].id; positiveFragments.Remove(fragmentName); } else { if (!negativeFragments.ContainsKey(fragmentName)) return; - projectionId = negativeFragments[fragmentName]; + projectionId = negativeFragments[fragmentName].id; negativeFragments.Remove(fragmentName); } @@ -585,6 +607,7 @@ public Graphics setClipping(Graphics g, Form form) foreach (var decorator in node.decorators) { NodeProjection decoratorProjection = decorator.nodeProjections[currentProjection]; + if (!developmentView && decoratorProjection.nodeState == NodeState.Hidden) continue; RectangleF rd = new RectangleF(decorator.boundingBox.X + decoratorProjection.shift.X, decorator.boundingBox.Y + decoratorProjection.shift.Y, decorator.boundingBox.Width, decorator.boundingBox.Height); clippingGraphics.SetClip(rd); @@ -645,13 +668,23 @@ public void countNodeConnections() public void changeFragment(string fragmentName = "", bool charge = false) { - currentProjection = (fragmentName.Length == 0) ? 0 : ((charge ? positiveFragments : negativeFragments)[fragmentName]); + currentFragment = (fragmentName.Length == 0) ? null : ((charge ? positiveFragments : negativeFragments)[fragmentName]); + currentProjection = (fragmentName.Length == 0) ? 0 : ((charge ? positiveFragments : negativeFragments)[fragmentName].id); computeBonds(); } + public void changeGlobalCharge() + { + if (currentFragment == null) return; + currentFragment.toggleCharge(); + } + + + + public void releaseClipping(Graphics g, Graphics clippingGraphics) { clippingGraphics.Dispose(); @@ -749,6 +782,13 @@ public void drawNodes(Graphics g) } + + int minX = (1 << 30); + int maxX = -(1 << 30); + int minY = (1 << 30); + int maxY = -(1 << 30); + + foreach (var node in nodes) { NodeProjection nodeProjection = node.nodeProjections[currentProjection]; @@ -760,17 +800,16 @@ public void drawNodes(Graphics g) else if (nodeProjection.nodeState == NodeState.Disabled) brush = solidBrushDisabled; RectangleF r = new RectangleF(nodePoint.X, nodePoint.Y, node.boundingBox.Width, node.boundingBox.Height); - if (node.isCarbon) + if (!node.isCarbon || developmentView) g.DrawString(node.text, nodeFont, brush, r, drawFormat); + if (nodeProjection.nodeState == NodeState.Enabled) { - if (developmentView) - { - g.DrawString("C", nodeFont, brush, r, drawFormat); - } - continue; + minX = Math.Min(minX, (int)nodePoint.X); + maxX = Math.Max(maxX, (int)(nodePoint.X + node.boundingBox.Width)); + minY = Math.Min(minY, (int)nodePoint.Y); + maxY = Math.Max(maxY, (int)(nodePoint.Y + node.boundingBox.Height)); } - - g.DrawString(node.text, nodeFont, brush, r, drawFormat); + if (node.isCarbon) continue; foreach (var decorator in node.decorators) { @@ -836,6 +875,22 @@ public void drawNodes(Graphics g) g.DrawString(Convert.ToString(unusedElectrons), decoratorFont, brush, rd, drawFormat); } } + + if (currentFragment == null || currentFragment.charge == 0) return; + + g.DrawLine(penEnabled, new Point(minX, minY), new Point(minX, maxY)); + g.DrawLine(penEnabled, new Point(maxX, minY), new Point(maxX, maxY)); + + int h = (int)((maxY - minY) * 0.06); + g.DrawLine(penEnabled, new Point(minX, minY), new Point(minX + h, minY)); + g.DrawLine(penEnabled, new Point(maxX, minY), new Point(maxX - h, minY)); + + g.DrawLine(penEnabled, new Point(minX, maxY), new Point(minX + h, maxY)); + g.DrawLine(penEnabled, new Point(maxX, maxY), new Point(maxX - h, maxY)); + + string chargeSign = currentFragment.charge > 0 ? "+" : "-"; + Size size = TextRenderer.MeasureText(graphics, chargeSign, nodeFont); + g.DrawString(chargeSign, nodeFont, solidBrushEnabled, new RectangleF(maxX, minY - (size.Height >> 1), size.Width, size.Height), drawFormat); } } } diff --git a/LipidCreator/StructureEditor/StructureEditor.Designer.cs b/LipidCreator/StructureEditor/StructureEditor.Designer.cs index b89f946..4c850ae 100644 --- a/LipidCreator/StructureEditor/StructureEditor.Designer.cs +++ b/LipidCreator/StructureEditor/StructureEditor.Designer.cs @@ -73,6 +73,7 @@ partial class LipidCreatorStructureEditor public Button actionChangeAtomState = new Button(); public Button actionChangeBondState = new Button(); + public Button actionChangeGlobalCharge = new Button(); public Button actionDrawBond = new Button(); public Button actionFinalView = new Button(); public Button actionMoveAtom = new Button(); @@ -129,22 +130,29 @@ private void InitializeComponent() actionChangeBondState.Location = new Point(10, 45); actionChangeBondState.Click += actionChangeBondStateClicked; + + this.Controls.Add(actionChangeGlobalCharge); + actionChangeGlobalCharge.Size = new Size(120, 25); + actionChangeGlobalCharge.Text = "Change global charge"; + actionChangeGlobalCharge.Location = new Point(10, 80); + actionChangeGlobalCharge.Click += actionChangeGlobalChargeClicked; + this.Controls.Add(actionDrawBond); actionDrawBond.Size = new Size(120, 25); actionDrawBond.Text = "Draw bond"; - actionDrawBond.Location = new Point(10, 80); + actionDrawBond.Location = new Point(10, 115); actionDrawBond.Click += actionDrawBondClicked; this.Controls.Add(actionMoveAtom); actionMoveAtom.Size = new Size(120, 25); actionMoveAtom.Text = "Move atom"; - actionMoveAtom.Location = new Point(10, 115); + actionMoveAtom.Location = new Point(10, 150); actionMoveAtom.Click += actionMoveAtomClicked; this.Controls.Add(actionFinalView); actionFinalView.Size = new Size(120, 25); actionFinalView.Text = "Final View"; - actionFinalView.Location = new Point(10, 160); + actionFinalView.Location = new Point(10, 195); actionFinalView.Click += actionFinalViewClicked; @@ -157,7 +165,7 @@ private void InitializeComponent() this.Controls.Add(positiveFragmentsListBox); positiveFragmentsListBox.Width = 130; positiveFragmentsListBox.Height = 300; - positiveFragmentsListBox.Location = new Point(10, 210); + positiveFragmentsListBox.Location = new Point(10, 245); positiveFragmentsListBox.KeyUp += fragmentKeyPressed; positiveFragmentsListBox.SelectedIndexChanged += fragmentClicked; positiveFragmentsListBox.DoubleClick += positiveFragmentDoubleClicked; @@ -165,32 +173,32 @@ private void InitializeComponent() this.Controls.Add(negativeFragmentsListBox); negativeFragmentsListBox.Width = 130; negativeFragmentsListBox.Height = 300; - negativeFragmentsListBox.Location = new Point(150, 210); + negativeFragmentsListBox.Location = new Point(150, 245); negativeFragmentsListBox.KeyUp += fragmentKeyPressed; negativeFragmentsListBox.SelectedIndexChanged += fragmentClicked; negativeFragmentsListBox.DoubleClick += negativeFragmentDoubleClicked; this.Controls.Add(addPositiveFragmentButton); - addPositiveFragmentButton.Location = new Point(90, 505); + addPositiveFragmentButton.Location = new Point(90, 540); addPositiveFragmentButton.Size = new Size(25, 25); addPositiveFragmentButton.Text = "+"; addPositiveFragmentButton.Click += addPositiveFragment; this.Controls.Add(removePositiveFragmentButton); - removePositiveFragmentButton.Location = new Point(115, 505); + removePositiveFragmentButton.Location = new Point(115, 540); removePositiveFragmentButton.Size = new Size(25, 25); removePositiveFragmentButton.Text = "-"; removePositiveFragmentButton.Click += removePositiveFragment; this.Controls.Add(addNegativeFragmentButton); - addNegativeFragmentButton.Location = new Point(230, 505); + addNegativeFragmentButton.Location = new Point(230, 540); addNegativeFragmentButton.Size = new Size(25, 25); addNegativeFragmentButton.Text = "+"; addNegativeFragmentButton.Click += addNegativeFragment; this.Controls.Add(removeNegativeFragmentButton); - removeNegativeFragmentButton.Location = new Point(255, 505); + removeNegativeFragmentButton.Location = new Point(255, 540); removeNegativeFragmentButton.Size = new Size(25, 25); removeNegativeFragmentButton.Text = "-"; removeNegativeFragmentButton.Click += removeNegativeFragment; diff --git a/LipidCreator/StructureEditor/StructureEditor.cs b/LipidCreator/StructureEditor/StructureEditor.cs index f7451d9..4379e81 100644 --- a/LipidCreator/StructureEditor/StructureEditor.cs +++ b/LipidCreator/StructureEditor/StructureEditor.cs @@ -451,6 +451,15 @@ private void actionChangeBondStateClicked(Object sender, EventArgs e) + + private void actionChangeGlobalChargeClicked(Object sender, EventArgs e) + { + lipidStructure.changeGlobalCharge(); + updateStructure(); + } + + + private void actionDrawBondClicked(Object sender, EventArgs e) { @@ -686,12 +695,6 @@ private void removeFragment(Object sender, EventArgs e) private void computeFragmentMass(Object sender, EventArgs e) { - int C = 0; - int H = 0; - int N = 0; - int O = 0; - int P = 0; - int S = 0; double mass = 0; Dictionary residues = new Dictionary(); @@ -712,7 +715,14 @@ private void computeFragmentMass(Object sender, EventArgs e) } catch(Exception){} - int adductCharge = 0; + int adductCharge = lipidStructure.currentFragment == null ? 0 : lipidStructure.currentFragment.charge; + int C = 0; + int H = lipidStructure.currentFragment == null ? 0 : lipidStructure.currentFragment.charge; + int N = 0; + int O = 0; + int P = 0; + int S = 0; + bool useAdduct = false; foreach (var node in lipidStructure.nodes) { diff --git a/LipidCreator/makefile b/LipidCreator/makefile index 5e9a52c..d7f759e 100644 --- a/LipidCreator/makefile +++ b/LipidCreator/makefile @@ -4,7 +4,7 @@ Log4Net_DLL = ../packages/log4net.2.0.12/lib/net40-client/log4net.dll LIBS = -r:$(Log4Net_DLL) -r:System.Xml.Linq.dll -r:csgoslin.dll -r:System.Text.Json.dll -r:System.Net.Http.dll -r:SkylineTool.dll -r:Ionic.Zip.dll -r:$(SQLite_DLL) -r:ExcelLibrary.dll DLLS = $(Log4Net_DLL) System.Xml.Linq.dll System.Text.Json.dll csgoslin.dll SkylineTool.dll Ionic.Zip.dll $(SQLite_DLL) ExcelLibrary.dll -CORE_FILES = LipidCreator.cs FattyAcid.cs FattyAcidGroup.cs MS2Fragment.cs Lipid.cs Glycerolipid.cs Phospholipid.cs Sphingolipid.cs Sterol.cs Mediator.cs Precursor.cs CollisionEnergy.cs BaseParserEventHandler.cs IonFormulaParserEventHandler.cs MoleculeFormulaParserEventHandler.cs Parser.cs LipidCreatorExtensionMethods.cs Element.cs ListingParserEventHandler.cs Adduct.cs IsotopeParserEventHandler.cs CrossPlatform.cs +CORE_FILES = LipidCreator.cs FattyAcid.cs FattyAcidGroup.cs MS2Fragment.cs Lipid.cs Glycerolipid.cs Phospholipid.cs Sphingolipid.cs Sterol.cs Mediator.cs Precursor.cs CollisionEnergy.cs BaseParserEventHandler.cs IonFormulaParserEventHandler.cs MoleculeFormulaParserEventHandler.cs Parser.cs LipidCreatorExtensionMethods.cs Element.cs ListingParserEventHandler.cs FunctionalGroup.cs Adduct.cs IsotopeParserEventHandler.cs CrossPlatform.cs GUI_FILES = CreatorGUI.cs CreatorGUI.Designer.cs MS2Form.cs MS2Form.Designer.cs LipidsReview.cs LipidsReview.Designer.cs NewMediatorFragment.cs NewMediatorFragment.Designer.cs NewFragment.cs NewFragment.Designer.cs SpectralName.cs SpectralName.Designer.cs AboutDialog.cs AboutDialog.Designer.cs AssemblyInfo.cs MediatorMS2Form.cs MediatorMS2Form.Designer.cs AddHeavyPrecursor.cs AddHeavyPrecursor.Designer.cs Tutorial.cs FilterDialog.cs FilterDialog.Designer.cs TranslatorDialog.cs TranslatorDialog.Designer.cs CEInspector.cs CEInspector.Designer.cs LCMessageBox.cs LCMessageBox.Designer.cs LipidsInterList.cs LipidsInterList.Designer.cs Wizard.cs Wizard.Designer.cs