diff -Nru mmass-3.12.1/configs/aminoacids.xml mmass-4.0.0/configs/aminoacids.xml
--- mmass-3.12.1/configs/aminoacids.xml 2011-04-14 18:24:45.000000000 +0000
+++ mmass-4.0.0/configs/aminoacids.xml 1970-01-01 00:00:00.000000000 +0000
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -Nru mmass-3.12.1/configs/compounds.xml mmass-4.0.0/configs/compounds.xml
--- mmass-3.12.1/configs/compounds.xml 2011-04-14 14:17:41.000000000 +0000
+++ mmass-4.0.0/configs/compounds.xml 2011-11-11 13:18:19.000000000 +0000
@@ -1,6 +1,6 @@
-
+
Fatty Acyls [FA] with formula: C40H66O5
Fatty Acyls [FA] with formula: C13H25NO5
@@ -14,48 +14,40 @@
Fatty Acyls [FA] with formula: C47H75N5O8
Fatty Acyls [FA] with formula: C2H4O2
Fatty Acyls [FA] with formula: C3H6O2
- Fatty Acyls [FA] with formula: C22H44O2
- Fatty Acyls [FA] with formula: C23H46O2
- Fatty Acyls [FA] with formula: C24H48O2
- Fatty Acyls [FA] with formula: C25H50O2
- Fatty Acyls [FA] with formula: C26H52O2
- Fatty Acyls [FA] with formula: C27H54O2
- Fatty Acyls [FA] with formula: C28H56O2
- Fatty Acyls [FA] with formula: C29H58O2
Fatty Acyls [FA] with formula: C33H66O2
Fatty Acyls [FA] with formula: C36H72O2
Fatty Acyls [FA] with formula: CH2O2
Fatty Acyls [FA] with formula: C31H62O2
- Fatty Acyls [FA] with formula: C21H42O2
Fatty Acyls [FA] with formula: C12H24O2
Fatty Acyls [FA] with formula: C4H8O2
Fatty Acyls [FA] with formula: C5H10O2
Fatty Acyls [FA] with formula: C7H14O2
- Fatty Acyls [FA] with formula: C11H22O2
+ Fatty Acyls [FA] with formula: C11H22O2
Fatty Acyls [FA] with formula: C17H34O2
Fatty Acyls [FA] with formula: C5H8O2
Fatty Acyls [FA] with formula: C6H10O2
- Fatty Acyls [FA] with formula: C11H20O2
+ Fatty Acyls [FA] with formula: C11H20O2
Fatty Acyls [FA] with formula: C14H26O2
- Fatty Acyls [FA] with formula: C16H30O2
- Fatty Acyls [FA] with formula: C22H42O2
- Fatty Acyls [FA] with formula: C21H40O2
- Fatty Acyls [FA] with formula: C19H36O2
- Fatty Acyls [FA] with formula: C21H38O2
+ Fatty Acyls [FA] with formula: C22H42O2
+ Fatty Acyls [FA] with formula: C21H40O2
+ Fatty Acyls [FA] with formula: C19H36O2
+ Fatty Acyls [FA] with formula: C21H42O2
+ Fatty Acyls [FA] with formula: C22H44O2
+ Fatty Acyls [FA] with formula: C23H46O2
+ Fatty Acyls [FA] with formula: C24H48O2
Fatty Acyls [FA] with formula: C25H46O2
Fatty Acyls [FA] with formula: C30H60O2
Fatty Acyls [FA] with formula: C8H16O2
Fatty Acyls [FA] with formula: C10H20O2
- Fatty Acyls [FA] with formula: C15H30O2
- Fatty Acyls [FA] with formula: C16H32O2
- Fatty Acyls [FA] with formula: C13H26O2
- Fatty Acyls [FA] with formula: C27H52O2
+ Fatty Acyls [FA] with formula: C15H30O2
+ Fatty Acyls [FA] with formula: C16H32O2
+ Fatty Acyls [FA] with formula: C13H26O2
+ Fatty Acyls [FA] with formula: C27H52O2
Fatty Acyls [FA] with formula: C41H82O2
Fatty Acyls [FA] with formula: C14H28O2
Fatty Acyls [FA] with formula: C38H76O2
Fatty Acyls [FA] with formula: C5H8O3
Fatty Acyls [FA] with formula: C6H10O3
- Fatty Acyls [FA] with formula: C5H8O4
Fatty Acyls [FA] with formula: C37H74O2
Fatty Acyls [FA] with formula: C39H78O2
Fatty Acyls [FA] with formula: C40H80O2
@@ -63,6 +55,11 @@
Fatty Acyls [FA] with formula: C45H90O2
Fatty Acyls [FA] with formula: C46H92O2
Fatty Acyls [FA] with formula: C48H96O2
+ Fatty Acyls [FA] with formula: C25H50O2
+ Fatty Acyls [FA] with formula: C26H52O2
+ Fatty Acyls [FA] with formula: C27H54O2
+ Fatty Acyls [FA] with formula: C28H56O2
+ Fatty Acyls [FA] with formula: C29H58O2
Fatty Acyls [FA] with formula: C32H64O2
Fatty Acyls [FA] with formula: C34H68O2
Fatty Acyls [FA] with formula: C35H70O2
@@ -81,45 +78,44 @@
Fatty Acyls [FA] with formula: C24H48O3
Fatty Acyls [FA] with formula: C27H54O3
Fatty Acyls [FA] with formula: C28H56O3
+ Fatty Acyls [FA] with formula: C29H56O2
+ Fatty Acyls [FA] with formula: C37H62O2
+ Fatty Acyls [FA] with formula: C27H50O2
+ Fatty Acyls [FA] with formula: C29H54O2
+ Fatty Acyls [FA] with formula: C19H26O2
+ Fatty Acyls [FA] with formula: C20H32O2
Fatty Acyls [FA] with formula: C4H6O2
- Fatty Acyls [FA] with formula: C13H24O2
- Fatty Acyls [FA] with formula: C24H46O2
- Fatty Acyls [FA] with formula: C26H50O2
- Fatty Acyls [FA] with formula: C28H54O2
- Fatty Acyls [FA] with formula: C30H58O2
- Fatty Acyls [FA] with formula: C32H62O2
+ Fatty Acyls [FA] with formula: C24H46O2
+ Fatty Acyls [FA] with formula: C26H50O2
+ Fatty Acyls [FA] with formula: C28H54O2
+ Fatty Acyls [FA] with formula: C30H58O2
+ Fatty Acyls [FA] with formula: C32H62O2
Fatty Acyls [FA] with formula: C5H6O2
- Fatty Acyls [FA] with formula: C6H8O2
- Fatty Acyls [FA] with formula: C22H40O2
- Fatty Acyls [FA] with formula: C26H48O2
+ Fatty Acyls [FA] with formula: C6H8O2
+ Fatty Acyls [FA] with formula: C26H48O2
Fatty Acyls [FA] with formula: C3H4O2
Fatty Acyls [FA] with formula: C10H14O2
Fatty Acyls [FA] with formula: C11H18O2
- Fatty Acyls [FA] with formula: C12H20O2
+ Fatty Acyls [FA] with formula: C12H20O2
Fatty Acyls [FA] with formula: C12H14O2
Fatty Acyls [FA] with formula: C14H18O2
- Fatty Acyls [FA] with formula: C16H24O2
- Fatty Acyls [FA] with formula: C17H32O2
- Fatty Acyls [FA] with formula: C18H26O2
- Fatty Acyls [FA] with formula: C19H34O2
- Fatty Acyls [FA] with formula: C22H38O2
- Fatty Acyls [FA] with formula: C23H44O2
- Fatty Acyls [FA] with formula: C24H44O2
- Fatty Acyls [FA] with formula: C25H48O2
- Fatty Acyls [FA] with formula: C26H46O2
+ Fatty Acyls [FA] with formula: C17H32O2
+ Fatty Acyls [FA] with formula: C18H26O2
+ Fatty Acyls [FA] with formula: C23H44O2
+ Fatty Acyls [FA] with formula: C25H48O2
+ Fatty Acyls [FA] with formula: C26H46O2
Fatty Acyls [FA] with formula: C9H14O2
Fatty Acyls [FA] with formula: C10H12O2
Fatty Acyls [FA] with formula: C12H16O2
Fatty Acyls [FA] with formula: C12H12O2
- Fatty Acyls [FA] with formula: C17H26O2
+ Fatty Acyls [FA] with formula: C17H26O2
Fatty Acyls [FA] with formula: C17H22O2
Fatty Acyls [FA] with formula: C17H28O2
- Fatty Acyls [FA] with formula: C19H26O2
- Fatty Acyls [FA] with formula: C18H28O2
- Fatty Acyls [FA] with formula: C18H24O2
+ Fatty Acyls [FA] with formula: C18H28O2
+ Fatty Acyls [FA] with formula: C18H24O2
Fatty Acyls [FA] with formula: C15H18O2
- Fatty Acyls [FA] with formula: C18H30O2
- Fatty Acyls [FA] with formula: C18H32O2
+ Fatty Acyls [FA] with formula: C18H30O2
+ Fatty Acyls [FA] with formula: C18H32O2
Fatty Acyls [FA] with formula: C14H16O2
Fatty Acyls [FA] with formula: C13H22O2
Fatty Acyls [FA] with formula: C16H31BrO2
@@ -128,7 +124,6 @@
Fatty Acyls [FA] with formula: C22H24O2
Fatty Acyls [FA] with formula: C22H28O2
Fatty Acyls [FA] with formula: C22H32O2
- Fatty Acyls [FA] with formula: C20H32O2
Fatty Acyls [FA] with formula: C20H24O2
Fatty Acyls [FA] with formula: C20H28O2
Fatty Acyls [FA] with formula: C27H46O2
@@ -144,49 +139,94 @@
Fatty Acyls [FA] with formula: C25H42O2
Fatty Acyls [FA] with formula: C24H24O2
Fatty Acyls [FA] with formula: C24H28O2
- Fatty Acyls [FA] with formula: C27H50O2
Fatty Acyls [FA] with formula: C11H10O2
Fatty Acyls [FA] with formula: C11H8O2
- Fatty Acyls [FA] with formula: C10H18O2
+ Fatty Acyls [FA] with formula: C10H18O2
Fatty Acyls [FA] with formula: C7H8O2
Fatty Acyls [FA] with formula: C10H10O2
- Fatty Acyls [FA] with formula: C10H16O2
+ Fatty Acyls [FA] with formula: C10H16O2
Fatty Acyls [FA] with formula: C12H20O3
- Fatty Acyls [FA] with formula: C12H22O2
- Fatty Acyls [FA] with formula: C14H24O2
- Fatty Acyls [FA] with formula: C24H36O2
+ Fatty Acyls [FA] with formula: C12H22O2
+ Fatty Acyls [FA] with formula: C24H36O2
Fatty Acyls [FA] with formula: C28H40O2
Fatty Acyls [FA] with formula: C21H32O2
+ Fatty Acyls [FA] with formula: C26H44O2
+ Fatty Acyls [FA] with formula: C28H48O2
+ Fatty Acyls [FA] with formula: C30H52O2
+ Fatty Acyls [FA] with formula: C32H56O2
+ Fatty Acyls [FA] with formula: C34H60O2
+ Fatty Acyls [FA] with formula: C36H64O2
+ Fatty Acyls [FA] with formula: C38H68O2
+ Fatty Acyls [FA] with formula: C26H40O2
+ Fatty Acyls [FA] with formula: C28H44O2
+ Fatty Acyls [FA] with formula: C30H48O2
+ Fatty Acyls [FA] with formula: C32H52O2
+ Fatty Acyls [FA] with formula: C34H56O2
+ Fatty Acyls [FA] with formula: C36H60O2
+ Fatty Acyls [FA] with formula: C38H64O2
+ Fatty Acyls [FA] with formula: C26H42O2
+ Fatty Acyls [FA] with formula: C28H46O2
+ Fatty Acyls [FA] with formula: C30H50O2
+ Fatty Acyls [FA] with formula: C32H54O2
+ Fatty Acyls [FA] with formula: C34H58O2
+ Fatty Acyls [FA] with formula: C36H62O2
+ Fatty Acyls [FA] with formula: C38H66O2
+ Fatty Acyls [FA] with formula: C24H34O2
+ Fatty Acyls [FA] with formula: C23H34O2
+ Fatty Acyls [FA] with formula: C21H38O2
+ Fatty Acyls [FA] with formula: C21H36O2
+ Fatty Acyls [FA] with formula: C16H24O2
+ Fatty Acyls [FA] with formula: C30H54O2
+ Fatty Acyls [FA] with formula: C28H52O2
+ Fatty Acyls [FA] with formula: C28H50O2
+ Fatty Acyls [FA] with formula: C30H56O2
+ Fatty Acyls [FA] with formula: C27H49BrO2
+ Fatty Acyls [FA] with formula: C28H51BrO2
+ Fatty Acyls [FA] with formula: C29H53BrO2
+ Fatty Acyls [FA] with formula: C13H24O2
+ Fatty Acyls [FA] with formula: C16H30O2
+ Fatty Acyls [FA] with formula: C18H34O2
+ Fatty Acyls [FA] with formula: C14H24O2
+ Fatty Acyls [FA] with formula: C20H36O2
+ Fatty Acyls [FA] with formula: C19H34O2
+ Fatty Acyls [FA] with formula: C24H44O2
+ Fatty Acyls [FA] with formula: C24H42O2
+ Fatty Acyls [FA] with formula: C27H48O2
+ Fatty Acyls [FA] with formula: C29H52O2
Fatty Acyls [FA] with formula: C18H34O6
Fatty Acyls [FA] with formula: C19H30O6
Fatty Acyls [FA] with formula: C20H36O4
Fatty Acyls [FA] with formula: C23H42O4
Fatty Acyls [FA] with formula: C19H32O4
Fatty Acyls [FA] with formula: C19H32O6
+ Fatty Acyls [FA] with formula: C22H36O6
Fatty Acyls [FA] with formula: C19H32O8
Fatty Acyls [FA] with formula: C8H16O3
Fatty Acyls [FA] with formula: C10H20O3
Fatty Acyls [FA] with formula: C13H26O3
- Fatty Acyls [FA] with formula: C14H28O3
+ Fatty Acyls [FA] with formula: C14H28O3
Fatty Acyls [FA] with formula: C18H36O3
Fatty Acyls [FA] with formula: C19H38O3
Fatty Acyls [FA] with formula: C21H42O3
Fatty Acyls [FA] with formula: C22H44O3
Fatty Acyls [FA] with formula: C14H28O4
- Fatty Acyls [FA] with formula: C18H36O4
+ Fatty Acyls [FA] with formula: C18H36O4
Fatty Acyls [FA] with formula: C20H40O4
Fatty Acyls [FA] with formula: C6H12O5
- Fatty Acyls [FA] with formula: C16H32O5
+ Fatty Acyls [FA] with formula: C16H32O5
Fatty Acyls [FA] with formula: C18H36O5
Fatty Acyls [FA] with formula: C18H36O6
- Fatty Acyls [FA] with formula: C18H34O3
+ Fatty Acyls [FA] with formula: C16H30O3
Fatty Acyls [FA] with formula: C25H48O3
Fatty Acyls [FA] with formula: C18H34O4
Fatty Acyls [FA] with formula: C18H34O5
Fatty Acyls [FA] with formula: C17H26O5
Fatty Acyls [FA] with formula: C13H18O5
+ Fatty Acyls [FA] with formula: C11H22O3
Fatty Acyls [FA] with formula: C15H30O4
Fatty Acyls [FA] with formula: C16H32O4
+ Fatty Acyls [FA] with formula: C17H28O3
+ Fatty Acyls [FA] with formula: C18H34O3
Fatty Acyls [FA] with formula: C22H44O4
Fatty Acyls [FA] with formula: C23H46O3
Fatty Acyls [FA] with formula: C25H50O3
@@ -199,30 +239,30 @@
Fatty Acyls [FA] with formula: C20H40O3
Fatty Acyls [FA] with formula: C20H38O3
Fatty Acyls [FA] with formula: C17H26O3
- Fatty Acyls [FA] with formula: C17H30O3
+ Fatty Acyls [FA] with formula: C17H30O3
Fatty Acyls [FA] with formula: C7H14O3
Fatty Acyls [FA] with formula: C7H10O3
- Fatty Acyls [FA] with formula: C26H52O3
- Fatty Acyls [FA] with formula: C16H30O3
+ Fatty Acyls [FA] with formula: C26H52O3
Fatty Acyls [FA] with formula: C6H8O3
Fatty Acyls [FA] with formula: C9H18O3
Fatty Acyls [FA] with formula: C18H24O3
Fatty Acyls [FA] with formula: C18H26O3
Fatty Acyls [FA] with formula: C19H32O2
Fatty Acyls [FA] with formula: C15H30O3
- Fatty Acyls [FA] with formula: C11H22O3
Fatty Acyls [FA] with formula: C6H12O4
- Fatty Acyls [FA] with formula: C4H8O3
- Fatty Acyls [FA] with formula: C7H12O3
Fatty Acyls [FA] with formula: C5H10O4
Fatty Acyls [FA] with formula: C4H8O4
Fatty Acyls [FA] with formula: C5H10O5
Fatty Acyls [FA] with formula: C6H12O3
Fatty Acyls [FA] with formula: C5H10O3
- Fatty Acyls [FA] with formula: C16H32O3
+ Fatty Acyls [FA] with formula: C16H32O3
Fatty Acyls [FA] with formula: C6H13O7P
Fatty Acyls [FA] with formula: C6H14O10P2
- Fatty Acyls [FA] with formula: C4H6O3
+ Fatty Acyls [FA] with formula: C4H8O3
+ Fatty Acyls [FA] with formula: C24H46O4
+ Fatty Acyls [FA] with formula: C18H32O3
+ Fatty Acyls [FA] with formula: C4H6O3
+ Fatty Acyls [FA] with formula: C7H12O3
Fatty Acyls [FA] with formula: C8H14O3
Fatty Acyls [FA] with formula: C9H16O3
Fatty Acyls [FA] with formula: C3H4O3
@@ -254,11 +294,10 @@
Fatty Acyls [FA] with formula: C6H7NO3
Fatty Acyls [FA] with formula: C4H4O6
Fatty Acyls [FA] with formula: C6H8O7
- Fatty Acyls [FA] with formula: C18H30O4
+ Fatty Acyls [FA] with formula: C18H30O4
Fatty Acyls [FA] with formula: C19H32O3
- Fatty Acyls [FA] with formula: C18H28O3
- Fatty Acyls [FA] with formula: C18H32O3
- Fatty Acyls [FA] with formula: C16H26O3
+ Fatty Acyls [FA] with formula: C18H28O3
+ Fatty Acyls [FA] with formula: C16H26O3
Fatty Acyls [FA] with formula: C19H34O4
Fatty Acyls [FA] with formula: C20H38O5
Fatty Acyls [FA] with formula: C19H36O5
@@ -285,11 +324,11 @@
Fatty Acyls [FA] with formula: C16H30F2O2
Fatty Acyls [FA] with formula: C16H31ClO3
Fatty Acyls [FA] with formula: C18H35FO2
+ Fatty Acyls [FA] with formula: C16H31ClO2
Fatty Acyls [FA] with formula: C13H27NO2
Fatty Acyls [FA] with formula: C10H21NO2
Fatty Acyls [FA] with formula: C11H23NO2
Fatty Acyls [FA] with formula: C12H25NO2
- Fatty Acyls [FA] with formula: C14H29NO2
Fatty Acyls [FA] with formula: C9H19NO2
Fatty Acyls [FA] with formula: C7H15NO2
Fatty Acyls [FA] with formula: C16H33NO2
@@ -297,10 +336,10 @@
Fatty Acyls [FA] with formula: C5H8N2O2
Fatty Acyls [FA] with formula: C3H7NO3
Fatty Acyls [FA] with formula: C5H11NO2
- Fatty Acyls [FA] with formula: C6H13NO2
+ Fatty Acyls [FA] with formula: C6H13NO2
Fatty Acyls [FA] with formula: C3H8N2O2
Fatty Acyls [FA] with formula: C4H10N2O2
- Fatty Acyls [FA] with formula: C4H9NO2
+ Fatty Acyls [FA] with formula: C4H9NO2
Fatty Acyls [FA] with formula: C5H9NO3
Fatty Acyls [FA] with formula: C8H17NO2
Fatty Acyls [FA] with formula: C25H45NO2
@@ -314,8 +353,8 @@
Fatty Acyls [FA] with formula: C16H22O2
Fatty Acyls [FA] with formula: C24H40O2
Fatty Acyls [FA] with formula: C24H38O2
- Fatty Acyls [FA] with formula: C19H30O2
- Fatty Acyls [FA] with formula: C20H34O2
+ Fatty Acyls [FA] with formula: C19H30O2
+ Fatty Acyls [FA] with formula: C20H34O2
Fatty Acyls [FA] with formula: C15H23BrO2
Fatty Acyls [FA] with formula: C22H38O3
Fatty Acyls [FA] with formula: C12H16O5
@@ -328,14 +367,13 @@
Fatty Acyls [FA] with formula: C11H20O4
Fatty Acyls [FA] with formula: C12H14O4
Fatty Acyls [FA] with formula: C12H22O4
- Fatty Acyls [FA] with formula: C13H24O4
+ Fatty Acyls [FA] with formula: C13H24O4
Fatty Acyls [FA] with formula: C14H26O4
Fatty Acyls [FA] with formula: C15H28O4
Fatty Acyls [FA] with formula: C17H32O4
Fatty Acyls [FA] with formula: C21H40O4
Fatty Acyls [FA] with formula: C22H42O4
Fatty Acyls [FA] with formula: C23H44O4
- Fatty Acyls [FA] with formula: C24H46O4
Fatty Acyls [FA] with formula: C26H50O4
Fatty Acyls [FA] with formula: C3H4O4
Fatty Acyls [FA] with formula: C30H58O4
@@ -345,7 +383,7 @@
Fatty Acyls [FA] with formula: C16H30O4
Fatty Acyls [FA] with formula: C4H4O5
Fatty Acyls [FA] with formula: C7H10O6
- Fatty Acyls [FA] with formula: C5H6O4
+ Fatty Acyls [FA] with formula: C5H6O4
Fatty Acyls [FA] with formula: C7H12O5
Fatty Acyls [FA] with formula: C7H6O6
Fatty Acyls [FA] with formula: C8H8O6
@@ -358,7 +396,7 @@
Fatty Acyls [FA] with formula: C17H30O7
Fatty Acyls [FA] with formula: C10H18O5
Fatty Acyls [FA] with formula: C6H7NO4
- Fatty Acyls [FA] with formula: C6H10O4
+ Fatty Acyls [FA] with formula: C6H10O4
Fatty Acyls [FA] with formula: C8H12O4
Fatty Acyls [FA] with formula: C7H12O4
Fatty Acyls [FA] with formula: C6H10O5
@@ -367,6 +405,7 @@
Fatty Acyls [FA] with formula: C14H26O5
Fatty Acyls [FA] with formula: C6H11NO4
Fatty Acyls [FA] with formula: C7H14N2O4
+ Fatty Acyls [FA] with formula: C5H8O4
Fatty Acyls [FA] with formula: C6H10O8
Fatty Acyls [FA] with formula: C4H5NO4
Fatty Acyls [FA] with formula: C4H6O4
@@ -375,7 +414,7 @@
Fatty Acyls [FA] with formula: C21H38O4
Fatty Acyls [FA] with formula: C21H36O4
Fatty Acyls [FA] with formula: C18H30O3
- Fatty Acyls [FA] with formula: C18H32O4
+ Fatty Acyls [FA] with formula: C18H32O4
Fatty Acyls [FA] with formula: C14H22O3
Fatty Acyls [FA] with formula: C16H28O3
Fatty Acyls [FA] with formula: C14H24O3
@@ -384,7 +423,9 @@
Fatty Acyls [FA] with formula: C18H30O9
Fatty Acyls [FA] with formula: C13H20O3
Fatty Acyls [FA] with formula: C12H18O3
- Fatty Acyls [FA] with formula: C20H36O3
+ Fatty Acyls [FA] with formula: C20H36O3
+ Fatty Acyls [FA] with formula: C20H34O8
+ Fatty Acyls [FA] with formula: C26H42O4
Fatty Acyls [FA] with formula: C21H34O4
Fatty Acyls [FA] with formula: C23H38O4
Fatty Acyls [FA] with formula: C22H28O5
@@ -394,12 +435,10 @@
Fatty Acyls [FA] with formula: C23H32O5
Fatty Acyls [FA] with formula: C22H36O4
Fatty Acyls [FA] with formula: C21H34O5
- Fatty Acyls [FA] with formula: C22H36O6
Fatty Acyls [FA] with formula: C23H38O6
Fatty Acyls [FA] with formula: C24H38O8
Fatty Acyls [FA] with formula: C25H40O8
Fatty Acyls [FA] with formula: C21H32O4
- Fatty Acyls [FA] with formula: C22H41NO3
Fatty Acyls [FA] with formula: C23H33NO4
Fatty Acyls [FA] with formula: C26H38O5
Fatty Acyls [FA] with formula: C20H36O5
@@ -407,14 +446,12 @@
Fatty Acyls [FA] with formula: C22H37NO5
Fatty Acyls [FA] with formula: C18H32O5
Fatty Acyls [FA] with formula: C22H38O5
- Fatty Acyls [FA] with formula: C22H32O3
Fatty Acyls [FA] with formula: C20H34O4
Fatty Acyls [FA] with formula: C20H36O6
- Fatty Acyls [FA] with formula: C20H30O5
- Fatty Acyls [FA] with formula: C18H30O5
- Fatty Acyls [FA] with formula: C20H32O5
- Fatty Acyls [FA] with formula: C20H30O3
- Fatty Acyls [FA] with formula: C20H28O3
+ Fatty Acyls [FA] with formula: C20H30O5
+ Fatty Acyls [FA] with formula: C18H30O5
+ Fatty Acyls [FA] with formula: C20H30O3
+ Fatty Acyls [FA] with formula: C20H28O3
Fatty Acyls [FA] with formula: C20H38O4
Fatty Acyls [FA] with formula: C23H40O7
Fatty Acyls [FA] with formula: C23H40O8
@@ -423,8 +460,8 @@
Fatty Acyls [FA] with formula: C23H41NO6
Fatty Acyls [FA] with formula: C16H24O7
Fatty Acyls [FA] with formula: C22H36O5
- Fatty Acyls [FA] with formula: C20H30O4
- Fatty Acyls [FA] with formula: C20H28O4
+ Fatty Acyls [FA] with formula: C20H30O4
+ Fatty Acyls [FA] with formula: C20H28O4
Fatty Acyls [FA] with formula: C23H36O6
Fatty Acyls [FA] with formula: C23H34O5
Fatty Acyls [FA] with formula: C22H39NO5
@@ -445,13 +482,15 @@
Fatty Acyls [FA] with formula: C19H34O5
Fatty Acyls [FA] with formula: C30H47N3O10S
Fatty Acyls [FA] with formula: C25H40N2O7S
- Fatty Acyls [FA] with formula: C17H28O3
Fatty Acyls [FA] with formula: C20H34O3
Fatty Acyls [FA] with formula: C21H34O8
- Fatty Acyls [FA] with formula: C20H32O4
- Fatty Acyls [FA] with formula: C20H32O6
- Fatty Acyls [FA] with formula: C20H32O3
- Fatty Acyls [FA] with formula: C20H34O5
+ Fatty Acyls [FA] with formula: C20H32O4
+ Fatty Acyls [FA] with formula: C20H32O6
+ Fatty Acyls [FA] with formula: C20H32O3
+ Fatty Acyls [FA] with formula: C30H49N3O10S
+ Fatty Acyls [FA] with formula: C25H42N2O7S
+ Fatty Acyls [FA] with formula: C20H32O5
+ Fatty Acyls [FA] with formula: C20H34O5
Fatty Acyls [FA] with formula: C25H34O7
Fatty Acyls [FA] with formula: C27H36O9
Fatty Acyls [FA] with formula: C21H29ClO4
@@ -476,12 +515,15 @@
Fatty Acyls [FA] with formula: C23H33ClO6
Fatty Acyls [FA] with formula: C22H30O4
Fatty Acyls [FA] with formula: C22H32O5
- Fatty Acyls [FA] with formula: C22H30O3
Fatty Acyls [FA] with formula: C22H34O4
Fatty Acyls [FA] with formula: C22H34O5
- Fatty Acyls [FA] with formula: C22H32O4
- Fatty Acyls [FA] with formula: C22H34O2
- Fatty Acyls [FA] with formula: C22H36O2
+ Fatty Acyls [FA] with formula: C22H32O4
+ Fatty Acyls [FA] with formula: C22H30O3
+ Fatty Acyls [FA] with formula: C22H32O3
+ Fatty Acyls [FA] with formula: C22H38O2
+ Fatty Acyls [FA] with formula: C22H34O2
+ Fatty Acyls [FA] with formula: C22H40O2
+ Fatty Acyls [FA] with formula: C22H36O2
Fatty Acyls [FA] with formula: C12H26O
Fatty Acyls [FA] with formula: C26H54O
Fatty Acyls [FA] with formula: C28H58O
@@ -500,7 +542,7 @@
Fatty Acyls [FA] with formula: C15H30O
Fatty Acyls [FA] with formula: C20H40O
Fatty Acyls [FA] with formula: C17H34O
- Fatty Acyls [FA] with formula: C18H34O
+ Fatty Acyls [FA] with formula: C18H34O
Fatty Acyls [FA] with formula: C6H12O
Fatty Acyls [FA] with formula: C10H22O
Fatty Acyls [FA] with formula: C18H28O
@@ -526,19 +568,19 @@
Fatty Acyls [FA] with formula: C7H16O
Fatty Acyls [FA] with formula: C9H20O
Fatty Acyls [FA] with formula: C8H18O
- Fatty Acyls [FA] with formula: C9H18O2
+ Fatty Acyls [FA] with formula: C9H18O2
Fatty Acyls [FA] with formula: C11H19ClO
Fatty Acyls [FA] with formula: C11H24O
Fatty Acyls [FA] with formula: C12H18F4O
Fatty Acyls [FA] with formula: C12H20F2O
Fatty Acyls [FA] with formula: C13H28O
- Fatty Acyls [FA] with formula: C14H28O
+ Fatty Acyls [FA] with formula: C14H28O
Fatty Acyls [FA] with formula: C14H26O
Fatty Acyls [FA] with formula: C17H36O
- Fatty Acyls [FA] with formula: C15H28O
+ Fatty Acyls [FA] with formula: C15H28O
Fatty Acyls [FA] with formula: C15H32O
Fatty Acyls [FA] with formula: C16H32O
- Fatty Acyls [FA] with formula: C16H30O
+ Fatty Acyls [FA] with formula: C16H30O
Fatty Acyls [FA] with formula: C20H36O
Fatty Acyls [FA] with formula: C18H36O
Fatty Acyls [FA] with formula: C18H32O
@@ -546,28 +588,27 @@
Fatty Acyls [FA] with formula: C20H42O
Fatty Acyls [FA] with formula: C24H50O
Fatty Acyls [FA] with formula: C26H52O
- Fatty Acyls [FA] with formula: C14H22O2
+ Fatty Acyls [FA] with formula: C14H22O2
Fatty Acyls [FA] with formula: C14H21F5O2
Fatty Acyls [FA] with formula: C14H24F2O2
- Fatty Acyls [FA] with formula: C15H28O2
+ Fatty Acyls [FA] with formula: C15H28O2
Fatty Acyls [FA] with formula: C15H24O2
Fatty Acyls [FA] with formula: C15H26O2
- Fatty Acyls [FA] with formula: C16H26O2
- Fatty Acyls [FA] with formula: C16H28O2
+ Fatty Acyls [FA] with formula: C16H26O2
+ Fatty Acyls [FA] with formula: C16H28O2
Fatty Acyls [FA] with formula: C16H27F3O2
Fatty Acyls [FA] with formula: C16H29FO2
- Fatty Acyls [FA] with formula: C17H30O2
- Fatty Acyls [FA] with formula: C18H34O2
+ Fatty Acyls [FA] with formula: C17H30O2
Fatty Acyls [FA] with formula: C18H36O2
- Fatty Acyls [FA] with formula: C19H38O2
- Fatty Acyls [FA] with formula: C20H38O2
- Fatty Acyls [FA] with formula: C20H36O2
- Fatty Acyls [FA] with formula: C20H40O2
+ Fatty Acyls [FA] with formula: C19H38O2
+ Fatty Acyls [FA] with formula: C20H38O2
+ Fatty Acyls [FA] with formula: C20H40O2
Fatty Acyls [FA] with formula: C27H42O2
Fatty Acyls [FA] with formula: C27H56O
Fatty Acyls [FA] with formula: C29H60O
Fatty Acyls [FA] with formula: C32H66O
Fatty Acyls [FA] with formula: C34H70O
+ Fatty Acyls [FA] with formula: C16H33ClO
Fatty Acyls [FA] with formula: C6H10O
Fatty Acyls [FA] with formula: C6H8O
Fatty Acyls [FA] with formula: C6H6O2
@@ -582,11 +623,11 @@
Fatty Acyls [FA] with formula: C8H10O
Fatty Acyls [FA] with formula: C8H12O2
Fatty Acyls [FA] with formula: C8H14O2
- Fatty Acyls [FA] with formula: C9H16O
Fatty Acyls [FA] with formula: C9H14O
Fatty Acyls [FA] with formula: C9H4O
Fatty Acyls [FA] with formula: C9H16O2
Fatty Acyls [FA] with formula: C10H20O
+ Fatty Acyls [FA] with formula: C10H16O
Fatty Acyls [FA] with formula: C10H14O
Fatty Acyls [FA] with formula: C10H12O
Fatty Acyls [FA] with formula: C10H8O
@@ -608,11 +649,11 @@
Fatty Acyls [FA] with formula: C16H31ClO
Fatty Acyls [FA] with formula: C16H31BrO
Fatty Acyls [FA] with formula: C9H12O
- Fatty Acyls [FA] with formula: C10H16O
- Fatty Acyls [FA] with formula: C10H18O
- Fatty Acyls [FA] with formula: C12H24O
- Fatty Acyls [FA] with formula: C12H20O
- Fatty Acyls [FA] with formula: C12H22O
+ Fatty Acyls [FA] with formula: C9H16O
+ Fatty Acyls [FA] with formula: C10H18O
+ Fatty Acyls [FA] with formula: C12H24O
+ Fatty Acyls [FA] with formula: C12H20O
+ Fatty Acyls [FA] with formula: C12H22O
Fatty Acyls [FA] with formula: C14H18O3
Fatty Acyls [FA] with formula: C17H30O
Fatty Acyls [FA] with formula: C14H20O
@@ -621,18 +662,25 @@
Fatty Acyls [FA] with formula: C15H26O
Fatty Acyls [FA] with formula: C16H26O
Fatty Acyls [FA] with formula: C20H32O
- Fatty Acyls [FA] with formula: C16H28O
+ Fatty Acyls [FA] with formula: C16H28O
Fatty Acyls [FA] with formula: C17H32O
Fatty Acyls [FA] with formula: C18H30O
Fatty Acyls [FA] with formula: C19H36O
Fatty Acyls [FA] with formula: C19H38O
Fatty Acyls [FA] with formula: C20H38O
- Fatty Acyls [FA] with formula: C34H66O2
- Fatty Acyls [FA] with formula: C35H68O2
+ Fatty Acyls [FA] with formula: C34H66O2
+ Fatty Acyls [FA] with formula: C35H68O2
Fatty Acyls [FA] with formula: C42H84O2
Fatty Acyls [FA] with formula: C44H88O2
Fatty Acyls [FA] with formula: C36H64O4
Fatty Acyls [FA] with formula: C34H60O4
+ Fatty Acyls [FA] with formula: C36H70O2
+ Fatty Acyls [FA] with formula: C37H72O2
+ Fatty Acyls [FA] with formula: C38H74O2
+ Fatty Acyls [FA] with formula: C39H76O2
+ Fatty Acyls [FA] with formula: C40H78O2
+ Fatty Acyls [FA] with formula: C41H80O2
+ Fatty Acyls [FA] with formula: C42H82O2
Fatty Acyls [FA] with formula: C42H82O4
Fatty Acyls [FA] with formula: C41H71NO4
Fatty Acyls [FA] with formula: C27H46N7O17P3S
@@ -664,12 +712,12 @@
Fatty Acyls [FA] with formula: C43H74N7O17P3S
Fatty Acyls [FA] with formula: C43H70N7O17P3S
Fatty Acyls [FA] with formula: C45H74N7O17P3S
+ Fatty Acyls [FA] with formula: C45H72N7O17P3S
Fatty Acyls [FA] with formula: C43H68N7O17P3S
Fatty Acyls [FA] with formula: C41H68N7O17P3S
Fatty Acyls [FA] with formula: C39H64N7O17P3S
Fatty Acyls [FA] with formula: C39H62N7O17P3S
Fatty Acyls [FA] with formula: C41H66N7O17P3S
- Fatty Acyls [FA] with formula: C45H72N7O17P3S
Fatty Acyls [FA] with formula: C43H66N7O17P3S
Fatty Acyls [FA] with formula: C45H70N7O17P3S
Fatty Acyls [FA] with formula: C43H78N7O17P3S
@@ -682,6 +730,10 @@
Fatty Acyls [FA] with formula: C37H64N7O17P3S
Fatty Acyls [FA] with formula: C41H70N7O17P3S
Fatty Acyls [FA] with formula: C41H64N7O17P3S
+ Fatty Acyls [FA] with formula: C40H72N7O17P3S
+ Fatty Acyls [FA] with formula: C45H68N7O17P3S
+ Fatty Acyls [FA] with formula: C45H70N7O18P3S
+ Fatty Acyls [FA] with formula: C45H68N7O18P3S
Fatty Acyls [FA] with formula: C393H636N95O143PS2
Fatty Acyls [FA] with formula: C393H636N95O142PS2
Fatty Acyls [FA] with formula: C391H632N95O142PS2
@@ -709,8 +761,8 @@
Fatty Acyls [FA] with formula: C21H35NO
Fatty Acyls [FA] with formula: C23H39NO
Fatty Acyls [FA] with formula: C24H41NO
- Fatty Acyls [FA] with formula: C25H43NO
- Fatty Acyls [FA] with formula: C23H39NO2
+ Fatty Acyls [FA] with formula: C25H43NO
+ Fatty Acyls [FA] with formula: C23H39NO2
Fatty Acyls [FA] with formula: C24H41NO2
Fatty Acyls [FA] with formula: C26H46N2O
Fatty Acyls [FA] with formula: C24H41NO3
@@ -730,10 +782,9 @@
Fatty Acyls [FA] with formula: C26H44FNO
Fatty Acyls [FA] with formula: C27H46FNO
Fatty Acyls [FA] with formula: C23H39NO3
- Fatty Acyls [FA] with formula: C24H39NO3
+ Fatty Acyls [FA] with formula: C24H39NO3
Fatty Acyls [FA] with formula: C22H37NO4S
Fatty Acyls [FA] with formula: C29H41NO4
- Fatty Acyls [FA] with formula: C20H39NO3
Fatty Acyls [FA] with formula: C20H41NO4S
Fatty Acyls [FA] with formula: C18H35NO3
Fatty Acyls [FA] with formula: C18H37NO4S
@@ -742,6 +793,54 @@
Fatty Acyls [FA] with formula: C24H49NO4S
Fatty Acyls [FA] with formula: C28H41NO3
Fatty Acyls [FA] with formula: C18H29NO3
+ Fatty Acyls [FA] with formula: C25H39NO5
+ Fatty Acyls [FA] with formula: C21H39NO5
+ Fatty Acyls [FA] with formula: C23H41NO5
+ Fatty Acyls [FA] with formula: C27H39NO5
+ Fatty Acyls [FA] with formula: C23H43NO5
+ Fatty Acyls [FA] with formula: C25H41NO3
+ Fatty Acyls [FA] with formula: C27H43NO3
+ Fatty Acyls [FA] with formula: C27H45NO3
+ Fatty Acyls [FA] with formula: C31H41NO3
+ Fatty Acyls [FA] with formula: C27H42N2O3
+ Fatty Acyls [FA] with formula: C29H44N2O3
+ Fatty Acyls [FA] with formula: C29H46N2O3
+ Fatty Acyls [FA] with formula: C25H41NO4
+ Fatty Acyls [FA] with formula: C27H43NO4
+ Fatty Acyls [FA] with formula: C27H45NO4
+ Fatty Acyls [FA] with formula: C19H37NO4
+ Fatty Acyls [FA] with formula: C21H41NO4
+ Fatty Acyls [FA] with formula: C20H39NO3
+ Fatty Acyls [FA] with formula: C22H41NO3
+ Fatty Acyls [FA] with formula: C26H39NO3
+ Fatty Acyls [FA] with formula: C22H43NO3
+ Fatty Acyls [FA] with formula: C20H39NO4
+ Fatty Acyls [FA] with formula: C22H41NO4
+ Fatty Acyls [FA] with formula: C21H41NO3S
+ Fatty Acyls [FA] with formula: C23H43NO3S
+ Fatty Acyls [FA] with formula: C24H45NO3
+ Fatty Acyls [FA] with formula: C21H39NO3
+ Fatty Acyls [FA] with formula: C23H41NO3
+ Fatty Acyls [FA] with formula: C23H43NO3
+ Fatty Acyls [FA] with formula: C21H41NO3
+ Fatty Acyls [FA] with formula: C23H45NO3
+ Fatty Acyls [FA] with formula: C19H37NO3
+ Fatty Acyls [FA] with formula: C25H40N2O4
+ Fatty Acyls [FA] with formula: C21H40N2O4
+ Fatty Acyls [FA] with formula: C23H42N2O4
+ Fatty Acyls [FA] with formula: C27H40N2O4
+ Fatty Acyls [FA] with formula: C23H44N2O4
+ Fatty Acyls [FA] with formula: C26H39N3O3
+ Fatty Acyls [FA] with formula: C22H39N3O3
+ Fatty Acyls [FA] with formula: C24H41N3O3
+ Fatty Acyls [FA] with formula: C28H39N3O3
+ Fatty Acyls [FA] with formula: C24H43N3O3
+ Fatty Acyls [FA] with formula: C23H46N4O3
+ Fatty Acyls [FA] with formula: C22H40N2O4
+ Fatty Acyls [FA] with formula: C20H37NO4S
+ Fatty Acyls [FA] with formula: C26H43NO3
+ Fatty Acyls [FA] with formula: C30H42N2O2
+ Fatty Acyls [FA] with formula: C7H15NO
Fatty Acyls [FA] with formula: C16H27NO4
Fatty Acyls [FA] with formula: C8H13NO3
Fatty Acyls [FA] with formula: C10H15NO4
@@ -763,6 +862,7 @@
Fatty Acyls [FA] with formula: C22H39NO2
Fatty Acyls [FA] with formula: C22H45NO2
Fatty Acyls [FA] with formula: C22H37NO3
+ Fatty Acyls [FA] with formula: C14H29NO2
Fatty Acyls [FA] with formula: C18H35NO2
Fatty Acyls [FA] with formula: C17H35NO2
Fatty Acyls [FA] with formula: C19H39NO2
@@ -785,12 +885,13 @@
Fatty Acyls [FA] with formula: C31H64
Fatty Acyls [FA] with formula: C30H60
Fatty Acyls [FA] with formula: C33H68
+ Fatty Acyls [FA] with formula: C31H46
Fatty Acyls [FA] with formula: C11H22O
Fatty Acyls [FA] with formula: C5H10O
Fatty Acyls [FA] with formula: C7H14O
Fatty Acyls [FA] with formula: C31H62O
- Fatty Acyls [FA] with formula: C31H60O2
- Fatty Acyls [FA] with formula: C33H64O2
+ Fatty Acyls [FA] with formula: C31H60O2
+ Fatty Acyls [FA] with formula: C33H64O2
Fatty Acyls [FA] with formula: C29H58O
Fatty Acyls [FA] with formula: C40H78O8
Fatty Acyls [FA] with formula: C42H82O8
@@ -804,7 +905,7 @@
Fatty Acyls [FA] with formula: C38H76O9
Fatty Acyls [FA] with formula: C34H66O8
Fatty Acyls [FA] with formula: C32H62O8
- Fatty Acyls [FA] with formula: C36H70O9
+ Fatty Acyls [FA] with formula: C36H70O9
Fatty Acyls [FA] with formula: C32H64O8
Fatty Acyls [FA] with formula: C34H66O9
Fatty Acyls [FA] with formula: C38H74O9
@@ -816,7 +917,7 @@
Fatty Acyls [FA] with formula: C34H64O13
Fatty Acyls [FA] with formula: C27H50O9
-
+
Glycerolipids [GL] with formula: C50H85NO7
Glycerolipids [GL] with formula: C41H80O8
@@ -826,13 +927,15 @@
Glycerolipids [GL] with formula: C48H83NO7
Glycerolipids [GL] with formula: C20H40O4
Glycerolipids [GL] with formula: C21H42O4
- Glycerolipids [GL] with formula: C21H40O4
+ Glycerolipids [GL] with formula: C21H40O4
Glycerolipids [GL] with formula: C21H38O4
Glycerolipids [GL] with formula: C23H46O4
Glycerolipids [GL] with formula: C15H30O4
- Glycerolipids [GL] with formula: C19H38O4
+ Glycerolipids [GL] with formula: C19H38O4
Glycerolipids [GL] with formula: C23H38O4
- Glycerolipids [GL] with formula: C23H40O3
+ Glycerolipids [GL] with formula: C23H36O4
+ Glycerolipids [GL] with formula: C25H38O4
+ Glycerolipids [GL] with formula: C23H40O3
Glycerolipids [GL] with formula: C9H20O3
Glycerolipids [GL] with formula: C11H24O3
Glycerolipids [GL] with formula: C35H68O5
@@ -1035,7 +1138,7 @@
Glycerolipids [GL] with formula: C59H100O6
Glycerolipids [GL] with formula: C60H106O6
Glycerolipids [GL] with formula: C59H96O6
- Glycerolipids [GL] with formula: C60H104O6
+ Glycerolipids [GL] with formula: C60H104O6
Glycerolipids [GL] with formula: C59H94O6
Glycerolipids [GL] with formula: C62H118O6
Glycerolipids [GL] with formula: C59H92O6
@@ -1065,7 +1168,7 @@
Glycerolipids [GL] with formula: C61H94O6
Glycerolipids [GL] with formula: C64H122O6
Glycerolipids [GL] with formula: C65H126O6
- Glycerolipids [GL] with formula: C63H116O6
+ Glycerolipids [GL] with formula: C63H116O6
Glycerolipids [GL] with formula: C62H104O6
Glycerolipids [GL] with formula: C62H108O6
Glycerolipids [GL] with formula: C61H98O6
@@ -1113,7 +1216,7 @@
Glycerolipids [GL] with formula: C63H94O6
Glycerolipids [GL] with formula: C64H104O6
Glycerolipids [GL] with formula: C65H108O6
- Glycerolipids [GL] with formula: C65H116O6
+ Glycerolipids [GL] with formula: C65H116O6
Glycerolipids [GL] with formula: C66H120O6
Glycerolipids [GL] with formula: C65H106O6
Glycerolipids [GL] with formula: C67H124O6
@@ -1211,14 +1314,14 @@
Glycerolipids [GL] with formula: C43H80O10
Glycerolipids [GL] with formula: C43H78O10
Glycerolipids [GL] with formula: C43H68O11
+ Glycerolipids [GL] with formula: C49H99N2O17P2
Glycerolipids [GL] with formula: C104H205O26PS
Glycerolipids [GL] with formula: C55H108O16S
Glycerolipids [GL] with formula: C61H118O21S
Glycerolipids [GL] with formula: C99H197O21PS
-
+
- Glycerophospholipids [GP] with formula: C43H82NO10P
Glycerophospholipids [GP] with formula: C39H77O8PS
Glycerophospholipids [GP] with formula: C35H69O8PS
Glycerophospholipids [GP] with formula: C37H73O8PS
@@ -1226,165 +1329,197 @@
Glycerophospholipids [GP] with formula: C51H101O8PS
Glycerophospholipids [GP] with formula: C21H41O6P
Glycerophospholipids [GP] with formula: C21H39O6P
- Glycerophospholipids [GP] with formula: C10H18NO8P
- Glycerophospholipids [GP] with formula: C45H82NO8P
- Glycerophospholipids [GP] with formula: C51H90NO8P
- Glycerophospholipids [GP] with formula: C36H68NO8P
- Glycerophospholipids [GP] with formula: C32H64NO8P
- Glycerophospholipids [GP] with formula: C33H66NO8P
- Glycerophospholipids [GP] with formula: C35H70NO8P
- Glycerophospholipids [GP] with formula: C36H72NO8P
- Glycerophospholipids [GP] with formula: C37H74NO8P
- Glycerophospholipids [GP] with formula: C30H56NO8P
- Glycerophospholipids [GP] with formula: C35H68NO8P
- Glycerophospholipids [GP] with formula: C30H60NO8P
- Glycerophospholipids [GP] with formula: C31H62NO8P
- Glycerophospholipids [GP] with formula: C38H74NO8P
- Glycerophospholipids [GP] with formula: C22H44NO8P
- Glycerophospholipids [GP] with formula: C42H72NO8P
- Glycerophospholipids [GP] with formula: C40H72NO8P
- Glycerophospholipids [GP] with formula: C39H76NO8P
- Glycerophospholipids [GP] with formula: C41H78NO8P
- Glycerophospholipids [GP] with formula: C42H78NO8P
- Glycerophospholipids [GP] with formula: C43H86NO8P
- Glycerophospholipids [GP] with formula: C39H78NO8P
- Glycerophospholipids [GP] with formula: C40H80NO8P
- Glycerophospholipids [GP] with formula: C41H82NO8P
- Glycerophospholipids [GP] with formula: C42H82NO8P
- Glycerophospholipids [GP] with formula: C43H80NO8P
+ Glycerophospholipids [GP] with formula: C19H37O6P
+ Glycerophospholipids [GP] with formula: C59H104NO11P
+ Glycerophospholipids [GP] with formula: C59H104NO12P
+ Glycerophospholipids [GP] with formula: C59H104NO13P
+ Glycerophospholipids [GP] with formula: C51H90NO8P
+ Glycerophospholipids [GP] with formula: C36H72NO8P
+ Glycerophospholipids [GP] with formula: C38H76NO8P
+ Glycerophospholipids [GP] with formula: C39H78NO8P
+ Glycerophospholipids [GP] with formula: C40H80NO8P
+ Glycerophospholipids [GP] with formula: C39H76NO8P
Glycerophospholipids [GP] with formula: C27H52NO8P
- Glycerophospholipids [GP] with formula: C29H56NO8P
- Glycerophospholipids [GP] with formula: C40H76NO8P
- Glycerophospholipids [GP] with formula: C42H74NO8P
+ Glycerophospholipids [GP] with formula: C42H74NO8P
Glycerophospholipids [GP] with formula: C26H50NO8P
- Glycerophospholipids [GP] with formula: C46H78NO8P
- Glycerophospholipids [GP] with formula: C43H84NO8P
- Glycerophospholipids [GP] with formula: C43H82NO8P
- Glycerophospholipids [GP] with formula: C47H84NO8P
- Glycerophospholipids [GP] with formula: C47H82NO8P
- Glycerophospholipids [GP] with formula: C37H72NO8P
- Glycerophospholipids [GP] with formula: C45H84NO8P
- Glycerophospholipids [GP] with formula: C28H56NO8P
- Glycerophospholipids [GP] with formula: C46H90NO8P
- Glycerophospholipids [GP] with formula: C46H88NO8P
- Glycerophospholipids [GP] with formula: C46H86NO8P
- Glycerophospholipids [GP] with formula: C48H90NO8P
- Glycerophospholipids [GP] with formula: C48H84NO8P
- Glycerophospholipids [GP] with formula: C50H98NO8P
- Glycerophospholipids [GP] with formula: C44H86NO8P
- Glycerophospholipids [GP] with formula: C44H84NO8P
- Glycerophospholipids [GP] with formula: C44H82NO8P
- Glycerophospholipids [GP] with formula: C44H80NO8P
- Glycerophospholipids [GP] with formula: C28H54NO8P
- Glycerophospholipids [GP] with formula: C46H84NO8P
- Glycerophospholipids [GP] with formula: C46H82NO8P
- Glycerophospholipids [GP] with formula: C48H86NO8P
- Glycerophospholipids [GP] with formula: C30H58NO8P
- Glycerophospholipids [GP] with formula: C28H52NO8P
- Glycerophospholipids [GP] with formula: C48H82NO8P
- Glycerophospholipids [GP] with formula: C44H76NO8P
- Glycerophospholipids [GP] with formula: C42H76NO8P
- Glycerophospholipids [GP] with formula: C44H72NO8P
- Glycerophospholipids [GP] with formula: C11H22NO8P
- Glycerophospholipids [GP] with formula: C12H24NO8P
- Glycerophospholipids [GP] with formula: C50H90NO8P
- Glycerophospholipids [GP] with formula: C50H88NO8P
- Glycerophospholipids [GP] with formula: C48H92NO8P
- Glycerophospholipids [GP] with formula: C50H80NO8P
- Glycerophospholipids [GP] with formula: C50H78NO8P
- Glycerophospholipids [GP] with formula: C48H94NO8P
- Glycerophospholipids [GP] with formula: C52H102NO8P
+ Glycerophospholipids [GP] with formula: C44H78NO8P
+ Glycerophospholipids [GP] with formula: C27H54NO8P
+ Glycerophospholipids [GP] with formula: C28H56NO8P
+ Glycerophospholipids [GP] with formula: C46H92NO8P
+ Glycerophospholipids [GP] with formula: C46H90NO8P
+ Glycerophospholipids [GP] with formula: C46H88NO8P
+ Glycerophospholipids [GP] with formula: C48H84NO8P
+ Glycerophospholipids [GP] with formula: C50H98NO8P
+ Glycerophospholipids [GP] with formula: C52H104NO8P
+ Glycerophospholipids [GP] with formula: C29H58NO8P
+ Glycerophospholipids [GP] with formula: C29H56NO8P
+ Glycerophospholipids [GP] with formula: C46H80NO8P
+ Glycerophospholipids [GP] with formula: C48H94NO8P
+ Glycerophospholipids [GP] with formula: C48H82NO8P
+ Glycerophospholipids [GP] with formula: C28H54NO8P
+ Glycerophospholipids [GP] with formula: C44H80NO8P
+ Glycerophospholipids [GP] with formula: C44H72NO8P
+ Glycerophospholipids [GP] with formula: C26H52NO8P
+ Glycerophospholipids [GP] with formula: C12H24NO8P
+ Glycerophospholipids [GP] with formula: C54H108NO8P
+ Glycerophospholipids [GP] with formula: C48H80NO8P
+ Glycerophospholipids [GP] with formula: C47H94NO8P
Glycerophospholipids [GP] with formula: C54H106NO8P
- Glycerophospholipids [GP] with formula: C52H100NO8P
- Glycerophospholipids [GP] with formula: C52H96NO8P
- Glycerophospholipids [GP] with formula: C48H88NO8P
- Glycerophospholipids [GP] with formula: C46H80NO8P
- Glycerophospholipids [GP] with formula: C48H80NO8P
- Glycerophospholipids [GP] with formula: C52H80NO8P
- Glycerophospholipids [GP] with formula: C54H104NO8P
- Glycerophospholipids [GP] with formula: C57H114NO8P
- Glycerophospholipids [GP] with formula: C58H116NO8P
- Glycerophospholipids [GP] with formula: C56H108NO8P
- Glycerophospholipids [GP] with formula: C56H104NO8P
- Glycerophospholipids [GP] with formula: C44H88NO8P
- Glycerophospholipids [GP] with formula: C45H90NO8P
- Glycerophospholipids [GP] with formula: C59H118NO8P
- Glycerophospholipids [GP] with formula: C60H120NO8P
+ Glycerophospholipids [GP] with formula: C52H80NO8P
+ Glycerophospholipids [GP] with formula: C54H104NO8P
+ Glycerophospholipids [GP] with formula: C48H96NO8P
+ Glycerophospholipids [GP] with formula: C56H112NO8P
+ Glycerophospholipids [GP] with formula: C56H108NO8P
Glycerophospholipids [GP] with formula: C60H116NO8P
- Glycerophospholipids [GP] with formula: C60H112NO8P
- Glycerophospholipids [GP] with formula: C50H96NO8P
- Glycerophospholipids [GP] with formula: C13H26NO8P
- Glycerophospholipids [GP] with formula: C14H28NO8P
- Glycerophospholipids [GP] with formula: C16H32NO8P
- Glycerophospholipids [GP] with formula: C18H36NO8P
- Glycerophospholipids [GP] with formula: C20H40NO8P
+ Glycerophospholipids [GP] with formula: C14H28NO8P
+ Glycerophospholipids [GP] with formula: C60H112NO8P
+ Glycerophospholipids [GP] with formula: C58H116NO8P
+ Glycerophospholipids [GP] with formula: C60H120NO8P
+ Glycerophospholipids [GP] with formula: C30H60NO8P
+ Glycerophospholipids [GP] with formula: C30H58NO8P
+ Glycerophospholipids [GP] with formula: C16H32NO8P
+ Glycerophospholipids [GP] with formula: C18H36NO8P
+ Glycerophospholipids [GP] with formula: C20H40NO8P
+ Glycerophospholipids [GP] with formula: C22H44NO8P
Glycerophospholipids [GP] with formula: C20H32NO8P
- Glycerophospholipids [GP] with formula: C28H48NO8P
+ Glycerophospholipids [GP] with formula: C28H48NO8P
+ Glycerophospholipids [GP] with formula: C37H74NO8P
+ Glycerophospholipids [GP] with formula: C24H48NO8P
Glycerophospholipids [GP] with formula: C24H40NO8P
- Glycerophospholipids [GP] with formula: C44H78NO8P
- Glycerophospholipids [GP] with formula: C37H76NO7P
- Glycerophospholipids [GP] with formula: C38H78NO7P
- Glycerophospholipids [GP] with formula: C38H76NO7P
- Glycerophospholipids [GP] with formula: C40H80NO7P
- Glycerophospholipids [GP] with formula: C40H76NO7P
- Glycerophospholipids [GP] with formula: C42H78NO7P
- Glycerophospholipids [GP] with formula: C44H90NO7P
- Glycerophospholipids [GP] with formula: C43H80NO7P
- Glycerophospholipids [GP] with formula: C40H82NO7P
- Glycerophospholipids [GP] with formula: C41H84NO7P
- Glycerophospholipids [GP] with formula: C42H86NO7P
- Glycerophospholipids [GP] with formula: C42H84NO7P
- Glycerophospholipids [GP] with formula: C42H82NO7P
- Glycerophospholipids [GP] with formula: C42H80NO7P
- Glycerophospholipids [GP] with formula: C44H88NO7P
- Glycerophospholipids [GP] with formula: C44H84NO7P
- Glycerophospholipids [GP] with formula: C44H82NO7P
- Glycerophospholipids [GP] with formula: C44H80NO7P
- Glycerophospholipids [GP] with formula: C46H82NO7P
- Glycerophospholipids [GP] with formula: C50H102NO7P
- Glycerophospholipids [GP] with formula: C27H54NO7P
- Glycerophospholipids [GP] with formula: C43H86NO7P
- Glycerophospholipids [GP] with formula: C45H92NO7P
- Glycerophospholipids [GP] with formula: C45H84NO7P
- Glycerophospholipids [GP] with formula: C47H96NO7P
- Glycerophospholipids [GP] with formula: C46H94NO7P
- Glycerophospholipids [GP] with formula: C46H92NO7P
- Glycerophospholipids [GP] with formula: C46H86NO7P
- Glycerophospholipids [GP] with formula: C46H84NO7P
- Glycerophospholipids [GP] with formula: C48H98NO7P
- Glycerophospholipids [GP] with formula: C48H88NO7P
- Glycerophospholipids [GP] with formula: C48H86NO7P
- Glycerophospholipids [GP] with formula: C29H60NO7P
- Glycerophospholipids [GP] with formula: C29H58NO7P
- Glycerophospholipids [GP] with formula: C30H62NO7P
- Glycerophospholipids [GP] with formula: C49H100NO7P
- Glycerophospholipids [GP] with formula: C20H40NO7P
- Glycerophospholipids [GP] with formula: C21H42NO7P
- Glycerophospholipids [GP] with formula: C28H56NO7P
- Glycerophospholipids [GP] with formula: C28H54NO7P
- Glycerophospholipids [GP] with formula: C40H78NO7P
+ Glycerophospholipids [GP] with formula: C35H70NO8P
+ Glycerophospholipids [GP] with formula: C40H74NO8P
+ Glycerophospholipids [GP] with formula: C40H72NO8P
+ Glycerophospholipids [GP] with formula: C40H70NO8P
+ Glycerophospholipids [GP] with formula: C33H66NO8P
+ Glycerophospholipids [GP] with formula: C41H82NO8P
+ Glycerophospholipids [GP] with formula: C41H80NO8P
+ Glycerophospholipids [GP] with formula: C42H82NO8P
+ Glycerophospholipids [GP] with formula: C42H80NO8P
+ Glycerophospholipids [GP] with formula: C42H78NO8P
+ Glycerophospholipids [GP] with formula: C43H86NO8P
+ Glycerophospholipids [GP] with formula: C44H86NO8P
+ Glycerophospholipids [GP] with formula: C44H84NO8P
+ Glycerophospholipids [GP] with formula: C34H66NO8P
+ Glycerophospholipids [GP] with formula: C47H78NO8P
+ Glycerophospholipids [GP] with formula: C46H76NO8P
+ Glycerophospholipids [GP] with formula: C39H70NO8P
+ Glycerophospholipids [GP] with formula: C48H76NO8P
+ Glycerophospholipids [GP] with formula: C49H86NO8P
+ Glycerophospholipids [GP] with formula: C43H84NO8P
+ Glycerophospholipids [GP] with formula: C43H82NO8P
+ Glycerophospholipids [GP] with formula: C44H82NO8P
+ Glycerophospholipids [GP] with formula: C45H88NO8P
+ Glycerophospholipids [GP] with formula: C45H86NO8P
+ Glycerophospholipids [GP] with formula: C45H84NO8P
+ Glycerophospholipids [GP] with formula: C49H84NO8P
+ Glycerophospholipids [GP] with formula: C46H82NO8P
+ Glycerophospholipids [GP] with formula: C48H92NO8P
+ Glycerophospholipids [GP] with formula: C48H90NO8P
+ Glycerophospholipids [GP] with formula: C48H88NO8P
+ Glycerophospholipids [GP] with formula: C48H86NO8P
+ Glycerophospholipids [GP] with formula: C46H86NO8P
+ Glycerophospholipids [GP] with formula: C50H80NO8P
+ Glycerophospholipids [GP] with formula: C46H74NO8P
+ Glycerophospholipids [GP] with formula: C48H78NO8P
+ Glycerophospholipids [GP] with formula: C49H88NO8P
+ Glycerophospholipids [GP] with formula: C50H90NO8P
+ Glycerophospholipids [GP] with formula: C50H88NO8P
+ Glycerophospholipids [GP] with formula: C50H86NO8P
+ Glycerophospholipids [GP] with formula: C50H82NO8P
+ Glycerophospholipids [GP] with formula: C45H90NO8P
+ Glycerophospholipids [GP] with formula: C49H98NO8P
+ Glycerophospholipids [GP] with formula: C50H100NO8P
+ Glycerophospholipids [GP] with formula: C50H96NO8P
+ Glycerophospholipids [GP] with formula: C50H94NO8P
+ Glycerophospholipids [GP] with formula: C50H92NO8P
+ Glycerophospholipids [GP] with formula: C51H102NO8P
+ Glycerophospholipids [GP] with formula: C52H102NO8P
+ Glycerophospholipids [GP] with formula: C52H100NO8P
+ Glycerophospholipids [GP] with formula: C52H96NO8P
+ Glycerophospholipids [GP] with formula: C49H94NO8P
+ Glycerophospholipids [GP] with formula: C51H100NO8P
+ Glycerophospholipids [GP] with formula: C52H98NO8P
+ Glycerophospholipids [GP] with formula: C52H94NO8P
+ Glycerophospholipids [GP] with formula: C51H98NO8P
+ Glycerophospholipids [GP] with formula: C52H92NO8P
+ Glycerophospholipids [GP] with formula: C52H88NO8P
+ Glycerophospholipids [GP] with formula: C49H90NO8P
+ Glycerophospholipids [GP] with formula: C50H84NO8P
+ Glycerophospholipids [GP] with formula: C51H94NO8P
+ Glycerophospholipids [GP] with formula: C50H78NO8P
+ Glycerophospholipids [GP] with formula: C52H90NO8P
+ Glycerophospholipids [GP] with formula: C52H84NO8P
+ Glycerophospholipids [GP] with formula: C40H78NO7P
+ Glycerophospholipids [GP] with formula: C40H76NO7P
+ Glycerophospholipids [GP] with formula: C44H90NO7P
+ Glycerophospholipids [GP] with formula: C44H80NO7P
+ Glycerophospholipids [GP] with formula: C48H86NO7P
+ Glycerophospholipids [GP] with formula: C29H60NO7P
+ Glycerophospholipids [GP] with formula: C29H58NO7P
+ Glycerophospholipids [GP] with formula: C30H62NO7P
+ Glycerophospholipids [GP] with formula: C49H100NO7P
+ Glycerophospholipids [GP] with formula: C50H102NO7P
+ Glycerophospholipids [GP] with formula: C28H56NO7P
+ Glycerophospholipids [GP] with formula: C46H84NO7P
+ Glycerophospholipids [GP] with formula: C28H54NO7P
+ Glycerophospholipids [GP] with formula: C36H74NO7P
+ Glycerophospholipids [GP] with formula: C37H76NO7P
+ Glycerophospholipids [GP] with formula: C38H78NO7P
+ Glycerophospholipids [GP] with formula: C38H76NO7P
+ Glycerophospholipids [GP] with formula: C45H92NO7P
+ Glycerophospholipids [GP] with formula: C46H90NO7P
+ Glycerophospholipids [GP] with formula: C46H86NO7P
+ Glycerophospholipids [GP] with formula: C39H80NO7P
+ Glycerophospholipids [GP] with formula: C41H84NO7P
+ Glycerophospholipids [GP] with formula: C43H88NO7P
+ Glycerophospholipids [GP] with formula: C46H88NO7P
+ Glycerophospholipids [GP] with formula: C47H96NO7P
+ Glycerophospholipids [GP] with formula: C48H98NO7P
+ Glycerophospholipids [GP] with formula: C48H90NO7P
+ Glycerophospholipids [GP] with formula: C50H94NO7P
+ Glycerophospholipids [GP] with formula: C50H90NO7P
Glycerophospholipids [GP] with formula: C48H84NO7P
- Glycerophospholipids [GP] with formula: C21H46NO6P
- Glycerophospholipids [GP] with formula: C36H76NO6P
- Glycerophospholipids [GP] with formula: C40H84NO6P
- Glycerophospholipids [GP] with formula: C42H88NO6P
- Glycerophospholipids [GP] with formula: C42H86NO6P
- Glycerophospholipids [GP] with formula: C26H56NO6P
- Glycerophospholipids [GP] with formula: C28H60NO6P
- Glycerophospholipids [GP] with formula: C29H62NO6P
- Glycerophospholipids [GP] with formula: C30H64NO6P
- Glycerophospholipids [GP] with formula: C27H58NO6P
- Glycerophospholipids [GP] with formula: C44H92NO6P
- Glycerophospholipids [GP] with formula: C28H58NO6P
- Glycerophospholipids [GP] with formula: C29H61NO6P
- Glycerophospholipids [GP] with formula: C27H56NO6P
- Glycerophospholipids [GP] with formula: C44H88NO6P
+ Glycerophospholipids [GP] with formula: C46H80NO7P
+ Glycerophospholipids [GP] with formula: C50H74NO10P
+ Glycerophospholipids [GP] with formula: C39H76NO7P
+ Glycerophospholipids [GP] with formula: C42H76NO7P
+ Glycerophospholipids [GP] with formula: C44H78NO7P
+ Glycerophospholipids [GP] with formula: C41H80NO7P
+ Glycerophospholipids [GP] with formula: C43H82NO7P
+ Glycerophospholipids [GP] with formula: C44H88NO7P
+ Glycerophospholipids [GP] with formula: C44H84NO7P
+ Glycerophospholipids [GP] with formula: C44H82NO7P
+ Glycerophospholipids [GP] with formula: C46H82NO7P
+ Glycerophospholipids [GP] with formula: C48H96NO7P
+ Glycerophospholipids [GP] with formula: C48H94NO7P
+ Glycerophospholipids [GP] with formula: C48H92NO7P
+ Glycerophospholipids [GP] with formula: C48H88NO7P
+ Glycerophospholipids [GP] with formula: C40H80NO7P
+ Glycerophospholipids [GP] with formula: C41H82NO7P
+ Glycerophospholipids [GP] with formula: C42H84NO7P
+ Glycerophospholipids [GP] with formula: C42H82NO7P
+ Glycerophospholipids [GP] with formula: C43H86NO7P
+ Glycerophospholipids [GP] with formula: C43H84NO7P
+ Glycerophospholipids [GP] with formula: C49H98NO7P
+ Glycerophospholipids [GP] with formula: C50H100NO7P
+ Glycerophospholipids [GP] with formula: C50H98NO7P
+ Glycerophospholipids [GP] with formula: C50H96NO7P
+ Glycerophospholipids [GP] with formula: C50H92NO7P
+ Glycerophospholipids [GP] with formula: C50H88NO7P
+ Glycerophospholipids [GP] with formula: C21H46NO6P
+ Glycerophospholipids [GP] with formula: C32H68NO6P
+ Glycerophospholipids [GP] with formula: C36H76NO6P
+ Glycerophospholipids [GP] with formula: C40H84NO6P
+ Glycerophospholipids [GP] with formula: C42H88NO6P
+ Glycerophospholipids [GP] with formula: C26H56NO6P
+ Glycerophospholipids [GP] with formula: C27H58NO6P
+ Glycerophospholipids [GP] with formula: C27H56NO6P
+ Glycerophospholipids [GP] with formula: C42H86NO6P
+ Glycerophospholipids [GP] with formula: C44H88NO6P
Glycerophospholipids [GP] with formula: C11H26NO6P
- Glycerophospholipids [GP] with formula: C29H58NO6P
- Glycerophospholipids [GP] with formula: C22H48NO6P
- Glycerophospholipids [GP] with formula: C17H38NO6P
- Glycerophospholipids [GP] with formula: C32H68NO6P
- Glycerophospholipids [GP] with formula: C18H40NO6P
+ Glycerophospholipids [GP] with formula: C12H28NO6P
+ Glycerophospholipids [GP] with formula: C29H62NO6P
+ Glycerophospholipids [GP] with formula: C20H44NO6P
Glycerophospholipids [GP] with formula: C46H78NO6P
Glycerophospholipids [GP] with formula: C48H82NO6P
Glycerophospholipids [GP] with formula: C46H80NO6P
@@ -1396,261 +1531,1207 @@
Glycerophospholipids [GP] with formula: C48H88NO6P
Glycerophospholipids [GP] with formula: C48H96NO6P
Glycerophospholipids [GP] with formula: C48H100NO6P
- Glycerophospholipids [GP] with formula: C25H50NO7P
Glycerophospholipids [GP] with formula: C27H50NO7P
Glycerophospholipids [GP] with formula: C29H52NO7P
- Glycerophospholipids [GP] with formula: C24H48NO7P
- Glycerophospholipids [GP] with formula: C26H52NO7P
- Glycerophospholipids [GP] with formula: C26H50NO7P
- Glycerophospholipids [GP] with formula: C26H48NO7P
- Glycerophospholipids [GP] with formula: C26H46NO7P
+ Glycerophospholipids [GP] with formula: C20H42NO7P
+ Glycerophospholipids [GP] with formula: C24H48NO7P
+ Glycerophospholipids [GP] with formula: C26H50NO7P
+ Glycerophospholipids [GP] with formula: C26H46NO7P
Glycerophospholipids [GP] with formula: C28H48NO7P
- Glycerophospholipids [GP] with formula: C30H50NO7P
- Glycerophospholipids [GP] with formula: C32H66NO7P
- Glycerophospholipids [GP] with formula: C15H32NO7P
- Glycerophospholipids [GP] with formula: C22H46NO7P
- Glycerophospholipids [GP] with formula: C24H50NO7P
- Glycerophospholipids [GP] with formula: C26H54NO7P
- Glycerophospholipids [GP] with formula: C10H22NO7P
- Glycerophospholipids [GP] with formula: C11H24NO7P
- Glycerophospholipids [GP] with formula: C11H22NO7P
- Glycerophospholipids [GP] with formula: C12H26NO7P
- Glycerophospholipids [GP] with formula: C13H28NO7P
- Glycerophospholipids [GP] with formula: C14H30NO7P
- Glycerophospholipids [GP] with formula: C16H34NO7P
- Glycerophospholipids [GP] with formula: C28H50NO7P
- Glycerophospholipids [GP] with formula: C20H44NO6P
- Glycerophospholipids [GP] with formula: C23H50NO6P
- Glycerophospholipids [GP] with formula: C24H52NO6P
- Glycerophospholipids [GP] with formula: C25H54NO6P
- Glycerophospholipids [GP] with formula: C12H28NO6P
+ Glycerophospholipids [GP] with formula: C30H50NO7P
+ Glycerophospholipids [GP] with formula: C32H66NO7P
+ Glycerophospholipids [GP] with formula: C14H30NO7P
+ Glycerophospholipids [GP] with formula: C15H32NO7P
+ Glycerophospholipids [GP] with formula: C16H34NO7P
+ Glycerophospholipids [GP] with formula: C26H52NO7P
+ Glycerophospholipids [GP] with formula: C10H22NO7P
+ Glycerophospholipids [GP] with formula: C11H24NO7P
+ Glycerophospholipids [GP] with formula: C11H22NO7P
+ Glycerophospholipids [GP] with formula: C12H26NO7P
+ Glycerophospholipids [GP] with formula: C13H28NO7P
+ Glycerophospholipids [GP] with formula: C28H50NO7P
+ Glycerophospholipids [GP] with formula: C30H54NO7P
+ Glycerophospholipids [GP] with formula: C26H48NO7P
+ Glycerophospholipids [GP] with formula: C28H52NO7P
+ Glycerophospholipids [GP] with formula: C30H60NO7P
+ Glycerophospholipids [GP] with formula: C30H58NO7P
+ Glycerophospholipids [GP] with formula: C22H48NO6P
Glycerophospholipids [GP] with formula: C13H30NO6P
- Glycerophospholipids [GP] with formula: C14H32NO6P
Glycerophospholipids [GP] with formula: C28H52NO6P
Glycerophospholipids [GP] with formula: C18H38NO6P
- Glycerophospholipids [GP] with formula: C24H48NO6P
+ Glycerophospholipids [GP] with formula: C24H52NO6P
+ Glycerophospholipids [GP] with formula: C28H60NO6P
Glycerophospholipids [GP] with formula: C22H46NO6P
- Glycerophospholipids [GP] with formula: C23H48NO6P
- Glycerophospholipids [GP] with formula: C24H50NO6P
- Glycerophospholipids [GP] with formula: C25H52NO6P
- Glycerophospholipids [GP] with formula: C26H54NO6P
+ Glycerophospholipids [GP] with formula: C24H50NO6P
+ Glycerophospholipids [GP] with formula: C26H54NO6P
Glycerophospholipids [GP] with formula: C27H54NO6P
- Glycerophospholipids [GP] with formula: C26H52NO6P
+ Glycerophospholipids [GP] with formula: C26H52NO6P
+ Glycerophospholipids [GP] with formula: C28H58NO6P
Glycerophospholipids [GP] with formula: C46H76NO7P
Glycerophospholipids [GP] with formula: C48H80NO7P
Glycerophospholipids [GP] with formula: C46H78NO7P
Glycerophospholipids [GP] with formula: C48H82NO7P
- Glycerophospholipids [GP] with formula: C44H86NO7P
- Glycerophospholipids [GP] with formula: C25H52NO7P
- Glycerophospholipids [GP] with formula: C28H58NO7P
- Glycerophospholipids [GP] with formula: C27H56NO7P
- Glycerophospholipids [GP] with formula: C36H70NO8P
- Glycerophospholipids [GP] with formula: C25H50NO8P
- Glycerophospholipids [GP] with formula: C37H70NO8P
- Glycerophospholipids [GP] with formula: C41H70NO8P
- Glycerophospholipids [GP] with formula: C45H74NO8P
- Glycerophospholipids [GP] with formula: C39H74NO8P
- Glycerophospholipids [GP] with formula: C41H76NO8P
- Glycerophospholipids [GP] with formula: C39H72NO8P
- Glycerophospholipids [GP] with formula: C26H52NO8P
- Glycerophospholipids [GP] with formula: C27H54NO8P
- Glycerophospholipids [GP] with formula: C29H58NO8P
- Glycerophospholipids [GP] with formula: C50H100NO8P
- Glycerophospholipids [GP] with formula: C51H102NO8P
- Glycerophospholipids [GP] with formula: C52H104NO8P
- Glycerophospholipids [GP] with formula: C53H106NO8P
- Glycerophospholipids [GP] with formula: C54H108NO8P
- Glycerophospholipids [GP] with formula: C55H110NO8P
- Glycerophospholipids [GP] with formula: C56H112NO8P
+ Glycerophospholipids [GP] with formula: C42H78NO7P
+ Glycerophospholipids [GP] with formula: C25H52NO7P
+ Glycerophospholipids [GP] with formula: C40H82NO7P
+ Glycerophospholipids [GP] with formula: C42H86NO7P
+ Glycerophospholipids [GP] with formula: C28H58NO7P
Glycerophospholipids [GP] with formula: C49H74NO8P
- Glycerophospholipids [GP] with formula: C21H42NO8P
- Glycerophospholipids [GP] with formula: C17H34NO8P
- Glycerophospholipids [GP] with formula: C41H74NO8P
- Glycerophospholipids [GP] with formula: C45H86NO8P
- Glycerophospholipids [GP] with formula: C47H94NO8P
- Glycerophospholipids [GP] with formula: C45H88NO8P
- Glycerophospholipids [GP] with formula: C47H74NO8P
- Glycerophospholipids [GP] with formula: C57H106NO8P
- Glycerophospholipids [GP] with formula: C49H98NO8P
- Glycerophospholipids [GP] with formula: C48H96NO8P
- Glycerophospholipids [GP] with formula: C46H92NO8P
- Glycerophospholipids [GP] with formula: C24H48NO8P
- Glycerophospholipids [GP] with formula: C23H46NO8P
- Glycerophospholipids [GP] with formula: C51H100NO8P
- Glycerophospholipids [GP] with formula: C47H92NO8P
- Glycerophospholipids [GP] with formula: C49H96NO8P
- Glycerophospholipids [GP] with formula: C41H80NO8P
- Glycerophospholipids [GP] with formula: C34H68NO8P
- Glycerophospholipids [GP] with formula: C42H84NO8P
- Glycerophospholipids [GP] with formula: C38H76NO8P
- Glycerophospholipids [GP] with formula: C42H80NO8P
- Glycerophospholipids [GP] with formula: C40H78NO8P
+ Glycerophospholipids [GP] with formula: C25H50NO8P
+ Glycerophospholipids [GP] with formula: C21H42NO8P
+ Glycerophospholipids [GP] with formula: C17H34NO8P
+ Glycerophospholipids [GP] with formula: C47H74NO8P
+ Glycerophospholipids [GP] with formula: C57H106NO8P
+ Glycerophospholipids [GP] with formula: C31H62NO8P
+ Glycerophospholipids [GP] with formula: C47H92NO8P
+ Glycerophospholipids [GP] with formula: C49H96NO8P
Glycerophospholipids [GP] with formula: C57H108NO9P
- Glycerophospholipids [GP] with formula: C39H80NO7P
- Glycerophospholipids [GP] with formula: C43H78NO7P
- Glycerophospholipids [GP] with formula: C43H88NO7P
- Glycerophospholipids [GP] with formula: C39H78NO7P
- Glycerophospholipids [GP] with formula: C41H76NO7P
+ Glycerophospholipids [GP] with formula: C37H68NO8P
+ Glycerophospholipids [GP] with formula: C37H66NO8P
+ Glycerophospholipids [GP] with formula: C37H64NO8P
+ Glycerophospholipids [GP] with formula: C36H64NO8P
+ Glycerophospholipids [GP] with formula: C38H68NO8P
+ Glycerophospholipids [GP] with formula: C31H60NO8P
+ Glycerophospholipids [GP] with formula: C41H72NO8P
+ Glycerophospholipids [GP] with formula: C41H68NO8P
+ Glycerophospholipids [GP] with formula: C32H64NO8P
+ Glycerophospholipids [GP] with formula: C34H68NO8P
+ Glycerophospholipids [GP] with formula: C37H72NO8P
+ Glycerophospholipids [GP] with formula: C38H70NO8P
+ Glycerophospholipids [GP] with formula: C32H62NO8P
+ Glycerophospholipids [GP] with formula: C33H64NO8P
+ Glycerophospholipids [GP] with formula: C34H64NO8P
+ Glycerophospholipids [GP] with formula: C35H66NO8P
+ Glycerophospholipids [GP] with formula: C38H66NO8P
+ Glycerophospholipids [GP] with formula: C40H68NO8P
+ Glycerophospholipids [GP] with formula: C44H74NO8P
+ Glycerophospholipids [GP] with formula: C36H66NO8P
+ Glycerophospholipids [GP] with formula: C42H76NO8P
+ Glycerophospholipids [GP] with formula: C42H72NO8P
+ Glycerophospholipids [GP] with formula: C42H70NO8P
+ Glycerophospholipids [GP] with formula: C42H84NO8P
+ Glycerophospholipids [GP] with formula: C44H88NO8P
+ Glycerophospholipids [GP] with formula: C35H68NO8P
+ Glycerophospholipids [GP] with formula: C36H70NO8P
+ Glycerophospholipids [GP] with formula: C37H70NO8P
+ Glycerophospholipids [GP] with formula: C38H74NO8P
+ Glycerophospholipids [GP] with formula: C38H72NO8P
+ Glycerophospholipids [GP] with formula: C36H68NO8P
+ Glycerophospholipids [GP] with formula: C39H72NO8P
+ Glycerophospholipids [GP] with formula: C43H80NO8P
+ Glycerophospholipids [GP] with formula: C43H78NO8P
+ Glycerophospholipids [GP] with formula: C43H76NO8P
+ Glycerophospholipids [GP] with formula: C43H72NO8P
+ Glycerophospholipids [GP] with formula: C35H64NO8P
+ Glycerophospholipids [GP] with formula: C43H70NO8P
+ Glycerophospholipids [GP] with formula: C35H62NO8P
+ Glycerophospholipids [GP] with formula: C41H66NO8P
+ Glycerophospholipids [GP] with formula: C41H76NO8P
+ Glycerophospholipids [GP] with formula: C46H78NO8P
+ Glycerophospholipids [GP] with formula: C47H86NO8P
+ Glycerophospholipids [GP] with formula: C39H74NO8P
+ Glycerophospholipids [GP] with formula: C40H78NO8P
+ Glycerophospholipids [GP] with formula: C40H76NO8P
+ Glycerophospholipids [GP] with formula: C41H78NO8P
+ Glycerophospholipids [GP] with formula: C47H90NO8P
+ Glycerophospholipids [GP] with formula: C47H88NO8P
+ Glycerophospholipids [GP] with formula: C47H84NO8P
+ Glycerophospholipids [GP] with formula: C39H68NO8P
+ Glycerophospholipids [GP] with formula: C43H68NO8P
+ Glycerophospholipids [GP] with formula: C45H72NO8P
+ Glycerophospholipids [GP] with formula: C45H70NO8P
+ Glycerophospholipids [GP] with formula: C47H82NO8P
+ Glycerophospholipids [GP] with formula: C47H80NO8P
+ Glycerophospholipids [GP] with formula: C47H76NO8P
+ Glycerophospholipids [GP] with formula: C49H92NO8P
+ Glycerophospholipids [GP] with formula: C49H82NO8P
+ Glycerophospholipids [GP] with formula: C44H76NO8P
+ Glycerophospholipids [GP] with formula: C45H82NO8P
+ Glycerophospholipids [GP] with formula: C45H80NO8P
+ Glycerophospholipids [GP] with formula: C45H78NO8P
+ Glycerophospholipids [GP] with formula: C45H76NO8P
+ Glycerophospholipids [GP] with formula: C45H74NO8P
+ Glycerophospholipids [GP] with formula: C46H84NO8P
+ Glycerophospholipids [GP] with formula: C49H78NO8P
+ Glycerophospholipids [GP] with formula: C47H72NO8P
+ Glycerophospholipids [GP] with formula: C43H74NO8P
+ Glycerophospholipids [GP] with formula: C41H74NO8P
+ Glycerophospholipids [GP] with formula: C33H62NO8P
+ Glycerophospholipids [GP] with formula: C41H70NO8P
+ Glycerophospholipids [GP] with formula: C39H66NO8P
+ Glycerophospholipids [GP] with formula: C33H68NO7P
+ Glycerophospholipids [GP] with formula: C34H70NO7P
+ Glycerophospholipids [GP] with formula: C35H72NO7P
+ Glycerophospholipids [GP] with formula: C37H74NO7P
+ Glycerophospholipids [GP] with formula: C41H78NO7P
+ Glycerophospholipids [GP] with formula: C41H76NO7P
+ Glycerophospholipids [GP] with formula: C39H78NO7P
+ Glycerophospholipids [GP] with formula: C46H94NO7P
+ Glycerophospholipids [GP] with formula: C47H88NO7P
+ Glycerophospholipids [GP] with formula: C47H84NO7P
Glycerophospholipids [GP] with formula: C43H74NO7P
- Glycerophospholipids [GP] with formula: C41H80NO7P
Glycerophospholipids [GP] with formula: C45H78NO7P
- Glycerophospholipids [GP] with formula: C37H78NO6P
- Glycerophospholipids [GP] with formula: C41H86NO6P
- Glycerophospholipids [GP] with formula: C39H82NO6P
+ Glycerophospholipids [GP] with formula: C33H66NO7P
+ Glycerophospholipids [GP] with formula: C34H68NO7P
+ Glycerophospholipids [GP] with formula: C35H68NO7P
+ Glycerophospholipids [GP] with formula: C36H70NO7P
+ Glycerophospholipids [GP] with formula: C38H72NO7P
+ Glycerophospholipids [GP] with formula: C39H72NO7P
+ Glycerophospholipids [GP] with formula: C39H70NO7P
+ Glycerophospholipids [GP] with formula: C41H72NO7P
+ Glycerophospholipids [GP] with formula: C35H70NO7P
+ Glycerophospholipids [GP] with formula: C36H72NO7P
+ Glycerophospholipids [GP] with formula: C37H72NO7P
+ Glycerophospholipids [GP] with formula: C38H74NO7P
+ Glycerophospholipids [GP] with formula: C43H76NO7P
+ Glycerophospholipids [GP] with formula: C42H80NO7P
+ Glycerophospholipids [GP] with formula: C43H80NO7P
+ Glycerophospholipids [GP] with formula: C43H78NO7P
+ Glycerophospholipids [GP] with formula: C44H86NO7P
+ Glycerophospholipids [GP] with formula: C45H90NO7P
+ Glycerophospholipids [GP] with formula: C45H88NO7P
+ Glycerophospholipids [GP] with formula: C45H86NO7P
+ Glycerophospholipids [GP] with formula: C45H84NO7P
+ Glycerophospholipids [GP] with formula: C45H82NO7P
+ Glycerophospholipids [GP] with formula: C45H80NO7P
+ Glycerophospholipids [GP] with formula: C46H92NO7P
+ Glycerophospholipids [GP] with formula: C47H94NO7P
+ Glycerophospholipids [GP] with formula: C47H92NO7P
+ Glycerophospholipids [GP] with formula: C47H90NO7P
+ Glycerophospholipids [GP] with formula: C47H86NO7P
+ Glycerophospholipids [GP] with formula: C47H82NO7P
+ Glycerophospholipids [GP] with formula: C41H74NO7P
+ Glycerophospholipids [GP] with formula: C39H74NO7P
+ Glycerophospholipids [GP] with formula: C37H78NO6P
+ Glycerophospholipids [GP] with formula: C41H86NO6P
+ Glycerophospholipids [GP] with formula: C39H82NO6P
Glycerophospholipids [GP] with formula: C35H74NO6P
Glycerophospholipids [GP] with formula: C34H72NO6P
- Glycerophospholipids [GP] with formula: C38H80NO6P
+ Glycerophospholipids [GP] with formula: C38H80NO6P
Glycerophospholipids [GP] with formula: C43H72NO6P
Glycerophospholipids [GP] with formula: C45H76NO6P
Glycerophospholipids [GP] with formula: C39H74NO6P
Glycerophospholipids [GP] with formula: C43H74NO6P
Glycerophospholipids [GP] with formula: C45H78NO6P
Glycerophospholipids [GP] with formula: C45H94NO7P
- Glycerophospholipids [GP] with formula: C23H48NO7P
- Glycerophospholipids [GP] with formula: C21H44NO7P
- Glycerophospholipids [GP] with formula: C19H40NO7P
- Glycerophospholipids [GP] with formula: C17H36NO7P
- Glycerophospholipids [GP] with formula: C23H46NO7P
- Glycerophospholipids [GP] with formula: C18H38NO7P
- Glycerophospholipids [GP] with formula: C22H44NO7P
+ Glycerophospholipids [GP] with formula: C23H48NO7P
+ Glycerophospholipids [GP] with formula: C21H44NO7P
+ Glycerophospholipids [GP] with formula: C19H40NO7P
+ Glycerophospholipids [GP] with formula: C23H46NO7P
+ Glycerophospholipids [GP] with formula: C17H36NO7P
+ Glycerophospholipids [GP] with formula: C18H38NO7P
+ Glycerophospholipids [GP] with formula: C22H44NO7P
Glycerophospholipids [GP] with formula: C25H44NO7P
+ Glycerophospholipids [GP] with formula: C21H42NO7P
+ Glycerophospholipids [GP] with formula: C23H44NO7P
+ Glycerophospholipids [GP] with formula: C27H44NO7P
+ Glycerophospholipids [GP] with formula: C27H48NO7P
+ Glycerophospholipids [GP] with formula: C20H40NO7P
+ Glycerophospholipids [GP] with formula: C22H42NO7P
+ Glycerophospholipids [GP] with formula: C23H40NO7P
+ Glycerophospholipids [GP] with formula: C25H50NO7P
+ Glycerophospholipids [GP] with formula: C25H48NO7P
+ Glycerophospholipids [GP] with formula: C25H46NO7P
+ Glycerophospholipids [GP] with formula: C27H54NO7P
+ Glycerophospholipids [GP] with formula: C27H52NO7P
+ Glycerophospholipids [GP] with formula: C27H56NO7P
+ Glycerophospholipids [GP] with formula: C26H54NO7P
+ Glycerophospholipids [GP] with formula: C25H42NO7P
+ Glycerophospholipids [GP] with formula: C24H50NO7P
+ Glycerophospholipids [GP] with formula: C23H42NO7P
+ Glycerophospholipids [GP] with formula: C22H46NO7P
+ Glycerophospholipids [GP] with formula: C19H38NO7P
Glycerophospholipids [GP] with formula: C25H46NO6P
+ Glycerophospholipids [GP] with formula: C23H50NO6P
+ Glycerophospholipids [GP] with formula: C25H54NO6P
Glycerophospholipids [GP] with formula: C21H44NO6P
+ Glycerophospholipids [GP] with formula: C23H48NO6P
+ Glycerophospholipids [GP] with formula: C24H48NO6P
+ Glycerophospholipids [GP] with formula: C25H52NO6P
Glycerophospholipids [GP] with formula: C43H70NO7P
Glycerophospholipids [GP] with formula: C45H74NO7P
- Glycerophospholipids [GP] with formula: C45H76NO7P
- Glycerophospholipids [GP] with formula: C39H72NO7P
+ Glycerophospholipids [GP] with formula: C45H76NO7P
Glycerophospholipids [GP] with formula: C43H72NO7P
Glycerophospholipids [GP] with formula: C31H63N2O10P
Glycerophospholipids [GP] with formula: C43H79N2O10P
Glycerophospholipids [GP] with formula: C49H87N2O10P
Glycerophospholipids [GP] with formula: C37H73N2O10P
- Glycerophospholipids [GP] with formula: C42H76NO10P
+ Glycerophospholipids [GP] with formula: C18H34NO10P
Glycerophospholipids [GP] with formula: C22H42NO10P
Glycerophospholipids [GP] with formula: C26H50NO10P
- Glycerophospholipids [GP] with formula: C42H74NO10P
- Glycerophospholipids [GP] with formula: C40H76NO10P
- Glycerophospholipids [GP] with formula: C42H80NO10P
- Glycerophospholipids [GP] with formula: C18H34NO10P
- Glycerophospholipids [GP] with formula: C30H58NO10P
- Glycerophospholipids [GP] with formula: C34H66NO10P
- Glycerophospholipids [GP] with formula: C38H74NO10P
- Glycerophospholipids [GP] with formula: C42H78NO10P
- Glycerophospholipids [GP] with formula: C42H82NO10P
- Glycerophospholipids [GP] with formula: C43H84NO10P
- Glycerophospholipids [GP] with formula: C44H78NO10P
- Glycerophospholipids [GP] with formula: C46H78NO10P
+ Glycerophospholipids [GP] with formula: C30H58NO10P
Glycerophospholipids [GP] with formula: C58H110NO11P
Glycerophospholipids [GP] with formula: C61H114NO11P
- Glycerophospholipids [GP] with formula: C38H78NO8P
+ Glycerophospholipids [GP] with formula: C32H60NO10P
+ Glycerophospholipids [GP] with formula: C35H68NO10P
+ Glycerophospholipids [GP] with formula: C31H60NO10P
+ Glycerophospholipids [GP] with formula: C37H64NO10P
+ Glycerophospholipids [GP] with formula: C39H68NO10P
+ Glycerophospholipids [GP] with formula: C39H66NO10P
+ Glycerophospholipids [GP] with formula: C33H62NO10P
+ Glycerophospholipids [GP] with formula: C34H64NO10P
+ Glycerophospholipids [GP] with formula: C35H66NO10P
+ Glycerophospholipids [GP] with formula: C35H64NO10P
+ Glycerophospholipids [GP] with formula: C36H68NO10P
+ Glycerophospholipids [GP] with formula: C37H70NO10P
+ Glycerophospholipids [GP] with formula: C37H66NO10P
+ Glycerophospholipids [GP] with formula: C38H72NO10P
+ Glycerophospholipids [GP] with formula: C40H66NO10P
+ Glycerophospholipids [GP] with formula: C42H80NO10P
+ Glycerophospholipids [GP] with formula: C42H72NO10P
+ Glycerophospholipids [GP] with formula: C42H68NO10P
+ Glycerophospholipids [GP] with formula: C33H64NO10P
+ Glycerophospholipids [GP] with formula: C45H74NO10P
+ Glycerophospholipids [GP] with formula: C41H72NO10P
+ Glycerophospholipids [GP] with formula: C41H68NO10P
+ Glycerophospholipids [GP] with formula: C43H80NO10P
+ Glycerophospholipids [GP] with formula: C43H72NO10P
+ Glycerophospholipids [GP] with formula: C43H70NO10P
+ Glycerophospholipids [GP] with formula: C45H84NO10P
+ Glycerophospholipids [GP] with formula: C45H82NO10P
+ Glycerophospholipids [GP] with formula: C45H80NO10P
+ Glycerophospholipids [GP] with formula: C45H76NO10P
+ Glycerophospholipids [GP] with formula: C45H72NO10P
+ Glycerophospholipids [GP] with formula: C37H72NO10P
+ Glycerophospholipids [GP] with formula: C46H88NO10P
+ Glycerophospholipids [GP] with formula: C46H86NO10P
+ Glycerophospholipids [GP] with formula: C39H74NO10P
+ Glycerophospholipids [GP] with formula: C41H78NO10P
+ Glycerophospholipids [GP] with formula: C46H84NO10P
+ Glycerophospholipids [GP] with formula: C36H66NO10P
+ Glycerophospholipids [GP] with formula: C37H68NO10P
+ Glycerophospholipids [GP] with formula: C38H70NO10P
+ Glycerophospholipids [GP] with formula: C38H68NO10P
+ Glycerophospholipids [GP] with formula: C39H72NO10P
+ Glycerophospholipids [GP] with formula: C39H70NO10P
+ Glycerophospholipids [GP] with formula: C40H72NO10P
+ Glycerophospholipids [GP] with formula: C41H76NO10P
+ Glycerophospholipids [GP] with formula: C41H74NO10P
+ Glycerophospholipids [GP] with formula: C36H64NO10P
+ Glycerophospholipids [GP] with formula: C44H72NO10P
+ Glycerophospholipids [GP] with formula: C44H70NO10P
+ Glycerophospholipids [GP] with formula: C36H62NO10P
+ Glycerophospholipids [GP] with formula: C41H70NO10P
+ Glycerophospholipids [GP] with formula: C42H74NO10P
+ Glycerophospholipids [GP] with formula: C42H66NO10P
+ Glycerophospholipids [GP] with formula: C46H82NO10P
+ Glycerophospholipids [GP] with formula: C46H80NO10P
+ Glycerophospholipids [GP] with formula: C46H78NO10P
+ Glycerophospholipids [GP] with formula: C46H74NO10P
+ Glycerophospholipids [GP] with formula: C46H70NO10P
+ Glycerophospholipids [GP] with formula: C45H78NO10P
+ Glycerophospholipids [GP] with formula: C46H90NO10P
+ Glycerophospholipids [GP] with formula: C47H92NO10P
+ Glycerophospholipids [GP] with formula: C47H90NO10P
+ Glycerophospholipids [GP] with formula: C47H88NO10P
+ Glycerophospholipids [GP] with formula: C47H84NO10P
+ Glycerophospholipids [GP] with formula: C47H80NO10P
+ Glycerophospholipids [GP] with formula: C43H82NO10P
+ Glycerophospholipids [GP] with formula: C43H78NO10P
+ Glycerophospholipids [GP] with formula: C43H76NO10P
+ Glycerophospholipids [GP] with formula: C43H74NO10P
+ Glycerophospholipids [GP] with formula: C44H84NO10P
+ Glycerophospholipids [GP] with formula: C44H82NO10P
+ Glycerophospholipids [GP] with formula: C45H86NO10P
+ Glycerophospholipids [GP] with formula: C47H78NO10P
+ Glycerophospholipids [GP] with formula: C40H76NO10P
+ Glycerophospholipids [GP] with formula: C41H80NO10P
+ Glycerophospholipids [GP] with formula: C44H80NO10P
+ Glycerophospholipids [GP] with formula: C48H92NO10P
+ Glycerophospholipids [GP] with formula: C48H90NO10P
+ Glycerophospholipids [GP] with formula: C48H88NO10P
+ Glycerophospholipids [GP] with formula: C48H84NO10P
+ Glycerophospholipids [GP] with formula: C48H80NO10P
+ Glycerophospholipids [GP] with formula: C44H78NO10P
+ Glycerophospholipids [GP] with formula: C44H76NO10P
+ Glycerophospholipids [GP] with formula: C44H74NO10P
+ Glycerophospholipids [GP] with formula: C46H76NO10P
+ Glycerophospholipids [GP] with formula: C48H86NO10P
+ Glycerophospholipids [GP] with formula: C38H64NO10P
+ Glycerophospholipids [GP] with formula: C44H68NO10P
+ Glycerophospholipids [GP] with formula: C47H82NO10P
+ Glycerophospholipids [GP] with formula: C43H84NO10P
+ Glycerophospholipids [GP] with formula: C44H86NO10P
+ Glycerophospholipids [GP] with formula: C47H86NO10P
+ Glycerophospholipids [GP] with formula: C49H96NO10P
+ Glycerophospholipids [GP] with formula: C49H94NO10P
+ Glycerophospholipids [GP] with formula: C50H96NO10P
+ Glycerophospholipids [GP] with formula: C50H94NO10P
+ Glycerophospholipids [GP] with formula: C50H92NO10P
+ Glycerophospholipids [GP] with formula: C50H88NO10P
+ Glycerophospholipids [GP] with formula: C50H84NO10P
+ Glycerophospholipids [GP] with formula: C40H74NO10P
+ Glycerophospholipids [GP] with formula: C42H78NO10P
+ Glycerophospholipids [GP] with formula: C42H76NO10P
+ Glycerophospholipids [GP] with formula: C49H92NO10P
+ Glycerophospholipids [GP] with formula: C50H90NO10P
+ Glycerophospholipids [GP] with formula: C50H86NO10P
+ Glycerophospholipids [GP] with formula: C50H82NO10P
+ Glycerophospholipids [GP] with formula: C46H72NO10P
+ Glycerophospholipids [GP] with formula: C48H82NO10P
+ Glycerophospholipids [GP] with formula: C48H78NO10P
+ Glycerophospholipids [GP] with formula: C48H76NO10P
+ Glycerophospholipids [GP] with formula: C48H74NO10P
+ Glycerophospholipids [GP] with formula: C49H84NO10P
+ Glycerophospholipids [GP] with formula: C50H78NO10P
+ Glycerophospholipids [GP] with formula: C48H94NO10P
+ Glycerophospholipids [GP] with formula: C45H88NO10P
+ Glycerophospholipids [GP] with formula: C48H72NO10P
+ Glycerophospholipids [GP] with formula: C39H76NO10P
+ Glycerophospholipids [GP] with formula: C36H70NO10P
+ Glycerophospholipids [GP] with formula: C34H62NO10P
+ Glycerophospholipids [GP] with formula: C42H70NO10P
+ Glycerophospholipids [GP] with formula: C42H82NO10P
+ Glycerophospholipids [GP] with formula: C40H68NO10P
+ Glycerophospholipids [GP] with formula: C40H70NO10P
+ Glycerophospholipids [GP] with formula: C40H78NO10P
+ Glycerophospholipids [GP] with formula: C38H66NO10P
+ Glycerophospholipids [GP] with formula: C38H74NO10P
+ Glycerophospholipids [GP] with formula: C34H66NO10P
+ Glycerophospholipids [GP] with formula: C50H98NO10P
+ Glycerophospholipids [GP] with formula: C32H62NO10P
+ Glycerophospholipids [GP] with formula: C34H68NO9P
+ Glycerophospholipids [GP] with formula: C35H70NO9P
+ Glycerophospholipids [GP] with formula: C36H70NO9P
+ Glycerophospholipids [GP] with formula: C37H72NO9P
+ Glycerophospholipids [GP] with formula: C38H74NO9P
+ Glycerophospholipids [GP] with formula: C40H72NO9P
+ Glycerophospholipids [GP] with formula: C42H82NO9P
+ Glycerophospholipids [GP] with formula: C42H80NO9P
+ Glycerophospholipids [GP] with formula: C43H86NO9P
+ Glycerophospholipids [GP] with formula: C44H86NO9P
+ Glycerophospholipids [GP] with formula: C44H84NO9P
+ Glycerophospholipids [GP] with formula: C44H80NO9P
+ Glycerophospholipids [GP] with formula: C36H72NO9P
+ Glycerophospholipids [GP] with formula: C37H74NO9P
+ Glycerophospholipids [GP] with formula: C41H82NO9P
+ Glycerophospholipids [GP] with formula: C42H78NO9P
+ Glycerophospholipids [GP] with formula: C43H84NO9P
+ Glycerophospholipids [GP] with formula: C45H90NO9P
+ Glycerophospholipids [GP] with formula: C47H94NO9P
+ Glycerophospholipids [GP] with formula: C48H94NO9P
+ Glycerophospholipids [GP] with formula: C48H92NO9P
+ Glycerophospholipids [GP] with formula: C48H88NO9P
+ Glycerophospholipids [GP] with formula: C48H96NO9P
+ Glycerophospholipids [GP] with formula: C40H74NO9P
+ Glycerophospholipids [GP] with formula: C40H80NO9P
+ Glycerophospholipids [GP] with formula: C39H78NO9P
+ Glycerophospholipids [GP] with formula: C38H76NO9P
+ Glycerophospholipids [GP] with formula: C46H80NO9P
+ Glycerophospholipids [GP] with formula: C46H92NO9P
+ Glycerophospholipids [GP] with formula: C42H84NO9P
+ Glycerophospholipids [GP] with formula: C44H88NO9P
+ Glycerophospholipids [GP] with formula: C48H84NO9P
+ Glycerophospholipids [GP] with formula: C34H66NO9P
+ Glycerophospholipids [GP] with formula: C35H68NO9P
+ Glycerophospholipids [GP] with formula: C36H68NO9P
+ Glycerophospholipids [GP] with formula: C37H70NO9P
+ Glycerophospholipids [GP] with formula: C39H74NO9P
+ Glycerophospholipids [GP] with formula: C39H72NO9P
+ Glycerophospholipids [GP] with formula: C40H70NO9P
+ Glycerophospholipids [GP] with formula: C41H80NO9P
+ Glycerophospholipids [GP] with formula: C41H78NO9P
+ Glycerophospholipids [GP] with formula: C42H72NO9P
+ Glycerophospholipids [GP] with formula: C38H72NO9P
+ Glycerophospholipids [GP] with formula: C41H76NO9P
+ Glycerophospholipids [GP] with formula: C42H76NO9P
+ Glycerophospholipids [GP] with formula: C42H74NO9P
+ Glycerophospholipids [GP] with formula: C43H82NO9P
+ Glycerophospholipids [GP] with formula: C44H82NO9P
+ Glycerophospholipids [GP] with formula: C44H76NO9P
+ Glycerophospholipids [GP] with formula: C45H88NO9P
+ Glycerophospholipids [GP] with formula: C46H90NO9P
+ Glycerophospholipids [GP] with formula: C46H88NO9P
+ Glycerophospholipids [GP] with formula: C46H86NO9P
+ Glycerophospholipids [GP] with formula: C39H76NO9P
+ Glycerophospholipids [GP] with formula: C40H78NO9P
+ Glycerophospholipids [GP] with formula: C40H76NO9P
+ Glycerophospholipids [GP] with formula: C43H80NO9P
+ Glycerophospholipids [GP] with formula: C44H78NO9P
+ Glycerophospholipids [GP] with formula: C45H86NO9P
+ Glycerophospholipids [GP] with formula: C47H92NO9P
+ Glycerophospholipids [GP] with formula: C48H90NO9P
+ Glycerophospholipids [GP] with formula: C48H86NO9P
+ Glycerophospholipids [GP] with formula: C46H78NO9P
+ Glycerophospholipids [GP] with formula: C44H74NO9P
+ Glycerophospholipids [GP] with formula: C48H82NO9P
+ Glycerophospholipids [GP] with formula: C24H46NO9P
Glycerophospholipids [GP] with formula: C22H44NO9P
- Glycerophospholipids [GP] with formula: C24H48NO9P
- Glycerophospholipids [GP] with formula: C24H46NO9P
Glycerophospholipids [GP] with formula: C19H38NO9P
+ Glycerophospholipids [GP] with formula: C24H48NO9P
Glycerophospholipids [GP] with formula: C26H44NO9P
+ Glycerophospholipids [GP] with formula: C18H36NO9P
+ Glycerophospholipids [GP] with formula: C20H40NO9P
+ Glycerophospholipids [GP] with formula: C22H42NO9P
+ Glycerophospholipids [GP] with formula: C24H44NO9P
+ Glycerophospholipids [GP] with formula: C26H52NO9P
+ Glycerophospholipids [GP] with formula: C28H44NO9P
+ Glycerophospholipids [GP] with formula: C28H48NO9P
+ Glycerophospholipids [GP] with formula: C21H40NO9P
+ Glycerophospholipids [GP] with formula: C23H42NO9P
+ Glycerophospholipids [GP] with formula: C24H40NO9P
+ Glycerophospholipids [GP] with formula: C25H48NO9P
+ Glycerophospholipids [GP] with formula: C26H50NO9P
+ Glycerophospholipids [GP] with formula: C26H48NO9P
+ Glycerophospholipids [GP] with formula: C26H46NO9P
+ Glycerophospholipids [GP] with formula: C28H54NO9P
+ Glycerophospholipids [GP] with formula: C28H52NO9P
+ Glycerophospholipids [GP] with formula: C28H56NO9P
+ Glycerophospholipids [GP] with formula: C27H54NO9P
+ Glycerophospholipids [GP] with formula: C26H42NO9P
+ Glycerophospholipids [GP] with formula: C25H50NO9P
+ Glycerophospholipids [GP] with formula: C24H42NO9P
+ Glycerophospholipids [GP] with formula: C23H46NO9P
+ Glycerophospholipids [GP] with formula: C21H42NO9P
+ Glycerophospholipids [GP] with formula: C20H38NO9P
+ Glycerophospholipids [GP] with formula: C23H44NO9P
+ Glycerophospholipids [GP] with formula: C26H54NO8P
+ Glycerophospholipids [GP] with formula: C24H50NO8P
+ Glycerophospholipids [GP] with formula: C22H46NO8P
Glycerophospholipids [GP] with formula: C31H64NO10P
Glycerophospholipids [GP] with formula: C40H80NO10P
- Glycerophospholipids [GP] with formula: C49H88NO10P
- Glycerophospholipids [GP] with formula: C34H67O10P
- Glycerophospholipids [GP] with formula: C43H80NO10P
+ Glycerophospholipids [GP] with formula: C49H88NO10P
Glycerophospholipids [GP] with formula: C37H74NO10P
- Glycerophospholipids [GP] with formula: C40H77O10P
- Glycerophospholipids [GP] with formula: C40H79O10P
- Glycerophospholipids [GP] with formula: C36H71O10P
- Glycerophospholipids [GP] with formula: C38H75O10P
- Glycerophospholipids [GP] with formula: C18H35O10P
- Glycerophospholipids [GP] with formula: C22H43O10P
- Glycerophospholipids [GP] with formula: C26H51O10P
- Glycerophospholipids [GP] with formula: C42H79O10P
- Glycerophospholipids [GP] with formula: C30H59O10P
- Glycerophospholipids [GP] with formula: C42H75O10P
- Glycerophospholipids [GP] with formula: C42H81O10P
- Glycerophospholipids [GP] with formula: C42H83O10P
- Glycerophospholipids [GP] with formula: C44H79O10P
- Glycerophospholipids [GP] with formula: C46H79O10P
- Glycerophospholipids [GP] with formula: C38H79O8P
- Glycerophospholipids [GP] with formula: C44H73O8P
- Glycerophospholipids [GP] with formula: C40H75O8P
+ Glycerophospholipids [GP] with formula: C34H67O10P
+ Glycerophospholipids [GP] with formula: C18H35O10P
+ Glycerophospholipids [GP] with formula: C22H43O10P
+ Glycerophospholipids [GP] with formula: C26H51O10P
+ Glycerophospholipids [GP] with formula: C30H59O10P
+ Glycerophospholipids [GP] with formula: C48H75O10P
+ Glycerophospholipids [GP] with formula: C33H63O10P
+ Glycerophospholipids [GP] with formula: C34H65O10P
+ Glycerophospholipids [GP] with formula: C31H61O10P
+ Glycerophospholipids [GP] with formula: C33H65O10P
+ Glycerophospholipids [GP] with formula: C32H61O10P
+ Glycerophospholipids [GP] with formula: C40H67O10P
+ Glycerophospholipids [GP] with formula: C35H69O10P
+ Glycerophospholipids [GP] with formula: C35H67O10P
+ Glycerophospholipids [GP] with formula: C36H69O10P
+ Glycerophospholipids [GP] with formula: C41H79O10P
+ Glycerophospholipids [GP] with formula: C41H77O10P
+ Glycerophospholipids [GP] with formula: C41H69O10P
+ Glycerophospholipids [GP] with formula: C43H83O10P
+ Glycerophospholipids [GP] with formula: C43H81O10P
+ Glycerophospholipids [GP] with formula: C43H79O10P
+ Glycerophospholipids [GP] with formula: C39H75O10P
+ Glycerophospholipids [GP] with formula: C40H75O10P
+ Glycerophospholipids [GP] with formula: C42H83O10P
+ Glycerophospholipids [GP] with formula: C37H71O10P
+ Glycerophospholipids [GP] with formula: C37H69O10P
+ Glycerophospholipids [GP] with formula: C43H75O10P
+ Glycerophospholipids [GP] with formula: C45H85O10P
+ Glycerophospholipids [GP] with formula: C35H65O10P
+ Glycerophospholipids [GP] with formula: C36H67O10P
+ Glycerophospholipids [GP] with formula: C43H77O10P
+ Glycerophospholipids [GP] with formula: C39H77O10P
+ Glycerophospholipids [GP] with formula: C45H89O10P
+ Glycerophospholipids [GP] with formula: C45H87O10P
+ Glycerophospholipids [GP] with formula: C44H81O10P
+ Glycerophospholipids [GP] with formula: C45H83O10P
+ Glycerophospholipids [GP] with formula: C36H65O10P
+ Glycerophospholipids [GP] with formula: C37H67O10P
+ Glycerophospholipids [GP] with formula: C38H69O10P
+ Glycerophospholipids [GP] with formula: C39H71O10P
+ Glycerophospholipids [GP] with formula: C40H71O10P
+ Glycerophospholipids [GP] with formula: C41H75O10P
+ Glycerophospholipids [GP] with formula: C41H73O10P
+ Glycerophospholipids [GP] with formula: C41H71O10P
+ Glycerophospholipids [GP] with formula: C42H73O10P
+ Glycerophospholipids [GP] with formula: C42H71O10P
+ Glycerophospholipids [GP] with formula: C46H85O10P
+ Glycerophospholipids [GP] with formula: C46H83O10P
+ Glycerophospholipids [GP] with formula: C46H81O10P
+ Glycerophospholipids [GP] with formula: C46H77O10P
+ Glycerophospholipids [GP] with formula: C46H73O10P
+ Glycerophospholipids [GP] with formula: C36H63O10P
+ Glycerophospholipids [GP] with formula: C37H65O10P
+ Glycerophospholipids [GP] with formula: C38H67O10P
+ Glycerophospholipids [GP] with formula: C38H65O10P
+ Glycerophospholipids [GP] with formula: C39H69O10P
+ Glycerophospholipids [GP] with formula: C40H69O10P
+ Glycerophospholipids [GP] with formula: C42H67O10P
+ Glycerophospholipids [GP] with formula: C46H71O10P
+ Glycerophospholipids [GP] with formula: C47H93O10P
+ Glycerophospholipids [GP] with formula: C47H85O10P
+ Glycerophospholipids [GP] with formula: C47H81O10P
+ Glycerophospholipids [GP] with formula: C39H73O10P
+ Glycerophospholipids [GP] with formula: C47H87O10P
+ Glycerophospholipids [GP] with formula: C47H79O10P
+ Glycerophospholipids [GP] with formula: C47H91O10P
+ Glycerophospholipids [GP] with formula: C48H93O10P
+ Glycerophospholipids [GP] with formula: C48H91O10P
+ Glycerophospholipids [GP] with formula: C48H89O10P
+ Glycerophospholipids [GP] with formula: C44H77O10P
+ Glycerophospholipids [GP] with formula: C44H75O10P
+ Glycerophospholipids [GP] with formula: C44H73O10P
+ Glycerophospholipids [GP] with formula: C44H71O10P
+ Glycerophospholipids [GP] with formula: C45H81O10P
+ Glycerophospholipids [GP] with formula: C45H79O10P
+ Glycerophospholipids [GP] with formula: C48H79O10P
+ Glycerophospholipids [GP] with formula: C39H67O10P
+ Glycerophospholipids [GP] with formula: C44H69O10P
+ Glycerophospholipids [GP] with formula: C49H95O10P
+ Glycerophospholipids [GP] with formula: C49H97O10P
+ Glycerophospholipids [GP] with formula: C50H97O10P
+ Glycerophospholipids [GP] with formula: C47H89O10P
+ Glycerophospholipids [GP] with formula: C48H81O10P
+ Glycerophospholipids [GP] with formula: C49H93O10P
+ Glycerophospholipids [GP] with formula: C50H95O10P
+ Glycerophospholipids [GP] with formula: C50H93O10P
+ Glycerophospholipids [GP] with formula: C50H91O10P
+ Glycerophospholipids [GP] with formula: C50H87O10P
+ Glycerophospholipids [GP] with formula: C50H83O10P
+ Glycerophospholipids [GP] with formula: C47H83O10P
+ Glycerophospholipids [GP] with formula: C48H87O10P
+ Glycerophospholipids [GP] with formula: C48H85O10P
+ Glycerophospholipids [GP] with formula: C48H83O10P
+ Glycerophospholipids [GP] with formula: C49H89O10P
+ Glycerophospholipids [GP] with formula: C50H89O10P
+ Glycerophospholipids [GP] with formula: C42H69O10P
+ Glycerophospholipids [GP] with formula: C43H73O10P
+ Glycerophospholipids [GP] with formula: C43H71O10P
+ Glycerophospholipids [GP] with formula: C45H77O10P
+ Glycerophospholipids [GP] with formula: C45H75O10P
+ Glycerophospholipids [GP] with formula: C45H73O10P
+ Glycerophospholipids [GP] with formula: C46H79O10P
+ Glycerophospholipids [GP] with formula: C46H75O10P
+ Glycerophospholipids [GP] with formula: C48H77O10P
+ Glycerophospholipids [GP] with formula: C48H73O10P
+ Glycerophospholipids [GP] with formula: C49H85O10P
+ Glycerophospholipids [GP] with formula: C50H85O10P
+ Glycerophospholipids [GP] with formula: C50H79O10P
+ Glycerophospholipids [GP] with formula: C48H95O10P
+ Glycerophospholipids [GP] with formula: C46H87O10P
+ Glycerophospholipids [GP] with formula: C40H79O10P
+ Glycerophospholipids [GP] with formula: C37H73O10P
+ Glycerophospholipids [GP] with formula: C36H71O10P
+ Glycerophospholipids [GP] with formula: C34H63O10P
+ Glycerophospholipids [GP] with formula: C32H63O10P
+ Glycerophospholipids [GP] with formula: C50H99O10P
+ Glycerophospholipids [GP] with formula: C41H81O10P
+ Glycerophospholipids [GP] with formula: C40H73O10P
+ Glycerophospholipids [GP] with formula: C42H75O10P
+ Glycerophospholipids [GP] with formula: C46H89O10P
+ Glycerophospholipids [GP] with formula: C42H77O10P
+ Glycerophospholipids [GP] with formula: C42H81O10P
+ Glycerophospholipids [GP] with formula: C40H77O10P
+ Glycerophospholipids [GP] with formula: C44H83O10P
+ Glycerophospholipids [GP] with formula: C44H85O10P
+ Glycerophospholipids [GP] with formula: C43H85O10P
+ Glycerophospholipids [GP] with formula: C38H71O10P
+ Glycerophospholipids [GP] with formula: C44H79O10P
+ Glycerophospholipids [GP] with formula: C44H87O10P
+ Glycerophospholipids [GP] with formula: C50H75O10P
+ Glycerophospholipids [GP] with formula: C46H91O10P
+ Glycerophospholipids [GP] with formula: C38H73O10P
+ Glycerophospholipids [GP] with formula: C42H79O10P
+ Glycerophospholipids [GP] with formula: C38H75O10P
+ Glycerophospholipids [GP] with formula: C34H69O9P
+ Glycerophospholipids [GP] with formula: C35H71O9P
+ Glycerophospholipids [GP] with formula: C39H75O9P
+ Glycerophospholipids [GP] with formula: C41H81O9P
+ Glycerophospholipids [GP] with formula: C42H83O9P
+ Glycerophospholipids [GP] with formula: C36H73O9P
+ Glycerophospholipids [GP] with formula: C37H75O9P
+ Glycerophospholipids [GP] with formula: C42H77O9P
+ Glycerophospholipids [GP] with formula: C43H87O9P
+ Glycerophospholipids [GP] with formula: C43H85O9P
+ Glycerophospholipids [GP] with formula: C38H77O9P
+ Glycerophospholipids [GP] with formula: C39H79O9P
+ Glycerophospholipids [GP] with formula: C43H83O9P
+ Glycerophospholipids [GP] with formula: C44H89O9P
+ Glycerophospholipids [GP] with formula: C44H87O9P
+ Glycerophospholipids [GP] with formula: C44H85O9P
+ Glycerophospholipids [GP] with formula: C44H83O9P
+ Glycerophospholipids [GP] with formula: C45H91O9P
+ Glycerophospholipids [GP] with formula: C46H93O9P
+ Glycerophospholipids [GP] with formula: C47H95O9P
+ Glycerophospholipids [GP] with formula: C48H95O9P
+ Glycerophospholipids [GP] with formula: C48H93O9P
+ Glycerophospholipids [GP] with formula: C48H89O9P
+ Glycerophospholipids [GP] with formula: C48H97O9P
+ Glycerophospholipids [GP] with formula: C42H85O9P
+ Glycerophospholipids [GP] with formula: C40H81O9P
+ Glycerophospholipids [GP] with formula: C42H75O9P
+ Glycerophospholipids [GP] with formula: C42H79O9P
+ Glycerophospholipids [GP] with formula: C41H83O9P
+ Glycerophospholipids [GP] with formula: C40H75O9P
+ Glycerophospholipids [GP] with formula: C48H85O9P
+ Glycerophospholipids [GP] with formula: C34H67O9P
+ Glycerophospholipids [GP] with formula: C35H69O9P
+ Glycerophospholipids [GP] with formula: C36H71O9P
+ Glycerophospholipids [GP] with formula: C36H69O9P
+ Glycerophospholipids [GP] with formula: C37H73O9P
+ Glycerophospholipids [GP] with formula: C37H71O9P
+ Glycerophospholipids [GP] with formula: C38H73O9P
+ Glycerophospholipids [GP] with formula: C39H73O9P
+ Glycerophospholipids [GP] with formula: C40H71O9P
+ Glycerophospholipids [GP] with formula: C42H73O9P
+ Glycerophospholipids [GP] with formula: C41H77O9P
+ Glycerophospholipids [GP] with formula: C44H77O9P
+ Glycerophospholipids [GP] with formula: C45H89O9P
+ Glycerophospholipids [GP] with formula: C46H91O9P
+ Glycerophospholipids [GP] with formula: C46H89O9P
+ Glycerophospholipids [GP] with formula: C46H87O9P
+ Glycerophospholipids [GP] with formula: C46H83O9P
+ Glycerophospholipids [GP] with formula: C38H75O9P
+ Glycerophospholipids [GP] with formula: C39H77O9P
+ Glycerophospholipids [GP] with formula: C40H79O9P
+ Glycerophospholipids [GP] with formula: C40H77O9P
+ Glycerophospholipids [GP] with formula: C41H79O9P
+ Glycerophospholipids [GP] with formula: C43H81O9P
+ Glycerophospholipids [GP] with formula: C44H81O9P
+ Glycerophospholipids [GP] with formula: C44H79O9P
+ Glycerophospholipids [GP] with formula: C45H87O9P
+ Glycerophospholipids [GP] with formula: C46H85O9P
+ Glycerophospholipids [GP] with formula: C46H81O9P
+ Glycerophospholipids [GP] with formula: C47H93O9P
+ Glycerophospholipids [GP] with formula: C48H91O9P
+ Glycerophospholipids [GP] with formula: C48H87O9P
+ Glycerophospholipids [GP] with formula: C46H79O9P
+ Glycerophospholipids [GP] with formula: C42H81O9P
+ Glycerophospholipids [GP] with formula: C44H75O9P
+ Glycerophospholipids [GP] with formula: C48H83O9P
Glycerophospholipids [GP] with formula: C46H77O8P
- Glycerophospholipids [GP] with formula: C46H79O8P
+ Glycerophospholipids [GP] with formula: C46H79O8P
Glycerophospholipids [GP] with formula: C46H75O9P
Glycerophospholipids [GP] with formula: C46H95O9P
- Glycerophospholipids [GP] with formula: C20H41O9P
- Glycerophospholipids [GP] with formula: C24H47O9P
+ Glycerophospholipids [GP] with formula: C24H47O9P
Glycerophospholipids [GP] with formula: C19H39O9P
- Glycerophospholipids [GP] with formula: C22H45O9P
- Glycerophospholipids [GP] with formula: C24H49O9P
+ Glycerophospholipids [GP] with formula: C22H45O9P
+ Glycerophospholipids [GP] with formula: C24H49O9P
Glycerophospholipids [GP] with formula: C26H45O9P
+ Glycerophospholipids [GP] with formula: C18H37O9P
+ Glycerophospholipids [GP] with formula: C20H41O9P
+ Glycerophospholipids [GP] with formula: C22H43O9P
+ Glycerophospholipids [GP] with formula: C24H45O9P
+ Glycerophospholipids [GP] with formula: C26H53O9P
+ Glycerophospholipids [GP] with formula: C28H45O9P
+ Glycerophospholipids [GP] with formula: C28H49O9P
+ Glycerophospholipids [GP] with formula: C21H41O9P
+ Glycerophospholipids [GP] with formula: C23H43O9P
+ Glycerophospholipids [GP] with formula: C24H41O9P
+ Glycerophospholipids [GP] with formula: C25H49O9P
+ Glycerophospholipids [GP] with formula: C26H51O9P
+ Glycerophospholipids [GP] with formula: C26H49O9P
+ Glycerophospholipids [GP] with formula: C26H47O9P
+ Glycerophospholipids [GP] with formula: C28H55O9P
+ Glycerophospholipids [GP] with formula: C28H53O9P
+ Glycerophospholipids [GP] with formula: C28H57O9P
+ Glycerophospholipids [GP] with formula: C27H55O9P
+ Glycerophospholipids [GP] with formula: C26H43O9P
+ Glycerophospholipids [GP] with formula: C25H51O9P
+ Glycerophospholipids [GP] with formula: C24H43O9P
+ Glycerophospholipids [GP] with formula: C23H47O9P
+ Glycerophospholipids [GP] with formula: C21H43O9P
+ Glycerophospholipids [GP] with formula: C20H39O9P
+ Glycerophospholipids [GP] with formula: C23H45O9P
+ Glycerophospholipids [GP] with formula: C26H55O8P
+ Glycerophospholipids [GP] with formula: C24H51O8P
+ Glycerophospholipids [GP] with formula: C22H47O8P
+ Glycerophospholipids [GP] with formula: C26H53O8P
+ Glycerophospholipids [GP] with formula: C24H49O8P
+ Glycerophospholipids [GP] with formula: C22H45O8P
Glycerophospholipids [GP] with formula: C48H93O11P
Glycerophospholipids [GP] with formula: C60H111O11P
- Glycerophospholipids [GP] with formula: C44H71O10P
- Glycerophospholipids [GP] with formula: C40H73O9P
+ Glycerophospholipids [GP] with formula: C40H73O9P
Glycerophospholipids [GP] with formula: C44H71O9P
Glycerophospholipids [GP] with formula: C44H73O9P
Glycerophospholipids [GP] with formula: C46H77O9P
Glycerophospholipids [GP] with formula: C40H78O13P2
- Glycerophospholipids [GP] with formula: C43H81O13P
Glycerophospholipids [GP] with formula: C45H86NO13P
Glycerophospholipids [GP] with formula: C34H68NO13P
Glycerophospholipids [GP] with formula: C46H84NO13P
Glycerophospholipids [GP] with formula: C52H92NO13P
Glycerophospholipids [GP] with formula: C40H78NO13P
- Glycerophospholipids [GP] with formula: C41H79O13P
- Glycerophospholipids [GP] with formula: C45H87O13P
- Glycerophospholipids [GP] with formula: C45H83O13P
- Glycerophospholipids [GP] with formula: C47H83O13P
+ Glycerophospholipids [GP] with formula: C35H65O13P
+ Glycerophospholipids [GP] with formula: C36H69O13P
+ Glycerophospholipids [GP] with formula: C36H67O13P
+ Glycerophospholipids [GP] with formula: C37H69O13P
+ Glycerophospholipids [GP] with formula: C38H73O13P
+ Glycerophospholipids [GP] with formula: C38H71O13P
+ Glycerophospholipids [GP] with formula: C39H67O13P
+ Glycerophospholipids [GP] with formula: C41H71O13P
+ Glycerophospholipids [GP] with formula: C41H69O13P
+ Glycerophospholipids [GP] with formula: C42H81O13P
+ Glycerophospholipids [GP] with formula: C43H81O13P
+ Glycerophospholipids [GP] with formula: C34H65O13P
+ Glycerophospholipids [GP] with formula: C40H69O13P
+ Glycerophospholipids [GP] with formula: C41H77O13P
+ Glycerophospholipids [GP] with formula: C42H79O13P
+ Glycerophospholipids [GP] with formula: C42H77O13P
+ Glycerophospholipids [GP] with formula: C42H75O13P
+ Glycerophospholipids [GP] with formula: C42H71O13P
+ Glycerophospholipids [GP] with formula: C43H77O13P
+ Glycerophospholipids [GP] with formula: C43H73O13P
+ Glycerophospholipids [GP] with formula: C38H69O13P
+ Glycerophospholipids [GP] with formula: C44H73O13P
+ Glycerophospholipids [GP] with formula: C46H75O13P
+ Glycerophospholipids [GP] with formula: C39H71O13P
+ Glycerophospholipids [GP] with formula: C48H91O13P
+ Glycerophospholipids [GP] with formula: C48H89O13P
+ Glycerophospholipids [GP] with formula: C40H75O13P
+ Glycerophospholipids [GP] with formula: C40H73O13P
+ Glycerophospholipids [GP] with formula: C46H79O13P
+ Glycerophospholipids [GP] with formula: C46H77O13P
+ Glycerophospholipids [GP] with formula: C48H81O13P
+ Glycerophospholipids [GP] with formula: C48H77O13P
+ Glycerophospholipids [GP] with formula: C40H77O13P
+ Glycerophospholipids [GP] with formula: C44H85O13P
+ Glycerophospholipids [GP] with formula: C44H81O13P
+ Glycerophospholipids [GP] with formula: C45H81O13P
+ Glycerophospholipids [GP] with formula: C46H87O13P
+ Glycerophospholipids [GP] with formula: C48H93O13P
+ Glycerophospholipids [GP] with formula: C49H93O13P
+ Glycerophospholipids [GP] with formula: C45H73O13P
+ Glycerophospholipids [GP] with formula: C46H83O13P
+ Glycerophospholipids [GP] with formula: C46H81O13P
+ Glycerophospholipids [GP] with formula: C47H85O13P
+ Glycerophospholipids [GP] with formula: C47H83O13P
+ Glycerophospholipids [GP] with formula: C47H81O13P
+ Glycerophospholipids [GP] with formula: C47H79O13P
+ Glycerophospholipids [GP] with formula: C47H77O13P
+ Glycerophospholipids [GP] with formula: C47H75O13P
+ Glycerophospholipids [GP] with formula: C48H87O13P
+ Glycerophospholipids [GP] with formula: C39H69O13P
+ Glycerophospholipids [GP] with formula: C40H71O13P
+ Glycerophospholipids [GP] with formula: C42H73O13P
+ Glycerophospholipids [GP] with formula: C43H75O13P
+ Glycerophospholipids [GP] with formula: C44H79O13P
+ Glycerophospholipids [GP] with formula: C44H77O13P
+ Glycerophospholipids [GP] with formula: C44H75O13P
+ Glycerophospholipids [GP] with formula: C45H77O13P
+ Glycerophospholipids [GP] with formula: C45H75O13P
+ Glycerophospholipids [GP] with formula: C45H71O13P
+ Glycerophospholipids [GP] with formula: C49H85O13P
+ Glycerophospholipids [GP] with formula: C44H83O13P
+ Glycerophospholipids [GP] with formula: C45H87O13P
+ Glycerophospholipids [GP] with formula: C50H93O13P
+ Glycerophospholipids [GP] with formula: C46H85O13P
+ Glycerophospholipids [GP] with formula: C49H79O13P
+ Glycerophospholipids [GP] with formula: C50H91O13P
+ Glycerophospholipids [GP] with formula: C51H93O13P
+ Glycerophospholipids [GP] with formula: C51H91O13P
+ Glycerophospholipids [GP] with formula: C51H89O13P
+ Glycerophospholipids [GP] with formula: C51H81O13P
+ Glycerophospholipids [GP] with formula: C48H85O13P
+ Glycerophospholipids [GP] with formula: C48H83O13P
+ Glycerophospholipids [GP] with formula: C49H87O13P
+ Glycerophospholipids [GP] with formula: C49H83O13P
+ Glycerophospholipids [GP] with formula: C49H81O13P
+ Glycerophospholipids [GP] with formula: C47H73O13P
+ Glycerophospholipids [GP] with formula: C52H93O13P
+ Glycerophospholipids [GP] with formula: C49H89O13P
+ Glycerophospholipids [GP] with formula: C50H97O13P
+ Glycerophospholipids [GP] with formula: C50H95O13P
+ Glycerophospholipids [GP] with formula: C51H95O13P
+ Glycerophospholipids [GP] with formula: C52H101O13P
+ Glycerophospholipids [GP] with formula: C53H101O13P
+ Glycerophospholipids [GP] with formula: C52H99O13P
+ Glycerophospholipids [GP] with formula: C53H93O13P
+ Glycerophospholipids [GP] with formula: C52H97O13P
+ Glycerophospholipids [GP] with formula: C53H99O13P
+ Glycerophospholipids [GP] with formula: C53H97O13P
+ Glycerophospholipids [GP] with formula: C53H95O13P
+ Glycerophospholipids [GP] with formula: C53H87O13P
+ Glycerophospholipids [GP] with formula: C50H89O13P
+ Glycerophospholipids [GP] with formula: C50H87O13P
+ Glycerophospholipids [GP] with formula: C51H85O13P
+ Glycerophospholipids [GP] with formula: C48H79O13P
+ Glycerophospholipids [GP] with formula: C49H77O13P
+ Glycerophospholipids [GP] with formula: C49H75O13P
+ Glycerophospholipids [GP] with formula: C50H85O13P
+ Glycerophospholipids [GP] with formula: C50H83O13P
+ Glycerophospholipids [GP] with formula: C51H87O13P
+ Glycerophospholipids [GP] with formula: C51H83O13P
+ Glycerophospholipids [GP] with formula: C51H79O13P
+ Glycerophospholipids [GP] with formula: C51H77O13P
+ Glycerophospholipids [GP] with formula: C52H89O13P
+ Glycerophospholipids [GP] with formula: C53H89O13P
+ Glycerophospholipids [GP] with formula: C45H79O13P
+ Glycerophospholipids [GP] with formula: C37H67O13P
+ Glycerophospholipids [GP] with formula: C41H73O13P
+ Glycerophospholipids [GP] with formula: C43H71O13P
+ Glycerophospholipids [GP] with formula: C43H83O13P
+ Glycerophospholipids [GP] with formula: C41H79O13P
+ Glycerophospholipids [GP] with formula: C39H73O13P
+ Glycerophospholipids [GP] with formula: C39H75O13P
+ Glycerophospholipids [GP] with formula: C37H71O13P
+ Glycerophospholipids [GP] with formula: C53H103O13P
+ Glycerophospholipids [GP] with formula: C51H97O13P
+ Glycerophospholipids [GP] with formula: C51H99O13P
+ Glycerophospholipids [GP] with formula: C49H91O13P
+ Glycerophospholipids [GP] with formula: C47H89O13P
+ Glycerophospholipids [GP] with formula: C47H87O13P
+ Glycerophospholipids [GP] with formula: C47H91O13P
+ Glycerophospholipids [GP] with formula: C46H89O13P
+ Glycerophospholipids [GP] with formula: C41H75O13P
+ Glycerophospholipids [GP] with formula: C35H67O13P
+ Glycerophospholipids [GP] with formula: C53H79O13P
+ Glycerophospholipids [GP] with formula: C53H83O13P
+ Glycerophospholipids [GP] with formula: C53H91O13P
+ Glycerophospholipids [GP] with formula: C49H95O13P
+ Glycerophospholipids [GP] with formula: C45H83O13P
+ Glycerophospholipids [GP] with formula: C45H85O13P
+ Glycerophospholipids [GP] with formula: C43H79O13P
+ Glycerophospholipids [GP] with formula: C33H63O13P
+ Glycerophospholipids [GP] with formula: C51H89O12P
+ Glycerophospholipids [GP] with formula: C37H73O12P
+ Glycerophospholipids [GP] with formula: C38H75O12P
+ Glycerophospholipids [GP] with formula: C39H77O12P
+ Glycerophospholipids [GP] with formula: C39H75O12P
+ Glycerophospholipids [GP] with formula: C40H79O12P
+ Glycerophospholipids [GP] with formula: C41H81O12P
+ Glycerophospholipids [GP] with formula: C42H83O12P
+ Glycerophospholipids [GP] with formula: C49H93O12P
+ Glycerophospholipids [GP] with formula: C46H91O12P
+ Glycerophospholipids [GP] with formula: C46H89O12P
+ Glycerophospholipids [GP] with formula: C46H87O12P
+ Glycerophospholipids [GP] with formula: C47H93O12P
+ Glycerophospholipids [GP] with formula: C47H91O12P
+ Glycerophospholipids [GP] with formula: C47H87O12P
+ Glycerophospholipids [GP] with formula: C47H85O12P
+ Glycerophospholipids [GP] with formula: C48H95O12P
+ Glycerophospholipids [GP] with formula: C48H93O12P
+ Glycerophospholipids [GP] with formula: C49H97O12P
+ Glycerophospholipids [GP] with formula: C49H95O12P
+ Glycerophospholipids [GP] with formula: C49H87O12P
+ Glycerophospholipids [GP] with formula: C50H99O12P
+ Glycerophospholipids [GP] with formula: C51H99O12P
+ Glycerophospholipids [GP] with formula: C51H97O12P
+ Glycerophospholipids [GP] with formula: C51H93O12P
+ Glycerophospholipids [GP] with formula: C51H101O12P
+ Glycerophospholipids [GP] with formula: C45H89O12P
+ Glycerophospholipids [GP] with formula: C43H83O12P
+ Glycerophospholipids [GP] with formula: C43H85O12P
+ Glycerophospholipids [GP] with formula: C45H83O12P
+ Glycerophospholipids [GP] with formula: C44H87O12P
+ Glycerophospholipids [GP] with formula: C43H79O12P
+ Glycerophospholipids [GP] with formula: C49H85O12P
+ Glycerophospholipids [GP] with formula: C47H81O12P
+ Glycerophospholipids [GP] with formula: C51H87O12P
+ Glycerophospholipids [GP] with formula: C37H71O12P
+ Glycerophospholipids [GP] with formula: C38H73O12P
+ Glycerophospholipids [GP] with formula: C39H73O12P
+ Glycerophospholipids [GP] with formula: C40H75O12P
+ Glycerophospholipids [GP] with formula: C42H77O12P
+ Glycerophospholipids [GP] with formula: C43H77O12P
+ Glycerophospholipids [GP] with formula: C43H75O12P
+ Glycerophospholipids [GP] with formula: C45H77O12P
+ Glycerophospholipids [GP] with formula: C40H77O12P
+ Glycerophospholipids [GP] with formula: C41H79O12P
+ Glycerophospholipids [GP] with formula: C41H77O12P
+ Glycerophospholipids [GP] with formula: C42H81O12P
+ Glycerophospholipids [GP] with formula: C42H79O12P
+ Glycerophospholipids [GP] with formula: C43H81O12P
+ Glycerophospholipids [GP] with formula: C44H85O12P
+ Glycerophospholipids [GP] with formula: C44H83O12P
+ Glycerophospholipids [GP] with formula: C44H81O12P
+ Glycerophospholipids [GP] with formula: C45H87O12P
+ Glycerophospholipids [GP] with formula: C45H81O12P
+ Glycerophospholipids [GP] with formula: C45H79O12P
+ Glycerophospholipids [GP] with formula: C47H89O12P
+ Glycerophospholipids [GP] with formula: C46H85O12P
+ Glycerophospholipids [GP] with formula: C48H91O12P
+ Glycerophospholipids [GP] with formula: C49H91O12P
+ Glycerophospholipids [GP] with formula: C49H89O12P
+ Glycerophospholipids [GP] with formula: C50H97O12P
+ Glycerophospholipids [GP] with formula: C51H95O12P
+ Glycerophospholipids [GP] with formula: C51H91O12P
+ Glycerophospholipids [GP] with formula: C49H83O12P
+ Glycerophospholipids [GP] with formula: C47H83O12P
+ Glycerophospholipids [GP] with formula: C45H85O12P
+ Glycerophospholipids [GP] with formula: C47H79O12P
Glycerophospholipids [GP] with formula: C59H119O11P
Glycerophospholipids [GP] with formula: C22H43O12P
Glycerophospholipids [GP] with formula: C25H49O12P
- Glycerophospholipids [GP] with formula: C26H49O12P
Glycerophospholipids [GP] with formula: C27H53O12P
Glycerophospholipids [GP] with formula: C27H51O12P
Glycerophospholipids [GP] with formula: C29H49O12P
+ Glycerophospholipids [GP] with formula: C21H41O12P
+ Glycerophospholipids [GP] with formula: C23H45O12P
+ Glycerophospholipids [GP] with formula: C25H47O12P
+ Glycerophospholipids [GP] with formula: C27H49O12P
+ Glycerophospholipids [GP] with formula: C29H57O12P
+ Glycerophospholipids [GP] with formula: C31H49O12P
+ Glycerophospholipids [GP] with formula: C31H53O12P
+ Glycerophospholipids [GP] with formula: C24H45O12P
+ Glycerophospholipids [GP] with formula: C26H47O12P
+ Glycerophospholipids [GP] with formula: C27H47O12P
+ Glycerophospholipids [GP] with formula: C27H45O12P
+ Glycerophospholipids [GP] with formula: C28H53O12P
+ Glycerophospholipids [GP] with formula: C29H55O12P
+ Glycerophospholipids [GP] with formula: C29H53O12P
+ Glycerophospholipids [GP] with formula: C29H51O12P
+ Glycerophospholipids [GP] with formula: C31H59O12P
+ Glycerophospholipids [GP] with formula: C31H57O12P
+ Glycerophospholipids [GP] with formula: C31H61O12P
+ Glycerophospholipids [GP] with formula: C30H59O12P
+ Glycerophospholipids [GP] with formula: C29H47O12P
+ Glycerophospholipids [GP] with formula: C28H55O12P
+ Glycerophospholipids [GP] with formula: C26H51O12P
+ Glycerophospholipids [GP] with formula: C24H47O12P
+ Glycerophospholipids [GP] with formula: C23H43O12P
+ Glycerophospholipids [GP] with formula: C26H49O12P
+ Glycerophospholipids [GP] with formula: C29H59O11P
+ Glycerophospholipids [GP] with formula: C27H55O11P
+ Glycerophospholipids [GP] with formula: C25H51O11P
+ Glycerophospholipids [GP] with formula: C29H57O11P
+ Glycerophospholipids [GP] with formula: C27H53O11P
+ Glycerophospholipids [GP] with formula: C25H49O11P
Glycerophospholipids [GP] with formula: C43H82O16P2
Glycerophospholipids [GP] with formula: C46H88N2O16P2
Glycerophospholipids [GP] with formula: C46H92N3O19P3
Glycerophospholipids [GP] with formula: C46H84O22P4
Glycerophospholipids [GP] with formula: C28H58NO8P
- Glycerophospholipids [GP] with formula: C40H74NO8P
- Glycerophospholipids [GP] with formula: C33H65O8P
- Glycerophospholipids [GP] with formula: C35H69O8P
- Glycerophospholipids [GP] with formula: C39H77O8P
- Glycerophospholipids [GP] with formula: C39H65O8P
- Glycerophospholipids [GP] with formula: C35H67O8P
Glycerophospholipids [GP] with formula: C15H29O8P
Glycerophospholipids [GP] with formula: C19H37O8P
- Glycerophospholipids [GP] with formula: C23H45O8P
- Glycerophospholipids [GP] with formula: C37H69O8P
- Glycerophospholipids [GP] with formula: C41H73O8P
- Glycerophospholipids [GP] with formula: C39H69O8P
- Glycerophospholipids [GP] with formula: C31H61O8P
- Glycerophospholipids [GP] with formula: C27H53O8P
- Glycerophospholipids [GP] with formula: C37H71O8P
- Glycerophospholipids [GP] with formula: C43H85O8P
- Glycerophospholipids [GP] with formula: C39H73O8P
- Glycerophospholipids [GP] with formula: C39H75O8P
- Glycerophospholipids [GP] with formula: C41H69O8P
- Glycerophospholipids [GP] with formula: C43H73O8P
- Glycerophospholipids [GP] with formula: C31H65O6P
- Glycerophospholipids [GP] with formula: C35H73O6P
+ Glycerophospholipids [GP] with formula: C23H45O8P
+ Glycerophospholipids [GP] with formula: C27H53O8P
+ Glycerophospholipids [GP] with formula: C43H85O8P
+ Glycerophospholipids [GP] with formula: C47H69O8P
+ Glycerophospholipids [GP] with formula: C28H55O8P
+ Glycerophospholipids [GP] with formula: C30H59O8P
+ Glycerophospholipids [GP] with formula: C37H69O8P
+ Glycerophospholipids [GP] with formula: C29H55O8P
+ Glycerophospholipids [GP] with formula: C35H59O8P
+ Glycerophospholipids [GP] with formula: C37H63O8P
+ Glycerophospholipids [GP] with formula: C33H63O8P
+ Glycerophospholipids [GP] with formula: C35H67O8P
+ Glycerophospholipids [GP] with formula: C35H65O8P
+ Glycerophospholipids [GP] with formula: C36H69O8P
+ Glycerophospholipids [GP] with formula: C36H65O8P
+ Glycerophospholipids [GP] with formula: C36H63O8P
+ Glycerophospholipids [GP] with formula: C37H71O8P
+ Glycerophospholipids [GP] with formula: C38H73O8P
+ Glycerophospholipids [GP] with formula: C30H57O8P
+ Glycerophospholipids [GP] with formula: C31H59O8P
+ Glycerophospholipids [GP] with formula: C32H59O8P
+ Glycerophospholipids [GP] with formula: C33H61O8P
+ Glycerophospholipids [GP] with formula: C35H63O8P
+ Glycerophospholipids [GP] with formula: C36H61O8P
+ Glycerophospholipids [GP] with formula: C32H61O8P
+ Glycerophospholipids [GP] with formula: C34H65O8P
+ Glycerophospholipids [GP] with formula: C34H63O8P
+ Glycerophospholipids [GP] with formula: C38H63O8P
+ Glycerophospholipids [GP] with formula: C39H73O8P
+ Glycerophospholipids [GP] with formula: C40H71O8P
+ Glycerophospholipids [GP] with formula: C40H69O8P
+ Glycerophospholipids [GP] with formula: C40H67O8P
+ Glycerophospholipids [GP] with formula: C40H65O8P
+ Glycerophospholipids [GP] with formula: C38H71O8P
+ Glycerophospholipids [GP] with formula: C39H67O8P
+ Glycerophospholipids [GP] with formula: C39H65O8P
+ Glycerophospholipids [GP] with formula: C40H75O8P
+ Glycerophospholipids [GP] with formula: C40H73O8P
+ Glycerophospholipids [GP] with formula: C41H77O8P
+ Glycerophospholipids [GP] with formula: C41H75O8P
+ Glycerophospholipids [GP] with formula: C41H71O8P
+ Glycerophospholipids [GP] with formula: C37H65O8P
+ Glycerophospholipids [GP] with formula: C38H69O8P
+ Glycerophospholipids [GP] with formula: C38H67O8P
+ Glycerophospholipids [GP] with formula: C38H65O8P
+ Glycerophospholipids [GP] with formula: C39H71O8P
+ Glycerophospholipids [GP] with formula: C39H69O8P
+ Glycerophospholipids [GP] with formula: C33H59O8P
+ Glycerophospholipids [GP] with formula: C34H61O8P
+ Glycerophospholipids [GP] with formula: C39H63O8P
+ Glycerophospholipids [GP] with formula: C43H71O8P
+ Glycerophospholipids [GP] with formula: C43H67O8P
+ Glycerophospholipids [GP] with formula: C33H57O8P
+ Glycerophospholipids [GP] with formula: C34H59O8P
+ Glycerophospholipids [GP] with formula: C35H61O8P
+ Glycerophospholipids [GP] with formula: C39H61O8P
+ Glycerophospholipids [GP] with formula: C41H69O8P
+ Glycerophospholipids [GP] with formula: C41H65O8P
+ Glycerophospholipids [GP] with formula: C41H63O8P
+ Glycerophospholipids [GP] with formula: C44H75O8P
+ Glycerophospholipids [GP] with formula: C42H73O8P
+ Glycerophospholipids [GP] with formula: C42H71O8P
+ Glycerophospholipids [GP] with formula: C44H81O8P
+ Glycerophospholipids [GP] with formula: C44H77O8P
+ Glycerophospholipids [GP] with formula: C44H73O8P
+ Glycerophospholipids [GP] with formula: C44H87O8P
+ Glycerophospholipids [GP] with formula: C43H73O8P
+ Glycerophospholipids [GP] with formula: C45H77O8P
+ Glycerophospholipids [GP] with formula: C45H73O8P
+ Glycerophospholipids [GP] with formula: C45H75O8P
+ Glycerophospholipids [GP] with formula: C45H71O8P
+ Glycerophospholipids [GP] with formula: C41H67O8P
+ Glycerophospholipids [GP] with formula: C45H69O8P
+ Glycerophospholipids [GP] with formula: C43H65O8P
+ Glycerophospholipids [GP] with formula: C43H83O8P
+ Glycerophospholipids [GP] with formula: C46H83O8P
+ Glycerophospholipids [GP] with formula: C40H79O8P
+ Glycerophospholipids [GP] with formula: C40H77O8P
+ Glycerophospholipids [GP] with formula: C41H79O8P
+ Glycerophospholipids [GP] with formula: C42H83O8P
+ Glycerophospholipids [GP] with formula: C42H81O8P
+ Glycerophospholipids [GP] with formula: C42H79O8P
+ Glycerophospholipids [GP] with formula: C43H81O8P
+ Glycerophospholipids [GP] with formula: C46H91O8P
+ Glycerophospholipids [GP] with formula: C44H85O8P
+ Glycerophospholipids [GP] with formula: C44H83O8P
+ Glycerophospholipids [GP] with formula: C45H87O8P
+ Glycerophospholipids [GP] with formula: C45H85O8P
+ Glycerophospholipids [GP] with formula: C45H83O8P
+ Glycerophospholipids [GP] with formula: C45H81O8P
+ Glycerophospholipids [GP] with formula: C45H79O8P
+ Glycerophospholipids [GP] with formula: C46H89O8P
+ Glycerophospholipids [GP] with formula: C47H91O8P
+ Glycerophospholipids [GP] with formula: C47H89O8P
+ Glycerophospholipids [GP] with formula: C47H87O8P
+ Glycerophospholipids [GP] with formula: C47H83O8P
+ Glycerophospholipids [GP] with formula: C42H77O8P
+ Glycerophospholipids [GP] with formula: C42H75O8P
+ Glycerophospholipids [GP] with formula: C43H79O8P
+ Glycerophospholipids [GP] with formula: C43H77O8P
+ Glycerophospholipids [GP] with formula: C43H75O8P
+ Glycerophospholipids [GP] with formula: C46H87O8P
+ Glycerophospholipids [GP] with formula: C44H79O8P
+ Glycerophospholipids [GP] with formula: C47H85O8P
+ Glycerophospholipids [GP] with formula: C42H69O8P
+ Glycerophospholipids [GP] with formula: C42H67O8P
+ Glycerophospholipids [GP] with formula: C43H69O8P
+ Glycerophospholipids [GP] with formula: C45H67O8P
+ Glycerophospholipids [GP] with formula: C47H81O8P
+ Glycerophospholipids [GP] with formula: C47H79O8P
+ Glycerophospholipids [GP] with formula: C47H77O8P
+ Glycerophospholipids [GP] with formula: C47H73O8P
+ Glycerophospholipids [GP] with formula: C36H71O8P
+ Glycerophospholipids [GP] with formula: C34H67O8P
+ Glycerophospholipids [GP] with formula: C37H73O8P
+ Glycerophospholipids [GP] with formula: C36H67O8P
+ Glycerophospholipids [GP] with formula: C35H69O8P
+ Glycerophospholipids [GP] with formula: C31H57O8P
+ Glycerophospholipids [GP] with formula: C32H63O8P
+ Glycerophospholipids [GP] with formula: C29H57O8P
+ Glycerophospholipids [GP] with formula: C37H61O8P
+ Glycerophospholipids [GP] with formula: C47H93O8P
+ Glycerophospholipids [GP] with formula: C45H89O8P
+ Glycerophospholipids [GP] with formula: C41H73O8P
+ Glycerophospholipids [GP] with formula: C41H81O8P
+ Glycerophospholipids [GP] with formula: C39H75O8P
+ Glycerophospholipids [GP] with formula: C39H77O8P
+ Glycerophospholipids [GP] with formula: C38H75O8P
+ Glycerophospholipids [GP] with formula: C37H67O8P
+ Glycerophospholipids [GP] with formula: C31H61O8P
+ Glycerophospholipids [GP] with formula: C33H65O8P
+ Glycerophospholipids [GP] with formula: C31H63O7P
+ Glycerophospholipids [GP] with formula: C32H65O7P
+ Glycerophospholipids [GP] with formula: C33H67O7P
+ Glycerophospholipids [GP] with formula: C33H65O7P
+ Glycerophospholipids [GP] with formula: C34H67O7P
+ Glycerophospholipids [GP] with formula: C36H69O7P
+ Glycerophospholipids [GP] with formula: C37H67O7P
+ Glycerophospholipids [GP] with formula: C34H69O7P
+ Glycerophospholipids [GP] with formula: C35H69O7P
+ Glycerophospholipids [GP] with formula: C36H71O7P
+ Glycerophospholipids [GP] with formula: C38H77O7P
+ Glycerophospholipids [GP] with formula: C38H73O7P
+ Glycerophospholipids [GP] with formula: C39H77O7P
+ Glycerophospholipids [GP] with formula: C39H75O7P
+ Glycerophospholipids [GP] with formula: C43H85O7P
+ Glycerophospholipids [GP] with formula: C43H83O7P
+ Glycerophospholipids [GP] with formula: C43H79O7P
+ Glycerophospholipids [GP] with formula: C35H71O7P
+ Glycerophospholipids [GP] with formula: C36H73O7P
+ Glycerophospholipids [GP] with formula: C37H75O7P
+ Glycerophospholipids [GP] with formula: C37H73O7P
+ Glycerophospholipids [GP] with formula: C38H75O7P
+ Glycerophospholipids [GP] with formula: C40H81O7P
+ Glycerophospholipids [GP] with formula: C42H85O7P
+ Glycerophospholipids [GP] with formula: C42H83O7P
+ Glycerophospholipids [GP] with formula: C44H89O7P
+ Glycerophospholipids [GP] with formula: C45H83O7P
+ Glycerophospholipids [GP] with formula: C45H79O7P
+ Glycerophospholipids [GP] with formula: C45H91O7P
+ Glycerophospholipids [GP] with formula: C43H87O7P
+ Glycerophospholipids [GP] with formula: C41H71O7P
+ Glycerophospholipids [GP] with formula: C41H83O7P
+ Glycerophospholipids [GP] with formula: C39H79O7P
+ Glycerophospholipids [GP] with formula: C31H61O7P
+ Glycerophospholipids [GP] with formula: C32H63O7P
+ Glycerophospholipids [GP] with formula: C33H63O7P
+ Glycerophospholipids [GP] with formula: C34H65O7P
+ Glycerophospholipids [GP] with formula: C35H67O7P
+ Glycerophospholipids [GP] with formula: C36H67O7P
+ Glycerophospholipids [GP] with formula: C37H65O7P
+ Glycerophospholipids [GP] with formula: C39H67O7P
+ Glycerophospholipids [GP] with formula: C38H71O7P
+ Glycerophospholipids [GP] with formula: C39H73O7P
+ Glycerophospholipids [GP] with formula: C39H71O7P
+ Glycerophospholipids [GP] with formula: C39H69O7P
+ Glycerophospholipids [GP] with formula: C40H79O7P
+ Glycerophospholipids [GP] with formula: C40H77O7P
+ Glycerophospholipids [GP] with formula: C41H81O7P
+ Glycerophospholipids [GP] with formula: C41H79O7P
+ Glycerophospholipids [GP] with formula: C41H77O7P
+ Glycerophospholipids [GP] with formula: C41H75O7P
+ Glycerophospholipids [GP] with formula: C43H81O7P
+ Glycerophospholipids [GP] with formula: C43H77O7P
+ Glycerophospholipids [GP] with formula: C40H75O7P
+ Glycerophospholipids [GP] with formula: C41H73O7P
+ Glycerophospholipids [GP] with formula: C42H81O7P
+ Glycerophospholipids [GP] with formula: C43H75O7P
+ Glycerophospholipids [GP] with formula: C44H87O7P
+ Glycerophospholipids [GP] with formula: C45H89O7P
+ Glycerophospholipids [GP] with formula: C45H87O7P
+ Glycerophospholipids [GP] with formula: C45H85O7P
+ Glycerophospholipids [GP] with formula: C45H81O7P
+ Glycerophospholipids [GP] with formula: C45H77O7P
+ Glycerophospholipids [GP] with formula: C37H69O7P
+ Glycerophospholipids [GP] with formula: C37H71O7P
+ Glycerophospholipids [GP] with formula: C43H73O7P
+ Glycerophospholipids [GP] with formula: C41H69O7P
+ Glycerophospholipids [GP] with formula: C35H73O6P
Glycerophospholipids [GP] with formula: C16H36NO7P
- Glycerophospholipids [GP] with formula: C20H42NO7P
Glycerophospholipids [GP] with formula: C24H44NO7P
- Glycerophospholipids [GP] with formula: C22H42NO7P
Glycerophospholipids [GP] with formula: C21H43O7P
- Glycerophospholipids [GP] with formula: C19H39O7P
- Glycerophospholipids [GP] with formula: C17H35O7P
- Glycerophospholipids [GP] with formula: C21H41O7P
- Glycerophospholipids [GP] with formula: C19H37O6P
+ Glycerophospholipids [GP] with formula: C19H39O7P
+ Glycerophospholipids [GP] with formula: C17H35O7P
Glycerophospholipids [GP] with formula: C23H39O7P
+ Glycerophospholipids [GP] with formula: C21H41O7P
+ Glycerophospholipids [GP] with formula: C15H31O7P
+ Glycerophospholipids [GP] with formula: C19H37O7P
+ Glycerophospholipids [GP] with formula: C21H39O7P
+ Glycerophospholipids [GP] with formula: C23H47O7P
+ Glycerophospholipids [GP] with formula: C25H39O7P
+ Glycerophospholipids [GP] with formula: C25H43O7P
+ Glycerophospholipids [GP] with formula: C18H35O7P
+ Glycerophospholipids [GP] with formula: C20H37O7P
+ Glycerophospholipids [GP] with formula: C21H35O7P
+ Glycerophospholipids [GP] with formula: C22H43O7P
+ Glycerophospholipids [GP] with formula: C23H45O7P
+ Glycerophospholipids [GP] with formula: C23H43O7P
+ Glycerophospholipids [GP] with formula: C23H41O7P
+ Glycerophospholipids [GP] with formula: C25H49O7P
+ Glycerophospholipids [GP] with formula: C25H47O7P
+ Glycerophospholipids [GP] with formula: C25H51O7P
+ Glycerophospholipids [GP] with formula: C24H49O7P
+ Glycerophospholipids [GP] with formula: C23H37O7P
+ Glycerophospholipids [GP] with formula: C22H45O7P
+ Glycerophospholipids [GP] with formula: C21H37O7P
+ Glycerophospholipids [GP] with formula: C20H41O7P
+ Glycerophospholipids [GP] with formula: C18H37O7P
+ Glycerophospholipids [GP] with formula: C17H33O7P
Glycerophospholipids [GP] with formula: C23H41O6P
+ Glycerophospholipids [GP] with formula: C23H49O6P
+ Glycerophospholipids [GP] with formula: C21H45O6P
+ Glycerophospholipids [GP] with formula: C19H41O6P
+ Glycerophospholipids [GP] with formula: C23H47O6P
+ Glycerophospholipids [GP] with formula: C21H43O6P
+ Glycerophospholipids [GP] with formula: C19H39O6P
Glycerophospholipids [GP] with formula: C37H72O11P2
Glycerophospholipids [GP] with formula: C39H74O11P2
+ Glycerophospholipids [GP] with formula: C81H142O17P2
Glycerophospholipids [GP] with formula: C95H184N2O17P2
Glycerophospholipids [GP] with formula: C66H126N2O17P2
Glycerophospholipids [GP] with formula: C70H140N2O17P2
Glycerophospholipids [GP] with formula: C89H172N2O17P2
Glycerophospholipids [GP] with formula: C77H146O17P2
+ Glycerophospholipids [GP] with formula: C63H112O16P2
+ Glycerophospholipids [GP] with formula: C45H82O15P2
Glycerophospholipids [GP] with formula: C89H182O13P2
Glycerophospholipids [GP] with formula: C36H65N3O15P2
Glycerophospholipids [GP] with formula: C46H83N3O15P2
@@ -1658,19 +2739,15 @@
Glycerophospholipids [GP] with formula: C48H85N3O15P2
Glycerophospholipids [GP] with formula: C65H129O16P
Glycerophospholipids [GP] with formula: C64H121N2O35P2
- Glycerophospholipids [GP] with formula: C39H76NO7P
Glycerophospholipids [GP] with formula: C88H178NO9P
Glycerophospholipids [GP] with formula: C94H190NO15P
- Glycerophospholipids [GP] with formula: C46H84NO9P
- Glycerophospholipids [GP] with formula: C44H80NO9P
- Glycerophospholipids [GP] with formula: C46H82NO9P
+ Glycerophospholipids [GP] with formula: C46H84NO9P
+ Glycerophospholipids [GP] with formula: C46H82NO9P
Glycerophospholipids [GP] with formula: C43H78NO9P
Glycerophospholipids [GP] with formula: C43H74NO9P
Glycerophospholipids [GP] with formula: C45H78NO9P
- Glycerophospholipids [GP] with formula: C43H76NO8P
- Glycerophospholipids [GP] with formula: C43H78NO8P
- Glycerophospholipids [GP] with formula: C43H74NO8P
- Glycerophospholipids [GP] with formula: C45H78NO8P
+ Glycerophospholipids [GP] with formula: C81H142O19P2
+ Glycerophospholipids [GP] with formula: C81H142O21P2
@@ -1720,6 +2797,15 @@
Prenol Lipids [PR] with formula: C12H20O2
Prenol Lipids [PR] with formula: C16H26O3
Prenol Lipids [PR] with formula: C15H28O7P2
+ Prenol Lipids [PR] with formula: C17H34O2
+ Prenol Lipids [PR] with formula: C21H40O2
+ Prenol Lipids [PR] with formula: C23H44O2
+ Prenol Lipids [PR] with formula: C25H48O2
+ Prenol Lipids [PR] with formula: C23H42O2
+ Prenol Lipids [PR] with formula: C25H46O2
+ Prenol Lipids [PR] with formula: C23H40O2
+ Prenol Lipids [PR] with formula: C25H44O2
+ Prenol Lipids [PR] with formula: C27H48O2
Prenol Lipids [PR] with formula: C15H22O3
Prenol Lipids [PR] with formula: C14H24O
Prenol Lipids [PR] with formula: C15H22O
@@ -1736,7 +2822,7 @@
Prenol Lipids [PR] with formula: C15H18O3
Prenol Lipids [PR] with formula: C15H20O3
Prenol Lipids [PR] with formula: C15H22O5
- Prenol Lipids [PR] with formula: C15H24
+ Prenol Lipids [PR] with formula: C15H24
Prenol Lipids [PR] with formula: C15H20O2
Prenol Lipids [PR] with formula: C15H18O
Prenol Lipids [PR] with formula: C15H22O2
@@ -1745,12 +2831,12 @@
Prenol Lipids [PR] with formula: C30H30O8
Prenol Lipids [PR] with formula: C15H16O4
Prenol Lipids [PR] with formula: C17H28O4
- Prenol Lipids [PR] with formula: C15H20O4
Prenol Lipids [PR] with formula: C14H22O3
Prenol Lipids [PR] with formula: C34H50O12
Prenol Lipids [PR] with formula: C14H16
Prenol Lipids [PR] with formula: C17H22O5
Prenol Lipids [PR] with formula: C15H18
+ Prenol Lipids [PR] with formula: C15H20O4
Prenol Lipids [PR] with formula: C17H24O3
Prenol Lipids [PR] with formula: C16H24
Prenol Lipids [PR] with formula: C18H30
@@ -1773,9 +2859,7 @@
Prenol Lipids [PR] with formula: C15H24O2
Prenol Lipids [PR] with formula: C15H24O
Prenol Lipids [PR] with formula: C14H22O
- Prenol Lipids [PR] with formula: C20H40O
Prenol Lipids [PR] with formula: C20H40O2
- Prenol Lipids [PR] with formula: C20H42O
Prenol Lipids [PR] with formula: C20H41O4P
Prenol Lipids [PR] with formula: C20H34O2
Prenol Lipids [PR] with formula: C19H38O
@@ -1787,7 +2871,16 @@
Prenol Lipids [PR] with formula: C20H24O4
Prenol Lipids [PR] with formula: C20H24O2
Prenol Lipids [PR] with formula: C19H38O2
- Prenol Lipids [PR] with formula: C20H38O2
+ Prenol Lipids [PR] with formula: C20H38O2
+ Prenol Lipids [PR] with formula: C20H38O
+ Prenol Lipids [PR] with formula: C20H42O
+ Prenol Lipids [PR] with formula: C20H40O
+ Prenol Lipids [PR] with formula: C26H50O2
+ Prenol Lipids [PR] with formula: C28H54O2
+ Prenol Lipids [PR] with formula: C30H58O2
+ Prenol Lipids [PR] with formula: C28H52O2
+ Prenol Lipids [PR] with formula: C30H56O2
+ Prenol Lipids [PR] with formula: C28H50O2
Prenol Lipids [PR] with formula: C22H34O7
Prenol Lipids [PR] with formula: C20H36O7P2
Prenol Lipids [PR] with formula: C22H34O5
@@ -1876,24 +2969,25 @@
Prenol Lipids [PR] with formula: C25H38O4
Prenol Lipids [PR] with formula: C25H40O3
Prenol Lipids [PR] with formula: C24H38O2
+ Prenol Lipids [PR] with formula: C30H50O2
Prenol Lipids [PR] with formula: C30H52O7P2
Prenol Lipids [PR] with formula: C30H54
Prenol Lipids [PR] with formula: C30H50
Prenol Lipids [PR] with formula: C30H62
+ Prenol Lipids [PR] with formula: C30H52
Prenol Lipids [PR] with formula: C30H60
Prenol Lipids [PR] with formula: C34H58
Prenol Lipids [PR] with formula: C34H68
Prenol Lipids [PR] with formula: C31H48O6
Prenol Lipids [PR] with formula: C34H48O7
- Prenol Lipids [PR] with formula: C32H48O5
Prenol Lipids [PR] with formula: C30H52O2
- Prenol Lipids [PR] with formula: C30H50O
+ Prenol Lipids [PR] with formula: C30H50O
Prenol Lipids [PR] with formula: C35H44O16
Prenol Lipids [PR] with formula: C22H28O6
Prenol Lipids [PR] with formula: C32H52O2
Prenol Lipids [PR] with formula: C30H46O3
Prenol Lipids [PR] with formula: C36H56O9
- Prenol Lipids [PR] with formula: C30H48O3
+ Prenol Lipids [PR] with formula: C30H48O3
Prenol Lipids [PR] with formula: C30H48O4
Prenol Lipids [PR] with formula: C42H64O14
Prenol Lipids [PR] with formula: C30H48O5
@@ -1907,10 +3001,8 @@
Prenol Lipids [PR] with formula: C32H54O3
Prenol Lipids [PR] with formula: C30H52O
Prenol Lipids [PR] with formula: C31H54O
- Prenol Lipids [PR] with formula: C30H52
Prenol Lipids [PR] with formula: C31H50O3
Prenol Lipids [PR] with formula: C31H52O2
- Prenol Lipids [PR] with formula: C30H50O2
Prenol Lipids [PR] with formula: C39H50O7
Prenol Lipids [PR] with formula: C39H48O6
Prenol Lipids [PR] with formula: C47H66O9
@@ -1920,6 +3012,7 @@
Prenol Lipids [PR] with formula: C40H50
Prenol Lipids [PR] with formula: C40H52O
Prenol Lipids [PR] with formula: C40H54O3
+ Prenol Lipids [PR] with formula: C40H56O2
Prenol Lipids [PR] with formula: C40H50O4
Prenol Lipids [PR] with formula: C40H48O4
Prenol Lipids [PR] with formula: C40H52O2
@@ -1932,15 +3025,16 @@
Prenol Lipids [PR] with formula: C40H52O5
Prenol Lipids [PR] with formula: C40H50O3
Prenol Lipids [PR] with formula: C40H68
- Prenol Lipids [PR] with formula: C42H63
+ Prenol Lipids [PR] with formula: C40H56
Prenol Lipids [PR] with formula: C40H58O2
Prenol Lipids [PR] with formula: C40H52O3
Prenol Lipids [PR] with formula: C52H76O12
Prenol Lipids [PR] with formula: C52H72O14
Prenol Lipids [PR] with formula: C40H54O4
- Prenol Lipids [PR] with formula: C40H56O4
+ Prenol Lipids [PR] with formula: C40H56O4
Prenol Lipids [PR] with formula: C40H55NaO7S
Prenol Lipids [PR] with formula: C40H54O5
+ Prenol Lipids [PR] with formula: C61H94O8
Prenol Lipids [PR] with formula: C63H98O8
Prenol Lipids [PR] with formula: C82H134O14
Prenol Lipids [PR] with formula: C80H128O14
@@ -1971,17 +3065,15 @@
Prenol Lipids [PR] with formula: C52H76O4
Prenol Lipids [PR] with formula: C52H76O5
Prenol Lipids [PR] with formula: C40H53NaO8S
- Prenol Lipids [PR] with formula: C40H54O2
+ Prenol Lipids [PR] with formula: C40H54O2
Prenol Lipids [PR] with formula: C40H52
Prenol Lipids [PR] with formula: C47H68O6
Prenol Lipids [PR] with formula: C46H68O6
Prenol Lipids [PR] with formula: C47H70O7
Prenol Lipids [PR] with formula: C42H62O2
Prenol Lipids [PR] with formula: C46H66O8
- Prenol Lipids [PR] with formula: C40H56O2
Prenol Lipids [PR] with formula: C52H76O14
Prenol Lipids [PR] with formula: C35H46
- Prenol Lipids [PR] with formula: C61H94O8
Prenol Lipids [PR] with formula: C40H58
Prenol Lipids [PR] with formula: C40H56O5
Prenol Lipids [PR] with formula: C53H80O6
@@ -1993,7 +3085,6 @@
Prenol Lipids [PR] with formula: C26H32O4
Prenol Lipids [PR] with formula: C40H62O2
Prenol Lipids [PR] with formula: C40H58O3
- Prenol Lipids [PR] with formula: C40H56
Prenol Lipids [PR] with formula: C36H54O6
Prenol Lipids [PR] with formula: C40H68O7P2
Prenol Lipids [PR] with formula: C40H64
@@ -2002,13 +3093,13 @@
Prenol Lipids [PR] with formula: C40H74
Prenol Lipids [PR] with formula: C40H56O
Prenol Lipids [PR] with formula: C25H34O3
- Prenol Lipids [PR] with formula: C40H60
+ Prenol Lipids [PR] with formula: C40H60
Prenol Lipids [PR] with formula: C22H30O
Prenol Lipids [PR] with formula: C30H42O
Prenol Lipids [PR] with formula: C40H62
Prenol Lipids [PR] with formula: C50H72
Prenol Lipids [PR] with formula: C20H28O
- Prenol Lipids [PR] with formula: C20H26O
+ Prenol Lipids [PR] with formula: C20H26O
Prenol Lipids [PR] with formula: C20H30O
Prenol Lipids [PR] with formula: C22H32O2
Prenol Lipids [PR] with formula: C36H60O2
@@ -2019,7 +3110,7 @@
Prenol Lipids [PR] with formula: C21H28O
Prenol Lipids [PR] with formula: C23H32O
Prenol Lipids [PR] with formula: C23H30O3
- Prenol Lipids [PR] with formula: C20H28O2
+ Prenol Lipids [PR] with formula: C20H28O2
Prenol Lipids [PR] with formula: C26H36O8
Prenol Lipids [PR] with formula: C59H90O4
Prenol Lipids [PR] with formula: C39H58O4
@@ -2032,6 +3123,10 @@
Prenol Lipids [PR] with formula: C58H88O4
Prenol Lipids [PR] with formula: C53H80O4
Prenol Lipids [PR] with formula: C23H36O2
+ Prenol Lipids [PR] with formula: C56H82O6S
+ Prenol Lipids [PR] with formula: C51H74O2
+ Prenol Lipids [PR] with formula: C56H82O2
+ Prenol Lipids [PR] with formula: C56H80O2
Prenol Lipids [PR] with formula: C29H50O2
Prenol Lipids [PR] with formula: C21H30O9
Prenol Lipids [PR] with formula: C29H44O2
@@ -2044,23 +3139,24 @@
Prenol Lipids [PR] with formula: C41H56O2
Prenol Lipids [PR] with formula: C50H70O2
Prenol Lipids [PR] with formula: C31H46O2
- Prenol Lipids [PR] with formula: C31H48O3
+ Prenol Lipids [PR] with formula: C31H48O3
Prenol Lipids [PR] with formula: C31H48O2
Prenol Lipids [PR] with formula: C31H46O3
Prenol Lipids [PR] with formula: C55H90O
Prenol Lipids [PR] with formula: C15H29O10P3
+ Prenol Lipids [PR] with formula: C50H82O
Prenol Lipids [PR] with formula: C55H91O4P
Prenol Lipids [PR] with formula: C61H101O9P
Prenol Lipids [PR] with formula: C31H51O10P
Prenol Lipids [PR] with formula: C60H100NO7P
- Prenol Lipids [PR] with formula: C50H83O4P
+ Prenol Lipids [PR] with formula: C50H83O4P
Prenol Lipids [PR] with formula: C71H116N2O18P2
Prenol Lipids [PR] with formula: C95H156N8O28P2
Prenol Lipids [PR] with formula: C55H92O7P2
Prenol Lipids [PR] with formula: C35H60O7P2
Prenol Lipids [PR] with formula: C45H76O7P2
- Prenol Lipids [PR] with formula: C50H84O7P2
Prenol Lipids [PR] with formula: C61H102O12P2
+ Prenol Lipids [PR] with formula: C50H84O7P2
Prenol Lipids [PR] with formula: C45H80O
Prenol Lipids [PR] with formula: C95H156O
Prenol Lipids [PR] with formula: C85H140O
@@ -2112,6 +3208,69 @@
Saccharolipids [SL] with formula: C110H202N2O39P2
Saccharolipids [SL] with formula: C96H176N2O38P2
Saccharolipids [SL] with formula: C84H154N2O37P2
+ Saccharolipids [SL] with formula: C52H98O14
+ Saccharolipids [SL] with formula: C54H102O14
+ Saccharolipids [SL] with formula: C56H106O14
+ Saccharolipids [SL] with formula: C52H98O13
+ Saccharolipids [SL] with formula: C53H100O13
+ Saccharolipids [SL] with formula: C57H108O14
+ Saccharolipids [SL] with formula: C58H110O14
+ Saccharolipids [SL] with formula: C54H102O13
+ Saccharolipids [SL] with formula: C55H104O13
+ Saccharolipids [SL] with formula: C55H104O14
+ Saccharolipids [SL] with formula: C59H112O14
+ Saccharolipids [SL] with formula: C56H106O13
+ Saccharolipids [SL] with formula: C57H108O13
+ Saccharolipids [SL] with formula: C128H236O16
+ Saccharolipids [SL] with formula: C130H242O17
+ Saccharolipids [SL] with formula: C131H242O16
+ Saccharolipids [SL] with formula: C133H246O16
+ Saccharolipids [SL] with formula: C132H244O16
+ Saccharolipids [SL] with formula: C130H240O16
+ Saccharolipids [SL] with formula: C136H252O16
+ Saccharolipids [SL] with formula: C136H254O17
+ Saccharolipids [SL] with formula: C134H250O17
+ Saccharolipids [SL] with formula: C136H256O18
+ Saccharolipids [SL] with formula: C142H266O17
+ Saccharolipids [SL] with formula: C133H248O17
+ Saccharolipids [SL] with formula: C135H254O18
+ Saccharolipids [SL] with formula: C134H252O18
+ Saccharolipids [SL] with formula: C132H248O18
+ Saccharolipids [SL] with formula: C134H254O19
+ Saccharolipids [SL] with formula: C137H258O18
+ Saccharolipids [SL] with formula: C140H264O18
+ Saccharolipids [SL] with formula: C138H262O19
+ Saccharolipids [SL] with formula: C136H258O19
+ Saccharolipids [SL] with formula: C137H260O19
+ Saccharolipids [SL] with formula: C136H260O20
+ Saccharolipids [SL] with formula: C132H246O17
+ Saccharolipids [SL] with formula: C134H248O16
+ Saccharolipids [SL] with formula: C139H260O17
+ Saccharolipids [SL] with formula: C140H262O17
+ Saccharolipids [SL] with formula: C138H260O18
+ Saccharolipids [SL] with formula: C135H250O16
+ Saccharolipids [SL] with formula: C137H254O16
+ Saccharolipids [SL] with formula: C138H256O16
+ Saccharolipids [SL] with formula: C139H258O16
+ Saccharolipids [SL] with formula: C137H256O17
+ Saccharolipids [SL] with formula: C140H260O16
+ Saccharolipids [SL] with formula: C135H252O17
+ Saccharolipids [SL] with formula: C141H262O16
+ Saccharolipids [SL] with formula: C144H268O16
+ Saccharolipids [SL] with formula: C143H266O16
+ Saccharolipids [SL] with formula: C145H270O16
+ Saccharolipids [SL] with formula: C142H264O16
+ Saccharolipids [SL] with formula: C146H272O16
+ Saccharolipids [SL] with formula: C144H270O17
+ Saccharolipids [SL] with formula: C142H268O18
+ Saccharolipids [SL] with formula: C141H266O18
+ Saccharolipids [SL] with formula: C140H266O19
+ Saccharolipids [SL] with formula: C139H262O18
+ Saccharolipids [SL] with formula: C143H268O17
+ Saccharolipids [SL] with formula: C139H264O19
+ Saccharolipids [SL] with formula: C138H258O17
+ Saccharolipids [SL] with formula: C141H264O17
+ Saccharolipids [SL] with formula: C138H264O20
Saccharolipids [SL] with formula: C18H32O8
@@ -2223,6 +3382,7 @@
Sphingolipids [SP] with formula: C36H71NO3
Sphingolipids [SP] with formula: C32H65NO3
Sphingolipids [SP] with formula: C42H85NO4
+ Sphingolipids [SP] with formula: C35H71NO4
Sphingolipids [SP] with formula: C34H69NO4
Sphingolipids [SP] with formula: C42H85NO5
Sphingolipids [SP] with formula: C44H89NO5
@@ -2238,6 +3398,7 @@
Sphingolipids [SP] with formula: C42H84NO6P
Sphingolipids [SP] with formula: C44H88NO6P
Sphingolipids [SP] with formula: C46H90NO6P
+ Sphingolipids [SP] with formula: C26H52NO6P
Sphingolipids [SP] with formula: C35H71N2O6P
Sphingolipids [SP] with formula: C39H79N2O6P
Sphingolipids [SP] with formula: C39H81N2O6P
@@ -2284,9 +3445,20 @@
Sphingolipids [SP] with formula: C62H121NO26P2
Sphingolipids [SP] with formula: C56H110NO18P
Sphingolipids [SP] with formula: C34H69N2O5P
+ Sphingolipids [SP] with formula: C36H73N2O5P
+ Sphingolipids [SP] with formula: C62H109NO10S
+ Sphingolipids [SP] with formula: C52H91NO13
+ Sphingolipids [SP] with formula: C54H95NO13
+ Sphingolipids [SP] with formula: C56H99NO13
+ Sphingolipids [SP] with formula: C58H103NO13
+ Sphingolipids [SP] with formula: C58H101NO13
+ Sphingolipids [SP] with formula: C58H103NO14
+ Sphingolipids [SP] with formula: C56H99NO14
+ Sphingolipids [SP] with formula: C41H75NO9
Sphingolipids [SP] with formula: C36H69NO8
Sphingolipids [SP] with formula: C40H77NO8
Sphingolipids [SP] with formula: C40H79NO8
+ Sphingolipids [SP] with formula: C46H89NO8
Sphingolipids [SP] with formula: C48H91NO8
Sphingolipids [SP] with formula: C50H95NO8
Sphingolipids [SP] with formula: C42H83NO8
@@ -2300,7 +3472,7 @@
Sphingolipids [SP] with formula: C42H79NO8
Sphingolipids [SP] with formula: C38H75NO8
Sphingolipids [SP] with formula: C42H81NO8
- Sphingolipids [SP] with formula: C44H85NO8
+ Sphingolipids [SP] with formula: C44H85NO8
Sphingolipids [SP] with formula: C45H87NO8
Sphingolipids [SP] with formula: C47H91NO8
Sphingolipids [SP] with formula: C40H75NO8
@@ -2324,7 +3496,6 @@
Sphingolipids [SP] with formula: C56H107NO13
Sphingolipids [SP] with formula: C54H101NO13
Sphingolipids [SP] with formula: C48H91NO13
- Sphingolipids [SP] with formula: C46H89NO8
Sphingolipids [SP] with formula: C80H143N3O38
Sphingolipids [SP] with formula: C82H147N3O38
Sphingolipids [SP] with formula: C84H151N3O38
@@ -2435,7 +3606,7 @@
Sphingolipids [SP] with formula: C82H148N2O33
Sphingolipids [SP] with formula: C80H143N3O37
Sphingolipids [SP] with formula: C82H147N3O37
- Sphingolipids [SP] with formula: C84H151N3O37
+ Sphingolipids [SP] with formula: C84H151N3O37
Sphingolipids [SP] with formula: C86H155N3O37
Sphingolipids [SP] with formula: C88H159N3O37
Sphingolipids [SP] with formula: C90H163N3O37
@@ -2596,10 +3767,10 @@
Sphingolipids [SP] with formula: C114H200N4O55
Sphingolipids [SP] with formula: C116H204N4O55
Sphingolipids [SP] with formula: C82H146N4O38
- Sphingolipids [SP] with formula: C84H150N4O38
- Sphingolipids [SP] with formula: C86H154N4O38
- Sphingolipids [SP] with formula: C88H158N4O38
- Sphingolipids [SP] with formula: C90H162N4O38
+ Sphingolipids [SP] with formula: C84H150N4O38
+ Sphingolipids [SP] with formula: C86H154N4O38
+ Sphingolipids [SP] with formula: C88H158N4O38
+ Sphingolipids [SP] with formula: C90H162N4O38
Sphingolipids [SP] with formula: C92H166N4O38
Sphingolipids [SP] with formula: C90H160N4O38
Sphingolipids [SP] with formula: C92H164N4O38
@@ -2789,7 +3960,7 @@
Sphingolipids [SP] with formula: C66H120N2O28
Sphingolipids [SP] with formula: C70H128N2O28
Sphingolipids [SP] with formula: C76H140N2O28
- Sphingolipids [SP] with formula: C72H131N3O28
+ Sphingolipids [SP] with formula: C72H131N3O28
Sphingolipids [SP] with formula: C78H143N3O28
Sphingolipids [SP] with formula: C78H141N3O28
Sphingolipids [SP] with formula: C60H110N2O23
@@ -2800,6 +3971,8 @@
Sphingolipids [SP] with formula: C70H130N2O23
Sphingolipids [SP] with formula: C68H124N2O23
Sphingolipids [SP] with formula: C70H128N2O23
+ Sphingolipids [SP] with formula: C53H92N3O27
+ Sphingolipids [SP] with formula: C61H106N4O32
Sphingolipids [SP] with formula: C46H87NO13
Sphingolipids [SP] with formula: C56H105NO13
Sphingolipids [SP] with formula: C51H94N2O16
@@ -2885,7 +4058,7 @@
Sphingolipids [SP] with formula: C101H177N5O47
Sphingolipids [SP] with formula: C82H144N4O39
Sphingolipids [SP] with formula: C84H148N4O39
- Sphingolipids [SP] with formula: C86H152N4O39
+ Sphingolipids [SP] with formula: C86H152N4O39
Sphingolipids [SP] with formula: C88H156N4O39
Sphingolipids [SP] with formula: C90H160N4O39
Sphingolipids [SP] with formula: C90H158N4O39
@@ -3005,14 +4178,14 @@
Sphingolipids [SP] with formula: C81H145N3O35
Sphingolipids [SP] with formula: C85H153N3O35
Sphingolipids [SP] with formula: C87H155N3O35
- Sphingolipids [SP] with formula: C57H103N2O22
- Sphingolipids [SP] with formula: C59H107N2O22
- Sphingolipids [SP] with formula: C61H111N2O22
- Sphingolipids [SP] with formula: C63H115N2O22
- Sphingolipids [SP] with formula: C65H119N2O22
- Sphingolipids [SP] with formula: C67H123N2O22
- Sphingolipids [SP] with formula: C65H117N2O22
- Sphingolipids [SP] with formula: C67H121N2O22
+ Sphingolipids [SP] with formula: C65H117N3O27
+ Sphingolipids [SP] with formula: C67H121N3O27
+ Sphingolipids [SP] with formula: C69H125N3O27
+ Sphingolipids [SP] with formula: C71H129N3O27
+ Sphingolipids [SP] with formula: C73H133N3O27
+ Sphingolipids [SP] with formula: C75H137N3O27
+ Sphingolipids [SP] with formula: C74H133N3O27
+ Sphingolipids [SP] with formula: C75H135N3O27
Sphingolipids [SP] with formula: C81H147N3O32
Sphingolipids [SP] with formula: C84H146N4O40
Sphingolipids [SP] with formula: C86H150N4O40
@@ -3322,32 +4495,29 @@
- Sterol Lipids [ST] with formula: C30H50O
- Sterol Lipids [ST] with formula: C27H46O2
+ Sterol Lipids [ST] with formula: C27H46O2
Sterol Lipids [ST] with formula: C27H48
Sterol Lipids [ST] with formula: C32H46O9
Sterol Lipids [ST] with formula: C32H46O8
Sterol Lipids [ST] with formula: C32H44O8
Sterol Lipids [ST] with formula: C30H42O7
Sterol Lipids [ST] with formula: C30H44O8
- Sterol Lipids [ST] with formula: C30H44O7
Sterol Lipids [ST] with formula: C30H46O7
- Sterol Lipids [ST] with formula: C30H48O7
Sterol Lipids [ST] with formula: C32H48O8
Sterol Lipids [ST] with formula: C30H42O6
- Sterol Lipids [ST] with formula: C29H46O2
+ Sterol Lipids [ST] with formula: C28H44O
+ Sterol Lipids [ST] with formula: C28H46O2
Sterol Lipids [ST] with formula: C33H56O6
Sterol Lipids [ST] with formula: C27H44O9
Sterol Lipids [ST] with formula: C27H45O9P
Sterol Lipids [ST] with formula: C27H45O8P
Sterol Lipids [ST] with formula: C27H45O10P
+ Sterol Lipids [ST] with formula: C27H44O7
Sterol Lipids [ST] with formula: C29H47O10P
Sterol Lipids [ST] with formula: C30H54
Sterol Lipids [ST] with formula: C29H46O7
Sterol Lipids [ST] with formula: C33H54O11
Sterol Lipids [ST] with formula: C27H42O6
- Sterol Lipids [ST] with formula: C27H44O7
- Sterol Lipids [ST] with formula: C27H44O6
Sterol Lipids [ST] with formula: C27H44O8
Sterol Lipids [ST] with formula: C26H45NO
Sterol Lipids [ST] with formula: C26H46O5
@@ -3357,10 +4527,24 @@
Sterol Lipids [ST] with formula: C48H80N7O20P3S
Sterol Lipids [ST] with formula: C48H78N7O19P3S
Sterol Lipids [ST] with formula: C48H80N7O19P3S
- Sterol Lipids [ST] with formula: C30H48O2
Sterol Lipids [ST] with formula: C30H50O2
- Sterol Lipids [ST] with formula: C30H52O2
Sterol Lipids [ST] with formula: C27H46
+ Sterol Lipids [ST] with formula: C25H40O
+ Sterol Lipids [ST] with formula: C25H38O
+ Sterol Lipids [ST] with formula: C26H46O
+ Sterol Lipids [ST] with formula: C29H46O6
+ Sterol Lipids [ST] with formula: C27H38O
+ Sterol Lipids [ST] with formula: C27H42O2
+ Sterol Lipids [ST] with formula: C26H38O2
+ Sterol Lipids [ST] with formula: C35H54O9
+ Sterol Lipids [ST] with formula: C26H42O
+ Sterol Lipids [ST] with formula: C26H44O
+ Sterol Lipids [ST] with formula: C27H48O8
+ Sterol Lipids [ST] with formula: C27H48O7
+ Sterol Lipids [ST] with formula: C27H48O11S2
+ Sterol Lipids [ST] with formula: C51H86O21
+ Sterol Lipids [ST] with formula: C53H86O23
+ Sterol Lipids [ST] with formula: C33H54O6
Sterol Lipids [ST] with formula: C39H68O2
Sterol Lipids [ST] with formula: C46H82O2
Sterol Lipids [ST] with formula: C45H78O2
@@ -3393,54 +4577,122 @@
Sterol Lipids [ST] with formula: C48H82O2
Sterol Lipids [ST] with formula: C43H72O2
Sterol Lipids [ST] with formula: C43H74O7
- Sterol Lipids [ST] with formula: C28H50O
+ Sterol Lipids [ST] with formula: C28H50O
Sterol Lipids [ST] with formula: C30H48O
- Sterol Lipids [ST] with formula: C29H50O
- Sterol Lipids [ST] with formula: C28H46O
- Sterol Lipids [ST] with formula: C29H48O
- Sterol Lipids [ST] with formula: C28H48O
- Sterol Lipids [ST] with formula: C28H50O3
- Sterol Lipids [ST] with formula: C28H50O4
+ Sterol Lipids [ST] with formula: C28H46O
+ Sterol Lipids [ST] with formula: C28H48O
+ Sterol Lipids [ST] with formula: C28H50O3
+ Sterol Lipids [ST] with formula: C28H50O4
Sterol Lipids [ST] with formula: C28H50O5
- Sterol Lipids [ST] with formula: C28H46O4
- Sterol Lipids [ST] with formula: C28H48O3
- Sterol Lipids [ST] with formula: C28H48O2
- Sterol Lipids [ST] with formula: C28H50O2
- Sterol Lipids [ST] with formula: C28H44O
- Sterol Lipids [ST] with formula: C29H52O
+ Sterol Lipids [ST] with formula: C28H50O2
Sterol Lipids [ST] with formula: C28H42O
- Sterol Lipids [ST] with formula: C28H46O2
- Sterol Lipids [ST] with formula: C29H44O
Sterol Lipids [ST] with formula: C18H32O2
+ Sterol Lipids [ST] with formula: C46H78O2
Sterol Lipids [ST] with formula: C46H76O2
Sterol Lipids [ST] with formula: C44H72O2
- Sterol Lipids [ST] with formula: C46H78O2
Sterol Lipids [ST] with formula: C44H74O2
Sterol Lipids [ST] with formula: C28H46O7
- Sterol Lipids [ST] with formula: C30H54O
+ Sterol Lipids [ST] with formula: C30H52O5
+ Sterol Lipids [ST] with formula: C30H52O6
+ Sterol Lipids [ST] with formula: C29H52O
+ Sterol Lipids [ST] with formula: C27H48O9
+ Sterol Lipids [ST] with formula: C28H48O9
+ Sterol Lipids [ST] with formula: C28H48O2
+ Sterol Lipids [ST] with formula: C29H44O
+ Sterol Lipids [ST] with formula: C28H48O3
+ Sterol Lipids [ST] with formula: C28H40O3
+ Sterol Lipids [ST] with formula: C27H40O6S
+ Sterol Lipids [ST] with formula: C28H46O5
+ Sterol Lipids [ST] with formula: C28H44O3
+ Sterol Lipids [ST] with formula: C28H44O5
+ Sterol Lipids [ST] with formula: C28H44O4
+ Sterol Lipids [ST] with formula: C28H46O4
+ Sterol Lipids [ST] with formula: C30H48O5
Sterol Lipids [ST] with formula: C29H40O8
Sterol Lipids [ST] with formula: C29H44O8
- Sterol Lipids [ST] with formula: C30H52O
+ Sterol Lipids [ST] with formula: C29H50O
+ Sterol Lipids [ST] with formula: C31H52O
+ Sterol Lipids [ST] with formula: C30H50O
+ Sterol Lipids [ST] with formula: C29H48O
+ Sterol Lipids [ST] with formula: C29H48O2
+ Sterol Lipids [ST] with formula: C32H54O
+ Sterol Lipids [ST] with formula: C29H46O2
+ Sterol Lipids [ST] with formula: C30H54O
+ Sterol Lipids [ST] with formula: C30H52O2
+ Sterol Lipids [ST] with formula: C30H46O
+ Sterol Lipids [ST] with formula: C31H52O3
+ Sterol Lipids [ST] with formula: C30H48O2
+ Sterol Lipids [ST] with formula: C30H50O3
+ Sterol Lipids [ST] with formula: C30H50O4
+ Sterol Lipids [ST] with formula: C29H50O3
+ Sterol Lipids [ST] with formula: C29H40O4
+ Sterol Lipids [ST] with formula: C31H42O5
+ Sterol Lipids [ST] with formula: C28H42O6S
+ Sterol Lipids [ST] with formula: C29H46O3
+ Sterol Lipids [ST] with formula: C29H50O2
+ Sterol Lipids [ST] with formula: C35H60O6
+ Sterol Lipids [ST] with formula: C51H90O7
+ Sterol Lipids [ST] with formula: C35H58O6
+ Sterol Lipids [ST] with formula: C30H52O
Sterol Lipids [ST] with formula: C31H50O
- Sterol Lipids [ST] with formula: C31H52O
- Sterol Lipids [ST] with formula: C31H54O
Sterol Lipids [ST] with formula: C33H56O9
- Sterol Lipids [ST] with formula: C56H92O29
- Sterol Lipids [ST] with formula: C33H54O8
- Sterol Lipids [ST] with formula: C27H42O4
+ Sterol Lipids [ST] with formula: C33H57NO8
+ Sterol Lipids [ST] with formula: C57H92O27
+ Sterol Lipids [ST] with formula: C59H100O26
+ Sterol Lipids [ST] with formula: C53H88O23
+ Sterol Lipids [ST] with formula: C52H86O21
+ Sterol Lipids [ST] with formula: C53H88O22
+ Sterol Lipids [ST] with formula: C53H90O22
+ Sterol Lipids [ST] with formula: C52H88O22
+ Sterol Lipids [ST] with formula: C54H94O22
+ Sterol Lipids [ST] with formula: C56H92O29
+ Sterol Lipids [ST] with formula: C33H54O8
+ Sterol Lipids [ST] with formula: C34H48O7
+ Sterol Lipids [ST] with formula: C27H40O5
+ Sterol Lipids [ST] with formula: C27H42O3
+ Sterol Lipids [ST] with formula: C26H36O8
+ Sterol Lipids [ST] with formula: C27H40O4
+ Sterol Lipids [ST] with formula: C27H40O3
+ Sterol Lipids [ST] with formula: C46H76O16
+ Sterol Lipids [ST] with formula: C40H66O12
+ Sterol Lipids [ST] with formula: C52H86O22
+ Sterol Lipids [ST] with formula: C46H76O17
+ Sterol Lipids [ST] with formula: C52H86O20
+ Sterol Lipids [ST] with formula: C40H66O14
+ Sterol Lipids [ST] with formula: C40H66O15
+ Sterol Lipids [ST] with formula: C40H66O16
+ Sterol Lipids [ST] with formula: C57H96O28
+ Sterol Lipids [ST] with formula: C34H58O10
+ Sterol Lipids [ST] with formula: C40H68O15
+ Sterol Lipids [ST] with formula: C57H96O27
+ Sterol Lipids [ST] with formula: C56H94O27
+ Sterol Lipids [ST] with formula: C34H56O9
+ Sterol Lipids [ST] with formula: C46H76O19
+ Sterol Lipids [ST] with formula: C51H86O23
+ Sterol Lipids [ST] with formula: C51H84O23
+ Sterol Lipids [ST] with formula: C52H86O23
+ Sterol Lipids [ST] with formula: C57H94O27
+ Sterol Lipids [ST] with formula: C56H92O27
+ Sterol Lipids [ST] with formula: C58H98O27
+ Sterol Lipids [ST] with formula: C34H58O9
+ Sterol Lipids [ST] with formula: C56H92O28
+ Sterol Lipids [ST] with formula: C34H56O8
+ Sterol Lipids [ST] with formula: C27H42O4
Sterol Lipids [ST] with formula: C33H52O9
- Sterol Lipids [ST] with formula: C30H48O5
+ Sterol Lipids [ST] with formula: C30H48O7
+ Sterol Lipids [ST] with formula: C30H44O7
+ Sterol Lipids [ST] with formula: C30H44O6
Sterol Lipids [ST] with formula: C37H58O10
Sterol Lipids [ST] with formula: C39H60O11
Sterol Lipids [ST] with formula: C36H54O10
- Sterol Lipids [ST] with formula: C29H46O
+ Sterol Lipids [ST] with formula: C29H46O
+ Sterol Lipids [ST] with formula: C31H54O4
Sterol Lipids [ST] with formula: C23H34O4
Sterol Lipids [ST] with formula: C23H32O5
Sterol Lipids [ST] with formula: C23H34O6
Sterol Lipids [ST] with formula: C23H34O5
Sterol Lipids [ST] with formula: C29H44O9
Sterol Lipids [ST] with formula: C42H66O18
- Sterol Lipids [ST] with formula: C41H64O15
Sterol Lipids [ST] with formula: C29H42O10
Sterol Lipids [ST] with formula: C36H56O14
Sterol Lipids [ST] with formula: C29H44O10
@@ -3457,15 +4709,21 @@
Sterol Lipids [ST] with formula: C30H42O8
Sterol Lipids [ST] with formula: C38H54O16
Sterol Lipids [ST] with formula: C27H45NO
+ Sterol Lipids [ST] with formula: C27H43NO2
Sterol Lipids [ST] with formula: C28H47NO
Sterol Lipids [ST] with formula: C27H43NO
Sterol Lipids [ST] with formula: C27H45NO2
- Sterol Lipids [ST] with formula: C27H43NO2
Sterol Lipids [ST] with formula: C50H83NO21
- Sterol Lipids [ST] with formula: C18H24O2
+ Sterol Lipids [ST] with formula: C28H38O7
+ Sterol Lipids [ST] with formula: C28H38O3
+ Sterol Lipids [ST] with formula: C29H38O5
+ Sterol Lipids [ST] with formula: C28H38O5
+ Sterol Lipids [ST] with formula: C28H40O5
+ Sterol Lipids [ST] with formula: C29H42O5
Sterol Lipids [ST] with formula: C18H24O3
Sterol Lipids [ST] with formula: C18H22O2
Sterol Lipids [ST] with formula: C18H18O2
+ Sterol Lipids [ST] with formula: C18H24O2
Sterol Lipids [ST] with formula: C19H24O3
Sterol Lipids [ST] with formula: C18H30O2
Sterol Lipids [ST] with formula: C18H20O2
@@ -3484,8 +4742,8 @@
Sterol Lipids [ST] with formula: C19H30O
Sterol Lipids [ST] with formula: C20H28O2
Sterol Lipids [ST] with formula: C19H27ClO2
- Sterol Lipids [ST] with formula: C19H30O2
Sterol Lipids [ST] with formula: C20H29FO3
+ Sterol Lipids [ST] with formula: C19H30O2
Sterol Lipids [ST] with formula: C20H30O2
Sterol Lipids [ST] with formula: C19H32
Sterol Lipids [ST] with formula: C19H24O4
@@ -3495,19 +4753,20 @@
Sterol Lipids [ST] with formula: C19H26O2
Sterol Lipids [ST] with formula: C19H28O2
Sterol Lipids [ST] with formula: C19H30O3
- Sterol Lipids [ST] with formula: C19H28O3
+ Sterol Lipids [ST] with formula: C19H28O3
Sterol Lipids [ST] with formula: C19H28O
Sterol Lipids [ST] with formula: C19H32O
Sterol Lipids [ST] with formula: C20H32O2
- Sterol Lipids [ST] with formula: C21H30O5
+ Sterol Lipids [ST] with formula: C19H30O5
+ Sterol Lipids [ST] with formula: C21H30O5
Sterol Lipids [ST] with formula: C23H32O6
Sterol Lipids [ST] with formula: C20H26O2
- Sterol Lipids [ST] with formula: C21H32O5
+ Sterol Lipids [ST] with formula: C21H32O5
Sterol Lipids [ST] with formula: C21H28O4
- Sterol Lipids [ST] with formula: C21H30O4
+ Sterol Lipids [ST] with formula: C21H30O4
Sterol Lipids [ST] with formula: C21H29FO5
Sterol Lipids [ST] with formula: C22H30O
- Sterol Lipids [ST] with formula: C21H28O2
+ Sterol Lipids [ST] with formula: C21H28O2
Sterol Lipids [ST] with formula: C23H30O6
Sterol Lipids [ST] with formula: C29H42O6
Sterol Lipids [ST] with formula: C23H31FO6
@@ -3517,55 +4776,58 @@
Sterol Lipids [ST] with formula: C20H28O
Sterol Lipids [ST] with formula: C28H40O7
Sterol Lipids [ST] with formula: C27H40O6
- Sterol Lipids [ST] with formula: C21H34O2
Sterol Lipids [ST] with formula: C21H32O2
Sterol Lipids [ST] with formula: C21H30O2
- Sterol Lipids [ST] with formula: C21H34O5
+ Sterol Lipids [ST] with formula: C21H30O3
+ Sterol Lipids [ST] with formula: C21H34O5
Sterol Lipids [ST] with formula: C22H30O4
Sterol Lipids [ST] with formula: C21H34O
- Sterol Lipids [ST] with formula: C21H32O3
+ Sterol Lipids [ST] with formula: C21H32O3
+ Sterol Lipids [ST] with formula: C21H34O2
Sterol Lipids [ST] with formula: C21H36O
Sterol Lipids [ST] with formula: C22H32O3
Sterol Lipids [ST] with formula: C21H28O3
Sterol Lipids [ST] with formula: C22H30O5
Sterol Lipids [ST] with formula: C21H28O5
Sterol Lipids [ST] with formula: C21H26O5
- Sterol Lipids [ST] with formula: C21H32O4
Sterol Lipids [ST] with formula: C22H32O5
Sterol Lipids [ST] with formula: C20H28O4
Sterol Lipids [ST] with formula: C21H30O6
Sterol Lipids [ST] with formula: C21H28O6
- Sterol Lipids [ST] with formula: C21H36O2
+ Sterol Lipids [ST] with formula: C21H32O4
+ Sterol Lipids [ST] with formula: C21H36O2
+ Sterol Lipids [ST] with formula: C20H30O
+ Sterol Lipids [ST] with formula: C21H34O8S
+ Sterol Lipids [ST] with formula: C21H34O7S
+ Sterol Lipids [ST] with formula: C33H52O11
+ Sterol Lipids [ST] with formula: C39H62O15
+ Sterol Lipids [ST] with formula: C40H64O16
+ Sterol Lipids [ST] with formula: C51H82O23
Sterol Lipids [ST] with formula: C27H43NO4
Sterol Lipids [ST] with formula: C28H38F6O2
Sterol Lipids [ST] with formula: C28H41F3O2
Sterol Lipids [ST] with formula: C28H43FO3
- Sterol Lipids [ST] with formula: C28H44O2
+ Sterol Lipids [ST] with formula: C28H44O2
Sterol Lipids [ST] with formula: C28H44O3S
- Sterol Lipids [ST] with formula: C28H44O3
- Sterol Lipids [ST] with formula: C28H44O4
- Sterol Lipids [ST] with formula: C28H44O5
Sterol Lipids [ST] with formula: C34H52O7
- Sterol Lipids [ST] with formula: C21H30O3
Sterol Lipids [ST] with formula: C22H32O4S
Sterol Lipids [ST] with formula: C22H34O2
Sterol Lipids [ST] with formula: C22H34O3
Sterol Lipids [ST] with formula: C22H34O4S
- Sterol Lipids [ST] with formula: C23H36O2
+ Sterol Lipids [ST] with formula: C23H36O2
Sterol Lipids [ST] with formula: C23H36O3
Sterol Lipids [ST] with formula: C26H39F3O2
Sterol Lipids [ST] with formula: C25H38O4
Sterol Lipids [ST] with formula: C25H40O3
Sterol Lipids [ST] with formula: C25H40O4S
Sterol Lipids [ST] with formula: C25H42O3
- Sterol Lipids [ST] with formula: C26H38O3
+ Sterol Lipids [ST] with formula: C26H38O3
Sterol Lipids [ST] with formula: C26H40O4
Sterol Lipids [ST] with formula: C26H40O5
Sterol Lipids [ST] with formula: C26H42O2
Sterol Lipids [ST] with formula: C26H42O2S
Sterol Lipids [ST] with formula: C26H42O3S
- Sterol Lipids [ST] with formula: C26H42O4
- Sterol Lipids [ST] with formula: C26H42O5
+ Sterol Lipids [ST] with formula: C26H42O4
Sterol Lipids [ST] with formula: C26H43NO
Sterol Lipids [ST] with formula: C26H43NO3
Sterol Lipids [ST] with formula: C26H43O3P
@@ -3584,81 +4846,62 @@
Sterol Lipids [ST] with formula: C27H38F6O3
Sterol Lipids [ST] with formula: C27H38F6O4
Sterol Lipids [ST] with formula: C27H38O2
- Sterol Lipids [ST] with formula: C27H38O3
+ Sterol Lipids [ST] with formula: C27H38O3
Sterol Lipids [ST] with formula: C27H39F3O3
- Sterol Lipids [ST] with formula: C27H40O2
- Sterol Lipids [ST] with formula: C27H40O3
- Sterol Lipids [ST] with formula: C27H40O4
- Sterol Lipids [ST] with formula: C27H40O5
+ Sterol Lipids [ST] with formula: C27H40O2
Sterol Lipids [ST] with formula: C27H41FO3
Sterol Lipids [ST] with formula: C27H41F3O2
Sterol Lipids [ST] with formula: C27H41F3O3
Sterol Lipids [ST] with formula: C27H42F2O2
Sterol Lipids [ST] with formula: C27H42F2O3
Sterol Lipids [ST] with formula: C27H42F2O4
- Sterol Lipids [ST] with formula: C27H42O2
- Sterol Lipids [ST] with formula: C27H42O3
- Sterol Lipids [ST] with formula: C28H45O4
Sterol Lipids [ST] with formula: C27H43ClO3
- Sterol Lipids [ST] with formula: C27H43FO2
+ Sterol Lipids [ST] with formula: C27H43FO2
Sterol Lipids [ST] with formula: C27H43FO3
- Sterol Lipids [ST] with formula: C27H44O3S
- Sterol Lipids [ST] with formula: C26H42O3
+ Sterol Lipids [ST] with formula: C27H44O3S
+ Sterol Lipids [ST] with formula: C26H42O3
Sterol Lipids [ST] with formula: C27H44O4S
- Sterol Lipids [ST] with formula: C27H44O5
Sterol Lipids [ST] with formula: C27H44O5S
- Sterol Lipids [ST] with formula: C27H46O
- Sterol Lipids [ST] with formula: C27H46O3
- Sterol Lipids [ST] with formula: C28H38O3
- Sterol Lipids [ST] with formula: C28H40O3
+ Sterol Lipids [ST] with formula: C27H46O
+ Sterol Lipids [ST] with formula: C27H46O3
Sterol Lipids [ST] with formula: C28H42O2
- Sterol Lipids [ST] with formula: C28H42O3
Sterol Lipids [ST] with formula: C28H42O4
Sterol Lipids [ST] with formula: C28H44F2O3
Sterol Lipids [ST] with formula: C28H45ClO3
Sterol Lipids [ST] with formula: C28H45FO3
- Sterol Lipids [ST] with formula: C28H46O3S
- Sterol Lipids [ST] with formula: C28H46O3
+ Sterol Lipids [ST] with formula: C28H46O3S
Sterol Lipids [ST] with formula: C29H40O2
Sterol Lipids [ST] with formula: C29H42O3
Sterol Lipids [ST] with formula: C29H42O4
- Sterol Lipids [ST] with formula: C29H44O3
- Sterol Lipids [ST] with formula: C29H44O4
+ Sterol Lipids [ST] with formula: C29H44O3
+ Sterol Lipids [ST] with formula: C29H44O4
Sterol Lipids [ST] with formula: C29H46F2O3
- Sterol Lipids [ST] with formula: C29H46O3
- Sterol Lipids [ST] with formula: C29H46O4
- Sterol Lipids [ST] with formula: C29H46O5
- Sterol Lipids [ST] with formula: C29H48O2
- Sterol Lipids [ST] with formula: C29H48O3
- Sterol Lipids [ST] with formula: C29H48O3S
- Sterol Lipids [ST] with formula: C29H48O4
- Sterol Lipids [ST] with formula: C29H48O5
- Sterol Lipids [ST] with formula: C29H50O2
+ Sterol Lipids [ST] with formula: C29H46O4
+ Sterol Lipids [ST] with formula: C29H46O5
+ Sterol Lipids [ST] with formula: C29H48O3
+ Sterol Lipids [ST] with formula: C29H48O3S
+ Sterol Lipids [ST] with formula: C29H48O4
+ Sterol Lipids [ST] with formula: C29H48O5
Sterol Lipids [ST] with formula: C30H44O4
- Sterol Lipids [ST] with formula: C30H46O4
+ Sterol Lipids [ST] with formula: C30H46O4
Sterol Lipids [ST] with formula: C30H48F2O3
- Sterol Lipids [ST] with formula: C30H48O3
Sterol Lipids [ST] with formula: C30H48O4
Sterol Lipids [ST] with formula: C30H50O3S
- Sterol Lipids [ST] with formula: C30H50O4
- Sterol Lipids [ST] with formula: C30H50O5
+ Sterol Lipids [ST] with formula: C30H50O5
Sterol Lipids [ST] with formula: C31H44O3
Sterol Lipids [ST] with formula: C31H46O3
- Sterol Lipids [ST] with formula: C31H48O3
- Sterol Lipids [ST] with formula: C31H48O4
+ Sterol Lipids [ST] with formula: C31H48O4
Sterol Lipids [ST] with formula: C31H48O7
Sterol Lipids [ST] with formula: C31H50O3
Sterol Lipids [ST] with formula: C31H50O4
- Sterol Lipids [ST] with formula: C31H52O3
- Sterol Lipids [ST] with formula: C31H52O4
- Sterol Lipids [ST] with formula: C31H52O5
+ Sterol Lipids [ST] with formula: C31H52O4
Sterol Lipids [ST] with formula: C32H42O3
Sterol Lipids [ST] with formula: C32H48O3
- Sterol Lipids [ST] with formula: C32H50O3
+ Sterol Lipids [ST] with formula: C32H50O3
Sterol Lipids [ST] with formula: C32H50O4
Sterol Lipids [ST] with formula: C32H54O3
Sterol Lipids [ST] with formula: C32H54O4
- Sterol Lipids [ST] with formula: C32H54O5
+ Sterol Lipids [ST] with formula: C32H54O5
Sterol Lipids [ST] with formula: C33H48O3
Sterol Lipids [ST] with formula: C33H56O3
Sterol Lipids [ST] with formula: C33H56O4
@@ -3666,19 +4909,22 @@
Sterol Lipids [ST] with formula: C35H49N3O3
Sterol Lipids [ST] with formula: C35H53NO3
Sterol Lipids [ST] with formula: C36H50O5
+ Sterol Lipids [ST] with formula: C28H46O3
Sterol Lipids [ST] with formula: C42H59N5O6
Sterol Lipids [ST] with formula: C37H48O3
- Sterol Lipids [ST] with formula: C30H50O3
Sterol Lipids [ST] with formula: C26H32F6O3
Sterol Lipids [ST] with formula: C25H42O4
Sterol Lipids [ST] with formula: C26H44O4
- Sterol Lipids [ST] with formula: C29H50O5
+ Sterol Lipids [ST] with formula: C29H50O5
Sterol Lipids [ST] with formula: C33H50O4
Sterol Lipids [ST] with formula: C26H44O2
Sterol Lipids [ST] with formula: C31H51FO3
+ Sterol Lipids [ST] with formula: C31H48O3
+ Sterol Lipids [ST] with formula: C30H48O3
Sterol Lipids [ST] with formula: C32H44O3
+ Sterol Lipids [ST] with formula: C32H46O4
Sterol Lipids [ST] with formula: C34H50O4
- Sterol Lipids [ST] with formula: C27H38O4
+ Sterol Lipids [ST] with formula: C27H38O4
Sterol Lipids [ST] with formula: C20H30O3
Sterol Lipids [ST] with formula: C33H52O7
Sterol Lipids [ST] with formula: C29H45BrO3
@@ -3694,16 +4940,16 @@
Sterol Lipids [ST] with formula: C32H50O7
Sterol Lipids [ST] with formula: C30H42O3S
Sterol Lipids [ST] with formula: C30H46O3
- Sterol Lipids [ST] with formula: C30H44O3
- Sterol Lipids [ST] with formula: C26H40O3
- Sterol Lipids [ST] with formula: C27H44O2
+ Sterol Lipids [ST] with formula: C30H44O3
+ Sterol Lipids [ST] with formula: C26H40O3
+ Sterol Lipids [ST] with formula: C27H44O2
Sterol Lipids [ST] with formula: C26H42F2O4
- Sterol Lipids [ST] with formula: C27H44O
+ Sterol Lipids [ST] with formula: C27H44O
Sterol Lipids [ST] with formula: C30H52O3Si
Sterol Lipids [ST] with formula: C31H50O2
Sterol Lipids [ST] with formula: C27H43F
Sterol Lipids [ST] with formula: C27H43FO
- Sterol Lipids [ST] with formula: C27H42O
+ Sterol Lipids [ST] with formula: C27H42O
Sterol Lipids [ST] with formula: C27H42F2O
Sterol Lipids [ST] with formula: C39H64O12
Sterol Lipids [ST] with formula: C33H52O8
@@ -3711,59 +4957,63 @@
Sterol Lipids [ST] with formula: C27H44N3O
Sterol Lipids [ST] with formula: C29H45NO3
Sterol Lipids [ST] with formula: C31H44O4
- Sterol Lipids [ST] with formula: C32H46O4
Sterol Lipids [ST] with formula: C30H51NO2
+ Sterol Lipids [ST] with formula: C31H52O5
Sterol Lipids [ST] with formula: C23H34O3
Sterol Lipids [ST] with formula: C24H40O2
+ Sterol Lipids [ST] with formula: C24H40O4
Sterol Lipids [ST] with formula: C24H38O5
Sterol Lipids [ST] with formula: C24H38O2
- Sterol Lipids [ST] with formula: C24H42O4
+ Sterol Lipids [ST] with formula: C24H42O4
Sterol Lipids [ST] with formula: C24H42O3
Sterol Lipids [ST] with formula: C24H42O2
Sterol Lipids [ST] with formula: C24H30O4
Sterol Lipids [ST] with formula: C24H36O2
Sterol Lipids [ST] with formula: C24H34O2
- Sterol Lipids [ST] with formula: C24H36O3
+ Sterol Lipids [ST] with formula: C24H36O3
Sterol Lipids [ST] with formula: C24H34O3
Sterol Lipids [ST] with formula: C24H34O4
- Sterol Lipids [ST] with formula: C24H40O3
- Sterol Lipids [ST] with formula: C24H38O3
+ Sterol Lipids [ST] with formula: C24H40O3
+ Sterol Lipids [ST] with formula: C24H38O3
Sterol Lipids [ST] with formula: C24H38O4
- Sterol Lipids [ST] with formula: C24H36O4
+ Sterol Lipids [ST] with formula: C24H36O4
Sterol Lipids [ST] with formula: C24H32O5
Sterol Lipids [ST] with formula: C24H30O5
Sterol Lipids [ST] with formula: C24H32O4
- Sterol Lipids [ST] with formula: C24H40O4
Sterol Lipids [ST] with formula: C24H36O5
Sterol Lipids [ST] with formula: C24H38O6
Sterol Lipids [ST] with formula: C24H34O5
- Sterol Lipids [ST] with formula: C24H40O5
- Sterol Lipids [ST] with formula: C24H40O6
+ Sterol Lipids [ST] with formula: C24H40O5
+ Sterol Lipids [ST] with formula: C24H40O6
Sterol Lipids [ST] with formula: C24H32O3
Sterol Lipids [ST] with formula: C24H40O8S
Sterol Lipids [ST] with formula: C26H43NO5
Sterol Lipids [ST] with formula: C26H46O6
- Sterol Lipids [ST] with formula: C27H48O5
- Sterol Lipids [ST] with formula: C27H48O4
- Sterol Lipids [ST] with formula: C27H48O3
- Sterol Lipids [ST] with formula: C27H46O6
- Sterol Lipids [ST] with formula: C27H44O4
- Sterol Lipids [ST] with formula: C27H44O3
+ Sterol Lipids [ST] with formula: C27H48O6
+ Sterol Lipids [ST] with formula: C27H48O5
+ Sterol Lipids [ST] with formula: C27H48O4
+ Sterol Lipids [ST] with formula: C27H48O3
+ Sterol Lipids [ST] with formula: C27H44O4
+ Sterol Lipids [ST] with formula: C27H44O3
Sterol Lipids [ST] with formula: C27H48O2
Sterol Lipids [ST] with formula: C27H48O
- Sterol Lipids [ST] with formula: C27H42O5
- Sterol Lipids [ST] with formula: C27H46O4
- Sterol Lipids [ST] with formula: C27H46O5
- Sterol Lipids [ST] with formula: C27H48O6
- Sterol Lipids [ST] with formula: C28H48O6
- Sterol Lipids [ST] with formula: C28H48O5
- Sterol Lipids [ST] with formula: C28H46O5
- Sterol Lipids [ST] with formula: C28H48O4
+ Sterol Lipids [ST] with formula: C27H42O5
+ Sterol Lipids [ST] with formula: C27H46O4
+ Sterol Lipids [ST] with formula: C27H46O5
+ Sterol Lipids [ST] with formula: C26H42O5
+ Sterol Lipids [ST] with formula: C27H44O6
+ Sterol Lipids [ST] with formula: C27H44O5
+ Sterol Lipids [ST] with formula: C27H46O6
+ Sterol Lipids [ST] with formula: C28H42O3
+ Sterol Lipids [ST] with formula: C30H44O5
+ Sterol Lipids [ST] with formula: C28H48O6
+ Sterol Lipids [ST] with formula: C28H48O5
+ Sterol Lipids [ST] with formula: C28H48O4
Sterol Lipids [ST] with formula: C22H36O5
Sterol Lipids [ST] with formula: C23H40O5
- Sterol Lipids [ST] with formula: C23H38O4
+ Sterol Lipids [ST] with formula: C23H38O4
Sterol Lipids [ST] with formula: C23H40O4
- Sterol Lipids [ST] with formula: C23H40O3
+ Sterol Lipids [ST] with formula: C23H40O3
Sterol Lipids [ST] with formula: C23H38O3
Sterol Lipids [ST] with formula: C23H38O2
Sterol Lipids [ST] with formula: C25H40O4
@@ -3788,7 +5038,7 @@
Sterol Lipids [ST] with formula: C24H32O11S
Sterol Lipids [ST] with formula: C25H40O9
Sterol Lipids [ST] with formula: C25H34O9
- Sterol Lipids [ST] with formula: C25H38O8
+ Sterol Lipids [ST] with formula: C25H38O8
Sterol Lipids [ST] with formula: C33H56O10
Sterol Lipids [ST] with formula: C33H54O7
Sterol Lipids [ST] with formula: C30H48O11
@@ -3811,27 +5061,45 @@
Sterol Lipids [ST] with formula: C21H32O6S
Sterol Lipids [ST] with formula: C19H28O6S
Sterol Lipids [ST] with formula: C19H30O5S
+ Sterol Lipids [ST] with formula: C24H40O7S
Sterol Lipids [ST] with formula: C24H40O10S2
Sterol Lipids [ST] with formula: C26H45NO8S2
Sterol Lipids [ST] with formula: C26H45NO9S2
Sterol Lipids [ST] with formula: C26H45NO10S2
Sterol Lipids [ST] with formula: C19H28O5S
- Sterol Lipids [ST] with formula: C24H40O7S
Sterol Lipids [ST] with formula: C26H42NO7S
Sterol Lipids [ST] with formula: C26H43NO6
Sterol Lipids [ST] with formula: C26H43NO4
- Sterol Lipids [ST] with formula: C26H43NO9S
+ Sterol Lipids [ST] with formula: C26H43NO9S
Sterol Lipids [ST] with formula: C26H43NO8S
- Sterol Lipids [ST] with formula: C21H34O3
+ Sterol Lipids [ST] with formula: C21H34O3
Sterol Lipids [ST] with formula: C21H34O4
Sterol Lipids [ST] with formula: C26H45NO5S
- Sterol Lipids [ST] with formula: C29H51NO7S
+ Sterol Lipids [ST] with formula: C29H51NO7S
Sterol Lipids [ST] with formula: C29H51NO6S
Sterol Lipids [ST] with formula: C32H53NO11S
Sterol Lipids [ST] with formula: C26H45NO7S
Sterol Lipids [ST] with formula: C26H45NO6S
- Sterol Lipids [ST] with formula: C30H50
- Sterol Lipids [ST] with formula: C16H32O2
+ Sterol Lipids [ST] with formula: C27H44O14S2
+ Sterol Lipids [ST] with formula: C27H44O11S
+ Sterol Lipids [ST] with formula: C41H64O15
+ Sterol Lipids [ST] with formula: C35H54O10
+ Sterol Lipids [ST] with formula: C39H64O13
+ Sterol Lipids [ST] with formula: C28H42O7
+ Sterol Lipids [ST] with formula: C31H51NaO12S
+ Sterol Lipids [ST] with formula: C33H58O10
+ Sterol Lipids [ST] with formula: C37H64O13
+ Sterol Lipids [ST] with formula: C33H55NaO12S
+ Sterol Lipids [ST] with formula: C32H53NaO12S
+ Sterol Lipids [ST] with formula: C33H58O11
+ Sterol Lipids [ST] with formula: C32H54O10
+ Sterol Lipids [ST] with formula: C32H54O11
+ Sterol Lipids [ST] with formula: C33H55NaO13S
+ Sterol Lipids [ST] with formula: C43H72O19
+ Sterol Lipids [ST] with formula: C38H68O15
+ Sterol Lipids [ST] with formula: C38H65NO9
+ Sterol Lipids [ST] with formula: C33H53Na3O16S3
+ Sterol Lipids [ST] with formula: C36H56NNa3O17S3
@@ -4449,4 +5717,326 @@
Trichoderma viride
+
+ Aspergillus niger, CAS307304-29-6
+ Aspergillus niger, CAS307304-30-9
+ Aspergillus viride-nutans, CAS287102-34-5
+ Aspergillus flavus, CAS120-72-9
+ Aspergillus fumigatus, CAS111427-99-7
+ Aspergillus terreus, CAS2207-58-1
+ Aspergillus terreus, CAS2913-48-6
+ Aspergillus terreus, CAS15254-70-3
+ Aspergillus silvaticus, CAS4707-46-4
+ CAS6152-57-4
+ Aspergillus candidus, CAS66163-76-6
+ Aspergillus flavipes, CAS57514-29-1
+ Aspergillus multicolor, CAS74494-65-8
+ Aspergillus multicolor, CAS65176-75-2
+ Aspergillus versicolor, CAS55483-01-7
+ CAS22897-08-1
+ Aspergillus wentii, CAS77282-69-0
+ Aspergillus versicolor, CAS30517-65-8
+ Aspergillus terreus, CAS19314-92-2
+ Aspergillus variecolor, CAS13410-15-6
+ Aspergillus niger, CAS307001-93-0
+ Aspergillus flavus, CAS1162-65-8
+ Aspergillus flavus, CAS7220-81-7
+ CAS52373-83-8
+ Aspergillus flavus, CAS1165-39-5
+ CAS20421-10-7
+ Aspergillus flavus, CAS6795-23-9
+ Aspergillus flavus, CAS6885-57-0
+ Aspergillus flavus, CAS32215-02-4
+ Aspergillus flavus, CAS52819-96-2
+ Aspergillus flavus, CAS61740-00-9
+ Aspergillus flavus, CAS70553-75-2
+ Aspergillus flavus, CAS74328-59-9
+ CAS641-38-3
+ Aspergillus variecolor, CAS60451-42-5
+ Aspergillus variecolor, CAS60451-43-6
+ Aspergillus variecolor, CAS72693-37-9
+ Aspergillus variecolor, CAS72676-00-7
+ Aspergillus variecolor, CAS79874-93-4
+ Aspergillus panamensis, CAS75916-46-0
+ Aspergillus flavipes, CAS63631-36-7
+ Aspergillus nidulans, CAS30387-51-0
+ Aspergillus microcysticus, CAS72363-48-5
+ Aspergillus microcysticus, CAS72363-47-4
+ Aspergillus micorcysticus, CAS72401-79-7
+ Aspergillus microcysticus, CAS71968-02-0
+ Aspergillus terreus, CAS67309-95-9
+ Aspergillus terreus, CAS55215-37-7
+ Aspergillus melleus, CAS17398-00-4
+ Aspergillus terreus, CAS75310-10-0
+ Aspergillus variecolor, CAS55778-98-8
+ Aspergillus variecolor, CAS78834-89-6
+ Aspergillus terreus, CAS86925-92-0
+ Aspergillus terreus, CAS577-64-0
+ Aspergillus terreus, CAS60924-75-6
+ Aspergillus terreus, CAS78723-14-5
+ Aspergillus terreus, CAS78723-15-6
+ Aspergillus terreus, CAS78723-16-7
+ Aspergillus terreus, CAS78708-35-7
+ Aspergillus terreus, CAS78708-36-8
+ Aspergillus terreus, CAS78708-37-9
+ Aspergillus terreus, CAS78723-17-8
+ Aspergillus terreus, CAS78723-18-9
+ Aspergillus terreus, CAS78708-38-0
+ Aspergillus terreus, CAS78723-19-0
+ Aspergillus chevalieri, CAS41451-81-4
+ Aspergillus niger, CAS61103-89-7
+ Aspergillus niger, CAS72040-27-8
+ Aspergillus multicolor, CAS14016-29-6
+ Aspergillus terreus, CAS87414-44-6
+ Aspergillus terreus, CAS87414-45-7
+ Aspergillus terreus, CAS271587-58-7
+ Aspergillus candidus, CAS81474-59-1
+ Aspergillus candidus, CAS81474-60-4
+ Aspergillus candidus, CAS267007-58-9
+ CAS50335-03-0
+ Aspergillus candidus, CAS23363-64-6
+ CAS42599-89-3
+ Aspergillus silvaticus, CAS114090-43-6
+ Aspergillus wentii, CAS616-02-4
+ Aspergillus carneus, CAS518-75-2
+ Aspergillus ruber, CAS68836-03-3
+ CAS109171-13-3
+ CAS109171-14-4
+ CAS109171-15-5
+ Aspergillus versicolor, CAS477-99-6
+ Aspergillus flavus, CAS18172-33-3
+ Aspergillus niger, CAS82893-35-4
+ Aspergillus versicolor, CAS61407-06-5
+ Aspergillus versicolor, CAS61407-05-4
+ Aspergillus terreus, CAS18818-30-9
+ Aspergillus flavus, CAS7241-98-7
+ Aspergillus chevalieri, CAS77102-91-1
+ Aspergillus carneus, CAS65718-85-6
+ Aspergillus terreus, CAS11029-16-6
+ Aspergillus terreus aureus, CAS2151-16-8
+ CAS17878-54-5
+ Aspergillus terreus, CAS77517-29-4
+ CAS6795-16-0
+ Aspergillus flavus, CAS76410-56-5
+ Aspergillus flavus, CAS64947-43-9
+ Aspergillus terreus, CAS87869-00-9
+ Aspergillus terreus, CAS518-82-1
+ Aspergillus sydowi, CAS68027-81-6
+ Aspergillus silvaticus, CAS31581-32-5
+ Aspergillus ruber, CAS523-73-9
+ CAS113706-21-1
+ Aspergillus fumigatus, CAS12626-18-5
+ Aspergillus fumigatus, CAS12626-17-4
+ Aspergillus terreus, CAS427-63-4
+ Aspergillus fumigatus, CAS67-99-2
+ Aspergillus panamensis, CAS65794-79-8
+ Aspergillus panamensis, CAS58801-71-1
+ Aspergillus panamensis, CAS65831-50-7
+ Aspergillus sydowi, CAS65967-72-8
+ Aspergillus ruber, CAS74886-31-0
+ Aspergillus wentii, CAS77282-68-9
+ Aspergillus wentii, CAS77282-74-7
+ Aspergillus ruber, CAS74886-32-1
+ Aspergillus fumigatus, CAS61897-83-4
+ Aspergillus candidus, CAS501-30-4
+ Aspergillus viride-nutans, CAS19504-77-9
+ CAS3022-92-2
+ CAS83680-20-0
+ CAS138875-32-8
+ CAS138797-31-6
+ CAS149596-54-3
+ CAS149596-55-4
+ CAS149596-56-5
+ Aspergillus niger, CAS59926-78-2
+ CAS108351-20-8
+ CAS24280-93-1
+ Aspergillus nidulans, CAS21259-20-1
+ Aspergillus flavipes, CAS4503-96-2
+ Aspergillus terreus, CAS15254-67-8
+ Aspergillus versicolor, CAS17811-38-0
+ CAS24779-38-2
+ Aspergillus fumigatus, CAS61897-84-5
+ Aspergillus parvulus, CAS56495-98-8
+ CAS24945-81-1
+ Aspergillus parasiticus, CAS17878-69-2
+ Aspergillus melleus, CAS480-33-1
+ Aspergillus terreus, CAS87414-49-1
+ Aspergillus niger, CAS69975-77-5
+ Aspergillus silvaticus, CAS77392-58-6
+ CAS23315-33-5
+ Aspergillus parvulus, CAS73027-01-7
+ Aspergillus flavus, CAS63722-91-8
+ Aspergillus melleus, CAS90-65-3
+ Aspergillus ustus, CAS74798-20-2
+ Aspergillus viride-nutans, CAS164415-86-5
+ Aspergillus silvaticus, CAS642-27-3
+ Aspergillus terreus, CAS3774-64-9
+ Aspergillus terreus aureus, CAS87686-82-6
+
+ Aspergillus carneus, CAS13277-76-4
+ Aspergillus variecolor, CAS53377-54-1
+ Aspergillus silvaticus, CAS73606-98-1
+ Aspergillus silvaticus, CAS17811-36-8
+ Aspergillus multicolor, CAS10048-13-2
+ Aspergillus terreus, CAS519-57-3
+ Aspergillus terreus aureus, CAS89367-84-0
+ Aspergillus sydowi,CAS65967-73-9
+ CAS77782-90-2
+ Aspergillus candidus, CAS52452-60-5
+ Aspergillus terreus, CAS121-40-4
+ Aspergillus terreus, CAS582-46-7
+ Aspergillus terreus, CAS18746-82-2
+ Aspergillus chevalieri, CAS40434-07-9
+ Aspergillus fumigatus, CAS61897-87-8
+ Aspergillus fumigatus, CAS61897-89-0
+ Aspergillus fumigatus, CAS61897-91-4
+ Aspergillus fumigatus, CAS61949-67-5
+ Aspergillus fumigatus, CAS66180-23-2
+ Aspergillus fumigatus, CAS66212-51-9
+ Aspergillus fumigatus, CAS69483-20-1
+ Aspergillus fumigatus, ACS69575-59-3
+ Aspergillus fumigatus, CAS60676-61-1
+ CAS88389-71-3
+ Aspergillus versicolor, CAS6807-96-1
+ Aspergillus multicolor, CAS16049-49-3
+ Aspergillus versicolor, CAS84062-31-7
+ Aspergillus parasiticus, CAS52021-61-1
+ Aspergillus parasiticus, CAS62886-00-4
+ Aspergillus parasiticus, CAS22268-13-9
+ Aspergillus parasiticus, CAS70979-72-5
+ Aspergillus versicolor, CAS59684-36-5
+ Aspergillus viride-nutans, CAS287102-33-4
+ Aspergillus viride-nutans, CAS117841-42-6
+ Aspergillus viride-nutans, CAS287102-35-6
+ Aspergillus candidus, CAS61391-08-0
+ Aspergillus candidus, CAS62002-87-3
+ Aspergillus candidus, CAS62002-86-2
+ Aspergillus candidus, CAS580-74-5
+ Aspergillus niger, CAS307304-24-1
+ Aspergillus niger, CAS307304-25-2
+ Aspergillus niger, CAS307304-26-3
+ Aspergillus niger, CAS307304-27-4
+ Aspergillus niger, CAS307304-28-5
+ Aspergillus variecolor, CAS72746-68-0
+ Aspergillus variecolor, CAS72746-69-1
+ Aspergillus melleus, CAS32885-83-9
+ Aspergillus aculeatus, CAS35287-69-5
+ Aspergillus aculeatus, CAS60687-07-2
+
+
+
+ CAS921928-12-3
+ CAS56072-96-9
+ CAS147317-12-2
+ CAS58814-86-1
+ CAS64763-82-2
+ CAS26048-05-5
+ CAS75947-02-3
+ CAS75899-64-8
+ CAS75947-01-2
+ CAS75947-00-1
+ CAS62995-91-9
+ CAS76265-41-3
+ CAS76265-42-4
+ CAS154491-56-2
+
+
+
+
+
+
+
+
+
+
+
+ CAS74149-38-5
+ CAS139959-75-4
+ CAS139959-76-5
+ CAS162808-62-0
+ CAS53342-16-8
+ CAS12663-46-6
+ CAS59865-13-3
+ CAS63775-95-1
+ CAS59787-61-0
+ CAS63775-96-2
+ CAS63798-73-2
+ CAS83574-28-1
+ CAS74436-00-3
+ CAS83602-39-5
+ CAS83563-93-3
+ CAS121604-28-2
+ CAS108027-38-9
+ CAS108027-39-0
+ CAS108044-39-9
+ CAS108027-40-3
+ CAS108044-40-2
+ CAS108027-41-4
+ CAS108027-42-5
+ CAS108066-10-0
+ CAS108027-43-6
+ CAS108027-44-7
+ CAS108027-45-8
+ CAS108027-46-9
+ CAS108044-41-3
+ CAS108027-47-0
+ CAS108027-48-1
+ CAS108027-49-2
+ CAS42002-26-6
+ CAS149437-28-5
+ CAS27482-48-0
+ CAS6686-70-0
+ CAS79386-03-1
+ CAS79386-02-0
+ CAS148440-84-0
+ CAS176391-30-3
+ CAS176391-31-4
+ CAS2503-26-6
+ CAS79386-01-9
+
+ CAS27482-49-1
+ CAS79385-99-2
+ CAS121723-07-7
+ CAS27482-50-4
+ CAS79385-98-1
+ CAS79385-97-0
+ CAS76689-14-0
+ CAS79385-96-9
+ CAS121740-98-5
+ CAS134316-37-3
+ CAS207342-10-7
+ CAS148440-85-1
+ CAS30845-05-7
+ CAS26912-16-3
+ CAS79814-65-6, CAS54651-05-07
+ CAS19893-23-3
+ CAS67-99-2
+ CAS83209-65-8
+ CAS110538-19-7
+ CAS235114-32-6
+ CAS108351-20-8
+ CAS133413-70-4
+ CAS64925-80-0
+ CAS1233083-92-5
+ CAS1233083-94-7
+ CAS1233083-97-0
+ CAS1233083-99-2
+ CAS1233084-00-8
+ CAS58523-30-1
+ CAS168972-17-6
+
+
+ CAS55466-29-0
+
+ CAS641630-37-7
+ CAS24181-12-2
+ CAS2900-38-1
+ CAS28540-82-1
+ CAS133155-89-2
+ CAS832150-38-6
+ CAS74758-64-8
+ CAS86402-37-1
+ CAS1260586-31-9
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/configs/config.xml mmass-4.0.0/configs/config.xml
--- mmass-3.12.1/configs/config.xml 2011-07-01 07:27:19.000000000 +0000
+++ mmass-4.0.0/configs/config.xml 2011-11-28 11:32:18.000000000 +0000
@@ -11,6 +11,7 @@
+
@@ -149,7 +150,7 @@
-
+
@@ -168,6 +169,9 @@
+
+
+
@@ -178,17 +182,14 @@
-
-
+
-
-
@@ -199,7 +200,6 @@
-
@@ -240,6 +240,14 @@
+
+
+
+
+
+
+
+
diff -Nru mmass-3.12.1/configs/monomers.xml mmass-4.0.0/configs/monomers.xml
--- mmass-3.12.1/configs/monomers.xml 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/configs/monomers.xml 2011-11-28 17:24:47.000000000 +0000
@@ -0,0 +1,536 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/configs/presets.xml mmass-4.0.0/configs/presets.xml
--- mmass-3.12.1/configs/presets.xml 2011-05-10 07:53:42.000000000 +0000
+++ mmass-4.0.0/configs/presets.xml 2011-11-29 12:31:56.000000000 +0000
@@ -33,14 +33,21 @@
-
+
-
+
+
+
+
+
+
+
+
@@ -74,9 +81,16 @@
-
+
+
+
+
+
+
+
+
@@ -110,9 +124,16 @@
-
+
+
+
+
+
+
+
+
@@ -121,7 +142,7 @@
-
+
@@ -146,9 +167,16 @@
-
+
+
+
+
+
+
+
+
@@ -182,9 +210,16 @@
-
+
+
+
+
+
+
+
+
@@ -218,9 +253,16 @@
-
+
+
+
+
+
+
+
+
@@ -230,10 +272,12 @@
-
+
-
-
+
+
+
+
diff -Nru mmass-3.12.1/configs/references.xml mmass-4.0.0/configs/references.xml
--- mmass-3.12.1/configs/references.xml 2011-02-18 14:55:16.000000000 +0000
+++ mmass-4.0.0/configs/references.xml 2011-11-28 17:10:05.000000000 +0000
@@ -1,31 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -137,151 +112,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -299,23 +130,29 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
-
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/debian/changelog mmass-4.0.0/debian/changelog
--- mmass-3.12.1/debian/changelog 2011-08-29 07:38:48.000000000 +0000
+++ mmass-4.0.0/debian/changelog 2011-12-07 21:23:08.000000000 +0000
@@ -1,3 +1,13 @@
+mmass (4.0.0-1) unstable; urgency=low
+
+ * New upstream release.
+
+ - Feature improvements. One of these was suggested by me: provide
+ automatically the charge of the ion that produced one isotopic peak
+ over which the space ruler is used.
+
+ -- Filippo Rusconi Wed, 07 Dec 2011 22:04:02 +0100
+
mmass (3.12.1-1) unstable; urgency=low
* New upstream release.
diff -Nru mmass-3.12.1/debian/rules mmass-4.0.0/debian/rules
--- mmass-3.12.1/debian/rules 2011-08-29 07:38:48.000000000 +0000
+++ mmass-4.0.0/debian/rules 2011-12-07 21:23:08.000000000 +0000
@@ -6,7 +6,7 @@
export DH_VERBOSE=1
PACKAGE=mmass
-VERSION="3.11.0"
+VERSION="4.0.0"
PYVERS=$(shell pyversions -r)
INSTALLDIR=$(CURDIR)/debian/$(PACKAGE)
diff -Nru mmass-3.12.1/gui/config.py mmass-4.0.0/gui/config.py
--- mmass-3.12.1/gui/config.py 2011-08-28 19:04:44.000000000 +0000
+++ mmass-4.0.0/gui/config.py 2011-12-01 12:00:53.000000000 +0000
@@ -25,7 +25,7 @@
# SET VERSION
# -----------
-version = '3.12.1'
+version = '4.0.0'
nightbuild = ''
@@ -84,6 +84,7 @@
'lastSeqDir': '',
'errorUnits': 'Da',
'printQuality': 5,
+ 'reverseScrolling': 0,
'macListCtrlGeneric': 1,
'peaklistColumns': ['mz', 'int', 'rel', 'sn', 'z', 'fwhm', 'resol'],
'donate': '',
@@ -223,7 +224,7 @@
'isotopeShift': 0.0,
'removeIsotopes': 1,
'removeUnknown': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
'setAsMonoisotopic': 0,
},
@@ -243,6 +244,9 @@
}
sequence={
+ 'editor':{
+ 'gridSize': 20,
+ },
'digest':{
'maxMods': 1,
'maxCharge': 1,
@@ -253,17 +257,22 @@
'highMass': 5000,
'retainPos': 0,
'allowMods': 0,
- 'listFormat': 'b.S.a [m]',
- 'matchFormat': '[r] b.S.a [m]',
+ 'listTemplateAmino': 'b.S.a [m]',
+ 'listTemplateCustom': 'b . [ S ] . a [m]',
+ 'matchTemplateAmino': 'h b.S.a [m]',
+ 'matchTemplateCustom': ' h b . [ S ] . a [m]',
},
'fragment':{
'maxMods': 1,
'maxCharge': 1,
'massType': 1,
'fragments': ['a','b','y','-NH3','-H2O'],
+ 'maxLosses': 2,
'filterFragments': 1,
- 'listFormat': 'b.S.a [m]',
- 'matchFormat': 'f [r] [m]',
+ 'listTemplateAmino': 'b.S.a [m]',
+ 'listTemplateCustom': 'b . [ S ] . a [m]',
+ 'matchTemplateAmino': 'f h [m]',
+ 'matchTemplateCustom': 'f h [m]',
},
'search':{
'mass': 0,
@@ -275,7 +284,8 @@
'tolerance': 0.2,
'units': 'Da',
'retainPos': 0,
- 'listFormat': 'b.S.a [m]',
+ 'listTemplateAmino': 'b.S.a [m]',
+ 'listTemplateCustom': 'b . [ S ] . a [m]',
},
}
@@ -323,6 +333,19 @@
'showFlipped': 0,
}
+envfit={
+ 'loss': 'H',
+ 'gain': 'H{2}',
+ 'fit': 'spectrum',
+ 'scaleMin': 0,
+ 'scaleMax': 10,
+ 'charge': 1,
+ 'fwhm': 0.01,
+ 'forceFwhm': 0,
+ 'autoAlign': 1,
+ 'relThreshold': 0.05,
+}
+
mascot={
'common':{
'title':'',
@@ -641,6 +664,10 @@
sequenceTags = document.getElementsByTagName('sequence')
if sequenceTags:
+ editorTags = sequenceTags[0].getElementsByTagName('editor')
+ if editorTags:
+ _getParams(editorTags[0], sequence['editor'])
+
digestTags = sequenceTags[0].getElementsByTagName('digest')
if digestTags:
_getParams(digestTags[0], sequence['digest'])
@@ -684,6 +711,11 @@
if generatorTags:
_getParams(generatorTags[0], generator)
+ # envelope fit
+ envfitTags = document.getElementsByTagName('envfit')
+ if envfitTags:
+ _getParams(envfitTags[0], envfit)
+
# mascot
mascotTags = document.getElementsByTagName('mascot')
if mascotTags:
@@ -770,6 +802,7 @@
buff += ' \n' % (main['documentsHeight'])
buff += ' \n' % (main['peaklistWidth'])
buff += ' \n' % (main['peaklistHeight'])
+ buff += ' \n' % (bool(main['reverseScrolling']))
buff += ' \n' % (bool(main['macListCtrlGeneric']))
buff += ' \n' % (';'.join(main['peaklistColumns']))
buff += ' \n' % (main['mzDigits'])
@@ -916,6 +949,9 @@
# sequence
buff += ' \n'
+ buff += ' \n'
+ buff += ' \n' % (sequence['editor']['gridSize'])
+ buff += ' \n'
buff += ' \n'
buff += ' \n' % (sequence['digest']['maxMods'])
buff += ' \n' % (sequence['digest']['maxCharge'])
@@ -926,17 +962,14 @@
buff += ' \n' % (sequence['digest']['highMass'])
buff += ' \n' % (bool(sequence['digest']['retainPos']))
buff += ' \n' % (bool(sequence['digest']['allowMods']))
- buff += ' \n' % (sequence['digest']['listFormat'])
- buff += ' \n' % (sequence['digest']['matchFormat'])
buff += ' \n'
buff += ' \n'
buff += ' \n' % (sequence['fragment']['maxMods'])
buff += ' \n' % (sequence['fragment']['maxCharge'])
buff += ' \n' % (sequence['fragment']['massType'])
buff += ' \n' % (';'.join(sequence['fragment']['fragments']))
+ buff += ' \n' % (sequence['fragment']['maxLosses'])
buff += ' \n' % (bool(sequence['fragment']['filterFragments']))
- buff += ' \n' % (sequence['fragment']['listFormat'])
- buff += ' \n' % (sequence['fragment']['matchFormat'])
buff += ' \n'
buff += ' \n'
buff += ' \n' % (sequence['search']['maxMods'])
@@ -947,7 +980,6 @@
buff += ' \n' % (sequence['search']['tolerance'])
buff += ' \n' % (sequence['search']['units'])
buff += ' \n' % (bool(sequence['search']['retainPos']))
- buff += ' \n' % (sequence['search']['listFormat'])
buff += ' \n'
buff += ' \n\n'
@@ -993,6 +1025,15 @@
buff += ' \n' % (bool(generator['showOverlay']))
buff += ' \n\n'
+ # envelope fit
+ buff += ' \n'
+ buff += ' \n' % (envfit['fit'])
+ buff += ' \n' % (envfit['fwhm'])
+ buff += ' \n' % (bool(envfit['forceFwhm']))
+ buff += ' \n' % (bool(envfit['autoAlign']))
+ buff += ' \n' % (envfit['relThreshold'])
+ buff += ' \n\n'
+
# mascot
buff += ' \n'
buff += ' \n'
diff -Nru mmass-3.12.1/gui/dlg_clipboard_editor.py mmass-4.0.0/gui/dlg_clipboard_editor.py
--- mmass-3.12.1/gui/dlg_clipboard_editor.py 2011-07-01 13:17:50.000000000 +0000
+++ mmass-4.0.0/gui/dlg_clipboard_editor.py 2011-10-17 11:58:02.000000000 +0000
@@ -56,10 +56,13 @@
"""Make GUI elements."""
# make elements
- self.data_value = wx.TextCtrl(self, -1, "Reading data...", size=(300,400), style=wx.TE_MULTILINE)
+ self.data_value = wx.TextCtrl(self, -1, "Reading data...", size=(250,300), style=wx.TE_MULTILINE)
self.data_value.Bind(wx.EVT_TEXT_ENTER, self.onOK)
self.data_value.SetFont(wx.SMALL_FONT)
+ note_label = wx.StaticText(self, -1, "Please edit your clipboard data to consist\nof m/z and intensity columns only.\nRemove all non-digit characters.", style=wx.ALIGN_CENTER)
+ note_label.SetFont(wx.SMALL_FONT)
+
cancel_butt = wx.Button(self, wx.ID_CANCEL, "Cancel")
ok_butt = wx.Button(self, wx.ID_OK, "Import")
ok_butt.Bind(wx.EVT_BUTTON, self.onOK)
@@ -71,6 +74,7 @@
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(self.data_value, 1, wx.EXPAND|wx.CENTER|wx.TOP|wx.LEFT|wx.RIGHT, mwx.PANEL_SPACE_MAIN)
+ mainSizer.Add(note_label, 0, wx.CENTER|wx.TOP|wx.LEFT|wx.RIGHT, mwx.PANEL_SPACE_MAIN)
mainSizer.Add(buttons, 0, wx.CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
return mainSizer
diff -Nru mmass-3.12.1/gui/dlg_compounds_editor.py mmass-4.0.0/gui/dlg_compounds_editor.py
--- mmass-3.12.1/gui/dlg_compounds_editor.py 2011-06-28 14:42:53.000000000 +0000
+++ mmass-4.0.0/gui/dlg_compounds_editor.py 2011-11-04 14:01:39.000000000 +0000
@@ -142,7 +142,7 @@
self.itemDescription_value = wx.TextCtrl(self, -1, "", size=(250, -1))
itemFormula_label = wx.StaticText(self, -1, "Formula:")
- self.itemFormula_value = wx.TextCtrl(self, -1, "", size=(250, -1))
+ self.itemFormula_value = mwx.formulaCtrl(self, -1, "", size=(250, -1))
self.itemFormula_value.Bind(wx.EVT_TEXT, self.onFormulaEdited)
itemMoMass_label = wx.StaticText(self, -1, "Mo. mass:")
@@ -212,7 +212,7 @@
# update item editor
self.itemName_value.SetValue(name)
self.itemDescription_value.SetValue(compound.description)
- self.itemFormula_value.SetValue(compound.rawFormula)
+ self.itemFormula_value.SetValue(compound.expression)
# ----
@@ -484,7 +484,7 @@
mass = compound.mass()
self.itemsMap.append((
name,
- compound.rawFormula,
+ compound.expression,
mass[0],
mass[1],
compound.description,
diff -Nru mmass-3.12.1/gui/dlg_enzymes_editor.py mmass-4.0.0/gui/dlg_enzymes_editor.py
--- mmass-3.12.1/gui/dlg_enzymes_editor.py 2011-06-28 14:42:53.000000000 +0000
+++ mmass-4.0.0/gui/dlg_enzymes_editor.py 2011-11-04 14:02:07.000000000 +0000
@@ -105,10 +105,10 @@
self.itemExpression_value = wx.TextCtrl(self, -1, "", size=(200, -1))
itemCTerm_label = wx.StaticText(self, -1, "C-term formula:")
- self.itemCTerm_value = wx.TextCtrl(self, -1, "", size=(200, -1))
+ self.itemCTerm_value = mwx.formulaCtrl(self, -1, "", size=(200, -1))
itemNTerm_label = wx.StaticText(self, -1, "N-term formula:")
- self.itemNTerm_value = wx.TextCtrl(self, -1, "", size=(200, -1))
+ self.itemNTerm_value = mwx.formulaCtrl(self, -1, "", size=(200, -1))
self.itemModsBefore_check = wx.CheckBox(self, -1, "Allow modification before cut")
@@ -307,14 +307,14 @@
# make enzyme
try:
expr = re.compile(expression)
- enzyme = mspy.enzyme( \
- name=name, \
- expression=expression, \
- cTermFormula=cTermFormula, \
- nTermFormula=nTermFormula, \
- modsBefore=modsBefore, \
- modsAfter=modsAfter \
- )
+ enzyme = mspy.enzyme(
+ name = name,
+ expression = expression,
+ cTermFormula = cTermFormula,
+ nTermFormula = nTermFormula,
+ modsBefore = modsBefore,
+ modsAfter = modsAfter
+ )
except:
wx.Bell()
return False
diff -Nru mmass-3.12.1/gui/dlg_modifications_editor.py mmass-4.0.0/gui/dlg_modifications_editor.py
--- mmass-3.12.1/gui/dlg_modifications_editor.py 2011-06-28 14:42:53.000000000 +0000
+++ mmass-4.0.0/gui/dlg_modifications_editor.py 2011-11-10 14:02:05.000000000 +0000
@@ -73,7 +73,7 @@
"""Make list for items."""
# init list
- self.itemsList = mwx.sortListCtrl(self, -1, size=(751, 250), style=mwx.LISTCTRL_STYLE_MULTI)
+ self.itemsList = mwx.sortListCtrl(self, -1, size=(771, 250), style=mwx.LISTCTRL_STYLE_MULTI)
self.itemsList.SetFont(wx.SMALL_FONT)
self.itemsList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
@@ -91,7 +91,7 @@
self.itemsList.InsertColumn(7, "description", wx.LIST_FORMAT_LEFT)
# set column widths
- for col, width in enumerate((110,100,60,80,80,100,50,150)):
+ for col, width in enumerate((110,100,60,90,90,100,50,150)):
self.itemsList.SetColumnWidth(col, width)
# ----
@@ -116,11 +116,11 @@
self.itemTermSpecifity_combo.SetValue('None')
itemGainFormula_label = wx.StaticText(self, -1, "Gain formula:")
- self.itemGainFormula_value = wx.TextCtrl(self, -1, "", size=(150, -1))
+ self.itemGainFormula_value = mwx.formulaCtrl(self, -1, "", size=(150, -1))
self.itemGainFormula_value.Bind(wx.EVT_TEXT, self.onFormulaEdited)
itemLossFormula_label = wx.StaticText(self, -1, "Loss formula:")
- self.itemLossFormula_value = wx.TextCtrl(self, -1, "", size=(150, -1))
+ self.itemLossFormula_value = mwx.formulaCtrl(self, -1, "", size=(150, -1))
self.itemLossFormula_value.Bind(wx.EVT_TEXT, self.onFormulaEdited)
itemMoMass_label = wx.StaticText(self, -1, "Mo. mass:")
@@ -382,13 +382,13 @@
# make compound
try:
- modification = mspy.modification( \
- name=name, \
- gainFormula=gainFormula, \
- lossFormula=lossFormula, \
- aminoSpecifity=aminoSpecifity, \
- termSpecifity=termSpecifity, \
- description=description \
+ modification = mspy.modification(
+ name = name,
+ gainFormula = gainFormula,
+ lossFormula = lossFormula,
+ aminoSpecifity = aminoSpecifity,
+ termSpecifity = termSpecifity,
+ description = description
)
except:
wx.Bell()
diff -Nru mmass-3.12.1/gui/dlg_monomers_editor.py mmass-4.0.0/gui/dlg_monomers_editor.py
--- mmass-3.12.1/gui/dlg_monomers_editor.py 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/gui/dlg_monomers_editor.py 2011-11-28 16:36:46.000000000 +0000
@@ -0,0 +1,473 @@
+# -------------------------------------------------------------------------
+# Copyright (C) 2005-2011 Martin Strohalm
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# Complete text of GNU GPL can be found in the file LICENSE.TXT in the
+# main directory of the program
+# -------------------------------------------------------------------------
+
+# load libs
+import re
+import wx
+
+# load modules
+import mwx
+import config
+import mspy
+
+
+# MONOMERS EDITOR
+# ---------------
+
+class dlgMonomersEditor(wx.Dialog):
+ """Edit monomers library."""
+
+ def __init__(self, parent):
+ wx.Dialog.__init__(self, parent, -1, "Monomers Library", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+
+ self.itemsMap = []
+
+ # make GUI
+ sizer = self.makeGUI()
+
+ # fit layout
+ self.Layout()
+ sizer.Fit(self)
+ self.SetSizer(sizer)
+ self.SetMinSize(self.GetSize())
+ self.Centre()
+
+ # get regular amino acids
+ self._aminoacids = []
+ for abbr in mspy.monomers:
+ if mspy.monomers[abbr].category == '_InternalAA':
+ self._aminoacids.append(abbr)
+
+ # get used monomers
+ self.used = parent.getUsedMonomers()
+
+ # show data
+ self.updateItemsList()
+ # ----
+
+
+ def makeGUI(self):
+ """Make GUI elements."""
+
+ # make GUI elements
+ self.makeItemsList()
+ editor = self.makeItemEditor()
+
+ # pack elements
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self.itemsList, 1, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, mwx.LISTCTRL_SPACE)
+ sizer.Add(editor, 0, wx.EXPAND|wx.CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
+
+ return sizer
+ # ----
+
+
+ def makeItemsList(self):
+ """Make list for items."""
+
+ # init list
+ self.itemsList = mwx.sortListCtrl(self, -1, size=(871, 250), style=mwx.LISTCTRL_STYLE_MULTI)
+ self.itemsList.SetFont(wx.SMALL_FONT)
+ self.itemsList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
+
+ # set events
+ self.itemsList.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
+
+ # make columns
+ self.itemsList.InsertColumn(0, "abbr.", wx.LIST_FORMAT_LEFT)
+ self.itemsList.InsertColumn(1, "name", wx.LIST_FORMAT_LEFT)
+ self.itemsList.InsertColumn(2, "category", wx.LIST_FORMAT_LEFT)
+ self.itemsList.InsertColumn(3, "formula", wx.LIST_FORMAT_LEFT)
+ self.itemsList.InsertColumn(4, "mo. mass", wx.LIST_FORMAT_RIGHT)
+ self.itemsList.InsertColumn(5, "av. mass", wx.LIST_FORMAT_RIGHT)
+ self.itemsList.InsertColumn(6, "losses", wx.LIST_FORMAT_LEFT)
+
+ # set column widths
+ for col, width in enumerate((110,180,90,110,90,90,180)):
+ self.itemsList.SetColumnWidth(col, width)
+ # ----
+
+
+ def makeItemEditor(self):
+ """Make items editor."""
+
+ mainSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""), wx.VERTICAL)
+
+ # make elements
+ itemSearch_label = wx.StaticText(self, -1, "Search:")
+ self.itemSearch_value = wx.TextCtrl(self, -1, "", size=(200, -1), style=wx.TE_PROCESS_ENTER)
+ self.itemSearch_value.Bind(wx.EVT_TEXT, self.onSearch)
+
+ itemAbbr_label = wx.StaticText(self, -1, "Abbr.:")
+ self.itemAbbr_value = wx.TextCtrl(self, -1, "", size=(200, -1))
+
+ itemName_label = wx.StaticText(self, -1, "Name:")
+ self.itemName_value = wx.TextCtrl(self, -1, "", size=(200, -1))
+
+ itemCategory_label = wx.StaticText(self, -1, "Category:")
+ self.itemCategory_value = wx.TextCtrl(self, -1, "", size=(200, -1))
+
+ itemFormula_label = wx.StaticText(self, -1, "Formula:")
+ self.itemFormula_value = mwx.formulaCtrl(self, -1, "", size=(150, -1))
+ self.itemFormula_value.Bind(wx.EVT_TEXT, self.onFormulaEdited)
+
+ itemMoMass_label = wx.StaticText(self, -1, "Mo. mass:")
+ self.itemMoMass_value = wx.TextCtrl(self, -1, "", size=(150, -1))
+ itemMoMass_label.Enable(False)
+ self.itemMoMass_value.Enable(False)
+
+ itemAvMass_label = wx.StaticText(self, -1, "Av. mass:")
+ self.itemAvMass_value = wx.TextCtrl(self, -1, "", size=(150, -1))
+ itemAvMass_label.Enable(False)
+ self.itemAvMass_value.Enable(False)
+
+ itemLossMoMass_label = wx.StaticText(self, -1, "Mo. loss mass:")
+ self.itemLossMoMass_value = wx.TextCtrl(self, -1, "", size=(150, -1))
+ itemLossMoMass_label.Enable(False)
+ self.itemLossMoMass_value.Enable(False)
+
+ itemLosses_label = wx.StaticText(self, -1, "Losses:")
+ self.itemLosses_values = []
+ for x in range(4):
+ item = mwx.formulaCtrl(self, -1, "", size=(100, -1))
+ item.Bind(wx.EVT_TEXT, self.onLossFormula)
+ item.Bind(wx.EVT_SET_FOCUS, self.onLossFormula)
+ item.Bind(wx.EVT_KILL_FOCUS, self.onLossFormula)
+ self.itemLosses_values.append(item)
+
+ # buttons
+ add_butt = wx.Button(self, -1, "Add", size=(80,-1))
+ add_butt.Bind(wx.EVT_BUTTON, self.onAddItem)
+
+ delete_butt = wx.Button(self, -1, "Delete", size=(80,-1))
+ delete_butt.Bind(wx.EVT_BUTTON, self.onDeleteItem)
+
+ # pack elements
+ grid = wx.GridBagSizer(mwx.GRIDBAG_VSPACE, mwx.GRIDBAG_HSPACE)
+
+ grid.Add(itemSearch_label, (0,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemSearch_value, (0,1), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemAbbr_label, (1,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemAbbr_value, (1,1), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemName_label, (2,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemName_value, (2,1), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemCategory_label, (3,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemCategory_value, (3,1), flag=wx.ALIGN_CENTER_VERTICAL)
+
+ grid.Add(itemFormula_label, (0,3), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemFormula_value, (0,4), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemMoMass_label, (1,3), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemMoMass_value, (1,4), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemAvMass_label, (2,3), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemAvMass_value, (2,4), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(itemLossMoMass_label, (3,3), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemLossMoMass_value, (3,4), flag=wx.ALIGN_CENTER_VERTICAL)
+
+ grid.Add(itemLosses_label, (0,6), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemLosses_values[0], (0,7), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemLosses_values[1], (1,7), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemLosses_values[2], (2,7), flag=wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.itemLosses_values[3], (3,7), flag=wx.ALIGN_CENTER_VERTICAL)
+
+ grid.Add(add_butt, (0,10), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(delete_butt, (1,10), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+
+ mainSizer.Add(grid, 0, wx.ALIGN_CENTER|wx.ALL, 10)
+
+ return mainSizer
+ # ----
+
+
+ def onItemSelected(self, evt):
+ """Update item editor with selected item."""
+
+ # get selected item
+ abbr = evt.GetText()
+ monomer = mspy.monomers[abbr]
+
+ # update item editor
+ self.itemAbbr_value.SetValue(abbr)
+ self.itemName_value.SetValue(monomer.name)
+ self.itemCategory_value.SetValue(monomer.category)
+ self.itemFormula_value.SetValue(monomer.formula)
+
+ for x in range(4):
+ self.itemLosses_values[x].SetValue('')
+ if x < len(monomer.losses):
+ self.itemLosses_values[x].SetValue(monomer.losses[x])
+ # ----
+
+
+ def onAddItem(self, evt):
+ """Add/replace item."""
+
+ # get item data
+ itemData = self.getItemData()
+ if not itemData:
+ return
+
+ # check regular amino acids
+ if itemData.abbr in self._aminoacids:
+ wx.Bell()
+ dlg = mwx.dlgMessage(self, title='Specified abbreviation is reserved!', message='Specified abbreviation is already used for regular amino acids\nwhich cannot be modified.')
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ # check name
+ if itemData.abbr in mspy.monomers:
+ wx.Bell()
+ title = 'Monomer with the same abbreviation already exists.\nDo you want to replace it?'
+ message = 'Old monomer definition will be lost.'
+ buttons = [(wx.ID_CANCEL, "Cancel", 80, False, 15), (wx.ID_OK, "Replace", 80, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ if dlg.ShowModal() != wx.ID_OK:
+ dlg.Destroy()
+ return
+ else:
+ dlg.Destroy()
+
+ # add/replace item
+ mspy.monomers[itemData.abbr] = itemData
+
+ # update gui
+ self.updateItemsList()
+ self.clearEditor()
+ # ----
+
+
+ def onDeleteItem(self, evt):
+ """Remove selected items."""
+
+ # delete?
+ title = 'Do you really want to delete selected monomers?'
+ message = 'Monomer definitions will be lost.'
+ buttons = [(wx.ID_CANCEL, "Cancel", 80, False, 15), (wx.ID_OK, "Delete", 80, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ if dlg.ShowModal() != wx.ID_OK:
+ dlg.Destroy()
+ return
+ else:
+ dlg.Destroy()
+
+ # delete items
+ for i in self.itemsList.getSelected():
+ index = self.itemsList.GetItemData(i)
+ name = self.itemsMap[index][0]
+ if not name in self.used:
+ del mspy.monomers[name]
+ else:
+ wx.Bell()
+ dlg = mwx.dlgMessage(self, title='Monomer "'+name+'" is currently used\nand cannot be removed.', message='Remove the monomer from all of your documents first.')
+ dlg.ShowModal()
+ dlg.Destroy()
+
+ # update gui
+ self.updateItemsList()
+ self.clearEditor()
+ # ----
+
+
+ def onSearch(self, evt):
+ """Search monomers library."""
+
+ # clear editor
+ self.clearEditor()
+
+ # update list
+ self.updateItemsList()
+ # ----
+
+
+ def onFormulaEdited(self, evt):
+ """Update formula mass while editing."""
+ evt.Skip()
+ wx.CallAfter(self.updateFormulaMass)
+ # ----
+
+
+ def onLossFormula(self, evt):
+ """Update loss formula mass while editing."""
+ evt.Skip()
+ wx.CallAfter(self.updateLossFormulaMass)
+ # ----
+
+
+ def updateItemsMap(self):
+ """Update items map."""
+
+ self.itemsMap = []
+
+ # get search
+ search = self.itemSearch_value.GetValue().lower().split()
+
+ # make map
+ for abbr, monomer in sorted(mspy.monomers.items()):
+
+ # skip regular amino acids
+ if monomer.category == '_InternalAA':
+ continue
+
+ # skip by search filter
+ if search and not (
+ all(map(lambda x: x in monomer.abbr.lower(), search)) or
+ all(map(lambda x: x in monomer.name.lower(), search))
+ ):
+ continue
+
+ # append monomer
+ self.itemsMap.append((
+ abbr,
+ monomer.name,
+ monomer.category,
+ monomer.formula,
+ monomer.mass[0],
+ monomer.mass[1],
+ ', '.join(monomer.losses),
+ ))
+ # ----
+
+
+ def updateItemsList(self):
+ """Update items list."""
+
+ # clear previous data and set new
+ self.updateItemsMap()
+ self.itemsList.DeleteAllItems()
+ self.itemsList.setDataMap(self.itemsMap)
+
+ # check data
+ if not self.itemsMap:
+ return
+
+ # add new data
+ digits = '%0.' + `config.main['mzDigits']` + 'f'
+ for row, item in enumerate(self.itemsMap):
+
+ # format data
+ moMass = digits % (item[4])
+ avMass = digits % (item[5])
+
+ # add data
+ self.itemsList.InsertStringItem(row, item[0])
+ self.itemsList.SetStringItem(row, 1, item[1])
+ self.itemsList.SetStringItem(row, 2, item[2])
+ self.itemsList.SetStringItem(row, 3, item[3])
+ self.itemsList.SetStringItem(row, 4, str(moMass))
+ self.itemsList.SetStringItem(row, 5, str(avMass))
+ self.itemsList.SetStringItem(row, 6, item[6])
+ self.itemsList.SetItemData(row, row)
+
+ # sort
+ self.itemsList.sort()
+ # ----
+
+
+ def updateFormulaMass(self):
+ """Update formula mass."""
+
+ # get formula
+ formula = self.itemFormula_value.GetValue()
+
+ # show formula masses
+ try:
+ formula = mspy.compound(formula)
+ mass = formula.mass()
+ self.itemMoMass_value.SetValue(str(mass[0]))
+ self.itemAvMass_value.SetValue(str(mass[1]))
+ except:
+ self.itemMoMass_value.SetValue('')
+ self.itemAvMass_value.SetValue('')
+ # ----
+
+
+ def updateLossFormulaMass(self):
+ """Update loss formula mass."""
+
+ # erase old value
+ self.itemLossMoMass_value.SetValue('')
+
+ # get current item
+ focus = self.FindFocus()
+ for x in range(4):
+ item = self.itemLosses_values[x]
+
+ # found focused item
+ if item is focus:
+ try:
+ formula = item.GetValue()
+ formula = mspy.compound(formula)
+ mass = formula.mass()
+ self.itemLossMoMass_value.SetValue(str(mass[0]))
+ except:
+ pass
+ # ----
+
+
+ def clearEditor(self):
+ """Clear item editor."""
+
+ # update editor
+ self.itemAbbr_value.SetValue('')
+ self.itemName_value.SetValue('')
+ self.itemCategory_value.SetValue('')
+ self.itemFormula_value.SetValue('')
+ self.itemMoMass_value.SetValue('')
+ self.itemAvMass_value.SetValue('')
+
+ for x in range(4):
+ self.itemLosses_values[x].SetValue('')
+ # ----
+
+
+ def getItemData(self):
+ """Get formated item data."""
+
+ # get data
+ abbr = self.itemAbbr_value.GetValue()
+ name = self.itemName_value.GetValue()
+ category = self.itemCategory_value.GetValue()
+ formula = self.itemFormula_value.GetValue()
+
+ losses = []
+ for item in self.itemLosses_values:
+ if item.GetValue():
+ losses.append(item.GetValue())
+
+ # check values
+ if not abbr or not formula or not re.match('^[A-Za-z0-9\-_]*$', abbr):
+ wx.Bell()
+ return False
+
+ # make monomer
+ try:
+ monomer = mspy.monomer(
+ abbr = abbr,
+ name = name,
+ formula = formula,
+ losses = losses,
+ category = category
+ )
+ except:
+ wx.Bell()
+ return False
+
+ return monomer
+ # ----
+
+
+
diff -Nru mmass-3.12.1/gui/dlg_notation.py mmass-4.0.0/gui/dlg_notation.py
--- mmass-3.12.1/gui/dlg_notation.py 2011-04-17 20:23:29.000000000 +0000
+++ mmass-4.0.0/gui/dlg_notation.py 2011-11-10 14:20:50.000000000 +0000
@@ -67,7 +67,7 @@
self.label_value.Bind(wx.EVT_TEXT_ENTER, self.onOK)
formula_label = wx.StaticText(self, -1, "Formula:", style=wx.ALIGN_RIGHT)
- self.formula_value = wx.TextCtrl(self, -1, '', size=(300,-1), style=wx.TE_PROCESS_ENTER)
+ self.formula_value = mwx.formulaCtrl(self, -1, '', size=(300,-1), style=wx.TE_PROCESS_ENTER)
self.formula_value.Bind(wx.EVT_TEXT, self.onFormula)
self.formula_value.Bind(wx.EVT_TEXT_ENTER, self.onOK)
@@ -241,6 +241,9 @@
def onFormula(self, evt=None):
"""Check formula and calculate m/z."""
+ if evt != None:
+ evt.Skip()
+
# user-defined m/z
if self.mzByUser_radio.GetValue():
return
diff -Nru mmass-3.12.1/gui/dlg_preferences.py mmass-4.0.0/gui/dlg_preferences.py
--- mmass-3.12.1/gui/dlg_preferences.py 2011-04-14 18:08:00.000000000 +0000
+++ mmass-4.0.0/gui/dlg_preferences.py 2011-11-30 16:13:36.000000000 +0000
@@ -54,9 +54,9 @@
self.notebook = wx.Notebook(self, -1)
# add pages
- self.notebook.AddPage(self.makeUpdatesPage(), 'Software Updates')
if wx.Platform == '__WXMSW__':
self.notebook.AddPage(self.makeCompassPanel(), 'CompassXport')
+ self.notebook.AddPage(self.makeUpdatesPage(), 'Software Updates')
# pack elements
mainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -149,7 +149,7 @@
def onUpdateNow(self, evt):
"""Check for available updates now."""
- self.parent.onUpdate()
+ self.parent.onHelpUpdate()
# ----
diff -Nru mmass-3.12.1/gui/dlg_select_scans.py mmass-4.0.0/gui/dlg_select_scans.py
--- mmass-3.12.1/gui/dlg_select_scans.py 2011-05-02 09:16:27.000000000 +0000
+++ mmass-4.0.0/gui/dlg_select_scans.py 2011-11-25 13:42:21.000000000 +0000
@@ -147,6 +147,7 @@
self.chromCanvas.setProperties(autoScaleY=True)
self.chromCanvas.setProperties(xPosDigits=2)
self.chromCanvas.setProperties(yPosDigits=2)
+ self.chromCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.chromCanvas.setProperties(reverseDrawing=True)
self.chromCanvas.setMFunction('cross')
diff -Nru mmass-3.12.1/gui/doc.py mmass-4.0.0/gui/doc.py
--- mmass-3.12.1/gui/doc.py 2011-06-29 11:30:44.000000000 +0000
+++ mmass-4.0.0/gui/doc.py 2011-11-16 14:32:15.000000000 +0000
@@ -184,7 +184,7 @@
"""Make mSD XML."""
buff = '\n'
- buff += '\n\n'
+ buff += '\n\n'
# format description
buff += ' \n'
@@ -223,80 +223,99 @@
buff += ' \n\n'
# format peaklist
- buff += ' \n'
- for peak in self.spectrum.peaklist:
- attributes = 'mz="%.6f" intensity="%.6f" baseline="%.6f"' % (peak.mz, peak.ai, peak.base)
- if peak.sn != None:
- attributes += ' sn="%.3f"' % peak.sn
- if peak.charge != None:
- attributes += ' charge="%d"' % peak.charge
- if peak.isotope != None:
- attributes += ' isotope="%d"' % peak.isotope
- if peak.fwhm != None:
- attributes += ' fwhm="%.6f"' % peak.fwhm
- if peak.group:
- attributes += ' group="%s"' % self._escape(peak.group)
- buff += ' \n' % attributes
- buff += ' \n\n'
+ if len(self.spectrum.peaklist):
+ buff += ' \n'
+ for peak in self.spectrum.peaklist:
+ attributes = 'mz="%.6f" intensity="%.6f" baseline="%.6f"' % (peak.mz, peak.ai, peak.base)
+ if peak.sn != None:
+ attributes += ' sn="%.3f"' % peak.sn
+ if peak.charge != None:
+ attributes += ' charge="%d"' % peak.charge
+ if peak.isotope != None:
+ attributes += ' isotope="%d"' % peak.isotope
+ if peak.fwhm != None:
+ attributes += ' fwhm="%.6f"' % peak.fwhm
+ if peak.group:
+ attributes += ' group="%s"' % self._escape(peak.group)
+ buff += ' \n' % attributes
+ buff += ' \n\n'
# format annotations
- buff += ' \n'
- for annot in self.annotations:
- attributes = 'peakMZ="%.6f" peakIntensity="%.6f" peakBaseline="%.6f"' % (annot.mz, annot.ai, annot.base)
- if annot.charge != None:
- attributes += ' charge="%d"' % annot.charge
- if annot.radical:
- attributes += ' radical="1"'
- if annot.theoretical != None:
- attributes += ' calcMZ="%.6f"' % annot.theoretical
- if annot.formula != None:
- attributes += ' formula="%s"' % annot.formula
- buff += ' %s\n' % (attributes, self._escape(annot.label))
- buff += ' \n\n'
+ if len(self.annotations):
+ buff += ' \n'
+ for annot in self.annotations:
+ attributes = 'peakMZ="%.6f" peakIntensity="%.6f" peakBaseline="%.6f"' % (annot.mz, annot.ai, annot.base)
+ if annot.charge != None:
+ attributes += ' charge="%d"' % annot.charge
+ if annot.radical:
+ attributes += ' radical="1"'
+ if annot.theoretical != None:
+ attributes += ' calcMZ="%.6f"' % annot.theoretical
+ if annot.formula != None:
+ attributes += ' formula="%s"' % annot.formula
+ buff += ' %s\n' % (attributes, self._escape(annot.label))
+ buff += ' \n\n'
# format sequences
- buff += ' \n\n'
- for index, sequence in enumerate(self.sequences):
- attributes = 'index="%d"' % index
- buff += ' \n' % attributes
- buff += ' %s\n' % self._escape(sequence.title)
- buff += ' %s\n' % self._escape(sequence.accession)
- buff += ' %s\n' % sequence.format('S')
-
- # format modifications
- buff += ' \n'
- for mod in sequence.modifications:
- gainFormula = mspy.modifications[mod[0]].gainFormula
- lossFormula = mspy.modifications[mod[0]].lossFormula
- modtype = 'fixed'
- if mod[2] == 'v':
- modtype = 'variable'
- buff += ' \n' % (mod[0], mod[1], modtype, gainFormula, lossFormula)
- buff += ' \n'
-
- # format matches
- buff += ' \n'
- for match in sequence.matches:
- attributes = 'peakMZ="%.6f" peakIntensity="%.6f" peakBaseline="%.6f"' % (match.mz, match.ai, match.base)
- if match.charge != None:
- attributes += ' charge="%d"' % match.charge
- if match.radical:
- attributes += ' radical="1"'
- if match.theoretical != None:
- attributes += ' calcMZ="%.6f"' % match.theoretical
- if match.formula != None:
- attributes += ' formula="%s"' % match.formula
- if match.sequenceRange != None:
- attributes += ' sequenceRange="%d-%d"' % tuple(match.sequenceRange)
- if match.fragmentSerie != None:
- attributes += ' fragmentSerie="%s"' % match.fragmentSerie
- if match.fragmentIndex != None:
- attributes += ' fragmentIndex="%s"' % match.fragmentIndex
- buff += ' %s\n' % (attributes, self._escape(match.label))
- buff += ' \n'
-
- buff += ' \n\n'
- buff += ' \n\n'
+ if len(self.sequences):
+ buff += ' \n\n'
+ for index, sequence in enumerate(self.sequences):
+ buff += ' \n' % index
+ buff += ' %s\n' % self._escape(sequence.title)
+ buff += ' %s\n' % self._escape(sequence.accession)
+
+ attributes = 'type="%s"' % sequence.chainType
+ if sequence.cyclic:
+ attributes += ' cyclic="1"'
+ buff += ' %s\n' % (attributes, sequence.format('S'))
+
+ # save monomers for custom sequences
+ if sequence.chainType != 'aminoacids':
+ buff += ' \n'
+ savedMonomers = []
+ for abbr in sequence.chain:
+ if not abbr in savedMonomers:
+ savedMonomers.append(abbr)
+ formula = mspy.monomers[abbr].formula
+ buff += ' \n' % (abbr, formula)
+ buff += ' \n'
+
+ # format modifications
+ if len(sequence.modifications):
+ buff += ' \n'
+ for mod in sequence.modifications:
+ gainFormula = mspy.modifications[mod[0]].gainFormula
+ lossFormula = mspy.modifications[mod[0]].lossFormula
+ modtype = 'fixed'
+ if mod[2] == 'v':
+ modtype = 'variable'
+ buff += ' \n' % (mod[0], mod[1], modtype, gainFormula, lossFormula)
+ buff += ' \n'
+
+ # format matches
+ if len(sequence.matches):
+ buff += ' \n'
+ for match in sequence.matches:
+ attributes = 'peakMZ="%.6f" peakIntensity="%.6f" peakBaseline="%.6f"' % (match.mz, match.ai, match.base)
+ if match.charge != None:
+ attributes += ' charge="%d"' % match.charge
+ if match.radical:
+ attributes += ' radical="1"'
+ if match.theoretical != None:
+ attributes += ' calcMZ="%.6f"' % match.theoretical
+ if match.formula != None:
+ attributes += ' formula="%s"' % match.formula
+ if match.sequenceRange != None:
+ attributes += ' sequenceRange="%d-%d"' % tuple(match.sequenceRange)
+ if match.fragmentSerie != None:
+ attributes += ' fragmentSerie="%s"' % match.fragmentSerie
+ if match.fragmentIndex != None:
+ attributes += ' fragmentIndex="%s"' % match.fragmentIndex
+ buff += ' %s\n' % (attributes, self._escape(match.label))
+ buff += ' \n'
+
+ buff += ' \n\n'
+ buff += ' \n\n'
buff += '\n'
@@ -375,8 +394,9 @@
buff += ' δ (Da) | \n'
buff += ' δ (ppm) | \n'
buff += ' Rel. Int. (%) | \n'
- buff += ' Annotation | \n'
- buff += ' Formula | \n'
+ buff += ' z | \n'
+ buff += ' Annotation | \n'
+ buff += ' Formula | \n'
buff += ' \n'
buff += ' \n'
buff += ' \n' % tableID
@@ -384,6 +404,7 @@
mz = mzFormat % annot.mz
relIntensity = ''
theoretical = ''
+ charge = ''
deltaDa = ''
deltaPpm = ''
formula = ''
@@ -397,8 +418,12 @@
deltaPpm = ppmFormat % annot.delta('ppm')
if annot.formula:
formula = annot.formula
+ if annot.charge:
+ charge = annot.charge
+ if annot.radical:
+ charge = str(annot.charge) + ' •'
- buff += ' %s | %s | %s | %s | %s | %s | %s |
\n' % (mz, theoretical, deltaDa, deltaPpm, relIntensity, label, formula)
+ buff += ' %s | %s | %s | %s | %s | %s | %s | %s |
\n' % (mz, theoretical, deltaDa, deltaPpm, relIntensity, charge, label, formula)
buff += ' \n'
buff += ' \n'
@@ -411,8 +436,13 @@
avMass = mzFormat % mass[1]
chain = self._formatSequence(sequence)
coverage = self._getSequenceCoverage(sequence)
+ matchedInt = self._getMatchedIntensity(self.spectrum.peaklist, sequence.matches)
tableID = 'tableSequenceMatches%d' % x
+ cyclic = ''
+ if sequence.cyclic:
+ cyclic = ' (Cyclic)'
+
if accession:
buff += ' Sequence - %s - [%s]
\n' % (sequence.title, accession)
else:
@@ -420,11 +450,11 @@
buff += ' \n'
buff += ' \n'
- buff += ' Accession | Aminoacids | Mo. Mass | Av. Mass | Coverage |
\n'
+ buff += ' Accession | Length | Mo. Mass | Av. Mass | Coverage | Matched Int. |
\n'
buff += ' \n'
buff += ' \n'
- buff += ' %s | %s | %s | %s | %s |
\n' % (accession, len(sequence), moMass, avMass, coverage)
- buff += ' %s |
\n' % chain
+ buff += ' %s | %s%s | %s | %s | %s | %s |
\n' % (accession, len(sequence), cyclic, moMass, avMass, coverage, matchedInt)
+ buff += ' %s |
\n' % chain
buff += ' \n'
buff += '
\n'
@@ -448,8 +478,9 @@
buff += ' δ (Da) | \n'
buff += ' δ (ppm) | \n'
buff += ' Rel. Int. (%) | \n'
- buff += ' Annotation | \n'
- buff += ' Formula | \n'
+ buff += ' z | \n'
+ buff += ' Annotation | \n'
+ buff += ' Formula | \n'
buff += ' \n'
buff += ' \n'
buff += ' \n' % tableID
@@ -457,6 +488,7 @@
mz = mzFormat % m.mz
relIntensity = ''
theoretical = ''
+ charge = ''
deltaDa = ''
deltaPpm = ''
formula = ''
@@ -469,8 +501,12 @@
deltaPpm = ppmFormat % m.delta('ppm')
if m.formula:
formula = m.formula
+ if m.charge:
+ charge = m.charge
+ if m.radical:
+ charge = str(m.charge) + ' •'
- buff += ' %s | %s | %s | %s | %s | %s | %s |
\n' % (mz, theoretical, deltaDa, deltaPpm, relIntensity, m.label, formula)
+ buff += ' %s | %s | %s | %s | %s | %s | %s | %s |
\n' % (mz, theoretical, deltaDa, deltaPpm, relIntensity, charge, m.label, formula)
buff += ' \n'
buff += ' \n'
@@ -536,19 +572,22 @@
# format sequence
buff = ''
- for x, amino in enumerate(sequence):
+ for x, monomer in enumerate(sequence):
attributes = ''
if sequence.ismodified(x, True):
attributes += 'modified '
if coverage[x]:
attributes += 'matched '
+
if attributes:
- buff += '%s' % (attributes, amino)
+ buff += '%s' % (attributes, monomer)
else:
- buff += amino
+ buff += monomer
- if not (x+1) % 10:
+ if sequence.chainType != 'aminoacids' and (x+1) != len(sequence):
+ buff += ' | '
+ elif not (x+1) % 10:
buff += ' '
return buff
@@ -611,6 +650,34 @@
# ----
+ def _getMatchedIntensity(self, peaklist, matches):
+ """Get total matched intensity."""
+
+ # get total intensity
+ totalInt = 0
+ buff = {}
+ for peak in peaklist:
+ totalInt += peak.intensity
+ buff[round(peak.mz, 6)] = peak.intensity
+
+ # get matched intensity
+ matchedInt = 0
+ for item in matches:
+ mz = round(item.mz, 6)
+ if mz in buff:
+ matchedInt += buff[mz]
+ del buff[mz]
+
+ # get percentage
+ matched = '0.0'
+ if totalInt:
+ matched = '%.1f' % (100*matchedInt/totalInt)
+ matched += ' %'
+
+ return matched
+ # ----
+
+
def _replaceLabelIDs(self, section, label):
"""Replace IDs with links in annotations."""
@@ -709,6 +776,7 @@
def __init__(self, path):
self.path = path
+ self.errors = []
self._version = None
self._parsedData = None
@@ -722,6 +790,8 @@
def getDocument(self):
"""Get document."""
+ self.errors = []
+
# parse data
if not self._parsedData:
try:
@@ -752,6 +822,8 @@
def getSequences(self):
"""Get list of available sequences."""
+ self.errors = []
+
# parse data
if not self._parsedData:
try:
@@ -955,6 +1027,7 @@
group = peakTag.getAttribute('group')
except ValueError:
+ self.errors.append('Incorrect peak data.')
continue
# make peak
@@ -1005,6 +1078,7 @@
annot = annotation(label=label, mz=mz, ai=ai, base=base, charge=charge, radical=radical, theoretical=theoretical, formula=formula)
except ValueError:
+ self.errors.append('Incorrect annotation data.')
continue
# append annotation
@@ -1044,17 +1118,34 @@
if accessionTags:
accession = self._getNodeText(accessionTags[0])
- # get sequence
+ # get chain
chain = ''
+ chainType = 'aminoacids'
+ cyclic = False
seqTags = sequenceTag.getElementsByTagName('seq')
if seqTags:
chain = self._getNodeText(seqTags[0])
+
+ if seqTags[0].hasAttribute('type'):
+ chainType = str(seqTags[0].getAttribute('type'))
+ if seqTags[0].hasAttribute('cyclic'):
+ try: cyclic = bool(int(seqTags[0].getAttribute('cyclic')))
+ except ValueError: pass
+
+ # get monomers
+ monomerTags = sequenceTag.getElementsByTagName('monomer')
+ for monomerTag in monomerTags:
+ abbr = monomerTag.getAttribute('abbr')
+ formula = monomerTag.getAttribute('formula')
+ if not abbr in mspy.monomers:
+ self._addMonomer(abbr, formula)
# make sequence
try:
- sequence = mspy.sequence(chain, title=title, accession=accession)
+ sequence = mspy.sequence(chain, title=title, accession=accession, chainType=chainType, cyclic=cyclic)
sequence.matches = []
except:
+ self.errors.append('Unknown monomers in sequence data.')
return False
# get modifications
@@ -1080,6 +1171,16 @@
sequence.modify(name, position, modtype)
# get matches
+ sequence.matches[:] = self.handleSequenceMatches(sequenceTag)
+
+ return sequence
+ # ----
+
+
+ def handleSequenceMatches(self, sequenceTag):
+ """Get sequence amtches."""
+
+ # get matches
matches = []
matchTags = sequenceTag.getElementsByTagName('match')
for matchTag in matchTags:
@@ -1121,12 +1222,13 @@
m.fragmentSerie = fragmentSerie
m.fragmentIndex = fragmentIndex
- sequence.matches.append(m)
+ matches.append(m)
except ValueError:
+ self.errors.append('Incorrect sequence match data.')
continue
- return sequence
+ return matches
# ----
@@ -1152,6 +1254,7 @@
ai = float(peakTag.getAttribute('intens'))
annot = peakTag.getAttribute('annots')
except ValueError:
+ self.errors.append('Incorrect peak data.')
continue
# make peak
@@ -1202,6 +1305,7 @@
sequence = mspy.sequence(chain, title=title)
sequence.matches = []
except:
+ self.errors.append('Unknown monomers in sequence data.')
return False
# get modifications
@@ -1251,6 +1355,7 @@
return data
except:
+ self.errors.append('Incorrect spectrum data.')
return False
# ----
@@ -1289,28 +1394,39 @@
# ----
- def _addModification(self, name, gainFormula, lossFormula):
- """Add modification to the library."""
+ def _addMonomer(self, abbr, formula, losses=[], name='', category=''):
+ """Add monomer to library."""
- # check name
- if not name or name in mspy.modifications:
+ # check data
+ if not abbr or not formula or not re.match('^[A-Za-z0-9\-_]*$', abbr):
return False
- # check gain and loss
- if not gainFormula and not lossFormula:
- return False
+ # add new monomer
try:
- formula = mspy.compound(gainFormula)
- formula = mspy.compound(lossFormula)
+ monomer = mspy.monomer(abbr=abbr, formula=formula, losses=losses, name=name, category=category)
+ mspy.monomers[abbr] = monomer
+ mspy.saveMonomers(os.path.join(config.confdir,'monomers.xml'))
+ return True
except:
return False
+ # ----
+
+
+ def _addModification(self, name, gainFormula, lossFormula, aminoSpecifity=''):
+ """Add modification to library."""
- # make modification
- modification = mspy.modification(name=name, gainFormula=gainFormula, lossFormula=lossFormula, aminoSpecifity='ACDEFGHIKLMNPQRSTVWY')
- mspy.modifications[name] = modification
- mspy.saveModifications()
+ # check data
+ if not name or not (gainFormula or lossFormula):
+ return False
- return True
+ # add new modification
+ try:
+ modification = mspy.modification(name=name, gainFormula=gainFormula, lossFormula=lossFormula, aminoSpecifity=aminoSpecifity)
+ mspy.modifications[name] = modification
+ mspy.saveModifications(os.path.join(config.confdir,'modifications.xml'))
+ return True
+ except:
+ return False
# ----
@@ -1343,8 +1459,10 @@
#tableMainInfo td{text-align: left;}
#spectrum{text-align: center;}
#footer{font-size: .8em; font-style: italic; text-align: center; color: #aaa; margin: 2em 0 1em 0; padding-top: 0.5em; border-top: 1px solid #000;}
- .nowrap{white-space:nowrap;}
+ .left{text-align: left;}
.right{text-align: right;}
+ .center{text-align: center;}
+ .nowrap{white-space:nowrap;}
.sequence{font-size: 1.1em; font-family: monospace;}
.modified{color: #f00; font-weight: bold;}
.matched{text-decoration: underline;}
diff -Nru mmass-3.12.1/gui/ids.py mmass-4.0.0/gui/ids.py
--- mmass-3.12.1/gui/ids.py 2011-07-01 12:23:55.000000000 +0000
+++ mmass-4.0.0/gui/ids.py 2011-11-30 15:15:29.000000000 +0000
@@ -38,6 +38,7 @@
ID_documentCloseAll = wx.NewId()
ID_documentSave = wx.NewId()
ID_documentSaveAs = wx.NewId()
+ID_documentSaveAll = wx.NewId()
ID_documentExport = wx.NewId()
ID_documentInfo = wx.NewId()
ID_documentPrintSpectrum = wx.NewId()
@@ -49,7 +50,8 @@
ID_documentColour = wx.NewId()
ID_documentAnnotationEdit = wx.NewId()
ID_documentAnnotationDelete = wx.NewId()
-ID_documentAnnotationPattern = wx.NewId()
+ID_documentAnnotationSendToMassCalculator = wx.NewId()
+ID_documentAnnotationSendToEnvelopeFit = wx.NewId()
ID_documentAnnotationsDelete = wx.NewId()
ID_documentAnnotationsCalibrateBy = wx.NewId()
ID_documentNotationsDelete = wx.NewId()
@@ -73,6 +75,7 @@
HK_documentCloseAll = '\tShift+Ctrl+W'
HK_documentSave = '\tCtrl+S'
HK_documentSaveAs = '\tShift+Ctrl+S'
+HK_documentSaveAll = '\tAlt+Ctrl+S'
HK_documentExport = '\tCtrl+E'
HK_documentInfo = '\tCtrl+I'
HK_documentPrintSpectrum = '\tCtrl+P'
@@ -153,11 +156,14 @@
ID_sequenceDigest = wx.NewId()
ID_sequenceFragment = wx.NewId()
ID_sequenceSearch = wx.NewId()
+ID_sequenceSendToMassCalculator = wx.NewId()
+ID_sequenceSendToEnvelopeFit = wx.NewId()
ID_sequenceDelete = wx.NewId()
ID_sequenceSort = wx.NewId()
ID_sequenceMatchEdit = wx.NewId()
ID_sequenceMatchDelete = wx.NewId()
-ID_sequenceMatchPattern = wx.NewId()
+ID_sequenceMatchSendToMassCalculator = wx.NewId()
+ID_sequenceMatchSendToEnvelopeFit = wx.NewId()
ID_sequenceMatchesDelete = wx.NewId()
ID_sequenceMatchesCalibrateBy = wx.NewId()
@@ -172,12 +178,13 @@
ID_toolsMeasure = wx.NewId()
ID_toolsOffset = wx.NewId()
ID_toolsPeriodicTable = wx.NewId()
-ID_toolsMasscalc = wx.NewId()
+ID_toolsMassCalculator = wx.NewId()
ID_toolsMassFilter = wx.NewId()
ID_toolsCompoundsSearch = wx.NewId()
ID_toolsPeakDifferences = wx.NewId()
ID_toolsComparePeaklists = wx.NewId()
ID_toolsSpectrumGenerator = wx.NewId()
+ID_toolsEnvelopeFit = wx.NewId()
ID_toolsMascot = wx.NewId()
ID_toolsProfound = wx.NewId()
ID_toolsProspector = wx.NewId()
@@ -192,20 +199,22 @@
HK_toolsDeleteLabel = '\tShift+Ctrl+X'
HK_toolsMeasure = '\tShift+Ctrl+H'
HK_toolsPeriodicTable = '\tShift+Ctrl+T'
-HK_toolsMasscalc = '\tShift+Ctrl+M'
+HK_toolsMassCalculator = '\tShift+Ctrl+M'
HK_toolsMassFilter = '\tShift+Ctrl+F'
HK_toolsCompoundsSearch = '\tShift+Ctrl+U'
HK_toolsPeakDifferences = '\tShift+Ctrl+D'
HK_toolsComparePeaklists = '\tShift+Ctrl+C'
HK_toolsSpectrumGenerator = '\tShift+Ctrl+G'
+HK_toolsEnvelopeFit = '\tShift+Ctrl+V'
# library
+ID_libraryCompounds = wx.NewId()
ID_libraryModifications = wx.NewId()
+ID_libraryMonomers = wx.NewId()
ID_libraryEnzymes = wx.NewId()
-ID_libraryCompounds = wx.NewId()
ID_libraryReferences = wx.NewId()
-ID_libraryPresets = wx.NewId()
ID_libraryMascot = wx.NewId()
+ID_libraryPresets = wx.NewId()
# links
ID_linksBiomedMSTools = wx.NewId()
@@ -241,6 +250,7 @@
ID_helpCite = wx.NewId()
ID_helpDonate = wx.NewId()
ID_helpUpdate = wx.NewId()
+ID_helpUserGuide = wx.NewId()
# calibration panel
ID_calibrationReferences = wx.NewId()
@@ -294,6 +304,7 @@
ID_dlgReplace = wx.NewId()
ID_dlgReplaceAll = wx.NewId()
ID_dlgSkip = wx.NewId()
+ID_dlgAppend = wx.NewId()
# list pop-up menu
ID_listViewAll = wx.NewId()
@@ -301,3 +312,6 @@
ID_listViewUnmatched = wx.NewId()
ID_listCopy = wx.NewId()
ID_listCopySequence = wx.NewId()
+ID_listCopyFormula = wx.NewId()
+ID_listSendToMassCalculator = wx.NewId()
+ID_listSendToEnvelopeFit = wx.NewId()
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_bottombar.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_bottombar.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_controlbar_double.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_controlbar_double.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_controlbar.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_controlbar.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_peakeditor.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_peakeditor.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_toolbar_noborder.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_toolbar_noborder.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bgr_toolbar.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bgr_toolbar.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/bottombars_on.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/bottombars_on.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/toolbars_off.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/toolbars_off.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/toolbars_on.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/toolbars_on.png differ
Binary files /tmp/R798YdfeM1/mmass-3.12.1/gui/images/gtk/tools.png and /tmp/oRFJixBtcD/mmass-4.0.0/gui/images/gtk/tools.png differ
diff -Nru mmass-3.12.1/gui/images_lib_gtk.py mmass-4.0.0/gui/images_lib_gtk.py
--- mmass-3.12.1/gui/images_lib_gtk.py 2011-06-30 11:52:00.000000000 +0000
+++ mmass-4.0.0/gui/images_lib_gtk.py 2011-12-01 17:21:41.000000000 +0000
@@ -8657,7 +8657,16 @@
#----------------------------------------------------------------------
BgrToolbar = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAACMAAAAkCAYAAAAD3IPhAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "iVBORw0KGgoAAAANSUhEUgAAACMAAAAkCAYAAAAD3IPhAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "ZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNrs0LEJACAUQ0E/OLibRytnSHGB1x+ZJKtlAwMD"
+ "AwMDAwMDAwMDAwMDAwMD8zGv04LZTc9cAQYAXRFpP7LCOH4AAAAASUVORK5CYII=")
+getBgrToolbarData = BgrToolbar.GetData
+getBgrToolbarImage = BgrToolbar.GetImage
+getBgrToolbarBitmap = BgrToolbar.GetBitmap
+
+#----------------------------------------------------------------------
+BgrToolbarNoBorder = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACMAAAAmCAYAAABOFCLqAAAACXBIWXMAAAsTAAALEwEAmpwY"
"AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUI"
"IFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuj"
"a9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMB"
@@ -8707,17 +8716,16 @@
"Ft1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9D"
"BY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl"
"/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz"
- "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAGZJ"
- "REFUeNrs1qEOgDAMhOE7wvtb4C0BU1kUyyAYXJf8p9aK9kvVfB57qkgmFQoYMGDAgAEDBszo"
- "mDkiuAwYMGDAgAEDZuj/zLJurchM2W5vSbL96P/Je97XjL7vvLcWyAUAAP//AwCDkR7GsW/B"
- "2QAAAABJRU5ErkJggg==")
-getBgrToolbarData = BgrToolbar.GetData
-getBgrToolbarImage = BgrToolbar.GetImage
-getBgrToolbarBitmap = BgrToolbar.GetBitmap
+ "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAADlJ"
+ "REFUeNrszgENAAAIAyC1f+dbQzdIQCepK6YOkZGRkZGRkZGRkZGRkZGRkZGRkfmVWQAAAP//"
+ "AwC5TQNJT4QhUAAAAABJRU5ErkJggg==")
+getBgrToolbarNoBorderData = BgrToolbarNoBorder.GetData
+getBgrToolbarNoBorderImage = BgrToolbarNoBorder.GetImage
+getBgrToolbarNoBorderBitmap = BgrToolbarNoBorder.GetBitmap
#----------------------------------------------------------------------
-BgrToolbarNoBorder = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAACMAAAAkCAYAAAAD3IPhAAAACXBIWXMAAAsTAAALEwEAmpwY"
+BgrControlbar = PyEmbeddedImage(
+ "iVBORw0KGgoAAAANSUhEUgAAACMAAAAmCAYAAABOFCLqAAAACXBIWXMAAAsTAAALEwEAmpwY"
"AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUI"
"IFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuj"
"a9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMB"
@@ -8767,15 +8775,15 @@
"Ft1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9D"
"BY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl"
"/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz"
- "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEJJ"
- "REFUeNrs0MERABAMAMEw+q8VnzxpI8xeBTvX9ponitSjUDAwMDAwMDAwr2NGZjoDAwMDAwMD"
- "A/Mj5gIAAP//AwBajQcBeUkNKwAAAABJRU5ErkJggg==")
-getBgrToolbarNoBorderData = BgrToolbarNoBorder.GetData
-getBgrToolbarNoBorderImage = BgrToolbarNoBorder.GetImage
-getBgrToolbarNoBorderBitmap = BgrToolbarNoBorder.GetBitmap
+ "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAADlJ"
+ "REFUeNrszgENAAAIAyC1f+dbQzdIQCepK6YOkZGRkZGRkZGRkZGRkZGRkZGRkfmVWQAAAP//"
+ "AwC5TQNJT4QhUAAAAABJRU5ErkJggg==")
+getBgrControlbarData = BgrControlbar.GetData
+getBgrControlbarImage = BgrControlbar.GetImage
+getBgrControlbarBitmap = BgrControlbar.GetBitmap
#----------------------------------------------------------------------
-BgrControlbar = PyEmbeddedImage(
+BgrControlbarDouble = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAACMAAAAmCAYAAABOFCLqAAAACXBIWXMAAAsTAAALEwEAmpwY"
"AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUI"
"IFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuj"
@@ -8826,12 +8834,12 @@
"Ft1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9D"
"BY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl"
"/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz"
- "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAADxJ"
- "REFUeNrszgENACAIADCkf1M0A9TA7U/w8251LJGxiIyMjIyMjIyMjIyMjIyMjIyMjMxfmQEA"
- "AP//AwDmyQQP7AZRewAAAABJRU5ErkJggg==")
-getBgrControlbarData = BgrControlbar.GetData
-getBgrControlbarImage = BgrControlbar.GetImage
-getBgrControlbarBitmap = BgrControlbar.GetBitmap
+ "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAADlJ"
+ "REFUeNrszgENAAAIAyC1f+dbQzdIQCepK6YOkZGRkZGRkZGRkZGRkZGRkZGRkfmVWQAAAP//"
+ "AwC5TQNJT4QhUAAAAABJRU5ErkJggg==")
+getBgrControlbarDoubleData = BgrControlbarDouble.GetData
+getBgrControlbarDoubleImage = BgrControlbarDouble.GetImage
+getBgrControlbarDoubleBitmap = BgrControlbarDouble.GetBitmap
#----------------------------------------------------------------------
BgrBottombar = PyEmbeddedImage(
@@ -8885,17 +8893,17 @@
"Ft1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9D"
"BY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl"
"/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz"
- "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAGtJ"
- "REFUeNrs0QENADAIwLBz/05/NIANSDoJa+R/dTSmawEQAQEiIEAEBIiAABEQAQEiIEAEBIiA"
- "ABEQAQEiIEAEBIiAABEQAQEiIEAEBIiAABEQAQEiIEAEBIiAABEQAQEiIEtrAAAA//8DAMYH"
- "BCmP7+Z9AAAAAElFTkSuQmCC")
+ "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAGdJ"
+ "REFUeNrs0QENAAAIwzDAv+djA5JOwtpJSncaC4AICBABASIgQAQEiIAICBABASIgQAQEiIAI"
+ "CBABASIgQAQEiIAICBABASIgQAQEiIAICBABASIgQAQEiIAICBABedoCAAD//wMA/FsDY7NR"
+ "5NQAAAAASUVORK5CYII=")
getBgrBottombarData = BgrBottombar.GetData
getBgrBottombarImage = BgrBottombar.GetImage
getBgrBottombarBitmap = BgrBottombar.GetBitmap
#----------------------------------------------------------------------
BgrPeakEditor = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAACMAAAFmCAYAAADnOyMyAAAACXBIWXMAAAsTAAALEwEAmpwY"
+ "iVBORw0KGgoAAAANSUhEUgAAACMAAADICAYAAABiWlgYAAAACXBIWXMAAAsTAAALEwEAmpwY"
"AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUI"
"IFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuj"
"a9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMB"
@@ -8945,12 +8953,11 @@
"Ft1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9D"
"BY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl"
"/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz"
- "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAOZJ"
- "REFUeNrszkEBACAIBDCwf1Mlg9S4x5ZgPe/+CnEqiIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM"
- "jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM"
- "jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM"
- "jIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM"
- "jIyMjIyMjIxMWmYHAHGwBo+RFG7aAAAAAElFTkSuQmCC")
+ "/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAJFJ"
+ "REFUeNrszjEBAAAIAyC1f+fZwcsDEtBJ6oupR2RkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRk"
+ "ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRk"
+ "ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZG4WAAD//wMAvUcEjQNPYZUAAAAASUVORK5C"
+ "YII=")
getBgrPeakEditorData = BgrPeakEditor.GetData
getBgrPeakEditorImage = BgrPeakEditor.GetImage
getBgrPeakEditorBitmap = BgrPeakEditor.GetBitmap
@@ -8987,7 +8994,7 @@
#----------------------------------------------------------------------
Tools = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAY0AAAAXCAYAAAD3LRNAAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAbgAAAAXCAYAAAB591o8AAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -8998,57 +9005,68 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOUIwQzIyRTBFN0VGRiIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDozODYzQ0U4QjlCMzMxMUUwOEE4OUU2MTY0MUIzOTE0NCIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDozODYzQ0U4QTlCMzMxMUUwOEE4OUU2MTY0MUIzOTE0NCIgeG1wOkNy"
+ "eG1wLmRpZDpGRkZDQzY2MEYwMkYxMUUwOEIzRURDRTlEMEI2RjYwNiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDpGRkZDQzY1RkYwMkYxMUUwOEIzRURDRTlEMEI2RjYwNiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAzODAxMTc0MDcyMDY4MTE4NzQ4"
- "RDIyRkJBOTlFQzkxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZEN0YxMTc0MDcyMDY4MTE5MTA5"
+ "QjE0MEFDMDgzOEM1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5QjBDMjJFMEU3RUZGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VUBApgAACS5JREFUeNrsXLGO4zgM1QID"
- "pxlNozROlTRJk6km//8F6bZyNVflmk1zmcZu5hJAwr3lkhIpJ4tZnAgIji1boSiK4iNlO9eo"
- "UaNGjRo1atSoUaNGjRo1atSoUaNGjRo1avT16ZtwvbsWH4+Jpmu5xGMNcW2WyPKfmvbn9uFe"
- "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")
+ "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"
+ "AABJRU5ErkJggg==")
getToolsData = Tools.GetData
getToolsImage = Tools.GetImage
getToolsBitmap = Tools.GetBitmap
@@ -9066,61 +9084,61 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowOTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpENUE5MDQ5QTU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpENUE5MDQ5OTU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wOkNy"
+ "eG1wLmRpZDpGMDI4Qjk3OUQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDpGMDI4Qjk3OEQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5N0E1"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODAxMTc0MDcyMDY4MTE5N0E1"
"OTQ1MTJEN0FBRjE3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+laOwSgAAChlJREFUeNrsnb9y2zgQh5Eb"
- "D91EbuQmqs6Vq3R5iDzyPYQ7Va7cKU3cWG7ExkdegPN6DZAACIgS9X0zGv2jvQQE/LAAwd0v"
- "b29vBgBgTv6iCgAAIQIAhIgqAACECAAQIqoAAObmKuagLz8/vG26x8q+3nePVn759g+VCgD1"
- "PaJehH7bx4oqBIA5hKgJvAYAqDc1E9Ox/nktPnevW980bQrddFDa9PG/TaaDAJchRG46ptmK"
- "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")
+ "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"
+ "AAAAAElFTkSuQmCC")
getBottombarsOnData = BottombarsOn.GetData
getBottombarsOnImage = BottombarsOn.GetImage
getBottombarsOnBitmap = BottombarsOn.GetBitmap
@@ -9200,7 +9218,7 @@
#----------------------------------------------------------------------
ToolbarsOn = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9211,136 +9229,143 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDo5MkNEMjgxOTlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDo5MkNEMjgxODlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDo3MDRCRDA4RkJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo3MDRCRDA4RUJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA1ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5NUZF"
+ "REI1MDhCOEE3MTU2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+C64xIwAAGGNJREFUeNrsXU2IJFdyjpHG"
- "VSu5q2VRg2DqYKYFdsFCgxHNHnwSuxh8NNLio42xQPiwAiH2IgvGrIQvPgj2sqdl8Yq9rbBZ"
- "jL3Iwvjig0Td+rCUfajBLD1gT9ny1EizlbMa+b2ZiKno1+9lvr/66e7vgyArs7LyZWbF9yLi"
- "5YvIK1999RUBANCNp3ALAABkAQCQBQBAFgDYYVzd9glc+cPgVz0jA/7cON8tPdvO4Kuf4w8G"
- "1kiWFuXtgqvcPf68sOsZimuPdYc/HxiZGTkyMjEyUm000gb+TmDTlkWUPlUR+0q5rTKf8Of9"
- "jt+H2hOyHanPE14OjRyrY9j25iAMsGmyaKVPVcRx4HMsyXztTdiykLIsGkdMTBAG2DhZbDxw"
- "jXv7vURFnCqFnyrL0oZQe/d4u7h1++p4e+r3ExAG2BZZGlY4UnHCCSvunF2ifiDIzrEsOe0t"
- "VRzjEuaAlyAMUBVPdcQSvnVrAe6qYN61LFPP59gBgtj2GkUMcuKZWeDcAKC6ZdEK6cYWA6WI"
- "A6enz7Usue1pwszwVwLbsCy2Rx+ych5yjz1mhbzOS71+lxU717KUtOezMPbzAn8tsAnL4hud"
- "uqd68AOOJfT6kn9XazQspj3XJZPBADxzATZGFhmdCj33WLD0HOXsU9loWGp7oUECANgYWUKK"
- "t2DFXwbWl3R6qPeaE8+0xSo57QHAzgT4PqVuOtZr9u5d7QHARnEFmZIAEAdM0QcAkAUAQBYA"
- "AFkAAGQBAJAFAC4PvM9ZIlOL26bqnwHy4YHLZFkk/VfETn60kxpHdHZ6PQBcDssSgBSQsBMk"
- "7byvQ94ukxuLEq7YmiVZK1gyYJcsiy4moZOxiFbT5IUwA7VvLtoSy3oVjg8AayOLVl7p6SVX"
- "RE9oPGAlDil6rJs3VJ9d9Ol0LgsIBOysGyazfolOF40QF6w0lVdP8fcNIixpNetYtvfYNewq"
- "twQAa7csDa0K2kmuiciclfREfT8qUNolnU0Y6ytrpWMZ2U6KwLAwwNZjlpOAEroF+Nr2pQIC"
- "CRnuKmti5ZoiLnlcNADYOFkokgAp+8a4YdoF04lfkoas81u0iwYAWyHLJuG6YTqg11bMRwzU"
- "OwZ2hiz9hJggZd8YF2zZ4f4BwEYQOxpmR75mtKoSWWvfkBs2dI4XCxAJ2DhZ5PnFUCmyxXVe"
- "uoF97L5dlkTKHR0XXBOGkYGNksWt5SWlUY89Cpmyb5dV0BUmJX6ZJnyeI8gHNk0WXcvLp9TL"
- "zH1jCaNjlZTPsCjAxsmSUtZoEyWQUj4DwFqAUkgAEAlkSgIAyAIAIAsAgCwAALIAAMgCACAL"
- "AAAO2uqGlea3P5nU2FVpJVCnrLjSS6hdpz1UlAHyycKQ0kclSJl57CqttN92DCG0kLPtVXpd"
- "13nNKPu8g9Q12gMuGFl0pZXDFmWVNF93Dpj97XGiVXLJEZN5qSdx2vz/E/6cMvM4JcOzRnvA"
- "BSOLzi2Zs/hclWFE70+ZSts4y5C7lPOG5BJsuj1gx8kiKb7TQK/vKviwgivSeJa6WkzoHHLe"
- "kOy6fo86CHazpLNYGrfMdz0l7QEXNGahBFJMK1gXlxxSLeZah7tU0tNbAtrcmSNaZXdSh7WE"
- "ZbmkeCrCDXNJESqmN6SyvHu3lFKXW6bPaer5nNIJaPLI9Q2UpanVHnAJ3DCXFOuwLl2BdqiI"
- "X82efo8HJrSlmcOyACluWCwphEjrgOuWrSOG6HdYHsQsIEurGzb0fH+dTg8va0UaZ7hj+vmF"
- "Xd7zrA8Dli2np+85LpdL8IVyxR49XFXBPiwLyHLGDWurtHLcYXkoEF9QBDmnTq/tW9fPNXJ6"
- "evd5yT1aPTdx16lCe8AFJkutSiuxLpkueiE5+G3rS+d3pPYh6i6SoX/nq3TZOPsseYpMbnvA"
- "BY9ZNllpJbfoRc3f+QplzCu1B1wAeAtWRL6ANRqYYAhcWLIAAHAWyGcBAJAFAEAWAABZAABk"
- "AQCQBQAuD67iFpzKrW+b09b5VjE8TwJZYpTplCKlKo2qJhNTZSVqv8RziC3OYeeDzQn59iBL"
- "C74WoUwv8D65Tzljqrmk7JeCmFnSNsdFpv+ALCBLEA+MvGrkw5Z97OTJ/zHyZaayDiMVN6Ua"
- "SyqO2GJJXovMdzum1UxsaVtP7wd5EOA/wa+MfGzkXV7/1MhLRl408jo9fl/9w4LzcNOYY2KI"
- "wRoIs2BiTFjs59vsftnPM25zxNbtDn/uQZVgWZ6EAEY+N/K+keeMvGHkHSN/wdbm95hQuYit"
- "JqNRo0hGyEIO1HlZItyjVYqAFLkQzNZ0HsA5JQuxe2UtyHtGvm7kFSO/NPI9I28Z+XWhdfG5"
- "Wl0lltbRo/vqDuzzeQxpVQ1mAvUBWboI85mR14z8E1uYf2Pr8mXBebRVk2nrtQdUf3RKWxZx"
- "zSwp9zjAd4lyQOurOwCcY7Jc4d88x+vWLfuI8kfAQm6YRpt1WYcr5juHg4BFOWACIcAHWc4M"
- "Bjxj5GUjPzDytpGfcazyLB/rizUoThchalTDjLEsBKKALDF4mt0QG6d8l4nyCSvV8xyzfKeg"
- "l4+tJuP7XnL+hTClxAlZFgJRQJYY2IeSbxq5yesfVA64S6rJuAqe89BQl4w9pNP1w5ZqO9Gq"
- "UDqIArIE97uZoHSUoayl1WR0lZZU2N/q0kdtwBN8kKUV92n1nKFN4UtGhTZZTcbX9jzyGlH2"
- "CGSJUqZ1w1eOKOUzVSAMAHiB6i4AEAkkfwEAyAIAIAsAgCwAALIAAMgCAJcHsQUrBKEMxqKC"
- "FQBwYciiiGInMYamhGRXPil4xYUmbzJhVVUZN58+dtspJLYZU8mm9RrRMe0mWTRRxurPJvWH"
- "16p80qocHeRNnQ3sHuOACb8Xse3Evmcyk+gxadP6vZcz5xoXhEIZOxuzDBRR7B/kFnWQV8Yt"
- "C0liFfcGK9IJL2/w9l7gnI7UthmdzkWJva4j9fvrkdsGa/5vhFAysXTEyxlvH0B9d9eyyNLO"
- "8j104pUZ/5k1lMOFTL93e2FfQhZRXprApGBbDhq+Xzo1oM0tm3ssECrK7KhlEeg8j2NlVcbc"
- "8+b2du5rwo88+7jWpWlRxFgs6HRil/18O3JbyQzrHt+vnuoo7tLZDM1rLA1f/yDzOoENB/g+"
- "0hyxVTks7O0GyoIckb8whJteLIo+K1BiibV8by6O2VZClq77JbOgpU7ZzBOzAOeALG0Wp0R5"
- "xNUJlRrqBRS9azAgCA7S5x4Lp0fBvNs4uK8RaLtumduRCFHGhHTmc+OGCZbOsoYPHxMbNI5S"
- "D1hZb1NBqi8Pv8oxdaXJQeS2XoXO4iTiOEhnPkdk0eQYB7bnYOEczwdJHe6tQVmlB9/WyFib"
- "WyYx4RhEOR9uWKOWvjihVxh0xmQpzlWgq2Oa2uVTNz0yFgOJ5/ahsrtvWaSgw5RWlU6OeCnD"
- "yaPCoFNGf8Yei3LNc+zayrqpkTE9E2CgRNZ7Hmsuo2LI/z8nlmVO4QooNV7yI20sOoJ2dxSs"
- "aBhXPYHf1MiYrpE2VZ2QrLuzIFAb4JyRRf9pbgWUGoXtUlyykFKvq+3YbSlxn+4MGmcd1uMC"
- "kGWXerkq57GlSYiwFOcUqO4CAJUDfAAAWXALAABkAQCQBQBAFgAAWQAAZAGAS4PYUkihEkiC"
- "4lJIGYUfalR2iWkjtgoLKq2ALI9gX5N3p2OfF3ifTTzldLMHLbLe8xhScCbTkyosZr+53ebu"
- "X1DGCbigbtgDI6927DOu4NZJrsp18ld0EejswWp5JdaCGhmwJSWKS/8FQJZTsK/v/tjIu7z+"
- "qZGXjLxo5HV6XGzhYSVrocsghRK7eoooOhGrVKl9hSMAIIks1rX63Mj7Rr5v5BtG3uFtHxr5"
- "CROqVFFjrYW4WhMm1MTZXkLYR0vEH0AuWSy+5F73PbYyrxj5S/7uLXpcFulhBUWNsRY6UWui"
- "YpZaFU/61h2j8kIcwCUlixDmMyOvGfmFkTeMfIt79AeFwX2XtdDxjFVkya0Z8bKo6okTqO9x"
- "x7AXMxgAgCxenaLHI2jP8bp1yz6iOiNgbdbCF88MqUJlFwnsmYBiSdzlEzJh9Atkid33WSPf"
- "NPIPRv7ayF8Z+YK3/1ZhgK0zIF1rsZbRL09gvxdyy+w+llRiXUAakCWEp1mh/tjI3xh528gn"
- "vO06E+d/KyivZBG61mJdo19uvBSKUcQtG8rQMlyyy4eUh5JvGrnJ6x90KF1t6HjmiOqMfvXE"
- "WtDpOsshy0Iqlhqb3y3UOeD1DyDLqf1uJih1beiKLrVGv/p0dlbCJHI5dX63D7KALIL7dLaq"
- "i48o6ypWXaWusYNlxDXFnhsqsoAsZ2KJbaL2OaDKCpAEVHcBgEggnwUAQBYAAFkAAGQBAJAF"
- "AEAWALg8aH3OwpMFfcUq5FUJPWp5/UTu/Ck1STGpYERsmzzFJSZXJbrdlPY3jVrFQCoWAolq"
- "L/beZl6fq1deXdNtXo04qLyWzoXNuZ96ttd4sZHgScEIqvsAUY4r88xCS3st9+wN5LcaP7p5"
- "elmgsF0dQXRHkUHQLuWU+yMovf9d19L3tLdI7SgT7ptcny5yYn9jJ8sGpy5djVCqE1q9/LOn"
- "llNavRTV3b/GzZUZzcTL0MtJS6a9dM0Bk4mTI6Ps93IsTQRhhZCuNev6voQcPacDdP+vnuf3"
- "6+z0lnydcr/l1YEzSq/aE2pL3wOZOKuPL/93dszivlh16qw3gc+1bu4xrx/zBblyh/LSAnSi"
- "2VHLUpPmyRT9wuvr0en3SA752NfpdLGMXsv3XXXcQvdTJ861kaHpWE8hJ1F3lZyGO4SJ2m+m"
- "FLqf2Lavrb66B8dquz7+SY0A3z15fUL6T9hGyaCcNmVipjW5t5gMt3j933l5Upk0okCi/Hvq"
- "TyQ6+1LWfuD7oTrGoOI90iWoGtWZ5MzuHmSc357qqNz2l4UdU49WE2ftf3io9tHHH9Ugi3vy"
- "2prozMZaLoq8hFUu6lCZafdiS4kmMdlQ3dQFm/BO0iT08KJAI4cEE4/S3qVwjs1UHaOX8P9p"
- "zJ3/kzyd3rwg/uyyJK7l6XPbE/X/n6j7n6tXmrQ6sfC2unZ9/JPs0TDHrWpo9drtPbVcqn16"
- "mWbb1+5cHW+uLrAW3KDyybvmbTAvbqWxIEv+0/YCpJkk+tWTAElic2n05yah8zlQPvqcr1/i"
- "ob2AsusX3daEG1e4L6VdOG59SmDfjyDtgv9TN/4blZIlNOpFju9Hygqch0SoJZ1+RfgTk6zL"
- "tPIomOSshEgzixjUkHtZq25AysCGfjX7PTWAcBLwCBpabzXOnicmnlci4GHkSJnPtRRrlkUW"
- "GfU69AwtTloIdO0ckEXilgPfqItneFh6ujbSdGFa+RquJSqothRaYefOfVhQd6p1rPV24y/f"
- "uq8jy3X9+gWjctVGw6bqD9esPFJCa+qNJPi8roJQcgLenGC7z9cyotW4vgTYAw7iXemrezJS"
- "CtgVBC+VG0sRI3G+/Q4L4rU2S9EUxihtbd512vatD53luoobdlnLKqNhpNyxscfXniT0rqm9"
- "v1grPWR87FiyO4k3WAK/36XVs4w7vH43cnlHkWUQeS1zR/mXztI3qKC/v62OMaa6adxieXqV"
- "/799Z0DIt66xr/6jdY+uugMNRTGL60L4CHPkCTxrYUH+PPmhIswhK1HO8OKk0jImZtGB5Z5D"
- "jj31/cLj6s1VQDpQ25pEpRAlvOdZH6p72zjf57YlA0B7iesDpWfziPis5+mwhp7P7nLg6LN8"
- "7vnaTBkNG6serddBkKZizzTvOP7tjOBQjw51TXmJXcZej457lp71tv3ckZyU2EG70aPE9ZTq"
- "Nbqt444Boa71qbI2TWSbE8+xYttpbfNqhFKNAr7cYWA0rGaB7i6LQ5ltNc7IR43lMrH9pmW9"
- "bXuT0Rm5Q7NN4voys61aHeZyF9qMsSxzz4m4N1Rv30TBuRpDjQ1tcIh7y7ORN1nJZhtVczbS"
- "Zmt1l9J6vihxClwkoBQSAEQCmZIAALIAAMgCACALAOwyruIWXGwkjGgmFQe5jCOdsCyAJMDd"
- "oMfz3m5Q+sRUWJYd6AlDuebeh5+pvZ2n1FPxQ9Wucyh4dhU8z4JeXl5sq3N6ZLpHaqEIkGXL"
- "cEvyaNQoj+Qr9eSbpv4Uuyh2ot9Dq6icTVn64DaWqL7zTFHmkIulX2wrs5hlcuGM6pegght2"
- "jqFLPY14qafc2/vzjJEXjHzbyH9RejpAl+ujc99DLpCcp57hnfK2Zl8BCV0SyF73LXo8KfUW"
- "rSbNwh1rsywRrknWd5muwoJWaQGS9HRM9XM5tAKJknxu5DeM/JGRH/P2PzXyc75PwwLXLWQx"
- "pwGrKec1CZxvDvRMXX3++nWHqTOOL50b1mbyKfO7kpstv73t2VaK0KxqqyS/Y+T3jfwtb/sT"
- "I39v5IGR5wtdIp1r4ZviP/QocNu9ibmHI2f/peqIdM6Kzg0ZE96X2eqGhUz+DZbU73ILNIhS"
- "zWiV9rtQAWkNF0HPqpYyS79t5M+M/AcT5c/pcSrzT9na/GYFl2iqiOIei5QCa1IfOPukpEL4"
- "siD1TN0p/3/XeTkFNeIti8/k6xuY8l0vkyhCiiN2GYbKfRAlq2W5tMvztJF/Vev/YuS/jXxZ"
- "ySVyE+dCyWOuYpe8rdlXGbJPq3pwswBBUrIVLyVZQjdk7CFGzHdNAVGI2rMQZxUI4w5P23vy"
- "svr+m0b+0cj/UfsDuxSXiFo6F3c/7RbVUlhdBFtIOKSzKbZ6WbuYxYVww0Im/xZL6nc5pT9n"
- "yk3pQg1XT0akrPynkR9xzGID+h9yvPRtdsE+L7zOBZ0t+uHrfBbO+UmBjFqjUyPHst6iVTnb"
- "W3S2zsLJZR8dC1mWNpOf+13qiFRKbnvuH6iHjqVWloy2/dLI39mBPB4N+7EaDZsXXGdMVp/0"
- "4EMV00yo3rMPt4aYnFfjnIPrLp7QJX72cjXjD839LnX0a5LxG6rUtr2GX/G6Dez/2cgf0GoI"
- "eb/wOheO66MtytxjpSaFxGir5BIiui7qUXoOF5MsOzBBzv2TulBSIMM3dDxSx7NP6+9zrPJT"
- "tip221LuU+YT/EaRos1Cufci51q7KruEnqO4FTtL7/WFtSzbhOsGdu1bEvQ2kS6VkOa+bCit"
- "TxBpiRvHXcq51q7KLss1tw+ybIAwF7kaySbPb9u/vzBAwQoAiATyWQAAZAEAkAUAQBYAAFkA"
- "AGQBgMuDqOcs6gFcVAEJFAQHLi1ZFFHcTEiN7Cncm654EmgvqW6WD+gkQBaXKGOlWKSUS14O"
- "VDodYlsVT7reZKvPTaypWNhLnxgFsqygp7LrNxdrJb1GZfnaoohtM3Ebzzmlvo9e/16TI+a9"
- "731aFZrQEzBR1AFkOaXIstSVVqSHlTz5Emy64olLDrc4RMgtGwc+AxccqaNhul7WMUtDZ+tt"
- "5VgVt+KJCzdLr1Z6r17qCii+WltC3qnnMwCytJLmiK1KjAvTZVU2XfHEJYdbASV0TWM6/eZm"
- "WBe4YdkWJ9eykHKrNlXxROdqdLllrluok6j2oUogSwhLZ1mKbVQ86bKGvsJ0iFnghiWTxFWU"
- "UtLsSsUTn+XpIWYBUiyLdknc/PgDj+uSY1k2WfHEV8QhtqgDLAvI0tnzy3MFqyCHtBpWleHk"
- "EZUVM9hkxZOuIg5tRR0Qs4AsUT2/r4i2KE5ptcJNVjzpKuIQKuqwVAMCjfqM4tkgi1eZ3aor"
- "xW/LSnTJalQcyS3CgOINIMu5U5ai88CERyAHqO4CAJFA8hcAgCwAALIAAMgCACALAIAsAACy"
- "AADgwPtQkqufFFc7EaQ+BDTth0ouCVB6CdgNsjDaqp1UI1IAXyN/Pr7GC7wPnqoCW3XDdE68"
- "r3eXV0P3nd+0WYMUPDDyasc+Y7iRwC6QRU9h95HBWpR9Wk3RH9CqwEO/wnnZl59+bORdXv/U"
- "yEtGXjTyOrfzEH8fsAtkWdLZxCaxJgPHBZPtRKu8jlILY10r+775941838g3jLzD2z408hMm"
- "FADsRMziI9A+k+CuIkaP4xoJuAfq+5J45ks+zntGvm7kFXr8bvrvGXnLyK9hXYBddMN0QL9Q"
- "LphUaGwUMbSLVgpLmM+MvGbkF0beMPItbusBgntgF90wHdDrYVsfMWomg11h6/ccr1u37COQ"
- "BNhlNyxkLRpaX41fS+RnjLxs5AdG3jbyM45VnuVz/4JQYxjYMlm0G6bLqu4lHLvEwjzNbdk4"
- "5btMlE84HnqeY5bvUHpVFwCoThZrQaQoxHHB8XODfPtQ8k0jN3n9g8B+PfyFwLZjFikKIbWE"
- "Q/V92z6XvILiqiJKl/UCgK3HLPoFRUtlKWI/lyjyfTpbRSbk5gHATgT4bgCf+jkXKDkE7BxQ"
- "3QUACmMWAABAFgDIw/8LMADjpmK1kIH28AAAAABJRU5ErkJggg==")
+ "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")
getToolbarsOnData = ToolbarsOn.GetData
getToolbarsOnImage = ToolbarsOn.GetImage
getToolbarsOnBitmap = ToolbarsOn.GetBitmap
#----------------------------------------------------------------------
ToolbarsOff = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9351,131 +9376,138 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpDMUQyNzdDQTlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpDMUQyNzdDOTlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDo4RTM5NjVDRUJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo4RTM5NjVDREJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA1ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5NUZF"
+ "REI1MDhCOEE3MTU2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Q9PQiAAAGNhJREFUeNrsXU2IbMd1rpGe"
- "u5/k6XkRdxCZhsAbkUwTo4GgN3iRlXDIPkghWdkJwSCysCEIbxSBgiWyyULgjddJ8C6CYEIc"
- "FG2zkOjdLMJkM4KYHgjTifP6Sbjv83ty1bxzpk/XVN1bf7enZ/r74HB/+vat+3O+OufUrTq1"
- "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")
+ "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")
getToolbarsOffData = ToolbarsOff.GetData
getToolbarsOffImage = ToolbarsOff.GetImage
getToolbarsOffBitmap = ToolbarsOff.GetBitmap
diff -Nru mmass-3.12.1/gui/images_lib_mac.py mmass-4.0.0/gui/images_lib_mac.py
--- mmass-3.12.1/gui/images_lib_mac.py 2011-06-30 11:51:59.000000000 +0000
+++ mmass-4.0.0/gui/images_lib_mac.py 2011-12-01 17:21:41.000000000 +0000
@@ -8697,6 +8697,65 @@
getBgrControlbarBitmap = BgrControlbar.GetBitmap
#----------------------------------------------------------------------
+BgrControlbarDouble = PyEmbeddedImage(
+ "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")
+getBgrControlbarDoubleData = BgrControlbarDouble.GetData
+getBgrControlbarDoubleImage = BgrControlbarDouble.GetImage
+getBgrControlbarDoubleBitmap = BgrControlbarDouble.GetBitmap
+
+#----------------------------------------------------------------------
BgrBottombar = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAAGQAAAAzCAIAAADuCzpMAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNrs1MENABAQRUFEf6IQ0f9lVwuuZH4Jk7db117F"
@@ -8799,7 +8858,7 @@
#----------------------------------------------------------------------
Tools = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAcIAAAAWCAYAAABTwJzIAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAf4AAAAXCAYAAADqUy3bAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -8810,88 +8869,126 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOUIwQzIyRTBFN0VGRiIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDoxQTFCQUQ1QzVDNzcxMUUwQTg5NUJGNEIwOTA4NkJDNiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDoxQTFCQUQ1QjVDNzcxMUUwQTg5NUJGNEIwOTA4NkJDNiIgeG1wOkNy"
+ "eG1wLmRpZDoxMDRCMjJCOUYwRDkxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDoxMDRCMjJCOEYwRDkxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkY3N0YxMTc0MDcyMDY4MTE5NUZF"
- "QTY3MTUyOUYyODY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkVFQ0Q3NTgyMjQyMDY4MTE5MTA5"
+ "RUQ3QUYzNkI1QjJGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5QjBDMjJFMEU3RUZGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+JzkUqwAAD59JREFUeNrsnemrHUUaxjtO"
- "3Le4G9BA4geFiBuIoqIxLqiYhWhiRBEJouCA84/MlxFGUERE3B1DoqLi1UmURJSIUVFRP+iX"
- "iEvc4hY3zNxfwXN4z3uruquq742Z0AWH6u6qrqeed63qPvfcWbt27WqWLVv296Zprp38LGpm"
- "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"
- "RU5ErkJggg==")
+ "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")
getToolsData = Tools.GetData
getToolsImage = Tools.GetImage
getToolsBitmap = Tools.GetBitmap
@@ -8909,101 +9006,132 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowOTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpBQTIzQzQ0RjU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpBQTIzQzQ0RTU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wOkNy"
+ "eG1wLmRpZDowNDAxREZEMkY5NzAxMUUwOTI5OUIxMThFMjdGMTA4QiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDowNDAxREZEMUY5NzAxMUUwOTI5OUIxMThFMjdGMTA4QiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5N0E1"
- "OTQ1MTJEN0FBRjE3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5MkIw"
+ "OEEzNjZBNEQxM0ZBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+z+fP6AAAEmlJREFUeNrsnUmv5UQShe8r"
- "HkMxSPULkGAFf4B1r2qLegUCinkoxgJW9KLXsEJqUEExz4iWetFv+1a9Zd8SSC3Vgl+AmOfq"
- "91mcp6iozHSmr13v2jeOZPle29fHkXaGI9K+cXYuXLiwuv322/+5Wq1OHkwnVsvC1wfT/t7e"
- "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"
- "m3aeeCgp8AAAAABJRU5ErkJggg==")
+ "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")
getBottombarsOnData = BottombarsOn.GetData
getBottombarsOnImage = BottombarsOn.GetImage
getBottombarsOnBitmap = BottombarsOn.GetBitmap
@@ -9021,110 +9149,135 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowOTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpBQTIzQzQ1MzU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpBQTIzQzQ1MjU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wOkNy"
+ "eG1wLmRpZDo0RkZCQTdDMUYwRDgxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo0RkZCQTdDMEYwRDgxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5N0E1"
- "OTQ1MTJEN0FBRjE3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU5Q0Q3NTgyMjQyMDY4MTE5MTA5"
+ "RUQ3QUYzNkI1QjJGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+IC44+AAAEtBJREFUeNrsXV2IHUUW7gnx"
- "X+MYiObBFyOLDypEMSb4g9HEwYgxEtEYEBER9CXs6+7DIj75vMyu+CAShvgTXWVGReXq1Qgm"
- "GJREYRSiJL4koA7qxFEjUcner8nXnKmp6qrq7nvndvf54NL//dWprjp9qm/3+UZOnTqVbNmy"
- "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"
- "sKMAAAAASUVORK5CYII=")
+ "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"
+ "YII=")
getBottombarsOffData = BottombarsOff.GetData
getBottombarsOffImage = BottombarsOff.GetImage
getBottombarsOffBitmap = BottombarsOff.GetBitmap
#----------------------------------------------------------------------
ToolbarsOn = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9135,215 +9288,308 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDo1QkEzNDNFMDlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDo1QkEzNDNERjlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDozRTdEODk3REY5NzExMUUwOTI5OUIxMThFMjdGMTA4QiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDozRTdEODk3Q0Y5NzExMUUwOTI5OUIxMThFMjdGMTA4QiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkVEQ0Q3NTgyMjQyMDY4MTE5MTA5"
+ "RUQ3QUYzNkI1QjJGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+j4mR0gAAKQpJREFUeNrsnd3vFVfVxwfE"
- "19pqmjQhmCjEBmpjTAAtvwsDxCZi8AKf5FGb1kqptrUvQOkf0kopKr7X2hax+jxcYNTe/IyS"
- "hkK50KSVihj1Qm6MIWrrOw+fefyeLBZ7z+w5Zw6tM2slc+bMnDl7zctas9fes9dnlpw/f77a"
- "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")
+ "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")
getToolbarsOnData = ToolbarsOn.GetData
getToolbarsOnImage = ToolbarsOn.GetImage
getToolbarsOnBitmap = ToolbarsOn.GetBitmap
#----------------------------------------------------------------------
ToolbarsOff = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9354,207 +9600,291 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDo1QkEzNDNEQzlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDo1QkEzNDNEQjlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDo4RDYwQkY4RUYwRDgxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo4RDYwQkY4REYwRDgxMUUwQTQ4Q0VBN0VFRjlCQTk5MSIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkVCQ0Q3NTgyMjQyMDY4MTE5MTA5"
+ "RUQ3QUYzNkI1QjJGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+vqGfkgAAKMdJREFUeNrsnW3MHVXV94cX"
- "FVQUBBGiMaGa2hSslLbWApa2QkOJUB68aUshrTFUW27tHdP4RWOaiIWkJqY3vnwwaKQVbEV8"
- "qJKCiBSrrdQSarE0SGL5oqm2xTd8AV/qw28//Z+sa3fPzJ5z5lxtz1krua6Z2bNnr9kza+21"
- "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"
- "AInzC9/yqBJgAAAAAElFTkSuQmCC")
+ "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+R6cApwAAOotJREFUeNrsnWnMXVX1xi+I"
+ "ihaJSKpYMX6RNuGLQwghBANlRrCIQNEiZZ4nGYIQteLIoCCjMlXGMA+lioJAWyiIYEhICIng"
+ "BxUoKM44j/z72+E5ed7dfYb7vve9/L13reRmn3v2PnudYa291t5nrees9corr/ROOOGEz/d6"
+ "vQWrf7N7o0XP/Oc//7l+dfmFCy64oBcUNBVaB0VZLVCnf+xjH+ttvvnm087wM5/5TO8rX/nK"
+ "UC7usccem33nnXee/urfL8TjDpqSsmBRUJQPfvCDvX//+99pJ9amjtZaa61qu9SOevY3tROf"
+ "pn4Gwe8DH/hAKm+//fYFoSxBU1aW1VZl9vve974kwLng+X8JoP/P25Xq83bQap6N/QySH9e2"
+ "Wllmx6MOGoRl6f33v/+tBE9CiKCx3wVQQqh2+q92Xl/Xbtj83OIEBU1ZWWRV8lHbBZgyH7Ul"
+ "9Hl9UzusShd+//rXv3r/+Mc/0vbrXve6Ce3WWWed3tprr92Jn7aDgqZKa8stQqgo9UNY/b9+"
+ "ebt//vOfVfnnP/+595e//KX3t7/9LZX8V73668qPPrbffvvedtttl/raeuute7/5zW9622yz"
+ "TeqX3x//+MdUB4+m/oKCBuqGIVQaiRnRKRm93/CGN6SRXaR2PqJjKRDYnXbaKbX57ne/29tt"
+ "t93S9r333tt7/etfX7Xryo/+3vve9/bOP//8anuvvfZKJYrCtgh+6667brI4+XkFBQ1UWTT6"
+ "ImAI5i677FI1uPPOO5MgyhXyibq7OAjmD37wg7T997//PW3L7crnDV34yeXadddde0uWLEnb"
+ "3/nOd3gnlHihNNB5552XFHPp0qW9N73pTek8w/UKmvY5CwKKoD3wwANptEeQEcTbbrutN2PG"
+ "jAkWReST6x133DFt33777dU2Ap4f04UfCrN48eLU/uWXX+5deeWVvT/84Q+pfOmll6q+pCjz"
+ "5s1LfKXY4udWMShoynMWhNcn3n/961+Tq4MgMqrvueeeaW4gd4t65gSa1FPy/3vf+17v+9//"
+ "fmpHyX/qvF1Xflgn9v3pT39K7Zif4GaxD1ft4osvTn1hYVAULBLvi2jPufh5BQUNTFkQLAk/"
+ "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")
getToolbarsOffData = ToolbarsOff.GetData
getToolbarsOffImage = ToolbarsOff.GetImage
getToolbarsOffBitmap = ToolbarsOff.GetBitmap
diff -Nru mmass-3.12.1/gui/images_lib_msw.py mmass-4.0.0/gui/images_lib_msw.py
--- mmass-3.12.1/gui/images_lib_msw.py 2011-06-30 11:52:00.000000000 +0000
+++ mmass-4.0.0/gui/images_lib_msw.py 2011-12-01 17:21:41.000000000 +0000
@@ -8783,6 +8783,65 @@
getBgrControlbarBitmap = BgrControlbar.GetBitmap
#----------------------------------------------------------------------
+BgrControlbarDouble = PyEmbeddedImage(
+ "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"
+ "AwC5TQNJT4QhUAAAAABJRU5ErkJggg==")
+getBgrControlbarDoubleData = BgrControlbarDouble.GetData
+getBgrControlbarDoubleImage = BgrControlbarDouble.GetImage
+getBgrControlbarDoubleBitmap = BgrControlbarDouble.GetBitmap
+
+#----------------------------------------------------------------------
BgrBottombar = PyEmbeddedImage(
"iVBORw0KGgoAAAANSUhEUgAAAGQAAAAzCAYAAABhaa0bAAAACXBIWXMAAAsTAAALEwEAmpwY"
"AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUI"
@@ -8929,7 +8988,7 @@
#----------------------------------------------------------------------
Tools = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAY0AAAAXCAYAAAD3LRNAAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAbgAAAAXCAYAAAB591o8AAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -8940,57 +8999,68 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOUIwQzIyRTBFN0VGRiIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDozODYzQ0U4RjlCMzMxMUUwOEE4OUU2MTY0MUIzOTE0NCIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDozODYzQ0U4RTlCMzMxMUUwOEE4OUU2MTY0MUIzOTE0NCIgeG1wOkNy"
+ "eG1wLmRpZDo2NkU5M0ZCOUYwMzAxMUUwOEIzRURDRTlEMEI2RjYwNiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo2NkU5M0ZCOEYwMzAxMUUwOEIzRURDRTlEMEI2RjYwNiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAzODAxMTc0MDcyMDY4MTE4NzQ4"
- "RDIyRkJBOTlFQzkxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZEN0YxMTc0MDcyMDY4MTE5MTA5"
+ "QjE0MEFDMDgzOEM1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5QjBDMjJFMEU3RUZGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+7QT34QAACS5JREFUeNrsXLGO4zgM1QID"
- "pxlNozROlTRJk6km//8F6bZyNVflmk1zmcZu5hJAwr3lkhIpJ4tZnAgIji1boSiK4iNlO9eo"
- "UaNGjRo1atSoUaNGjRo1atSoUaNGjRo1avT16ZtwvbsWH4+Jpmu5xGMNcW2WyPKfmvbn9uFe"
- "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")
+ "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"
+ "AABJRU5ErkJggg==")
getToolsData = Tools.GetData
getToolsImage = Tools.GetImage
getToolsBitmap = Tools.GetBitmap
@@ -9008,63 +9078,63 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowOTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpENUE5MDQ5NjU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpENUE5MDQ5NTU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wOkNy"
+ "eG1wLmRpZDpDQzJCN0I0NkQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDpDQzJCN0I0NUQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5N0E1"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODAxMTc0MDcyMDY4MTE5N0E1"
"OTQ1MTJEN0FBRjE3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+j8iuxgAACnxJREFUeNrsnbuS4joQhsUp"
- "yiQLCZOsozPRRJPNQ+xjzWOdhyAjIiJjkyUZSFAyx96VdppGsnX19f+qKG6eaUvIv7plu3vx"
- "+fkpAACgT/5BFwAAIEQAAAgRugAAMDshWiwW79XTO7oeAACPCAAwGJZOXsyPu7dF9Vir15fq"
- "IemXn/+hUwEA+T2iWoR+qccaXQgA6EOICstrAADIF5qRcKx+3pLP9WtpCtNiqMJBatPEX5sI"
- "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")
+ "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"
+ "gg==")
getBottombarsOnData = BottombarsOn.GetData
getBottombarsOnImage = BottombarsOn.GetImage
getBottombarsOnBitmap = BottombarsOn.GetBitmap
@@ -9082,70 +9152,69 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowOTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDpBQTIzQzQ1NzU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDpBQTIzQzQ1NjU0N0ExMUUwOTg4M0ZFNjBENDk0NUM4QiIgeG1wOkNy"
+ "eG1wLmRpZDpDQzJCN0I0QUQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDpDQzJCN0I0OUQxNTgxMUUwQUJCMEFBNzg4OTFEQjQ4MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5N0E1"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODAxMTc0MDcyMDY4MTE5N0E1"
"OTQ1MTJEN0FBRjE3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA5ODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+mGqPvwAACl5JREFUeNrsnbty2zoQhuGM"
- "hmoiNXRjVseVK3d5wDygOlWq3ClN1ERuhCaHTIBovQaIO6//N8PR1V4CAn7uguTuw+/fvwUA"
- "AIzJA4QIAAAhAgBAiCBEAIDVCdHDw8N3ZfM7uh8A0PEFXQAAGJuNpxdDX1bttlPPr+0m6YcI"
- "9QAAQ3hEnQj9VNsOXQgAGEOIKstzAAAoF5qRcKx7rMn7+rk0hWkptOEgtWnin02EgwCsQ4h0"
- "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"
- "AAAAAElFTkSuQmCC")
+ "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+V8nIhQAACkhJREFUeNrsnT134yoQhsk9"
+ "PnITu1GaqLqpXKXbH5gfmM6VK3feZt2s05hmV9pAPJ4AAgH6fJ9zdPylZARGr2ZAnnn48+eP"
+ "AACAIfkPXQAAgBABACBE6AIAwOKE6OHh4a1+eEPXAwDgEQEARsPK04uhL4t626jnl3qT9EOs"
+ "wgEA+vCIGhH6pbYNuhAAMIQQFZbnAACQLzQj4VjzWJL39XNpCtNiqMNBatPEl02EgwAsQ4h0"
+ "OMbZk+dP9XZOeGw2myKjTQDAREIzAAAYxCO6KO9Dh2baE3pVHokOk1JCbbpCMwDAQoRIWkKg"
+ "5r2fmY5NIuwCAELkEgjT86RgAhoACJFPyCQQGgEAhvSIEDIBAPoVIoRJAICcYPkeAAAhAgCA"
+ "h77DruaX/Aj1AADwiAAAECIAAIAQAQAgRAAAACECAIyK1QA239hjdprKIWql7o293/anzS//"
+ "1/V2FZ6/q9MrgjabAIBxCNGocN1KUItJI0K/621b7yct+4SKYlvmSRs07cm34gW4JQLMXojm"
+ "XMVDCYPL66lMfRHRTp/MkzYqdaxH9fql3k4iYxYEAPoAVTw+2/Bbt6URGCUyOgnciXovJPQq"
+ "6q1U+4R4NzEFB0oiQkI9RyUVsMjQbM5VPAoVjl2Z51EY+qCK9Ex0dksfmmN5FJ+ZMX/U2zuG"
+ "LliiEM25iodUoiKJt/ekXuuTflMfz7mZJ1LHZfJMQhP5f5D+kqqdhaE/qT0uQi8COaHAgoRo"
+ "zlU8CuXNPBk+0yf9od62an5Ih2uxnklB2lep/0nZErE/WUQI80NgsaHZ3CjI4wfxjq7ilrxf"
+ "eohCqGciifhJcV8oQNvfQIQAhOjGUqp4UO/oQrytYiDPpGCe2Z29JiQNvX0AgCkL0VKqeHx5"
+ "R3TeqT7Zc3gmPqEZ/7/whABCMyIQpudJGfp+JMO9UyKxJ+QTmunwcEOEHzcwAgiRmFcVD3pz"
+ "Jl8NpCtXOTyTRyU0QphvDyjZ64Pud4gQgBDNq4rHWp3gDXQFUD/fqiV7Ol/1T6D0Tz46zNFI"
+ "g73JeIoADCZEMx78V2GfEP8XHimh+Sa+EZPEbZPwLgG7YHIawCOaH0N4d6gLBwCEaFhPD6EV"
+ "AN9BFQ8AwOAgQyMAAEIEAAAQIgAAhAgAACBEAIDBGVUVD8PNejQ5mnfyNb4qN0RFDdgc3iYZ"
+ "T97VWGwrukvp21EJkeXu3U6i4PpyPeDJ0XgitM7HFHGHsrV4QEg7LQUJ6N3W1vYE2gmtGsKr"
+ "hXzLGjnB2y9o5s1zRuFwFpbIcH50thlrt0+PiJ/kOldPclFosRkjVMHCYisbRL70kvRDqrQc"
+ "tmyUKU6cLlVD9I+af2U4niEoDI9GkY20syZ9Zuqr4Dp5CWxOPjTjA/hVPeqcPEUGUeD/o8nT"
+ "sxOfP0zdiTyJ0O6EpRabk0OMeF6io0iXrlb38Vncks8VCU9C/f3xH9vSJP4mu/TvvI4nonab"
+ "y0Pr4onp4yhJ+6RFZLcJxOFKxqur4ELKvFI2m9xTEl09pzF4RFR41gYlLon3smkRqphBSDuT"
+ "2pSRQmUVFu7yMnHKVUUjZ6K5mGPqwwtr89C6HMeaHceeXeD4iZrTI6NVX1KLUdt3wD3c0XlO"
+ "IZPVV3YSFhaPKYaLQVjKFq/rkkDl39tCsMZTUjZexH0ZoUvE4DRVRqGUPnNGHmJu8oSE432f"
+ "sDjUCzN5XsLiCXbyxCxjthkjz+QYtNAfDB5RijDpYHn/yN47JvLCbDYLNo6k5bPRC5FkJ+lZ"
+ "3Ofk4R4QP6m7dLBMJCwhwmcSFqOnVHtFZyVITwmO0cdr2CfwDELTjkh2ASgTeVMub8/0WYor"
+ "ts50UJD/qV+bMmKmDJN8BDGnTcpBjeVJzhF9SwbWoqofhv1zCIfLY+oyUF3C8i0EUyHaOUFe"
+ "oLa5m1RzRrFpR/ZifiwtFcvoi3KuIr4s7jFdevhyk3tMWlhYaOYMwWgGgQSCdJ7YnBHoFpqZ"
+ "5qpyhmZ8HO089pvEHJGPxzQLVHrYO0/JtawfSenxWTnRriw9ntvaOcU2u0KzFzZP9JI5NJPs"
+ "XLV9NnkhmrV7a/KUMnh3baHPfuwDKKBtIe3k7029fJKeAtBi1EdZKFORi9EWvVg55i9i7wPp"
+ "sspDl8ybx4/A1+cAe/9sqRWyYEhI1nU1y1S0knsGdKVpSl5n17zcbeH4lEIzaRGjrUh/Q6PJ"
+ "pulCOlrHYeVoXIr7QEJjYNqpzWMV+DrEXqo2do31JRMZk2fwc6Je59i8ZdmTZ3Vt8TpkhmNo"
+ "szkJVi2Ni/WIrh07ld6wGPL62tGW6LmdPh7E0J6A9HzPFNaO0UPbJpqTGZsAz2KKZDWyxvVp"
+ "d0xf4BgHExfHKS9I5PBERiHAc8n/vhpT4/q0O/QXOIEBNPkrLYo0TAdU8QAADA4yNAIAIEQA"
+ "AAAhAgBAiAAAAEIEAFikEL2JnqsSNNUQYHM+NsH8CKniQQlKAu6zXD9Cm8HFANpsetgztc9Z"
+ "4aNDRQ/fPrzbN/SWi8BSPs59cLsHPCLboGl+lPlb3PJH5yabzWaQmzZxy6B4Uo8by36520eP"
+ "40SPp4OdjbKxMYgcFzy+b1fW6v+sHW2v1D6VGGEaUzBOIaJpVE8JBupYbfaJq320iAF97HLC"
+ "0nI6VAA2RHgq8rlIJAxViwjRpPIQIwhRa4hiK1FSiDSpQ1z2TTZTz3cU9VbW27P6/zqNa/PY"
+ "fPasPi8ytU842vcu0qX8XDMBeFYbFYN1wvadLN+XLan8GqcmhMjmzv+vtiO7Oh/JZylceR6u"
+ "aJs6N49OLpXDK+JhECU2LHLZ1O17V4+m9v0gYpSib6kA7MV9CpJjQqGnoR4XWJ0BgQr+k8j/"
+ "K3kwMlYBA+nArs6Ug2H/VKJATxY6SOfivtNft1ds/ka/T/s8pkqKIH9LU5fyBP4vmdrZXKhS"
+ "5GkGCxQiPWh2ajDt1VVZl93RV3GpBEkmPkHb3osOx9iV+lW1cUfa8iFueYG/wjSRrlQx9bp2"
+ "7L0cuYquzLukCfp1GtMcOaMrQ2iWK6k8mJkQ6aRSggzOs7jl3tUn6lmkTT7VlphrLW5L6yk9"
+ "r1fSbnriXplgaGKqZhZkPkSyuRnavhzpOHjqUiHSpzE1zRVVrE9zJZUHM5sj0lffgojPRQ0o"
+ "WnanSOwdXIh3oOcOLszm1FfPNqxPTz23j3p0qb07YfB+dJv1cj5NKk+9MXhDECLr1YyuXEky"
+ "YHKuZOkBqXM3yww2qeDtlHfn4oPtH1tymvZp1UOfjoHK4plBhBCaGU8SuuKhy9ZuyEmoQzW9"
+ "ekZPzNArbJvNgl1dc9ik98/Yamw9Gv7e1ya1Z2rfgcxNmdrXpY0mYZeJ93W1tTR4gbqdj+yz"
+ "x0TtBDMRIluFi7Z7WHiRtxRVNfq0ue/43NemqY3vLe0xVefsOpkbkkQ+NuE8bytf9fOpOopJ"
+ "64UL0RBVPJZgc6jqKPRvZYZ9c7Q1RXUUMHEhWkpZlL5tDpqQvucfj866EjDoQYiWUhalb5tL"
+ "+hU5fjEPQnjAgAEADA0yNAIABuevAAMATr+XjPvqrBcAAAAASUVORK5CYII=")
getBottombarsOffData = BottombarsOff.GetData
getBottombarsOffImage = BottombarsOff.GetImage
getBottombarsOffBitmap = BottombarsOff.GetBitmap
#----------------------------------------------------------------------
ToolbarsOn = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9156,138 +9225,146 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDo5MkNEMjgxNTlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDo5MkNEMjgxNDlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDo3MDRCRDA4QkJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo3MDRCRDA4QUJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA1ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5NUZF"
+ "REI1MDhCOEE3MTU2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+GBLuqwAAGNlJREFUeNrsXU2IZNd1vi1N"
- "qiylq2VRg2BqEaYFSYGhIYjGi6yETcDLIJksE0IEIgsLhPBGEcxgiWyyEHjjlQmx8M4iwYTE"
- "KCJkk4VE7XphKlnUEEwPJFOJMjXSuN54pnPv9Dldp2/f+979q1d/3weHV+/Vq7rv53z3nHPf"
- "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")
+ "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"
+ "AElFTkSuQmCC")
getToolbarsOnData = ToolbarsOn.GetData
getToolbarsOnImage = ToolbarsOn.GetImage
getToolbarsOnBitmap = ToolbarsOn.GetBitmap
#----------------------------------------------------------------------
ToolbarsOff = PyEmbeddedImage(
- "iVBORw0KGgoAAAANSUhEUgAAAMsAAADcCAYAAADeKFUQAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "iVBORw0KGgoAAAANSUhEUgAAAMsAAADyCAYAAADjjjFWAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
"ZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl"
"dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1l"
"dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUu"
@@ -9298,131 +9375,139 @@
"YmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9u"
"cy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRp"
"ZDowMTgwMTE3NDA3MjA2ODExOTEwOURDQkFDQjFGMDFEOCIgeG1wTU06RG9jdW1lbnRJRD0i"
- "eG1wLmRpZDo5MkNEMjgxMTlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wTU06SW5zdGFu"
- "Y2VJRD0ieG1wLmlpZDo5MkNEMjgxMDlBODExMUUwODY3Q0U2MzRDNzYzRjNGMiIgeG1wOkNy"
+ "eG1wLmRpZDo3MDRCRDA4N0JBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wTU06SW5zdGFu"
+ "Y2VJRD0ieG1wLmlpZDo3MDRCRDA4NkJBQTUxMUUwQjQ4NkRCM0I1Nzk0NTg3MiIgeG1wOkNy"
"ZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJp"
- "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA1ODAxMTc0MDcyMDY4MTE5OTRD"
- "Qzc2RTMwRTk0MDg1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
+ "dmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAxODAxMTc0MDcyMDY4MTE5NUZF"
+ "REI1MDhCOEE3MTU2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4"
"MTE5MTA5RENCQUNCMUYwMUQ4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv"
- "eDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+oFZZ7AAAGMhJREFUeNrsXU2IJEd2jpbG"
- "VSu5q2VRjaDrYKYF3oKFBiOaPfgkdvHdSIuPNsYC4cMKhNiLLJhhJXzxQbCXPRnjFXtbYbMY"
- "28jC+OKDRN36sJR9qMEsPWBP2fLUSLOVsyM5QvNe16voiMz4q6y/74NH/lRWRWbW++K9Fxnv"
- "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")
+ "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"
+ "SUVORK5CYII=")
getToolbarsOffData = ToolbarsOff.GetData
getToolbarsOffImage = ToolbarsOff.GetImage
getToolbarsOffBitmap = ToolbarsOff.GetBitmap
diff -Nru mmass-3.12.1/gui/images.py mmass-4.0.0/gui/images.py
--- mmass-3.12.1/gui/images.py 2011-06-30 11:47:28.000000000 +0000
+++ mmass-4.0.0/gui/images.py 2011-11-28 11:36:18.000000000 +0000
@@ -115,6 +115,7 @@
lib['bgrToolbar'] = images_lib.getBgrToolbarBitmap()
lib['bgrToolbarNoBorder'] = images_lib.getBgrToolbarNoBorderBitmap()
lib['bgrControlbar'] = images_lib.getBgrControlbarBitmap()
+ lib['bgrControlbarDouble'] = images_lib.getBgrControlbarDoubleBitmap()
lib['bgrBottombar'] = images_lib.getBgrBottombarBitmap()
lib['bgrPeakEditor'] = images_lib.getBgrPeakEditorBitmap()
@@ -132,27 +133,28 @@
# tools
if wx.Platform == '__WXMAC__':
tools = images_lib.getToolsBitmap()
- lib['toolsProcessing'] = tools.GetSubBitmap(wx.Rect(0, 0, 30, 22))
- lib['toolsCalibration'] = tools.GetSubBitmap(wx.Rect(30, 0, 30, 22))
- lib['toolsSequence'] = tools.GetSubBitmap(wx.Rect(60, 0, 30, 22))
- lib['toolsMassCalculator'] = tools.GetSubBitmap(wx.Rect(90, 0, 30, 22))
- lib['toolsCompoundsSearch'] = tools.GetSubBitmap(wx.Rect(120, 0, 30, 22))
- lib['toolsPeakDifferences'] = tools.GetSubBitmap(wx.Rect(150, 0, 30, 22))
- lib['toolsComparePeaklists'] = tools.GetSubBitmap(wx.Rect(180, 0, 30, 22))
- lib['toolsMascot'] = tools.GetSubBitmap(wx.Rect(210, 0, 30, 22))
- lib['toolsProfound'] = tools.GetSubBitmap(wx.Rect(240, 0, 30, 22))
- lib['toolsDocumentInfo'] = tools.GetSubBitmap(wx.Rect(270, 0, 30, 22))
- lib['toolsDocumentReport'] = tools.GetSubBitmap(wx.Rect(300, 0, 30, 22))
- lib['toolsDocumentExport'] = tools.GetSubBitmap(wx.Rect(330, 0, 30, 22))
+ lib['toolsProcessing'] = tools.GetSubBitmap(wx.Rect(0, 0, 30, 23))
+ lib['toolsCalibration'] = tools.GetSubBitmap(wx.Rect(30, 0, 30, 23))
+ lib['toolsSequence'] = tools.GetSubBitmap(wx.Rect(60, 0, 30, 23))
+ lib['toolsMassCalculator'] = tools.GetSubBitmap(wx.Rect(90, 0, 30, 23))
+ lib['toolsCompoundsSearch'] = tools.GetSubBitmap(wx.Rect(120, 0, 30, 23))
+ lib['toolsPeakDifferences'] = tools.GetSubBitmap(wx.Rect(150, 0, 30, 23))
+ lib['toolsComparePeaklists'] = tools.GetSubBitmap(wx.Rect(180, 0, 30, 23))
+ lib['toolsMascot'] = tools.GetSubBitmap(wx.Rect(210, 0, 30, 23))
+ lib['toolsProfound'] = tools.GetSubBitmap(wx.Rect(240, 0, 30, 23))
+ lib['toolsDocumentInfo'] = tools.GetSubBitmap(wx.Rect(270, 0, 30, 23))
+ lib['toolsDocumentReport'] = tools.GetSubBitmap(wx.Rect(300, 0, 30, 23))
+ lib['toolsDocumentExport'] = tools.GetSubBitmap(wx.Rect(330, 0, 30, 23))
lib['toolsPresets'] = tools.GetSubBitmap(wx.Rect(360, 0, 30, 22))
- lib['toolsMassFilter'] = tools.GetSubBitmap(wx.Rect(390, 0, 30, 22))
- lib['toolsSpectrumGenerator'] = tools.GetSubBitmap(wx.Rect(420, 0, 30, 22))
+ lib['toolsMassFilter'] = tools.GetSubBitmap(wx.Rect(390, 0, 30, 23))
+ lib['toolsSpectrumGenerator'] = tools.GetSubBitmap(wx.Rect(420, 0, 30, 23))
+ lib['toolsEnvelopeFit'] = tools.GetSubBitmap(wx.Rect(450, 0, 30, 23))
+ lib['toolsLibrary'] = tools.GetSubBitmap(wx.Rect(480, 0, 30, 22))
else:
tools = images_lib.getToolsBitmap()
lib['toolsOpen'] = tools.GetSubBitmap(wx.Rect(0, 0, 22, 22))
lib['toolsSave'] = tools.GetSubBitmap(wx.Rect(22, 0, 22, 22))
lib['toolsPrint'] = tools.GetSubBitmap(wx.Rect(44, 0, 22, 22))
-
lib['toolsProcessing'] = tools.GetSubBitmap(wx.Rect(66, 0, 22, 22))
lib['toolsCalibration'] = tools.GetSubBitmap(wx.Rect(88, 0, 22, 22))
lib['toolsSequence'] = tools.GetSubBitmap(wx.Rect(110, 0, 22, 22))
@@ -168,6 +170,8 @@
lib['toolsPresets'] = tools.GetSubBitmap(wx.Rect(330, 0, 22, 22))
lib['toolsMassFilter'] = tools.GetSubBitmap(wx.Rect(352, 0, 22, 22))
lib['toolsSpectrumGenerator'] = tools.GetSubBitmap(wx.Rect(374, 0, 22, 22))
+ lib['toolsEnvelopeFit'] = tools.GetSubBitmap(wx.Rect(396, 0, 22, 22))
+ lib['toolsLibrary'] = tools.GetSubBitmap(wx.Rect(418, 0, 22, 22))
# bottombars
bottombarsOn = images_lib.getBottombarsOnBitmap()
@@ -182,25 +186,24 @@
lib['peaklistEditorOn'] = bottombarsOn.GetSubBitmap(wx.Rect(87, 22, 29, 22))
lib['peaklistEditorOff'] = bottombarsOff.GetSubBitmap(wx.Rect(87, 22, 29, 22))
- lib['spectrumParams'] = bottombarsOff.GetSubBitmap(wx.Rect(0, 44, 29, 22))
- lib['spectrumLabelsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(29, 44, 29, 22))
- lib['spectrumLabelsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(29, 44, 29, 22))
- lib['spectrumTicksOn'] = bottombarsOn.GetSubBitmap(wx.Rect(58, 44, 29, 22))
- lib['spectrumTicksOff'] = bottombarsOff.GetSubBitmap(wx.Rect(58, 44, 29, 22))
- lib['spectrumNotationsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(87, 44, 29, 22))
- lib['spectrumNotationsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(87, 44, 29, 22))
- lib['spectrumLabelAngleOn'] = bottombarsOn.GetSubBitmap(wx.Rect(116, 44, 29, 22))
- lib['spectrumLabelAngleOff'] = bottombarsOff.GetSubBitmap(wx.Rect(116, 44, 29, 22))
- lib['spectrumPosBarsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(145, 44, 29, 22))
- lib['spectrumPosBarsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(145, 44, 29, 22))
- lib['spectrumGelOn'] = bottombarsOn.GetSubBitmap(wx.Rect(174, 44, 29, 22))
- lib['spectrumGelOff'] = bottombarsOff.GetSubBitmap(wx.Rect(174, 44, 29, 22))
- lib['spectrumTrackerOn'] = bottombarsOn.GetSubBitmap(wx.Rect(203, 44, 29, 22))
- lib['spectrumTrackerOff'] = bottombarsOff.GetSubBitmap(wx.Rect(203, 44, 29, 22))
- lib['spectrumAutoscaleOn'] = bottombarsOn.GetSubBitmap(wx.Rect(232, 44, 29, 22))
- lib['spectrumAutoscaleOff'] = bottombarsOff.GetSubBitmap(wx.Rect(232, 44, 29, 22))
- lib['spectrumNormalizeOn'] = bottombarsOn.GetSubBitmap(wx.Rect(261, 44, 29, 22))
- lib['spectrumNormalizeOff'] = bottombarsOff.GetSubBitmap(wx.Rect(261, 44, 29, 22))
+ lib['spectrumLabelsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(0, 44, 29, 22))
+ lib['spectrumLabelsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(0, 44, 29, 22))
+ lib['spectrumTicksOn'] = bottombarsOn.GetSubBitmap(wx.Rect(29, 44, 29, 22))
+ lib['spectrumTicksOff'] = bottombarsOff.GetSubBitmap(wx.Rect(29, 44, 29, 22))
+ lib['spectrumNotationsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(58, 44, 29, 22))
+ lib['spectrumNotationsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(58, 44, 29, 22))
+ lib['spectrumLabelAngleOn'] = bottombarsOn.GetSubBitmap(wx.Rect(87, 44, 29, 22))
+ lib['spectrumLabelAngleOff'] = bottombarsOff.GetSubBitmap(wx.Rect(87, 44, 29, 22))
+ lib['spectrumPosBarsOn'] = bottombarsOn.GetSubBitmap(wx.Rect(116, 44, 29, 22))
+ lib['spectrumPosBarsOff'] = bottombarsOff.GetSubBitmap(wx.Rect(116, 44, 29, 22))
+ lib['spectrumGelOn'] = bottombarsOn.GetSubBitmap(wx.Rect(145, 44, 29, 22))
+ lib['spectrumGelOff'] = bottombarsOff.GetSubBitmap(wx.Rect(145, 44, 29, 22))
+ lib['spectrumTrackerOn'] = bottombarsOn.GetSubBitmap(wx.Rect(174, 44, 29, 22))
+ lib['spectrumTrackerOff'] = bottombarsOff.GetSubBitmap(wx.Rect(174, 44, 29, 22))
+ lib['spectrumAutoscaleOn'] = bottombarsOn.GetSubBitmap(wx.Rect(203, 44, 29, 22))
+ lib['spectrumAutoscaleOff'] = bottombarsOff.GetSubBitmap(wx.Rect(203, 44, 29, 22))
+ lib['spectrumNormalizeOn'] = bottombarsOn.GetSubBitmap(wx.Rect(232, 44, 29, 22))
+ lib['spectrumNormalizeOff'] = bottombarsOff.GetSubBitmap(wx.Rect(232, 44, 29, 22))
lib['spectrumLabelPeakOn'] = bottombarsOn.GetSubBitmap(wx.Rect(0, 66, 29, 22))
lib['spectrumLabelPeakOff'] = bottombarsOff.GetSubBitmap(wx.Rect(0, 66, 29, 22))
@@ -661,6 +664,7 @@
"-a -u -n BgrToolbar images/"+platform+"/bgr_toolbar.png images_lib_"+platform+".py",
"-a -u -n BgrToolbarNoBorder images/"+platform+"/bgr_toolbar_noborder.png images_lib_"+platform+".py",
"-a -u -n BgrControlbar images/"+platform+"/bgr_controlbar.png images_lib_"+platform+".py",
+ "-a -u -n BgrControlbarDouble images/"+platform+"/bgr_controlbar_double.png images_lib_"+platform+".py",
"-a -u -n BgrBottombar images/"+platform+"/bgr_bottombar.png images_lib_"+platform+".py",
"-a -u -n BgrPeakEditor images/"+platform+"/bgr_peakeditor.png images_lib_"+platform+".py",
diff -Nru mmass-3.12.1/gui/libs.py mmass-4.0.0/gui/libs.py
--- mmass-3.12.1/gui/libs.py 2011-06-30 11:24:20.000000000 +0000
+++ mmass-4.0.0/gui/libs.py 2011-11-29 12:31:21.000000000 +0000
@@ -16,7 +16,9 @@
# -------------------------------------------------------------------------
# load libs
+import sys
import os.path
+import shutil
import xml.dom.minidom
import copy
@@ -25,11 +27,20 @@
import mspy
+# ENSURE DEFAULT LIBS ARE AVAILABLE AFTER MAC INSTALLATION
+# --------------------------------------------------------
+if sys.platform == 'darwin':
+ for item in ('monomers.xml', 'modifications.xml', 'enzymes.xml', 'presets.xml', 'references.xml', 'compounds.xml', 'mascot.xml'):
+ if not os.path.exists(os.path.join(config.confdir, item)):
+ try: shutil.copyfile(os.path.join('configs', item), os.path.join(config.confdir, item))
+ except: pass
+
+
# LOAD USER'S LIBS INTO MSPY
# --------------------------
-try: mspy.loadAminoacids(os.path.join(config.confdir,'aminoacids.xml'), clear=False)
-except: mspy.saveAminoacids(os.path.join(config.confdir,'aminoacids.xml'))
+try: mspy.loadMonomers(os.path.join(config.confdir,'monomers.xml'), clear=False)
+except: mspy.saveMonomers(os.path.join(config.confdir,'monomers.xml'))
try: mspy.loadModifications(os.path.join(config.confdir,'modifications.xml'), clear=False)
except: mspy.saveModifications(os.path.join(config.confdir,'modifications.xml'))
@@ -76,7 +87,7 @@
'removeIsotopes': 1,
'removeUnknown': 1,
'setAsMonoisotopic': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -118,7 +129,7 @@
'removeIsotopes': 1,
'removeUnknown': 1,
'setAsMonoisotopic': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -160,7 +171,7 @@
'removeIsotopes': 0,
'removeUnknown': 0,
'setAsMonoisotopic': 0,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -176,7 +187,7 @@
'highMass': 4000,
},
'baseline':{
- 'precision': 100,
+ 'precision': 20,
'offset': 0.25,
},
'smoothing':{
@@ -202,7 +213,7 @@
'removeIsotopes': 1,
'removeUnknown': 0,
'setAsMonoisotopic': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -244,7 +255,7 @@
'removeIsotopes': 1,
'removeUnknown': 1,
'setAsMonoisotopic': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -286,7 +297,7 @@
'removeIsotopes': 1,
'removeUnknown': 1,
'setAsMonoisotopic': 1,
- 'labelEnvelope': 'monoisotopic',
+ 'labelEnvelope': '1st',
'envelopeIntensity': 'maximum',
},
'deconvolution':{
@@ -299,15 +310,16 @@
},
'modifications':{
'-None-':[],
- 'Carbamidomethyl (C) Oxidation (MW)':[
+ 'Carbamidomethyl (C)':[
['Carbamidomethyl', 'C', 'f'],
- ['Oxidation', 'M', 'v'],
- ['Oxidation', 'W', 'v'],
],
'Oxidation (MW)':[
['Oxidation', 'M', 'v'],
['Oxidation', 'W', 'v'],
],
+ 'N-Formyl Met':[
+ ['FormylMet', 0, 'v']
+ ],
},
'fragments':{
'-None-':[],
@@ -321,71 +333,7 @@
}
references = {
- 'PepMix Bruker - MALDI Pos Mo':[
- ('Bradykinin (1-7) [M+H]+', 757.399150),
- ('Angiotensin II [M+H]+', 1046.541792),
- ('Angiotensin I [M+H]+', 1296.684768),
- ('Substance P [M+H]+', 1347.735423),
- ('Bombesin [M+H]+', 1619.822341),
- ('ACTH clip (1-17) [M+H]+', 2093.086160),
- ('ACTH clip (18-39) [M+H]+', 2465.198332),
- ('Somatostatin 28 [M+H]+', 3147.470975),
- ],
- 'PepMix Bruker - MALDI Neg Mo':[
- ('Angiotensin II [M-H]-', 1044.527247),
- ('Angiotensin I [M-H]-', 1294.670247),
- ('Substance P [M-H]-', 1345.720847),
- ('Bombesin [M-H]-', 1617.807747),
- ('ACTH clip (1-17) [M-H]-', 2091.071647),
- ('ACTH clip (18-39) [M-H]-', 2463.183747),
- ('Somatostatin 28 [M-H]-', 3145.456447),
- ],
- 'PepMix Bruker PAC - MALDI Pos Mo':[
- ('Bradykinin (1-7) [M+H]+', 757.399160),
- ('Angiotensin III [M+H]+', 931.514849),
- ('Angiotensin II [M+H]+', 1046.541792),
- ('Angiotensin I [M+H]+', 1296.684768),
- ('Substance P [M+H]+', 1347.735423),
- ('Bombesin [M+H]+', 1619.822341),
- ('Neurotensin [M+H]+', 1672.917000),
- ('Renin Substrate [M+H]+', 1758.932610),
- ('ACTH clip (1-17) [M+H]+', 2093.086160),
- ('ACTH clip (18-39) [M+H]+', 2465.198332),
- ('ACTH clip (1-24) [M+H]+', 2932.587870),
- ('Somatostatin 28 [M+H]+', 3147.470975),
- ('ACTH clip (7-38) [M+H]+', 3657.928900),
- ],
- 'ProtMix I Bruker - MALDI Pos Av':[
- ('Insulin [M+H]+', 5735),
- ('Cytochrome C [M+2H]2+', 6181),
- ('Myoglobin [M+2H]2+', 8477),
- ('Ubiquitin I [M+H]+', 8566),
- ('Cytochrom C [M+H]+', 12361),
- ('Myoglobin [M+H]+', 16953),
- ],
- 'ProtMix I Bruker - MALDI Neg Av':[
- ('Insulin [M-H]-', 5733),
- ('Cytochrome C [M-2H]2-', 6179),
- ('Myoglobin [M-2H]2-', 8475),
- ('Ubiquitin I [M-H]-', 8564),
- ('Cytochrom C [M-H]-', 12359),
- ('Myoglobin [M-H]-', 16951),
- ],
- 'ProtMix II Bruker - MALDI Pos Av':[
- ('Trypsinogen [M+H]+', 23982),
- ('Protein A [M+2H]2+', 22306),
- ('Albumin Bovine [M+2H]2+', 33216),
- ('Protein A [M+H]+', 44613),
- ('Albumin Bovine [M+H]+', 66431),
- ],
- 'ProtMix II Bruker - MALDI Neg Av':[
- ('Trypsinogen [M+H]+', 23980),
- ('Protein A [M+2H]2+', 22304),
- ('Albumin Bovine [M+2H]2+', 33214),
- ('Protein A [M+H]+', 44611),
- ('Albumin Bovine [M+H]+', 66429),
- ],
- 'Trypsin Promega (Porcine) - MALDI Pos Mo':[
+ 'Trypsin (Porcine) - MALDI Pos Mo':[
('Trypsin (108-115) [M+H]+', 842.5094),
('Trypsin (209-216) [M+H]+', 906.5044),
('Trypsin (1-8) [M+H]+', 952.3894),
@@ -402,23 +350,6 @@
('Trypsin (78-97) [M+H]+', 2283.1802),
('Trypsin (179-208) [M+H]+', 3013.3237),
],
- 'Trypsin Roche (Bovine) - MALDI Pos Mo':[
- ('Trypsin (112-119) [M+H]+', 805.4163),
- ('Trypsin (160-169) [M+H]+', 1020.503),
- ('Trypsin (229-237) [M+H]+', 1111.5605),
- ('Trypsin (207-220) [M+H]+', 1433.7206),
- ('Trypsin (70-89) [M+H]+', 2163.0564),
- ('Trypsin (90-109) [M+H]+', 2273.1595),
- ],
- 'Trypsin Roche (Porcine) - MALDI Pos Mo':[
- ('Trypsin (108-115) [M+H]+', 842.5094),
- ('Trypsin (134-147) [M+H]+', 1469.7305),
- ('Trypsin (58-74) [M+H]+', 1940.9354),
- ('Trypsin (116-133) [M+H]+', 1768.7993),
- ('Trypsin (98-107) [M+H]+', 1045.5637),
- ('Trypsin (58-77) [M+H]+', 2211.104),
- ('Trypsin (148-157) [M+H]+', 1006.4874),
- ],
'HCCA Clusters - MALDI Pos Mo':[
('HCCA [M+H-H2O]+', 172.039304),
('HCCA [M+H]+', 190.049869),
@@ -528,79 +459,7 @@
('DHB [7M+K]+', 1117.149421),
('DHB [7M+K+Na-H2O]+', 1122.128077),
],
- 'PEG - MALDI Pos':[
- ('C6H15O4 [M+H]+', 151.096485),
- ('C6H14O4 [M+Na]+', 173.078430),
- ('C8H19O5 [M+H]+', 195.122700),
- ('C8H18O5 [M+Na]+', 217.104645),
- ('C10H23O6 [M+H]+', 239.148915),
- ('C10H22O6 [M+Na]+', 261.130860),
- ('C12H27O7 [M+H]+', 283.175130),
- ('C12H26O7 [M+Na]+', 305.157074),
- ('C14H31O8 [M+H]+', 327.201344),
- ('C14H30O8 [M+Na]+', 349.183289),
- ('C16H35O9 [M+H]+', 371.227559),
- ('C16H34O9 [M+Na]+', 393.209504),
- ('C18H39O10 [M+H]+', 415.253774),
- ('C18H38O10 [M+Na]+', 437.235719),
- ('C20H43O11 [M+H]+', 459.279989),
- ('C20H42O11 [M+Na]+', 481.261933),
- ('C22H47O12 [M+H]+', 503.306203),
- ('C22H46O12 [M+Na]+', 525.288148),
- ('C24H51O13 [M+H]+', 547.332418),
- ('C24H50O13 [M+Na]+', 569.314363),
- ('C26H55O14 [M+H]+', 591.358633),
- ('C26H54O14 [M+Na]+', 613.340578),
- ('C28H59O15 [M+H]+', 635.384848),
- ('C28H58O15 [M+Na]+', 657.366792),
- ('C30H62O16 [M+Na]+', 701.393007),
- ('C32H66O17 [M+Na]+', 745.419222),
- ('C34H70O18 [M+Na]+', 789.445437),
- ('C36H74O19 [M+Na]+', 833.471651),
- ('C38H78O20 [M+Na]+', 877.497866),
- ('C40H82O21 [M+Na]+', 921.524081),
- ('C42H86O22 [M+Na]+', 965.550296),
- ('C44H90O23 [M+Na]+', 1009.576510),
- ('C46H94O24 [M+Na]+', 1053.602725),
- ('C48H98O25 [M+Na]+', 1097.628940),
- ('C50H102O26 [M+Na]+', 1141.655155),
- ('C52H106O27 [M+Na]+', 1185.681369),
- ('C54H110O28 [M+Na]+', 1229.707584),
- ('C56H114O29 [M+Na]+', 1273.733799),
- ('C58H118O30 [M+Na]+', 1317.760014),
- ('C60H122O31 [M+Na]+', 1361.786228),
- ('C62H126O32 [M+Na]+', 1405.812443),
- ('C64H130O33 [M+Na]+', 1449.838658),
- ('C66H134O34 [M+Na]+', 1493.864873),
- ('C68H138O35 [M+Na]+', 1537.891087),
- ('C70H142O36 [M+Na]+', 1581.917302),
- ('C72H146O37 [M+Na]+', 1625.943517),
- ('C74H150O38 [M+Na]+', 1669.969732),
- ('C76H154O39 [M+Na]+', 1713.995946),
- ('C78H158O40 [M+Na]+', 1758.022161),
- ('C80H162O41 [M+Na]+', 1802.048376),
- ('C82H166O42 [M+Na]+', 1846.074591),
- ('C84H170O43 [M+Na]+', 1890.100805),
- ('C86H174O44 [M+Na]+', 1934.127020),
- ('C88H178O45 [M+Na]+', 1978.153235),
- ('C90H182O46 [M+Na]+', 2022.179450),
- ('C92H186O47 [M+Na]+', 2066.205664),
- ('C94H190O48 [M+Na]+', 2110.231879),
- ('C96H194O49 [M+Na]+', 2154.258094),
- ('C98H198O50 [M+Na]+', 2198.284309),
- ('C100H2O2O51 [M+Na]+', 2242.310523),
- ('C104H210O53 [M+Na]+', 2330.362953),
- ('C108H218O55 [M+Na]+', 2418.415382),
- ('C112H226O57 [M+Na]+', 2506.467812),
- ('C116H234O59 [M+Na]+', 2594.520241),
- ('C120H242O61 [M+Na]+', 2682.572671),
- ('C124H250O63 [M+Na]+', 2770.652100),
- ('C128H258O65 [M+Na]+', 2858.677530),
- ('C132H266O67 [M+Na]+', 2946.729959),
- ('C136H274O69 [M+Na]+', 3034.782389),
- ('C140H282O71 [M+Na]+', 3122.834828),
- ],
- 'Contaminants - Trypsin In-Gel - MALDI Pos Mo':[
+ 'In-Gel (Trypsin) - MALDI Pos Mo':[
('Keratin 10 [M+H]+', 1165.5853),
('Keratin 1/II [M+H]+', 1179.6010),
('Keratin 1/II [M+H]+', 1300.5302),
@@ -643,7 +502,7 @@
# LOAD FUNCTIONS
# --------------
-def loadPresets(path=os.path.join(config.confdir, 'presets.xml'), clear=False):
+def loadPresets(path=os.path.join(config.confdir, 'presets.xml'), clear=True, replace=True):
"""Parse processing presets XML and get data."""
container = {}
@@ -734,14 +593,15 @@
# update current lib
for group in container:
- if clear:
+ if container[group] and clear:
presets[group].clear()
for key in container[group]:
- presets[group][key] = container[group][key]
+ if replace or not key in presets[group]:
+ presets[group][key] = container[group][key]
# ----
-def loadReferences(path=os.path.join(config.confdir, 'references.xml'), clear=False):
+def loadReferences(path=os.path.join(config.confdir, 'references.xml'), clear=True):
"""Parse calibration references XML and get data."""
container = {}
@@ -764,14 +624,14 @@
container[groupName].append((name, float(mass)))
# update current lib
- if clear:
+ if container and clear:
references.clear()
for group in container:
references[group] = container[group]
# ----
-def loadCompounds(path=os.path.join(config.confdir, 'compounds.xml'), clear=False):
+def loadCompounds(path=os.path.join(config.confdir, 'compounds.xml'), clear=True):
"""Parse compounds XML and get data."""
container = {}
@@ -798,14 +658,14 @@
pass
# update current lib
- if clear:
+ if container and clear:
compounds.clear()
for group in container:
compounds[group] = container[group]
# ----
-def loadMascot(path=os.path.join(config.confdir, 'mascot.xml'), clear=False):
+def loadMascot(path=os.path.join(config.confdir, 'mascot.xml'), clear=True, replace=True):
"""Parse mascot servers XML and get data."""
container = {}
@@ -829,7 +689,7 @@
_getParams(serverTag, container[name])
# update current lib
- if clear:
+ if container and clear:
mascot.clear()
for server in container:
mascot[server] = container[server]
@@ -1003,7 +863,7 @@
for group in sorted(compounds.keys()):
buff += ' \n' % (_escape(group))
for name, compound in sorted(compounds[group].items()):
- buff += ' %s\n' % (_escape(name), compound.rawFormula, _escape(compound.description))
+ buff += ' %s\n' % (_escape(name), compound.expression, _escape(compound.description))
buff += ' \n\n'
buff += ''
diff -Nru mmass-3.12.1/gui/main_frame.py mmass-4.0.0/gui/main_frame.py
--- mmass-3.12.1/gui/main_frame.py 2011-08-28 19:04:07.000000000 +0000
+++ mmass-4.0.0/gui/main_frame.py 2011-11-30 17:49:23.000000000 +0000
@@ -63,11 +63,13 @@
from panel_sequence import panelSequence
from panel_spectrum import panelSpectrum, dlgViewRange, dlgSpectrumOffset
from panel_spectrum_generator import panelSpectrumGenerator
+from panel_envelope_fit import panelEnvelopeFit
from dlg_compounds_editor import dlgCompoundsEditor
from dlg_enzymes_editor import dlgEnzymesEditor
from dlg_mascot_editor import dlgMascotEditor
from dlg_modifications_editor import dlgModificationsEditor
+from dlg_monomers_editor import dlgMonomersEditor
from dlg_presets_editor import dlgPresetsEditor
from dlg_references_editor import dlgReferencesEditor
@@ -170,6 +172,8 @@
document.Append(ID_documentCloseAll, "Close All"+HK_documentCloseAll, "")
document.Append(ID_documentSave, "Save"+HK_documentSave, "")
document.Append(ID_documentSaveAs, "Save As..."+HK_documentSaveAs, "")
+ document.Append(ID_documentSaveAll, "Save All"+HK_documentSaveAll, "")
+ document.AppendSeparator()
document.Append(ID_documentExport, "Export..."+HK_documentExport, "")
document.AppendSeparator()
document.Append(ID_documentPrintSpectrum, "Print Spectrum..."+HK_documentPrintSpectrum, "")
@@ -188,6 +192,7 @@
self.Bind(wx.EVT_MENU, self.onDocumentCloseAll, id=ID_documentCloseAll)
self.Bind(wx.EVT_MENU, self.onDocumentSave, id=ID_documentSave)
self.Bind(wx.EVT_MENU, self.onDocumentSave, id=ID_documentSaveAs)
+ self.Bind(wx.EVT_MENU, self.onDocumentSaveAll, id=ID_documentSaveAll)
self.Bind(wx.EVT_MENU, self.onDocumentExport, id=ID_documentExport)
self.Bind(wx.EVT_MENU, self.onDocumentInfo, id=ID_documentInfo)
self.Bind(wx.EVT_MENU, self.onDocumentPrintSpectrum, id=ID_documentPrintSpectrum)
@@ -377,12 +382,15 @@
sequence.Append(ID_sequenceFragment, "Fragment Peptide...", "")
sequence.Append(ID_sequenceSearch, "Mass Search...", "")
sequence.AppendSeparator()
+ sequence.Append(ID_sequenceSendToMassCalculator, "Show Isotopic Pattern...", "")
+ sequence.Append(ID_sequenceSendToEnvelopeFit, "Send to Envelope Fit...", "")
+ sequence.AppendSeparator()
sequence.Append(ID_sequenceMatchesCalibrateBy, "Calibrate by Matches...", "")
sequence.AppendSeparator()
sequence.Append(ID_sequenceMatchesDelete, "Delete All Matches", "")
sequence.Append(ID_sequenceDelete, "Delete Sequence", "")
sequence.AppendSeparator()
- sequence.Append(ID_sequenceSort, "Sort By Titles", "")
+ sequence.Append(ID_sequenceSort, "Sort by Titles", "")
self.Bind(wx.EVT_MENU, self.onSequenceNew, id=ID_sequenceNew)
self.Bind(wx.EVT_MENU, self.onSequenceImport, id=ID_sequenceImport)
@@ -391,6 +399,8 @@
self.Bind(wx.EVT_MENU, self.onToolsSequence, id=ID_sequenceDigest)
self.Bind(wx.EVT_MENU, self.onToolsSequence, id=ID_sequenceFragment)
self.Bind(wx.EVT_MENU, self.onToolsSequence, id=ID_sequenceSearch)
+ self.Bind(wx.EVT_MENU, self.onSequenceSendToMassCalculator, id=ID_sequenceSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onSequenceSendToEnvelopeFit, id=ID_sequenceSendToEnvelopeFit)
self.Bind(wx.EVT_MENU, self.onSequenceMatchesCalibrateBy, id=ID_sequenceMatchesCalibrateBy)
self.Bind(wx.EVT_MENU, self.onSequenceMatchesDelete, id=ID_sequenceMatchesDelete)
self.Bind(wx.EVT_MENU, self.onSequenceDelete, id=ID_sequenceDelete)
@@ -404,16 +414,17 @@
tools.Append(ID_toolsLabelPoint, "Label Point"+HK_toolsLabelPoint, "", wx.ITEM_RADIO)
tools.Append(ID_toolsLabelEnvelope, "Label Envelope"+HK_toolsLabelEnvelope, "", wx.ITEM_RADIO)
tools.Append(ID_toolsDeleteLabel, "Delete Label"+HK_toolsDeleteLabel, "", wx.ITEM_RADIO)
- tools.Append(ID_toolsMeasure, "Measure Distances"+HK_toolsMeasure, "", wx.ITEM_RADIO)
+ tools.Append(ID_toolsMeasure, "Measure Distance"+HK_toolsMeasure, "", wx.ITEM_RADIO)
tools.Append(ID_toolsOffset, "Offset Spectrum", "", wx.ITEM_RADIO)
tools.AppendSeparator()
tools.Append(ID_toolsPeriodicTable, "Periodic Table"+HK_toolsPeriodicTable, "")
- tools.Append(ID_toolsMasscalc, "Mass Calculator"+HK_toolsMasscalc, "")
+ tools.Append(ID_toolsMassCalculator, "Mass Calculator"+HK_toolsMassCalculator, "")
tools.Append(ID_toolsMassFilter, "Mass Filter"+HK_toolsMassFilter, "")
tools.Append(ID_toolsCompoundsSearch, "Compounds Search"+HK_toolsCompoundsSearch, "")
tools.Append(ID_toolsPeakDifferences, "Peak Differences"+HK_toolsPeakDifferences, "")
tools.Append(ID_toolsComparePeaklists, "Compare Peak Lists"+HK_toolsComparePeaklists, "")
tools.Append(ID_toolsSpectrumGenerator, "Spectrum Generator"+HK_toolsSpectrumGenerator, "")
+ tools.Append(ID_toolsEnvelopeFit, "Envelope Fit"+HK_toolsEnvelopeFit, "")
tools.AppendSeparator()
tools.Append(ID_mascotPMF, "Mascot PMF", "")
tools.Append(ID_mascotMIS, "Mascot MS/MS Search", "")
@@ -431,12 +442,13 @@
self.Bind(wx.EVT_MENU, self.onToolsSpectrum, id=ID_toolsMeasure)
self.Bind(wx.EVT_MENU, self.onToolsSpectrum, id=ID_toolsOffset)
self.Bind(wx.EVT_MENU, self.onToolsPeriodicTable, id=ID_toolsPeriodicTable)
- self.Bind(wx.EVT_MENU, self.onToolsMassCalculator, id=ID_toolsMasscalc)
+ self.Bind(wx.EVT_MENU, self.onToolsMassCalculator, id=ID_toolsMassCalculator)
self.Bind(wx.EVT_MENU, self.onToolsMassFilter, id=ID_toolsMassFilter)
self.Bind(wx.EVT_MENU, self.onToolsCompoundsSearch, id=ID_toolsCompoundsSearch)
self.Bind(wx.EVT_MENU, self.onToolsPeakDifferences, id=ID_toolsPeakDifferences)
self.Bind(wx.EVT_MENU, self.onToolsComparePeaklists, id=ID_toolsComparePeaklists)
self.Bind(wx.EVT_MENU, self.onToolsSpectrumGenerator, id=ID_toolsSpectrumGenerator)
+ self.Bind(wx.EVT_MENU, self.onToolsEnvelopeFit, id=ID_toolsEnvelopeFit)
self.Bind(wx.EVT_MENU, self.onToolsMascot, id=ID_mascotPMF)
self.Bind(wx.EVT_MENU, self.onToolsMascot, id=ID_mascotMIS)
self.Bind(wx.EVT_MENU, self.onToolsMascot, id=ID_mascotSQ)
@@ -450,20 +462,22 @@
# libraries
libraries = wx.Menu()
+ libraries.Append(ID_libraryCompounds, "Compounds...", "")
libraries.Append(ID_libraryModifications, "Modifications...", "")
+ libraries.Append(ID_libraryMonomers, "Monomers...", "")
libraries.Append(ID_libraryEnzymes, "Enzymes...", "")
- libraries.Append(ID_libraryCompounds, "Compounds...", "")
libraries.Append(ID_libraryReferences, "Reference Masses...", "")
libraries.Append(ID_libraryMascot, "Mascot Servers...", "")
libraries.AppendSeparator()
libraries.Append(ID_libraryPresets, "Presets...", "")
+ self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryCompounds)
self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryModifications)
+ self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryMonomers)
self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryEnzymes)
- self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryCompounds)
self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryReferences)
- self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryPresets)
self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryMascot)
+ self.Bind(wx.EVT_MENU, self.onLibraryEdit, id=ID_libraryPresets)
self.menubar.Append(libraries, "Libraries")
@@ -545,6 +559,8 @@
# help
help = wx.Menu()
+ help.Append(ID_helpUserGuide, "User's Guide...", "")
+ help.AppendSeparator()
help.Append(ID_helpHomepage, "Homepage...", "")
help.Append(ID_helpForum, "Support Forum...", "")
help.Append(ID_helpTwitter, "Twitter...", "")
@@ -557,13 +573,14 @@
help.AppendSeparator()
help.Append(ID_helpAbout, "About mMass", "")
+ self.Bind(wx.EVT_MENU, self.onHelpUserGuide, id=ID_helpUserGuide)
self.Bind(wx.EVT_MENU, self.onLibraryLink, id=ID_helpHomepage)
self.Bind(wx.EVT_MENU, self.onLibraryLink, id=ID_helpForum)
self.Bind(wx.EVT_MENU, self.onLibraryLink, id=ID_helpTwitter)
self.Bind(wx.EVT_MENU, self.onLibraryLink, id=ID_helpCite)
self.Bind(wx.EVT_MENU, self.onLibraryLink, id=ID_helpDonate)
- self.Bind(wx.EVT_MENU, self.onUpdate, id=ID_helpUpdate)
- self.Bind(wx.EVT_MENU, self.onAbout, id=ID_helpAbout)
+ self.Bind(wx.EVT_MENU, self.onHelpUpdate, id=ID_helpUpdate)
+ self.Bind(wx.EVT_MENU, self.onHelpAbout, id=ID_helpAbout)
self.menubar.Append(help, "&Help")
# ----
@@ -592,25 +609,33 @@
# tools
self.toolbar.AddLabelTool(ID_toolsProcessing, "Processing", images.lib['toolsProcessing'], shortHelp="Data processing...", longHelp="Mass spectrum processing")
self.toolbar.AddLabelTool(ID_toolsCalibration, "Calibration", images.lib['toolsCalibration'], shortHelp="Re-calibrate data...", longHelp="Mass spectrum calibration")
+
+ self.toolbar.AddSeparator()
+
self.toolbar.AddLabelTool(ID_toolsSequence, "Sequence", images.lib['toolsSequence'], shortHelp="Sequence editor...", longHelp="Sequence editor and tool")
- self.toolbar.AddLabelTool(ID_toolsMasscalc, "Masscalc", images.lib['toolsMassCalculator'], shortHelp="Mass calculator...", longHelp="Calculate ion series and isotopic pattern")
+ self.toolbar.AddLabelTool(ID_toolsMassCalculator, "Masscalc", images.lib['toolsMassCalculator'], shortHelp="Mass calculator...", longHelp="Calculate ion series and isotopic pattern")
self.toolbar.AddLabelTool(ID_toolsMassFilter, "Mass Filter", images.lib['toolsMassFilter'], shortHelp="Mass filter...", longHelp="Filter spectrum contaminants")
self.toolbar.AddLabelTool(ID_toolsCompoundsSearch, "Compounds", images.lib['toolsCompoundsSearch'], shortHelp="Compounds search...", longHelp="Search for compounds")
self.toolbar.AddLabelTool(ID_toolsPeakDifferences, "Differences", images.lib['toolsPeakDifferences'], shortHelp="Peak differences...", longHelp="Calculate peak differences")
self.toolbar.AddLabelTool(ID_toolsComparePeaklists, "Compare", images.lib['toolsComparePeaklists'], shortHelp="Compare peak lists...", longHelp="Compare multiple peaklists")
self.toolbar.AddLabelTool(ID_toolsSpectrumGenerator, "Generator", images.lib['toolsSpectrumGenerator'], shortHelp="Generate mass spectrum...", longHelp="Generate mass spectrum from current peak list")
+ self.toolbar.AddLabelTool(ID_toolsEnvelopeFit, "Envelope Fit", images.lib['toolsEnvelopeFit'], shortHelp="Calculate atom exchange...", longHelp="Calculate atom exchange from peak envelope")
+
+ self.toolbar.AddSeparator()
+
self.toolbar.AddLabelTool(ID_toolsMascot, "Mascot", images.lib['toolsMascot'], shortHelp="Mascot search...", longHelp="Send data to Mascot server")
self.toolbar.AddLabelTool(ID_toolsProfound, "ProFound", images.lib['toolsProfound'], shortHelp="ProFound search...", longHelp="Send data to ProFound server")
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsProcessing, id=ID_toolsProcessing)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsCalibration, id=ID_toolsCalibration)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsSequence, id=ID_toolsSequence)
- self.toolbar.Bind(wx.EVT_TOOL, self.onToolsMassCalculator, id=ID_toolsMasscalc)
+ self.toolbar.Bind(wx.EVT_TOOL, self.onToolsMassCalculator, id=ID_toolsMassCalculator)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsMassFilter, id=ID_toolsMassFilter)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsCompoundsSearch, id=ID_toolsCompoundsSearch)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsPeakDifferences, id=ID_toolsPeakDifferences)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsComparePeaklists, id=ID_toolsComparePeaklists)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsSpectrumGenerator, id=ID_toolsSpectrumGenerator)
+ self.toolbar.Bind(wx.EVT_TOOL, self.onToolsEnvelopeFit, id=ID_toolsEnvelopeFit)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsMascot, id=ID_toolsMascot)
self.toolbar.Bind(wx.EVT_TOOL, self.onToolsProfound, id=ID_toolsProfound)
@@ -625,11 +650,11 @@
self.toolbar.Bind(wx.EVT_TOOL, self.onDocumentExport, id=ID_toolsDocumentExport)
# search
- if wx.Platform == '__WXMAC__':
- self.toolbar.AddSeparator()
- self.search = wx.SearchCtrl(self.toolbar, -1, size=(150, -1), style=wx.TE_PROCESS_ENTER, validator=mwx.validator('floatPos'))
- self.search.Bind(wx.EVT_TEXT, self.onToolsSearch)
- self.toolbar.AddControl(self.search)
+ # if wx.Platform == '__WXMAC__':
+ # self.toolbar.AddSeparator()
+ # self.search = wx.SearchCtrl(self.toolbar, -1, size=(150, -1), style=wx.TE_PROCESS_ENTER, validator=mwx.validator('floatPos'))
+ # self.search.Bind(wx.EVT_TEXT, self.onToolsSearch)
+ # self.toolbar.AddControl(self.search)
# ----
@@ -655,6 +680,7 @@
self.peakDifferencesPanel = None
self.comparePeaklistsPanel = None
self.spectrumGeneratorPanel = None
+ self.envelopeFitPanel = None
self.sequencePanel = None
self.mascotPanel = None
self.profoundPanel = None
@@ -753,57 +779,6 @@
# ----
- def onAbout(self, evt):
- """Show About mMass panel."""
-
- about = panelAbout(self)
- about.Centre()
- about.Show()
- about.SetFocus()
- # ----
-
-
- def onUpdate(self, evt=None):
- """Check for available updates."""
-
- # check for available updates
- if not self.getAvailableUpdates():
- wx.Bell()
- title = 'Update Error!'
- message = 'An error occured in retrieving update information.\nPlease try again later.'
- buttons = [(wx.ID_CANCEL, "Cancel Update", -1, True, 0)]
- dlg = mwx.dlgMessage(self, title, message, buttons)
- dlg.ShowModal()
- dlg.Destroy()
- return
-
- # newer version is available
- if config.main['updatesAvailable'] != config.version or config.nightbuild:
- if config.nightbuild:
- title = 'Different stable version of mMass is available.'
- message = "Version %s is the latest stable version available for download.\nYou are currently using test version %s (%s)." % (config.main['updatesAvailable'], config.version, config.nightbuild)
- else:
- title = 'A newer version of mMass is available from mMass.org'
- message = "Version %s is now available for download.\nYou are currently using version %s." % (config.main['updatesAvailable'], config.version)
- buttons = [(wx.ID_CANCEL, "Ask Again Later", -1, False, 15), (wx.ID_OK, "Upgrade Now", -1, True, 0)]
- dlg = mwx.dlgMessage(self, title, message, buttons)
- if dlg.ShowModal() == wx.ID_OK:
- dlg.Destroy()
- try: webbrowser.open(config.links['mMassDownload'], autoraise=1)
- except: pass
- else:
- dlg.Destroy()
-
- # you are up to date
- else:
- title = "You're up to date!"
- message = "mMass %s is currently the newest version available." % config.version
- dlg = mwx.dlgMessage(self, title, message)
- dlg.ShowModal()
- dlg.Destroy()
- # ----
-
-
def onPreferences(self, evt):
"""Show mMass preferences."""
@@ -890,6 +865,10 @@
if self.spectrumGeneratorPanel:
self.spectrumGeneratorPanel.setData(docData)
+ # update envelope fit panel
+ if self.envelopeFitPanel:
+ self.envelopeFitPanel.setData(docData)
+
# update sequence panel
if self.sequencePanel:
self.sequencePanel.setData(None)
@@ -959,29 +938,35 @@
# update data-dependent panels
if 'spectrum' in items:
+ docData = self.documents[self.currentDocument]
+
# update document info panel
if self.documentInfoPanel:
- self.documentInfoPanel.setData(self.documents[self.currentDocument])
+ self.documentInfoPanel.setData(docData)
# update mascot panel
if self.mascotPanel:
- self.mascotPanel.setData(self.documents[self.currentDocument])
+ self.mascotPanel.setData(docData)
# update profound panel
if self.profoundPanel:
- self.profoundPanel.setData(self.documents[self.currentDocument])
+ self.profoundPanel.setData(docData)
# update prospector panel
if self.prospectorPanel:
- self.prospectorPanel.setData(self.documents[self.currentDocument])
+ self.prospectorPanel.setData(docData)
# update differences panel
if self.peakDifferencesPanel:
- self.peakDifferencesPanel.setData(self.documents[self.currentDocument])
+ self.peakDifferencesPanel.setData(docData)
# update spectrum generator panel
if self.spectrumGeneratorPanel:
- self.spectrumGeneratorPanel.setData(self.documents[self.currentDocument])
+ self.spectrumGeneratorPanel.setData(docData)
+
+ # update envelope fit panel
+ if self.envelopeFitPanel:
+ self.envelopeFitPanel.setData(docData)
# update sequence panel
if self.sequencePanel:
@@ -1204,7 +1189,6 @@
self.documentsPanel.deleteDocument(docIndex)
self.spectrumPanel.deleteSpectrum(docIndex)
del self.documents[docIndex]
- self.currentDocument = None
# select previous visible document
if selectPrevious:
@@ -1252,6 +1236,8 @@
self.comparePeaklistsPanel.Close()
if self.spectrumGeneratorPanel:
self.spectrumGeneratorPanel.Close()
+ if self.envelopeFitPanel:
+ self.envelopeFitPanel.Close()
if self.sequencePanel:
self.sequencePanel.Close()
if self.mascotPanel:
@@ -1296,20 +1282,30 @@
# ----
- def onDocumentSave(self, evt=None):
+ def onDocumentSave(self, evt=None, docIndex=None):
"""Save current document."""
# check document
- if self.currentDocument == None:
+ if docIndex == None:
+ docIndex = self.currentDocument
+ if docIndex == None:
wx.Bell()
return False
# get document
- document = self.documents[self.currentDocument]
+ document = self.documents[docIndex]
path = document.path
# check doctype and ask to save
if not path or document.format != 'mSD' or (evt and evt.GetId()==ID_documentSaveAs):
+
+ # ensure document is selected
+ if docIndex != self.currentDocument:
+ if not self.documents[docIndex].visible:
+ self.onDocumentEnable(docIndex)
+ self.documentsPanel.selectDocument(docIndex)
+
+ # ask for name
fileName = document.title+'.msd'
dlg = wx.FileDialog(self, "Save", config.main['lastDir'], fileName, "mMass Spectrum Document|*.msd", wx.SAVE|wx.OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK:
@@ -1325,7 +1321,7 @@
gauge.show()
# get document XML
- process = threading.Thread(target=self.runDocumentSave)
+ process = threading.Thread(target=self.runDocumentSave, kwargs={'docIndex':docIndex})
process.start()
while process.isAlive():
gauge.pulse()
@@ -1350,6 +1346,14 @@
# processing failed
if failed:
wx.Bell()
+
+ # ensure document is selected
+ if docIndex != self.currentDocument:
+ if not self.documents[docIndex].visible:
+ self.onDocumentEnable(docIndex)
+ self.documentsPanel.selectDocument(docIndex)
+
+ # show error message
dlg = mwx.dlgMessage(self, title="Unable to save the document.", message='Please ensure that you have sufficient permissions\nto write into the document folder.')
dlg.ShowModal()
dlg.Destroy()
@@ -1360,22 +1364,33 @@
document.path = path
document.dirty = False
- # update document and app title
- self.documentsPanel.updateDocumentTitle(self.currentDocument)
- title = 'mMass - %s' % (self.documents[self.currentDocument].title)
- self.SetTitle(title)
+ # update document title
+ self.documentsPanel.updateDocumentTitle(docIndex)
+
+ # update app title
+ if docIndex == self.currentDocument:
+ title = 'mMass - %s' % (self.documents[docIndex].title)
+ self.SetTitle(title)
+ self.updateControls()
# update recent files
self.updateRecentFiles(path)
- # update menubar and toolbar
- self.updateControls()
-
# document saved
return True
# ----
+ def onDocumentSaveAll(self, evt=None):
+ """Save all documents."""
+
+ # save documents
+ for docIndex, document in enumerate(self.documents):
+ if document.dirty:
+ self.onDocumentSave(docIndex=docIndex)
+ # ----
+
+
def onDocumentPrintSpectrum(self, evt):
"""Print spectrum."""
@@ -1826,7 +1841,7 @@
self.spectrumPanel.updateCanvasProperties(ID)
self.spectrumPanel.spectrumCanvas.SetFocus()
- # update spectrum generator
+ # update spectrum generator panel
if self.spectrumGeneratorPanel:
self.spectrumGeneratorPanel.updateCanvasProperties()
# ----
@@ -2175,14 +2190,14 @@
intensity = 2*baseline
# set data
- self.massCalculatorPanel.setData( \
- formula=formula, \
- charge=charge, \
- agentFormula=agentFormula, \
- agentCharge=agentCharge, \
- fwhm=fwhm, \
- intensity=intensity, \
- baseline=baseline \
+ self.massCalculatorPanel.setData(
+ formula = formula,
+ charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge,
+ fwhm = fwhm,
+ intensity = intensity,
+ baseline = baseline
)
# raise panel
@@ -2331,6 +2346,49 @@
# ----
+ def onToolsEnvelopeFit(self, evt=None, formula=None, sequence=None, charge=None, scale=None):
+ """Show envelope fit panel."""
+
+ # check document
+ if not self.envelopeFitPanel and self.currentDocument == None:
+ wx.Bell()
+ return
+
+ # destroy panel
+ if self.envelopeFitPanel and evt:
+ self.envelopeFitPanel.Close()
+ return
+
+ # init panel
+ if not self.envelopeFitPanel:
+ self.envelopeFitPanel = panelEnvelopeFit(self)
+ self.envelopeFitPanel.Centre()
+ self.envelopeFitPanel.Show(True)
+
+ # get current document
+ docData = None
+ if self.currentDocument != None:
+ docData = self.documents[self.currentDocument]
+
+ # get data from sequence
+ if sequence != None:
+ formula = sequence.formula()
+ if scale == None and config.envfit['loss'] == 'H' and config.envfit['gain'] == 'H{2}':
+ scale = (0, len(sequence) - sequence.count('P') - 1)
+
+ # set current data
+ self.envelopeFitPanel.setData(
+ document = docData,
+ formula = formula,
+ charge = charge,
+ scale = scale
+ )
+
+ # raise panel
+ self.envelopeFitPanel.Raise()
+ # ----
+
+
def onToolsMascot(self, evt=None):
"""Show Mascot search panel."""
@@ -2521,8 +2579,8 @@
if self.sequencePanel:
self.sequencePanel.setData(seqData)
- # update menubar and toolbar
- self.updateControls()
+ # update menubar and toolbar
+ self.updateControls()
# ----
@@ -2694,6 +2752,39 @@
# ----
+ def onSequenceSendToMassCalculator(self, evt):
+ """Show isotopic pattern of current sequence."""
+
+ # check selection
+ if self.currentDocument == None or self.currentSequence == None:
+ wx.Bell()
+ return
+
+ # get data
+ seqData = self.documents[self.currentDocument].sequences[self.currentSequence]
+ formula = seqData.formula()
+
+ # send data to Mass Calculator
+ self.onToolsMassCalculator(formula=formula)
+ # ----
+
+
+ def onSequenceSendToEnvelopeFit(self, evt):
+ """Send current sequence to envelope fit tool."""
+
+ # check selection
+ if self.currentDocument == None or self.currentSequence == None:
+ wx.Bell()
+ return
+
+ # get data
+ seqData = self.documents[self.currentDocument].sequences[self.currentSequence]
+
+ # send data to envelope fit
+ self.onToolsEnvelopeFit(sequence=seqData)
+ # ----
+
+
# LIBRARIES
@@ -2701,35 +2792,39 @@
"""Edit library."""
# set library to edit
- if evt.GetId() == ID_libraryModifications:
+ if evt.GetId() == ID_libraryCompounds:
+ library = 'compounds'
+ dlg = dlgCompoundsEditor(self)
+
+ elif evt.GetId() == ID_libraryModifications:
library = 'modifications'
dlg = dlgModificationsEditor(self)
+ elif evt.GetId() == ID_libraryMonomers:
+ library = 'monomers'
+ dlg = dlgMonomersEditor(self)
+
elif evt.GetId() == ID_libraryEnzymes:
library = 'enzymes'
dlg = dlgEnzymesEditor(self)
- elif evt.GetId() == ID_libraryCompounds:
- library = 'compounds'
- dlg = dlgCompoundsEditor(self)
-
elif evt.GetId() == ID_libraryReferences:
library = 'references'
dlg = dlgReferencesEditor(self)
- elif evt.GetId() == ID_libraryPresets:
- library = 'presets'
- dlg = dlgPresetsEditor(self)
-
elif evt.GetId() == ID_libraryMascot:
library = 'mascot'
dlg = dlgMascotEditor(self)
+ elif evt.GetId() == ID_libraryPresets:
+ library = 'presets'
+ dlg = dlgPresetsEditor(self)
+
# close related panels
- if library in ('modifications', 'enzymes') and self.sequencePanel:
- self.sequencePanel.Close()
- elif library == 'compounds' and self.compoundsSearchPanel:
+ if library == 'compounds' and self.compoundsSearchPanel:
self.compoundsSearchPanel.Close()
+ elif library in ('modifications', 'monomers', 'enzymes') and self.sequencePanel:
+ self.sequencePanel.Close()
elif library == 'references':
if self.calibrationPanel:
self.calibrationPanel.Close()
@@ -2854,6 +2949,99 @@
+ # HELP
+
+ def onHelpUserGuide(self, evt):
+ """Open User's Guide PDF."""
+
+ # get path
+ if sys.platform == 'darwin':
+ path = ''
+ else:
+ path = os.path.sep
+ for folder in os.path.dirname(os.path.realpath(__file__)).split(os.path.sep)[:-1]:
+ tmp = os.path.join(path, folder)
+ if os.path.isdir(tmp):
+ path = tmp
+
+ path = os.path.join(path, "User Guide.pdf")
+
+ # check path
+ if not os.path.exists(path):
+ wx.Bell()
+ dlg = mwx.dlgMessage(self, title="User's Guide PDF doesn't exists.", message="Please go to the mMass website, download the User's Guide PDF\nand move it into your mMass application folder.")
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ # try to open pdf
+ try:
+ if wx.Platform == '__WXMSW__':
+ os.startfile(path)
+ else:
+ try: subprocess.Popen(['xdg-open', path])
+ except: subprocess.Popen(['open', path])
+ except:
+ wx.Bell()
+ dlg = mwx.dlgMessage(self, title="Unable to open User's Guide.", message="Please make sure that you have any application associated\nwith a PDF format.")
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+ # ----
+
+
+ def onHelpUpdate(self, evt=None):
+ """Check for available updates."""
+
+ # check for available updates
+ if not self.getAvailableUpdates():
+ wx.Bell()
+ title = 'Update Error!'
+ message = 'An error occured in retrieving update information.\nPlease try again later.'
+ buttons = [(wx.ID_CANCEL, "Cancel Update", -1, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
+ # newer version is available
+ if config.main['updatesAvailable'] != config.version or config.nightbuild:
+ if config.nightbuild:
+ title = 'Different stable version of mMass is available.'
+ message = "Version %s is the latest stable version available for download.\nYou are currently using test version %s (%s)." % (config.main['updatesAvailable'], config.version, config.nightbuild)
+ else:
+ title = 'A newer version of mMass is available from mMass.org'
+ message = "Version %s is now available for download.\nYou are currently using version %s." % (config.main['updatesAvailable'], config.version)
+ buttons = [(wx.ID_CANCEL, "Ask Again Later", -1, False, 15), (wx.ID_OK, "Upgrade Now", -1, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ if dlg.ShowModal() == wx.ID_OK:
+ dlg.Destroy()
+ try: webbrowser.open(config.links['mMassDownload'], autoraise=1)
+ except: pass
+ else:
+ dlg.Destroy()
+
+ # you are up to date
+ else:
+ title = "You're up to date!"
+ message = "mMass %s is currently the newest version available." % config.version
+ dlg = mwx.dlgMessage(self, title, message)
+ dlg.ShowModal()
+ dlg.Destroy()
+ # ----
+
+
+ def onHelpAbout(self, evt):
+ """Show About mMass panel."""
+
+ about = panelAbout(self)
+ about.Centre()
+ about.Show()
+ about.SetFocus()
+ # ----
+
+
+
# DOCUMENT IMPORT
def importDocumentQueue(self):
@@ -3184,12 +3372,11 @@
# ----
- def runDocumentSave(self):
+ def runDocumentSave(self, docIndex):
"""Save current document."""
- # get XML data for current document
- document = self.documents[self.currentDocument]
- self.currentDocumentXML = document.msd()
+ # get XML data for selected document
+ self.currentDocumentXML = self.documents[docIndex].msd()
# ----
@@ -3199,18 +3386,20 @@
self.tmpLibrarySaved = False
# set process
- if library == 'modifications':
+ if library == 'compounds':
+ self.tmpLibrarySaved = libs.saveCompounds()
+ elif library == 'modifications':
self.tmpLibrarySaved = mspy.saveModifications(os.path.join(config.confdir,'modifications.xml'))
+ elif library == 'monomers':
+ self.tmpLibrarySaved = mspy.saveMonomers(os.path.join(config.confdir,'monomers.xml'))
elif library == 'enzymes':
self.tmpLibrarySaved = mspy.saveEnzymes(os.path.join(config.confdir,'enzymes.xml'))
- elif library == 'compounds':
- self.tmpLibrarySaved = libs.saveCompounds()
elif library == 'references':
self.tmpLibrarySaved = libs.saveReferences()
- elif library == 'presets':
- self.tmpLibrarySaved = libs.savePresets()
elif library == 'mascot':
self.tmpLibrarySaved = libs.saveMascot()
+ elif library == 'presets':
+ self.tmpLibrarySaved = libs.savePresets()
# ----
@@ -3428,7 +3617,7 @@
points += [[a.mz, a.ai, a.label] for a in document.annotations]
# get sequence matches
- elif selected in ('sequence', 'match'):
+ elif selected in ('sequence', 'match') and self.currentSequence != None:
sequence = self.documents[self.currentDocument].sequences[self.currentSequence]
points += [[m.mz, m.ai, m.label] for m in sequence.matches]
@@ -3466,6 +3655,7 @@
self.menubar.Enable(ID_documentCloseAll, bool(self.documents))
self.menubar.Enable(ID_documentSave, enable)
self.menubar.Enable(ID_documentSaveAs, enable)
+ self.menubar.Enable(ID_documentSaveAll, bool(self.documents))
self.menubar.Enable(ID_documentExport, bool(self.documents))
self.menubar.Enable(ID_documentReport, enable)
self.menubar.Enable(ID_documentInfo, enable)
@@ -3490,6 +3680,8 @@
self.menubar.Enable(ID_toolsPeakDifferences, enable)
self.menubar.Enable(ID_toolsComparePeaklists, bool(self.documents))
self.menubar.Enable(ID_toolsSpectrumGenerator, enable)
+ self.menubar.Enable(ID_toolsEnvelopeFit, enable)
+ self.menubar.Enable(ID_toolsEnvelopeFit, enable)
self.menubar.Enable(ID_mascotPMF, enable)
self.menubar.Enable(ID_mascotSQ, enable)
self.menubar.Enable(ID_mascotMIS, enable)
@@ -3508,6 +3700,7 @@
self.toolbar.EnableTool(ID_toolsPeakDifferences, enable)
self.toolbar.EnableTool(ID_toolsComparePeaklists, bool(self.documents))
self.toolbar.EnableTool(ID_toolsSpectrumGenerator, enable)
+ self.toolbar.EnableTool(ID_toolsEnvelopeFit, enable)
self.toolbar.EnableTool(ID_toolsMascot, enable)
self.toolbar.EnableTool(ID_toolsProfound, enable)
self.toolbar.EnableTool(ID_toolsDocumentExport, bool(self.documents))
@@ -3528,6 +3721,8 @@
self.menubar.Enable(ID_sequenceDigest, enable)
self.menubar.Enable(ID_sequenceFragment, enable)
self.menubar.Enable(ID_sequenceSearch, enable)
+ self.menubar.Enable(ID_sequenceSendToMassCalculator, enable)
+ self.menubar.Enable(ID_sequenceSendToEnvelopeFit, enable)
self.menubar.Enable(ID_sequenceMatchesCalibrateBy, bool(enable and sequence.matches))
self.menubar.Enable(ID_sequenceMatchesDelete, bool(enable and sequence.matches))
self.menubar.Enable(ID_sequenceDelete, enable)
@@ -3680,6 +3875,20 @@
# ----
+ def getUsedMonomers(self):
+ """Search all sequences for used monomers."""
+
+ # get monomers
+ monomers = []
+ for document in self.documents:
+ for sequence in document.sequences:
+ for monomer in sequence:
+ monomers.append(monomer)
+
+ return monomers
+ # ----
+
+
def getUsedModifications(self):
"""Search all sequences for used modifications."""
diff -Nru mmass-3.12.1/gui/mwx.py mmass-4.0.0/gui/mwx.py
--- mmass-3.12.1/gui/mwx.py 2011-07-01 13:59:39.000000000 +0000
+++ mmass-4.0.0/gui/mwx.py 2011-11-11 14:32:55.000000000 +0000
@@ -24,6 +24,7 @@
from ids import *
import images
import config
+import mspy
# GUI CONSTANTS
@@ -49,6 +50,7 @@
TOOLBAR_RSPACE = 10
TOOLBAR_TOOLSIZE = (-1,-1)
CONTROLBAR_HEIGHT = 32
+CONTROLBAR_DOUBLE_HEIGHT = 61
CONTROLBAR_LSPACE = 10
CONTROLBAR_RSPACE = 10
BOTTOMBAR_HEIGHT = 22
@@ -58,6 +60,7 @@
SMALL_COMBO_HEIGHT = -1
SMALL_BUTTON_HEIGHT = 22
SMALL_TEXTCTRL_HEIGHT = -1
+SMALL_SEARCH_HEIGHT = -1
BUTTON_SIZE_CORRECTION = 0
COMBO_HEIGHT = -1
@@ -98,21 +101,21 @@
GAUGE_HEIGHT = 11
GAUGE_SPACE = 15
- MAIN_TOOLBAR_TOOLSIZE = (30,22)
+ MAIN_TOOLBAR_TOOLSIZE = (30,23)
MAIN_TOOLBAR_STYLE = wx.TB_FLAT|wx.TB_NODIVIDER|wx.TB_HORIZONTAL|wx.TB_TEXT
TOOLBAR_HEIGHT = 38
TOOLBAR_LSPACE = 15
TOOLBAR_RSPACE = 15
- CONTROLBAR_HEIGHT = 32
CONTROLBAR_LSPACE = 15
CONTROLBAR_RSPACE = 15
- BOTTOMBAR_HEIGHT = 32
+ BOTTOMBAR_HEIGHT = 33
BOTTOMBAR_LSPACE = 10
BOTTOMBAR_RSPACE = 10
SMALL_COMBO_HEIGHT = 22
SMALL_BUTTON_HEIGHT = -1
SMALL_TEXTCTRL_HEIGHT = 18
+ SMALL_SEARCH_HEIGHT = 22
BUTTON_SIZE_CORRECTION = -3
COMBO_HEIGHT = 22
@@ -147,6 +150,7 @@
elif wx.Platform == '__WXMSW__':
SMALL_COMBO_HEIGHT = 22
SMALL_BUTTON_HEIGHT = 22
+ SMALL_SEARCH_HEIGHT = 22
DASHED_LINE = wx.DOT
@@ -155,7 +159,6 @@
SMALL_FONT_SIZE = 10
NORMAL_FONT_SIZE = 11
SASH_SIZE = 6
- SASH_COLOUR = (237,236,235)
TOOLBAR_TOOLSIZE = (32,26)
BOTTOMBAR_HEIGHT = 28
@@ -163,6 +166,7 @@
SMALL_COMBO_HEIGHT = 25
SMALL_BUTTON_HEIGHT = 25
SMALL_TEXTCTRL_HEIGHT = 25
+ SMALL_SEARCH_HEIGHT = 25
DOCTREE_BULLETSIZE = 4
DOCTREE_STYLE = wx.TR_DEFAULT_STYLE|wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER
@@ -214,7 +218,7 @@
# create paint surface
dc = wx.PaintDC(self)
- dc.Clear()
+ #dc.Clear()
# tile/wallpaper the image across the canvas
for x in range(0, self.GetSize()[0], self.image.GetWidth()):
@@ -633,6 +637,37 @@
+class formulaCtrl(wx.TextCtrl):
+ """TextCtrl to molecular formulae."""
+
+ def __init__(self, parent, id=-1, value="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator):
+ wx.TextCtrl.__init__(self, parent, id, value, pos, size, style, validator)
+ self.Bind(wx.EVT_TEXT, self._onText)
+ # ----
+
+
+ def _onText(self, evt):
+ """Check current formula."""
+ evt.Skip()
+ wx.CallAfter(self._checkFormula)
+ # ----
+
+
+ def _checkFormula(self):
+ """Check current formula."""
+
+ try:
+ formula = mspy.compound(self.GetValue())
+ self.SetBackgroundColour(wx.NullColour)
+ except:
+ self.SetBackgroundColour((250,100,100))
+
+ self.Refresh()
+ # ----
+
+
+
+
class gauge(wx.Gauge):
"""Gauge."""
diff -Nru mmass-3.12.1/gui/panel_calibration.py mmass-4.0.0/gui/panel_calibration.py
--- mmass-3.12.1/gui/panel_calibration.py 2011-06-29 11:31:31.000000000 +0000
+++ mmass-4.0.0/gui/panel_calibration.py 2011-11-25 13:43:21.000000000 +0000
@@ -267,6 +267,7 @@
self.errorCanvas.setProperties(autoScaleY=False)
self.errorCanvas.setProperties(xPosDigits=config.main['mzDigits'])
self.errorCanvas.setProperties(yPosDigits=2)
+ self.errorCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.errorCanvas.setProperties(reverseDrawing=True)
self.errorCanvas.setMFunction('cross')
diff -Nru mmass-3.12.1/gui/panel_compounds_search.py mmass-4.0.0/gui/panel_compounds_search.py
--- mmass-3.12.1/gui/panel_compounds_search.py 2011-06-28 13:29:30.000000000 +0000
+++ mmass-4.0.0/gui/panel_compounds_search.py 2011-11-10 14:28:18.000000000 +0000
@@ -406,20 +406,55 @@
def onItemActivated(self, evt):
"""Show isotopic pattern for selected compound."""
+ self.onItemSendToMassCalculator(evt)
+ # ----
+
+
+ def onItemSendToMassCalculator(self, evt):
+ """Show isotopic pattern for selected compound."""
- # get formula and charge
- item = self.currentCompounds[evt.GetData()]
- formula = item[4]
- charge = item[2]
+ # get data
+ selected = self.compoundsList.getSelected()
+ if selected:
+ index = self.compoundsList.GetItemData(selected[0])
+ formula = self.currentCompounds[index][4]
+ charge = self.currentCompounds[index][2]
+ radical = self.currentCompounds[index][3]
+ else:
+ wx.Bell()
+ return
- # send to masscalc
- if item[3] == 'radical':
+ # send data to masscalc
+ if radical == 'radical':
self.parent.onToolsMassCalculator(formula=formula, charge=charge, agentFormula='e', agentCharge=-1)
else:
self.parent.onToolsMassCalculator(formula=formula, charge=charge, agentFormula='H', agentCharge=1)
# ----
+ def onItemCopyFormula(self, evt):
+ """Copy selected compound formula into clipboard."""
+
+ # get data
+ selected = self.compoundsList.getSelected()
+ if selected:
+ index = self.compoundsList.GetItemData(selected[0])
+ formula = self.currentCompounds[index][4]
+ else:
+ wx.Bell()
+ return
+
+ # make text object for data
+ obj = wx.TextDataObject()
+ obj.SetText(formula)
+
+ # paste to clipboard
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(obj)
+ wx.TheClipboard.Close()
+ # ----
+
+
def onListKey(self, evt):
"""Export list if Ctrl+C."""
@@ -445,7 +480,10 @@
menu.Append(ID_listViewMatched, "Show Matched Only", "", wx.ITEM_RADIO)
menu.Append(ID_listViewUnmatched, "Show Unmatched Only", "", wx.ITEM_RADIO)
menu.AppendSeparator()
- menu.Append(ID_listCopy, "Copy All")
+ menu.Append(ID_listSendToMassCalculator, "Show Isotopic Pattern", "")
+ menu.AppendSeparator()
+ menu.Append(ID_listCopyFormula, "Copy Formula")
+ menu.Append(ID_listCopy, "Copy List")
# check item
if self._compoundsFilter == 1:
@@ -459,6 +497,8 @@
self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewAll)
self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewMatched)
self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewUnmatched)
+ self.Bind(wx.EVT_MENU, self.onItemSendToMassCalculator, id=ID_listSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onItemCopyFormula, id=ID_listCopyFormula)
self.Bind(wx.EVT_MENU, self.onListCopy, id=ID_listCopy)
# show menu
@@ -787,12 +827,12 @@
# main ion
mz = compound.mz(z*polarity)[config.compounds['massType']]
- self.currentCompounds.append([name, mz, z*polarity, None, compound.rawFormula, None, []])
+ self.currentCompounds.append([name, mz, z*polarity, None, compound.expression, None, []])
# radicals
if config.compounds['radicals']:
mz = compound.mz(z*polarity, agentFormula='e', agentCharge=-1)[config.compounds['massType']]
- self.currentCompounds.append([name, mz, z*polarity, 'radical', compound.rawFormula, None, []])
+ self.currentCompounds.append([name, mz, z*polarity, 'radical', compound.expression, None, []])
mspy.CHECK_FORCE_QUIT()
@@ -800,14 +840,14 @@
for item in config.compounds['adducts']:
if item in ('Na', 'K', 'Li', 'NH4', 'ACN', 'MeOH'):
- formula = '%s(%s)(H-1)' % (compound.rawFormula, adducts[item])
+ formula = '%s(%s)(H-1)' % (compound.expression, adducts[item])
elif item in ('-H2O'):
- formula = '%s(%s)' % (compound.rawFormula, adducts[item])
+ formula = '%s(%s)' % (compound.expression, adducts[item])
formula = mspy.compound(formula)
if formula.isvalid():
mz = formula.mz(z*polarity)[config.compounds['massType']]
- self.currentCompounds.append([name, mz, z*polarity, item, formula.rawFormula, None, []])
+ self.currentCompounds.append([name, mz, z*polarity, item, formula.expression, None, []])
mspy.CHECK_FORCE_QUIT()
@@ -819,15 +859,15 @@
if item2 in ('ACN', 'MeOH'):
adduct = '%s+%s' % (item1, item2)
- formula = '%s(%s)(%s)(H-2)' % (compound.rawFormula, adducts[item1], adducts[item2])
+ formula = '%s(%s)(%s)(H-2)' % (compound.expression, adducts[item1], adducts[item2])
elif item2 in ('-H2O'):
adduct = '%s%s' % (item1, item2)
- formula = '%s(%s)(%s)(H-1)' % (compound.rawFormula, adducts[item1], adducts[item2])
+ formula = '%s(%s)(%s)(H-1)' % (compound.expression, adducts[item1], adducts[item2])
formula = mspy.compound(formula)
if formula.isvalid():
mz = formula.mz(z*polarity)[config.compounds['massType']]
- self.currentCompounds.append([name, mz, z*polarity, adduct, formula.rawFormula, None, []])
+ self.currentCompounds.append([name, mz, z*polarity, adduct, formula.expression, None, []])
# task canceled
except mspy.ForceQuit:
diff -Nru mmass-3.12.1/gui/panel_document_export.py mmass-4.0.0/gui/panel_document_export.py
--- mmass-3.12.1/gui/panel_document_export.py 2011-06-14 15:51:38.000000000 +0000
+++ mmass-4.0.0/gui/panel_document_export.py 2011-09-02 12:19:00.000000000 +0000
@@ -746,7 +746,7 @@
if 'int' in config.export['peaklistColumns']:
line += str(peak.intensity) + separator
if 'rel' in config.export['peaklistColumns']:
- line += str(peak.relIntensity*100) + separator
+ line += str(peak.ri*100) + separator
if 'sn' in config.export['peaklistColumns']:
line += str(peak.sn) + separator
if 'z' in config.export['peaklistColumns']:
diff -Nru mmass-3.12.1/gui/panel_document_info.py mmass-4.0.0/gui/panel_document_info.py
--- mmass-3.12.1/gui/panel_document_info.py 2011-06-13 10:02:50.000000000 +0000
+++ mmass-4.0.0/gui/panel_document_info.py 2011-09-02 12:51:04.000000000 +0000
@@ -151,6 +151,9 @@
self.date_value = wx.TextCtrl(panel, -1, "", size=(300, -1))
self.date_value.Bind(wx.EVT_TEXT, self.onSave)
+ path_label = wx.StaticText(panel, -1, "Path:")
+ self.path_value = wx.TextCtrl(panel, -1, "", size=(300, -1))
+
# pack elements
grid = wx.GridBagSizer(mwx.GRIDBAG_VSPACE, mwx.GRIDBAG_HSPACE)
grid.Add(title_label, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
@@ -165,6 +168,8 @@
grid.Add(self.instrument_value, (4,1))
grid.Add(date_label, (5,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
grid.Add(self.date_value, (5,1))
+ grid.Add(path_label, (6,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
+ grid.Add(self.path_value, (6,1))
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(grid, 0, wx.ALIGN_CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
@@ -442,6 +447,7 @@
# clear previous values
self.title_value.ChangeValue('')
self.date_value.ChangeValue('')
+ self.path_value.ChangeValue('')
self.operator_value.ChangeValue('')
self.contact_value.ChangeValue('')
self.institution_value.ChangeValue('')
@@ -460,6 +466,7 @@
if self.currentDocument:
self.title_value.ChangeValue(document.title)
self.date_value.ChangeValue(document.date)
+ self.path_value.ChangeValue(document.path)
self.operator_value.ChangeValue(document.operator)
self.contact_value.ChangeValue(document.contact)
self.institution_value.ChangeValue(document.institution)
diff -Nru mmass-3.12.1/gui/panel_documents.py mmass-4.0.0/gui/panel_documents.py
--- mmass-3.12.1/gui/panel_documents.py 2011-06-26 17:54:47.000000000 +0000
+++ mmass-4.0.0/gui/panel_documents.py 2011-12-01 13:07:11.000000000 +0000
@@ -215,6 +215,7 @@
menu.Append(ID_documentDuplicate, "Duplicate Document")
menu.AppendSeparator()
menu.Append(ID_documentClose, "Close Document")
+ menu.Append(ID_documentCloseAll, "Close All Documents")
if config.spectrum['normalize']:
menu.Enable(ID_documentOffset, False)
@@ -232,7 +233,9 @@
elif itemType == 'annotation':
menu.Append(ID_documentAnnotationEdit, "Edit Annotation...")
- menu.Append(ID_documentAnnotationPattern, "Show Isotopic Pattern...")
+ menu.AppendSeparator()
+ menu.Append(ID_documentAnnotationSendToMassCalculator, "Show Isotopic Pattern...")
+ menu.Append(ID_documentAnnotationSendToEnvelopeFit, "Send to Envelope Fit...")
menu.AppendSeparator()
menu.Append(ID_documentAnnotationsCalibrateBy, "Calibrate by Annotations...")
menu.AppendSeparator()
@@ -240,7 +243,8 @@
menu.Append(ID_documentAnnotationsDelete, "Delete All Annotations")
if not itemData.formula:
- menu.Enable(ID_documentAnnotationPattern, False)
+ menu.Enable(ID_documentAnnotationSendToMassCalculator, False)
+ menu.Enable(ID_documentAnnotationSendToEnvelopeFit, False)
elif itemType == 'sequence':
menu.Append(ID_sequenceEditor, "Edit Sequence...")
@@ -250,6 +254,9 @@
menu.Append(ID_sequenceFragment, "Fragment Peptide...")
menu.Append(ID_sequenceSearch, "Mass Search...")
menu.AppendSeparator()
+ menu.Append(ID_sequenceSendToMassCalculator, "Show Isotopic Pattern...")
+ menu.Append(ID_sequenceSendToEnvelopeFit, "Send to Envelope Fit...")
+ menu.AppendSeparator()
menu.Append(ID_sequenceMatchesCalibrateBy, "Calibrate by Matches...")
menu.AppendSeparator()
menu.Append(ID_sequenceMatchesDelete, "Delete All Matches")
@@ -261,7 +268,9 @@
elif itemType == 'match':
menu.Append(ID_sequenceMatchEdit, "Edit Match...")
- menu.Append(ID_sequenceMatchPattern, "Show Isotopic Pattern...")
+ menu.AppendSeparator()
+ menu.Append(ID_sequenceMatchSendToMassCalculator, "Show Isotopic Pattern...")
+ menu.Append(ID_sequenceMatchSendToEnvelopeFit, "Send to Envelope Fit...")
menu.AppendSeparator()
menu.Append(ID_sequenceMatchesCalibrateBy, "Calibrate by Matches...")
menu.AppendSeparator()
@@ -269,7 +278,8 @@
menu.Append(ID_sequenceMatchesDelete, "Delete All Matches")
if not itemData.formula:
- menu.Enable(ID_documentAnnotationPattern, False)
+ menu.Enable(ID_sequenceMatchSendToMassCalculator, False)
+ menu.Enable(ID_sequenceMatchSendToEnvelopeFit, False)
# bind events
self.Bind(wx.EVT_MENU, self.parent.onDocumentInfo, id=ID_documentInfo)
@@ -280,9 +290,11 @@
self.Bind(wx.EVT_MENU, self.parent.onDocumentNotationsDelete, id=ID_documentNotationsDelete)
self.Bind(wx.EVT_MENU, self.parent.onDocumentDuplicate, id=ID_documentDuplicate)
self.Bind(wx.EVT_MENU, self.parent.onDocumentClose, id=ID_documentClose)
+ self.Bind(wx.EVT_MENU, self.parent.onDocumentCloseAll, id=ID_documentCloseAll)
self.Bind(wx.EVT_MENU, self.onNotationEdit, id=ID_documentAnnotationEdit)
- self.Bind(wx.EVT_MENU, self.onNotationPattern, id=ID_documentAnnotationPattern)
+ self.Bind(wx.EVT_MENU, self.onSendToMassCalculator, id=ID_documentAnnotationSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onSendToEnvelopeFit, id=ID_documentAnnotationSendToEnvelopeFit)
self.Bind(wx.EVT_MENU, self.parent.onDocumentAnnotationsCalibrateBy, id=ID_documentAnnotationsCalibrateBy)
self.Bind(wx.EVT_MENU, self.onNotationDelete, id=ID_documentAnnotationDelete)
self.Bind(wx.EVT_MENU, self.parent.onDocumentAnnotationsDelete, id=ID_documentAnnotationsDelete)
@@ -293,10 +305,13 @@
self.Bind(wx.EVT_MENU, self.parent.onToolsSequence, id=ID_sequenceDigest)
self.Bind(wx.EVT_MENU, self.parent.onToolsSequence, id=ID_sequenceFragment)
self.Bind(wx.EVT_MENU, self.parent.onToolsSequence, id=ID_sequenceSearch)
+ self.Bind(wx.EVT_MENU, self.onSendToMassCalculator, id=ID_sequenceSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onSendToEnvelopeFit, id=ID_sequenceSendToEnvelopeFit)
self.Bind(wx.EVT_MENU, self.parent.onSequenceDelete, id=ID_sequenceDelete)
self.Bind(wx.EVT_MENU, self.onNotationEdit, id=ID_sequenceMatchEdit)
- self.Bind(wx.EVT_MENU, self.onNotationPattern, id=ID_sequenceMatchPattern)
+ self.Bind(wx.EVT_MENU, self.onSendToMassCalculator, id=ID_sequenceMatchSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onSendToEnvelopeFit, id=ID_sequenceMatchSendToEnvelopeFit)
self.Bind(wx.EVT_MENU, self.parent.onSequenceMatchesCalibrateBy, id=ID_sequenceMatchesCalibrateBy)
self.Bind(wx.EVT_MENU, self.onNotationDelete, id=ID_sequenceMatchDelete)
self.Bind(wx.EVT_MENU, self.parent.onSequenceMatchesDelete, id=ID_sequenceMatchesDelete)
@@ -344,7 +359,7 @@
seqIndex = self._getSequenceIndex(item)
self.parent.onSequenceSelected(seqIndex)
- # highlight matches and annotations
+ # update notation marks
self.parent.updateNotationMarks()
# highlight mass of selected match or annotation
@@ -397,7 +412,9 @@
# popup menu
menu = wx.Menu()
menu.Append(ID_sequenceNew, "New Sequence...")
+ menu.AppendSeparator()
menu.Append(ID_documentNew, "New Document")
+ menu.Append(ID_documentNewFromClipboard, "New from Clipboard")
menu.AppendSeparator()
menu.Append(ID_documentOpen, "Open Document...")
@@ -406,6 +423,7 @@
# set events
self.Bind(wx.EVT_MENU, self.parent.onSequenceNew, id=ID_sequenceNew)
self.Bind(wx.EVT_MENU, self.parent.onDocumentNew, id=ID_documentNew)
+ self.Bind(wx.EVT_MENU, self.parent.onDocumentNewFromClipboard, id=ID_documentNewFromClipboard)
self.Bind(wx.EVT_MENU, self.parent.onDocumentOpen, id=ID_documentOpen)
self.PopupMenu(menu)
@@ -507,22 +525,6 @@
# ----
- def onNotationPattern(self, evt=None):
- """Show isotopic pattern for selected annotation or sequence match."""
-
- # get selected item
- item = self.documentTree.GetSelection()
- itemData = self.documentTree.GetPyData(item)
-
- # show profile
- if itemData.formula:
- if itemData.radical:
- self.parent.onToolsMassCalculator(formula=itemData.formula, charge=itemData.charge, agentFormula='e', agentCharge=-1)
- else:
- self.parent.onToolsMassCalculator(formula=itemData.formula, charge=itemData.charge, agentFormula='H', agentCharge=1)
- # ----
-
-
def onNotationDelete(self, evt=None):
"""Delete selected annotation or sequence match."""
@@ -544,6 +546,50 @@
# ----
+ def onSendToMassCalculator(self, evt=None):
+ """Send selected item to Mass Calculator panel."""
+
+ # get selected item
+ item = self.documentTree.GetSelection()
+ itemType = self.documentTree.getItemType(item)
+ itemData = self.documentTree.GetPyData(item)
+
+ # send data to Mass Calculator
+ if itemType == 'sequence':
+ self.parent.onToolsMassCalculator(formula=itemData.formula())
+ elif itemType in ('annotation', 'match'):
+ if itemData.radical:
+ self.parent.onToolsMassCalculator(formula=itemData.formula, charge=itemData.charge, agentFormula='e', agentCharge=-1)
+ else:
+ self.parent.onToolsMassCalculator(formula=itemData.formula, charge=itemData.charge, agentFormula='H', agentCharge=1)
+ # ----
+
+
+ def onSendToEnvelopeFit(self, evt=None):
+ """Send selected item to envelope fit panel."""
+
+ # get selected item
+ item = self.documentTree.GetSelection()
+ itemType = self.documentTree.getItemType(item)
+ itemData = self.documentTree.GetPyData(item)
+
+ # send data to envelope fit
+ if itemType == 'sequence':
+ self.parent.onToolsEnvelopeFit(sequence=itemData)
+
+ elif itemType == 'annotation':
+ self.parent.onToolsEnvelopeFit(formula=itemData.formula, charge=itemData.charge)
+
+ elif itemType == 'match':
+
+ scale = None
+ if itemData.sequenceRange and config.envfit['loss'] == 'H' and config.envfit['gain'] == 'H{2}':
+ scale = [0, itemData.sequenceRange[1]-itemData.sequenceRange[0]]
+
+ self.parent.onToolsEnvelopeFit(formula=itemData.formula, charge=itemData.charge, scale=scale)
+ # ----
+
+
# DOCUMENT
@@ -553,6 +599,7 @@
# deselect all documents
if docIndex == None:
self.documentTree.Unselect()
+ self.parent.onDocumentSelected(None)
return
# get item
diff -Nru mmass-3.12.1/gui/panel_envelope_fit.py mmass-4.0.0/gui/panel_envelope_fit.py
--- mmass-3.12.1/gui/panel_envelope_fit.py 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/gui/panel_envelope_fit.py 2011-11-30 18:09:56.000000000 +0000
@@ -0,0 +1,679 @@
+# -------------------------------------------------------------------------
+# Copyright (C) 2005-2011 Martin Strohalm
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# Complete text of GNU GPL can be found in the file LICENSE.TXT in the
+# main directory of the program
+# -------------------------------------------------------------------------
+
+# load libs
+import threading
+import wx
+
+# load modules
+from ids import *
+import mwx
+import images
+import config
+import libs
+import mspy
+
+
+# FLOATING PANEL WITH ENVELOPE FIT TOOL
+# -------------------------------------
+
+class panelEnvelopeFit(wx.MiniFrame):
+ """Envelope fit tool."""
+
+ def __init__(self, parent):
+ wx.MiniFrame.__init__(self, parent, -1, 'Envelope Fit', size=(400, 300), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BOX | wx.MAXIMIZE_BOX))
+
+ self.parent = parent
+
+ self.processing = None
+
+ self.currentDocument = None
+ self.currentCompound = None
+ self.currentFit = None
+
+ # make gui items
+ self.makeGUI()
+ wx.EVT_CLOSE(self, self.onClose)
+ # ----
+
+
+ def makeGUI(self):
+ """Make panel gui."""
+
+ # make toolbar
+ toolbar = self.makeToolbar()
+ controlbar = self.makeControlbar()
+
+ # make panels
+ results = self.makeResultsPanel()
+ gauge = self.makeGaugePanel()
+
+ # pack element
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.mainSizer.Add(toolbar, 0, wx.EXPAND, 0)
+ self.mainSizer.Add(controlbar, 0, wx.EXPAND, 0)
+ self.mainSizer.Add(results, 1, wx.EXPAND, 0)
+ self.mainSizer.Add(gauge, 0, wx.EXPAND, 0)
+
+ # hide gauge
+ self.mainSizer.Hide(3)
+
+ # fit layout
+ self.mainSizer.Fit(self)
+ self.SetSizer(self.mainSizer)
+ self.SetMinSize(self.GetSize())
+ mwx.layout(self, self.mainSizer)
+ # ----
+
+
+ def makeToolbar(self):
+ """Make toolbar."""
+
+ # init toolbar
+ panel = mwx.bgrPanel(self, -1, images.lib['bgrToolbar'], size=(-1, mwx.TOOLBAR_HEIGHT))
+
+ # make elements
+ formula_label = wx.StaticText(panel, -1, "Formula:")
+ formula_label.SetFont(wx.SMALL_FONT)
+ self.formula_value = mwx.formulaCtrl(panel, -1, "", size=(220, -1))
+
+ charge_label = wx.StaticText(panel, -1, "Charge:")
+ charge_label.SetFont(wx.SMALL_FONT)
+ self.charge_value = wx.TextCtrl(panel, -1, str(config.envfit['charge']), size=(35, -1), validator=mwx.validator('int'))
+
+ exchange_label = wx.StaticText(panel, -1, "Exchange:")
+ exchange_label.SetFont(wx.SMALL_FONT)
+ self.exchangeLoss_value = mwx.formulaCtrl(panel, -1, str(config.envfit['loss']), size=(40, -1))
+ exchangeVs_label = wx.StaticText(panel, -1, " vs.")
+ exchangeVs_label.SetFont(wx.SMALL_FONT)
+ self.exchangeGain_value = mwx.formulaCtrl(panel, -1, str(config.envfit['gain']), size=(40, -1))
+
+ scale_label = wx.StaticText(panel, -1, "Range:")
+ scale_label.SetFont(wx.SMALL_FONT)
+ scaleDash_label = wx.StaticText(panel, -1, "-")
+ scaleDash_label.SetFont(wx.SMALL_FONT)
+ self.scaleMin_value = wx.TextCtrl(panel, -1, str(config.envfit['scaleMin']), size=(35, -1), validator=mwx.validator('intPos'))
+ self.scaleMax_value = wx.TextCtrl(panel, -1, str(config.envfit['scaleMax']), size=(35, -1), validator=mwx.validator('intPos'))
+
+ self.calculate_butt = wx.Button(panel, -1, "Calculate", size=(-1, mwx.SMALL_BUTTON_HEIGHT))
+ self.calculate_butt.SetFont(wx.SMALL_FONT)
+ self.calculate_butt.Bind(wx.EVT_BUTTON, self.onCalculate)
+
+ # pack elements
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.AddSpacer(mwx.CONTROLBAR_LSPACE)
+ sizer.Add(formula_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.formula_value, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(charge_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.charge_value, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(exchange_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.exchangeLoss_value, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(exchangeVs_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.exchangeGain_value, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(scale_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.scaleMin_value, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(scaleDash_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.scaleMax_value, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddStretchSpacer()
+ sizer.AddSpacer(20)
+ sizer.Add(self.calculate_butt, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(mwx.CONTROLBAR_RSPACE)
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(sizer, 1, wx.EXPAND)
+ panel.SetSizer(mainSizer)
+ mainSizer.Fit(panel)
+
+ return panel
+ # ----
+
+
+ def makeControlbar(self):
+ """Make controlbar."""
+
+ # init toolbar
+ panel = mwx.bgrPanel(self, -1, images.lib['bgrControlbar'], size=(-1, mwx.CONTROLBAR_HEIGHT))
+
+ # make elements
+ self.collapse_butt = wx.BitmapButton(panel, -1, images.lib['arrowsDown'], size=(mwx.TOOLBAR_TOOLSIZE), style=wx.BORDER_NONE)
+ self.collapse_butt.Bind(wx.EVT_BUTTON, self.onCollapse)
+
+ fitTo_label = wx.StaticText(panel, -1, "Fit to:")
+ fitTo_label.SetFont(wx.SMALL_FONT)
+
+ self.fitToPeaklist_radio = wx.RadioButton(panel, -1, "Peak list", style=wx.RB_GROUP)
+ self.fitToPeaklist_radio.SetFont(wx.SMALL_FONT)
+
+ self.fitToSpectrum_radio = wx.RadioButton(panel, -1, "Spectrum")
+ self.fitToSpectrum_radio.SetFont(wx.SMALL_FONT)
+
+ self.fitToPeaklist_radio.SetValue(True)
+ if config.envfit['fit'] == 'spectrum':
+ self.fitToSpectrum_radio.SetValue(True)
+
+ fwhm_label = wx.StaticText(panel, -1, "Default FWHM:")
+ fwhm_label.SetFont(wx.SMALL_FONT)
+ self.fwhm_value = wx.TextCtrl(panel, -1, str(config.envfit['fwhm']), size=(50, mwx.SMALL_TEXTCTRL_HEIGHT), validator=mwx.validator('floatPos'))
+ self.fwhm_value.SetFont(wx.SMALL_FONT)
+
+ self.forceFwhm_check = wx.CheckBox(panel, -1, "Force")
+ self.forceFwhm_check.SetFont(wx.SMALL_FONT)
+ self.forceFwhm_check.SetValue(config.envfit['forceFwhm'])
+
+ relThreshold_label = wx.StaticText(panel, -1, "Rel. threshold:")
+ relThreshold_label.SetFont(wx.SMALL_FONT)
+ relThresholdUnits_label = wx.StaticText(panel, -1, "%")
+ relThresholdUnits_label.SetFont(wx.SMALL_FONT)
+ self.relThreshold_value = wx.TextCtrl(panel, -1, str(config.envfit['relThreshold']*100), size=(50, mwx.SMALL_TEXTCTRL_HEIGHT), validator=mwx.validator('floatPos'))
+ self.relThreshold_value.SetFont(wx.SMALL_FONT)
+
+ self.autoAlign_check = wx.CheckBox(panel, -1, "Auto align")
+ self.autoAlign_check.SetFont(wx.SMALL_FONT)
+ self.autoAlign_check.SetValue(config.envfit['autoAlign'])
+
+ self.average_label = wx.StaticText(panel, -1, "", size=(100, -1))
+ self.average_label.SetFont(wx.SMALL_FONT)
+ self.updateAverageLabel()
+
+ # pack elements
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.AddSpacer(mwx.CONTROLBAR_LSPACE)
+ sizer.Add(self.collapse_butt, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(10)
+ sizer.Add(fitTo_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.fitToPeaklist_radio, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.fitToSpectrum_radio, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(fwhm_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.fwhm_value, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.forceFwhm_check, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(relThreshold_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.relThreshold_value, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(relThresholdUnits_label, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(self.autoAlign_check, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(self.average_label, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(mwx.CONTROLBAR_RSPACE)
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(sizer, 1, wx.EXPAND)
+ mainSizer.Fit(panel)
+ panel.SetSizer(mainSizer)
+
+ return panel
+ # ----
+
+
+ def makeResultsPanel(self):
+ """Make results panel."""
+
+ panel = wx.Panel(self, -1)
+
+ # make table
+ self.makeSpectrumCanvas(panel)
+ self.makeResultsList(panel)
+
+ # pack main
+ mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ mainSizer.Add(self.spectrumCanvas, 1, wx.EXPAND)
+ mainSizer.AddSpacer(mwx.SASH_SIZE)
+ mainSizer.Add(self.resultsList, 0, wx.EXPAND|wx.ALL, mwx.LISTCTRL_NO_SPACE)
+
+ # fit layout
+ panel.SetSizer(mainSizer)
+
+ return panel
+ # ----
+
+
+ def makeSpectrumCanvas(self, panel):
+ """Make spectrum canvas and set defalt parameters."""
+
+ # init canvas
+ self.spectrumCanvas = mspy.plot.canvas(panel, size=(600, 350), style=mwx.PLOTCANVAS_STYLE_PANEL)
+
+ # set default params
+ self.spectrumCanvas.setProperties(xLabel='m/z')
+ self.spectrumCanvas.setProperties(yLabel='a.i.')
+ self.spectrumCanvas.setProperties(showLegend=True)
+ self.spectrumCanvas.setProperties(showPosBar=False)
+ self.spectrumCanvas.setProperties(showIntBar=True)
+ self.spectrumCanvas.setProperties(intBarHeight=6)
+ self.spectrumCanvas.setProperties(showGel=False)
+ self.spectrumCanvas.setProperties(checkLimits=True)
+ self.spectrumCanvas.setProperties(autoScaleY=True)
+ self.spectrumCanvas.setProperties(overlapLabels=False)
+ self.spectrumCanvas.setProperties(xPosDigits=5)
+ self.spectrumCanvas.setProperties(yPosDigits=2)
+ self.spectrumCanvas.setProperties(distanceDigits=5)
+ self.spectrumCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
+ self.spectrumCanvas.setProperties(reverseDrawing=False)
+ self.spectrumCanvas.setLMBFunction('xDistance')
+ self.spectrumCanvas.setMFunction('cross')
+
+ axisFont = wx.Font(config.spectrum['axisFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
+ self.spectrumCanvas.setProperties(axisFont=axisFont)
+
+ self.spectrumCanvas.draw(mspy.plot.container([]))
+
+ return self.spectrumCanvas
+ # ----
+
+
+ def makeResultsList(self, panel):
+ """Make results list."""
+
+ # init results list
+ self.resultsList = mwx.sortListCtrl(panel, -1, size=(171, -1), style=mwx.LISTCTRL_STYLE_MULTI)
+ self.resultsList.SetFont(wx.SMALL_FONT)
+ self.resultsList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
+ self.resultsList.Bind(wx.EVT_KEY_DOWN, self.onListKey)
+
+ # make columns
+ self.resultsList.InsertColumn(0, "# of X", wx.LIST_FORMAT_LEFT)
+ self.resultsList.InsertColumn(1, "%", wx.LIST_FORMAT_RIGHT)
+
+ # set column widths
+ for col, width in enumerate((75,75)):
+ self.resultsList.SetColumnWidth(col, width)
+ # ----
+
+
+ def makeGaugePanel(self):
+ """Make processing gauge."""
+
+ panel = wx.Panel(self, -1)
+
+ # make elements
+ self.gauge = mwx.gauge(panel, -1)
+
+ stop_butt = wx.BitmapButton(panel, -1, images.lib['stopper'], style=wx.BORDER_NONE)
+ stop_butt.Bind(wx.EVT_BUTTON, self.onStop)
+
+ # pack elements
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self.gauge, 1, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(10)
+ sizer.Add(stop_butt, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ # fit layout
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ if wx.Platform == '__WXMAC__':
+ mainSizer.Add(wx.StaticLine(panel), 0, wx.EXPAND|wx.TOP, -1)
+ mainSizer.Add(sizer, 1, wx.EXPAND|wx.ALL, mwx.GAUGE_SPACE)
+ panel.SetSizer(mainSizer)
+ mainSizer.Fit(panel)
+
+ return panel
+ # ----
+
+
+ def onClose(self, evt):
+ """Close panel."""
+
+ # check processing
+ if self.processing != None:
+ wx.Bell()
+ return
+
+ # clear tmp spectrum
+ self.parent.updateTmpSpectrum(None)
+
+ # close self
+ self.Destroy()
+ # ----
+
+
+ def onProcessing(self, status=True):
+ """Show processing gauge."""
+
+ self.gauge.SetValue(0)
+
+ if status:
+ self.MakeModal(True)
+ self.mainSizer.Show(3)
+ else:
+ self.MakeModal(False)
+ self.mainSizer.Hide(3)
+ self.processing = None
+ mspy.start()
+
+ # fit layout
+ self.Layout()
+ self.mainSizer.Fit(self)
+ try: wx.Yield()
+ except: pass
+ # ----
+
+
+ def onStop(self, evt):
+ """Cancel current processing."""
+
+ if self.processing and self.processing.isAlive():
+ mspy.stop()
+ else:
+ wx.Bell()
+ # ----
+
+
+ def onListKey(self, evt):
+ """Export list if Ctrl+C."""
+
+ # get key
+ key = evt.GetKeyCode()
+
+ # copy
+ if key == 67 and evt.CmdDown():
+ self.resultsList.copyToClipboard()
+
+ # select all
+ elif key == 65 and evt.CmdDown():
+ for x in range(self.resultsList.GetItemCount()):
+ self.resultsList.SetItemState(x, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+
+ # other keys
+ else:
+ evt.Skip()
+ # ----
+
+
+ def onCalculate(self, evt):
+ """Generate compounds ions."""
+
+ # check processing
+ if self.processing:
+ return
+
+ # clear recent
+ self.currentCompound = None
+ self.currentFit = None
+
+ # check document
+ if not self.currentDocument or not (self.currentDocument.spectrum.hasPoints() or self.currentDocument.spectrum.hasPeaks()):
+ wx.Bell()
+ return
+
+ # get params
+ if not self.getParams():
+ self.updateAverageLabel()
+ self.updateSpectrumCanvas()
+ self.updateResultsList()
+ return
+
+ # show processing gauge
+ self.onProcessing(True)
+ self.calculate_butt.Enable(False)
+
+ # do processing
+ self.processing = threading.Thread(target=self.runEnvelopeFit)
+ self.processing.start()
+
+ # pulse gauge while working
+ while self.processing and self.processing.isAlive():
+ self.gauge.pulse()
+
+ # update gui
+ self.updateAverageLabel()
+ self.updateSpectrumCanvas()
+ self.updateResultsList()
+
+ # hide processing gauge
+ self.onProcessing(False)
+ self.calculate_butt.Enable(True)
+
+ # check errors
+ if self.currentFit != None and self.currentFit.error == 1:
+ wx.Bell()
+ dlg = mwx.dlgMessage(self, title="No data to fit.", message="There are no data in relevant mass range. Please check\nyour specified formula and charge.")
+ dlg.ShowModal()
+ dlg.Destroy()
+ # ----
+
+
+ def onCollapse(self, evt):
+ """Collapse spectrum panel."""
+
+ # Show / hide panel
+ if self.mainSizer.IsShown(2):
+ self.mainSizer.Hide(2)
+ self.collapse_butt.SetBitmapLabel(images.lib['arrowsRight'])
+ else:
+ self.mainSizer.Show(2)
+ self.collapse_butt.SetBitmapLabel(images.lib['arrowsDown'])
+
+ # fit layout
+ self.SetMinSize((-1,-1))
+ self.Layout()
+ self.mainSizer.Fit(self)
+ self.SetMinSize(self.GetSize())
+ # ----
+
+
+ def setData(self, document=None, formula=None, charge=None, fwhm=None, scale=None):
+ """Set current data."""
+
+ self.currentCompound = None
+ self.currentFit = None
+
+ # set values
+ self.currentDocument = document
+ if formula:
+ self.formula_value.SetValue(str(formula))
+ if charge:
+ self.charge_value.SetValue(str(charge))
+ if fwhm:
+ self.fwhm_value.SetValue(str(fwhm))
+ if scale:
+ self.scaleMin_value.SetValue(str(scale[0]))
+ self.scaleMax_value.SetValue(str(scale[1]))
+
+ # update fitting options
+ if self.currentDocument and not self.currentDocument.spectrum.hasPoints():
+ self.fitToPeaklist_radio.SetValue(True)
+ self.fitToSpectrum_radio.Disable()
+ elif self.currentDocument and not self.currentDocument.spectrum.hasPeaks():
+ self.fitToPeaklist_radio.Disable()
+ self.fitToSpectrum_radio.SetValue(True)
+ else:
+ self.fitToPeaklist_radio.Enable()
+ self.fitToSpectrum_radio.Enable()
+
+ # clear gui
+ self.updateAverageLabel()
+ self.updateSpectrumCanvas()
+ self.updateResultsList()
+ # ----
+
+
+ def getParams(self):
+ """Get all params from dialog."""
+
+ # try to get values
+ try:
+
+ formula = self.formula_value.GetValue()
+ loss = self.exchangeLoss_value.GetValue()
+ gain = self.exchangeGain_value.GetValue()
+
+ if not formula or not loss or not gain:
+ raise ValueError
+
+ self.currentCompound = mspy.compound(formula)
+ lossCmpd = mspy.compound(loss)
+ gainCmpd = mspy.compound(gain)
+
+ config.envfit['loss'] = str(loss)
+ config.envfit['gain'] = str(gain)
+
+ config.envfit['fit'] = 'peaklist'
+ if self.fitToSpectrum_radio.GetValue():
+ config.envfit['fit'] = 'spectrum'
+
+ config.envfit['charge'] = int(self.charge_value.GetValue())
+ config.envfit['scaleMin'] = int(self.scaleMin_value.GetValue())
+ config.envfit['scaleMax'] = int(self.scaleMax_value.GetValue())
+ config.envfit['fwhm'] = float(self.fwhm_value.GetValue())
+ config.envfit['forceFwhm'] = self.forceFwhm_check.GetValue()
+ config.envfit['autoAlign'] = self.autoAlign_check.GetValue()
+ config.envfit['relThreshold'] = float(self.relThreshold_value.GetValue())/100.
+
+ return True
+
+ except:
+ wx.Bell()
+ return False
+ # ----
+
+
+ def updateAverageLabel(self):
+ """Update average label value."""
+
+ # get label
+ label = "Average X: "
+ if self.currentFit != None and not self.currentFit.error:
+ label += '%0.2f' % (self.currentFit.average)
+ #label += '%0.2f (%s%0.2f)' % (self.currentFit.average, unichr(177), self.currentFit.std)
+
+ # set label
+ self.average_label.SetLabel(label)
+ # ----
+
+
+ def updateSpectrumCanvas(self):
+ """Update spectrum canvas."""
+
+ # check fit
+ if self.currentFit == None or self.currentFit.error:
+ self.spectrumCanvas.draw(mspy.plot.container([]))
+ self.parent.updateTmpSpectrum(None)
+ return
+
+ # make container
+ container = mspy.plot.container([])
+
+ # show results
+ container.append(mspy.plot.points(self.currentFit.spectrum, legend='measured', showPoints=False, exactFit=True, lineColour=(16, 71, 185)))
+ container.append(mspy.plot.points(self.currentFit.envelope(), legend='model', showPoints=False, exactFit=True, lineColour=(241,144,0)))
+ container.append(mspy.plot.points(self.currentFit.data, legend='', showLines=False, pointColour=(16, 71, 185)))
+ container.append(mspy.plot.points(self.currentFit.model, legend='', showLines=False, pointColour=(241,144,0)))
+
+ # draw container
+ self.spectrumCanvas.draw(container)
+
+ # update spectrum overlay
+ self.parent.updateTmpSpectrum(self.currentFit.envelope())
+ # ----
+
+
+ def updateResultsList(self):
+ """Update results list."""
+
+ # make data map
+ if self.currentFit == None or self.currentFit.error:
+ data = []
+ else:
+ data = self.currentFit.ncomposition.items()
+ data.sort()
+
+ # clear previous data and set new
+ self.resultsList.DeleteAllItems()
+ self.resultsList.setDataMap(data)
+
+ # check data
+ if not data:
+ return
+
+ # add new data
+ for row, item in enumerate(data):
+ self.resultsList.InsertStringItem(row, str(item[0]))
+ self.resultsList.SetStringItem(row, 1, str(round(item[1]*100, 1)))
+ self.resultsList.SetItemData(row, row)
+
+ # sort data
+ self.resultsList.sort()
+
+ # scroll top
+ if self.resultsList.GetItemCount():
+ self.resultsList.EnsureVisible(0)
+ # ----
+
+
+ def runEnvelopeFit(self):
+ """Run envelope fitting."""
+
+ # run task
+ try:
+
+ # init module
+ self.currentFit = mspy.envelopeFit(
+ formula = self.currentCompound.formula(),
+ charge = config.envfit['charge'],
+ scale = (config.envfit['scaleMin'], config.envfit['scaleMax']),
+ loss = config.envfit['loss'],
+ gain = config.envfit['gain']
+ )
+
+ # fit data to peaklist
+ if config.envfit['fit'] == 'peaklist':
+ self.currentFit.fitToPeaklist(
+ peaklist = self.currentDocument.spectrum.peaklist,
+ fwhm = config.envfit['fwhm'],
+ forceFwhm = config.envfit['forceFwhm'],
+ autoAlign = config.envfit['autoAlign'],
+ iterLimit = 100*config.envfit['scaleMax']
+ )
+
+ # fit data to spectrum
+ elif config.envfit['fit'] == 'spectrum':
+
+ # get baseline window
+ baselineWindow = 1.
+ if config.processing['peakpicking']['baseline']:
+ baselineWindow = 1./config.processing['baseline']['precision']
+
+ # get baseline
+ baseline = self.currentDocument.spectrum.baseline(
+ window = baselineWindow,
+ smooth = True,
+ offset = config.processing['baseline']['offset']
+ )
+
+ # fit data to spectrum
+ self.currentFit.fitToSpectrum(
+ points = self.currentDocument.spectrum.points,
+ fwhm = config.envfit['fwhm'],
+ forceFwhm = config.envfit['forceFwhm'],
+ autoAlign = config.envfit['autoAlign'],
+ iterLimit = 100*config.envfit['scaleMax'],
+ pickingHeight = config.processing['peakpicking']['pickingHeight'],
+ relThreshold = config.envfit['relThreshold'],
+ baselineData = baseline
+ )
+
+ # task canceled
+ except mspy.ForceQuit:
+ self.currentFit = None
+ return
+ # ----
+
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/gui/panel_mass_calculator.py mmass-4.0.0/gui/panel_mass_calculator.py
--- mmass-3.12.1/gui/panel_mass_calculator.py 2011-07-01 14:02:13.000000000 +0000
+++ mmass-4.0.0/gui/panel_mass_calculator.py 2011-11-30 11:15:20.000000000 +0000
@@ -108,9 +108,10 @@
# make compound fields
compound_label = wx.StaticText(panel, -1, "Formula:")
- self.compound_value = wx.TextCtrl(panel, -1, "", size=(250, -1))
+ self.compound_value = mwx.formulaCtrl(panel, -1, "", size=(250, -1), style=wx.TE_PROCESS_ENTER)
compound_label.SetFont(wx.SMALL_FONT)
self.compound_value.Bind(wx.EVT_TEXT, self.onCompoundChanged)
+ self.compound_value.Bind(wx.EVT_TEXT_ENTER, self.onCompoundChanged)
# make save button
self.save_butt = wx.Button(panel, -1, "Save", size=(-1, mwx.SMALL_BUTTON_HEIGHT))
@@ -268,7 +269,7 @@
patternShift_label = wx.StaticText(ctrlPanel, -1, "Shift:")
patternShift_label.SetFont(wx.SMALL_FONT)
- self.patternShift_value = mwx.scrollTextCtrl(ctrlPanel, -1, str(0), step=0.001, digits=3, limits=(-1.,1.), size=(55, mwx.SMALL_TEXTCTRL_HEIGHT))
+ self.patternShift_value = mwx.scrollTextCtrl(ctrlPanel, -1, "0", step=0.001, digits=3, limits=(-1.,1.), size=(55, mwx.SMALL_TEXTCTRL_HEIGHT))
self.patternShift_value.SetFont(wx.SMALL_FONT)
self.patternShift_value.Bind(wx.EVT_TEXT, self.onPatternChanged)
@@ -338,16 +339,18 @@
self.patternCanvas.setProperties(xLabel='m/z')
self.patternCanvas.setProperties(yLabel='a.i.')
self.patternCanvas.setProperties(showLegend=True)
- self.patternCanvas.setProperties(showPosBar=False)
+ self.patternCanvas.setProperties(showPosBar=True)
self.patternCanvas.setProperties(showIntBar=True)
+ self.patternCanvas.setProperties(posBarHeight=6)
self.patternCanvas.setProperties(intBarHeight=6)
self.patternCanvas.setProperties(showGel=False)
- self.patternCanvas.setProperties(checkLimits=False)
+ self.patternCanvas.setProperties(checkLimits=True)
self.patternCanvas.setProperties(autoScaleY=True)
self.patternCanvas.setProperties(overlapLabels=False)
self.patternCanvas.setProperties(xPosDigits=5)
self.patternCanvas.setProperties(yPosDigits=2)
self.patternCanvas.setProperties(distanceDigits=5)
+ self.patternCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.patternCanvas.setProperties(reverseDrawing=True)
self.patternCanvas.setLMBFunction('xDistance')
self.patternCanvas.setMFunction('cross')
@@ -445,6 +448,9 @@
def onCompoundChanged(self, evt=None):
"""Recalc all if compound changed."""
+ if evt != None:
+ evt.Skip()
+
# get all params
if not self.getParams():
self.currentCompound = None
@@ -789,27 +795,27 @@
# add main profile spectrum to container
labelFont = wx.Font(config.spectrum['labelFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
- spectrum = mspy.plot.spectrum(self.currentPatternScan, \
- legend=legend, \
- spectrumColour=(16,71,185), \
- tickColour=(255,0,0), \
- showPoints=False, \
- showLabels=True, \
- showTicks=True, \
- labelDigits=config.main['mzDigits'], \
- labelBgr=True, \
- labelAngle=90,
- labelFont=labelFont \
+ spectrum = mspy.plot.spectrum(self.currentPatternScan,
+ legend = legend,
+ spectrumColour = (16,71,185),
+ tickColour = (255,0,0),
+ showPoints = False,
+ showLabels = True,
+ showTicks = True,
+ labelDigits = config.main['mzDigits'],
+ labelBgr = True,
+ labelAngle = 90,
+ labelFont = labelFont
)
container.append(spectrum)
# add individual peaks to container
for peak in self.currentPatternPeaks:
- spectrum = mspy.plot.points(peak, \
- lineColour=(50,140,0), \
- showLines=True, \
- showPoints=False, \
- exactFit=True \
+ spectrum = mspy.plot.points(peak,
+ lineColour = (50,140,0),
+ showLines = True,
+ showPoints = False,
+ exactFit = True
)
container.append(spectrum)
@@ -817,6 +823,9 @@
if not rescale:
xAxis = self.patternCanvas.getCurrentXRange()
yAxis = self.patternCanvas.getCurrentYRange()
+ if xAxis == (0,1) or yAxis == (0,1):
+ xAxis = None
+ yAxis = None
else:
xAxis = None
yAxis = None
@@ -902,24 +911,24 @@
charge = self.currentIon[3]
# calculate compound pattern
- pattern = self.currentCompound.pattern(\
- fwhm=min(0.9, config.masscalc['patternFwhm']), \
- threshold=config.masscalc['patternThreshold'], \
- charge=charge, \
- agentFormula=config.masscalc['ionseriesAgent'], \
- agentCharge=config.masscalc['ionseriesAgentCharge'] \
+ pattern = self.currentCompound.pattern(
+ fwhm = min(0.9, config.masscalc['patternFwhm']),
+ threshold = config.masscalc['patternThreshold'],
+ charge = charge,
+ agentFormula = config.masscalc['ionseriesAgent'],
+ agentCharge = config.masscalc['ionseriesAgentCharge']
)
# make peaklist from pattern
peaklist = []
for isotope in pattern:
ai = isotope[1]*(config.masscalc['patternIntensity'] - config.masscalc['patternBaseline']) + config.masscalc['patternBaseline']
- peak = mspy.peak( \
- mz=isotope[0], \
- ai=ai, \
- base=config.masscalc['patternBaseline'], \
- fwhm=config.masscalc['patternFwhm'], \
- charge=charge \
+ peak = mspy.peak(
+ mz = isotope[0],
+ ai = ai,
+ base = config.masscalc['patternBaseline'],
+ fwhm = config.masscalc['patternFwhm'],
+ charge = charge
)
peaklist.append(peak)
peaklist = mspy.peaklist(peaklist)
@@ -927,11 +936,11 @@
# make peaks
self.currentPatternPeaks = []
for isotope in peaklist:
- peak = mspy.gaussian(\
- mz=isotope.mz, \
- ai=isotope.ai, \
- base=isotope.base, \
- fwhm=isotope.fwhm \
+ peak = mspy.gaussian(
+ mz = isotope.mz,
+ ai = isotope.ai,
+ base = isotope.base,
+ fwhm = isotope.fwhm
)
self.currentPatternPeaks.append(peak)
diff -Nru mmass-3.12.1/gui/panel_mass_filter.py mmass-4.0.0/gui/panel_mass_filter.py
--- mmass-3.12.1/gui/panel_mass_filter.py 2011-04-14 18:18:47.000000000 +0000
+++ mmass-4.0.0/gui/panel_mass_filter.py 2011-10-31 11:12:15.000000000 +0000
@@ -113,7 +113,7 @@
sizer.Add(self.match_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
sizer.Add(self.annotate_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
sizer.Add(self.remove_butt, 0, wx.ALIGN_CENTER_VERTICAL)
- sizer.AddSpacer(mwx.CONTROLBAR_LSPACE)
+ sizer.AddSpacer(mwx.TOOLBAR_RSPACE)
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(sizer, 1, wx.EXPAND)
diff -Nru mmass-3.12.1/gui/panel_match.py mmass-4.0.0/gui/panel_match.py
--- mmass-3.12.1/gui/panel_match.py 2011-06-29 11:32:05.000000000 +0000
+++ mmass-4.0.0/gui/panel_match.py 2011-11-25 13:44:14.000000000 +0000
@@ -245,6 +245,7 @@
self.errorCanvas.setProperties(autoScaleY=False)
self.errorCanvas.setProperties(xPosDigits=config.main['mzDigits'])
self.errorCanvas.setProperties(yPosDigits=2)
+ self.errorCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.errorCanvas.setProperties(reverseDrawing=True)
self.errorCanvas.setMFunction('cross')
@@ -571,9 +572,9 @@
errorCol = 5
matchObject = doc.match
elif self.currentModule == 'fragment':
- massCol = 3
- chargeCol = 4
- errorCol = 6
+ massCol = 2
+ chargeCol = 3
+ errorCol = 5
matchObject = doc.match
elif self.currentModule == 'compounds':
massCol = 1
@@ -757,12 +758,31 @@
label = 'Number of %s matched' % itemName
self.currentSummary.append((label, sumMatched))
+ # get matched intensity
+ totalInt = 0
+ buff = {}
+ for peak in self.currentPeaklist:
+ totalInt += peak.intensity
+ buff[round(peak.mz, 6)] = peak.intensity
+ matchedInt = 0
+ for item in self.currentData:
+ for n in item[-1]:
+ mz = round(n.mz,6)
+ if mz in buff:
+ matchedInt += buff[mz]
+ del buff[mz]
+ if totalInt:
+ value = '%0.f %s' % ((100*matchedInt/totalInt), '%')
+ else:
+ value = '0 %'
+ self.currentSummary.append(('Intensity matched', value))
+
# get sequence coverage
if self.currentModule == 'digest':
sumPeptides = []
for item in self.currentData:
if item[-1]:
- sumPeptides.append(item[0])
+ sumPeptides.append([item[6].history[-1][1]+1, item[6].history[-1][2]])
coverage = mspy.coverage(sumPeptides, self.currentSummaryData['sequenceLength'])
value = '%0.f %s' % (coverage, '%')
self.currentSummary.append(('Sequence length', self.currentSummaryData['sequenceLength']))
@@ -774,18 +794,29 @@
series = {}
for item in self.currentData:
- if item[0][:3] == 'int':
+ frag = item[6]
+
+ if not frag.fragmentSerie in ('a','b','c','x','y','z','n-ladder','c-ladder'):
+ continue
+ elif 'break' in [x[0] for x in frag.history]:
continue
- if not item[0] in series:
- series[item[0]] = []
+
+ name = frag.fragmentSerie
+ for loss in frag.fragmentLosses:
+ name += ' -'+loss
+ for gain in frag.fragmentGains:
+ name += ' +'+gain
+
+ if not name in series:
+ series[name] = []
if item[-1]:
- series[item[0]].append(item[1])
+ series[name].append(frag.fragmentIndex)
for serie in sorted(series.keys()):
matches = series[serie]
matches.sort()
value = ', '.join(str(n) for n in matches)
- label = 'Ion serie "%s" matches' % serie
+ label = 'Ion serie matches for "%s"' % serie
self.currentSummary.append((label, value))
# ----
diff -Nru mmass-3.12.1/gui/panel_monomer_library.py mmass-4.0.0/gui/panel_monomer_library.py
--- mmass-3.12.1/gui/panel_monomer_library.py 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/gui/panel_monomer_library.py 2011-11-10 12:29:22.000000000 +0000
@@ -0,0 +1,234 @@
+# -------------------------------------------------------------------------
+# Copyright (C) 2005-2011 Martin Strohalm
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# Complete text of GNU GPL can be found in the file LICENSE.TXT in the
+# main directory of the program
+# -------------------------------------------------------------------------
+
+# load libs
+import wx
+
+# load modules
+from ids import *
+import mwx
+import images
+import config
+import libs
+import mspy
+
+
+# FLOATING PANEL WITH MONOMER LIBRARY
+# -----------------------------------
+
+class panelMonomerLibrary(wx.MiniFrame):
+ """Monomer library."""
+
+ def __init__(self, parent, filterIn=[], filterOut=[], DnD=True):
+ wx.MiniFrame.__init__(self, parent, -1, 'Monomer Library', size=(250, 300), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BOX | wx.MAXIMIZE_BOX))
+
+ self.parent = parent
+ self.filterIn = filterIn
+ self.filterOut = filterOut
+ self.DnD = DnD
+
+ # make gui items
+ self.makeGUI()
+ wx.EVT_CLOSE(self, self.onClose)
+
+ # update list
+ self.updateMonomerList()
+ # ----
+
+
+ def makeGUI(self):
+ """Make panel gui."""
+
+ # make toolbar
+ toolbar = self.makeToolbar()
+
+ # make list
+ self.makeMonomerList()
+
+ # pack elements
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.mainSizer.Add(toolbar, 0, wx.EXPAND, 0)
+ self.mainSizer.Add(self.monomerList, 1, wx.EXPAND|wx.ALL, mwx.LISTCTRL_NO_SPACE)
+
+ # fit layout
+ self.mainSizer.Fit(self)
+ self.SetSizer(self.mainSizer)
+ self.SetMinSize(self.GetSize())
+ # ----
+
+
+ def makeToolbar(self):
+ """Make toolbar."""
+
+ # init toolbar
+ panel = mwx.bgrPanel(self, -1, images.lib['bgrToolbarNoBorder'], size=(-1, mwx.TOOLBAR_HEIGHT))
+
+ # make elements
+ if wx.Platform == '__WXMAC__':
+ self.search_value = wx.SearchCtrl(panel, -1, size=(150, mwx.SMALL_SEARCH_HEIGHT), style=wx.TE_PROCESS_ENTER)
+ self.search_value.ShowCancelButton(True)
+ self.search_value.SetDescriptiveText('Search')
+ self.search_value.Bind(wx.EVT_TEXT, self.onSearch)
+ self.search_value.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda evt: self.search_value.SetValue(''))
+ else:
+ self.search_value = wx.TextCtrl(panel, -1, size=(150, mwx.SMALL_SEARCH_HEIGHT), style=wx.TE_PROCESS_ENTER)
+ self.search_value.Bind(wx.EVT_TEXT, self.onSearch)
+
+ # pack elements
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.AddSpacer(mwx.TOOLBAR_LSPACE)
+ sizer.Add(self.search_value, 1, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(mwx.TOOLBAR_LSPACE)
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(sizer, 1, wx.EXPAND)
+ panel.SetSizer(mainSizer)
+ mainSizer.Fit(panel)
+
+ return panel
+ # ----
+
+
+ def makeMonomerList(self):
+ """Make references list."""
+
+ # init list
+ self.monomerList = mwx.sortListCtrl(self, -1, size=(231, 300), style=mwx.LISTCTRL_STYLE_SINGLE)
+ self.monomerList.SetFont(wx.SMALL_FONT)
+ self.monomerList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
+
+ # set events
+ self.monomerList.Bind(wx.EVT_LIST_BEGIN_DRAG, self.onBeginDrag)
+
+ # make columns
+ self.monomerList.InsertColumn(0, "abbr", wx.LIST_FORMAT_LEFT)
+ self.monomerList.InsertColumn(1, "name", wx.LIST_FORMAT_LEFT)
+
+ # set column widths
+ for col, width in enumerate((100,110)):
+ self.monomerList.SetColumnWidth(col, width)
+ # ----
+
+
+ def onClose(self, evt):
+ """Hide this frame."""
+ self.Destroy()
+ # ----
+
+
+ def onSearch(self, evt):
+ """Search monomer library."""
+ self.updateMonomerList()
+ # ----
+
+
+ def onBeginDrag(self, evt):
+ """Start item drag."""
+
+ # check if enabled
+ if not self.DnD:
+ evt.Veto()
+ return
+
+ # get item
+ index = self.monomerList.getSelected()
+ if not index:
+ return
+
+ # get monomer abbr
+ abbr = self.monomerMap[index[0]][0]
+
+ # create data object with text
+ dataObject = wx.PyTextDataObject()
+ dataObject.SetText(abbr)
+
+ # create drop source
+ dropSource = wx.DropSource(self)
+ dropSource.SetData(dataObject)
+ dropSource.DoDragDrop(flags=wx.Drag_CopyOnly)
+ # ----
+
+
+ def setFilter(self, filterIn=[], filterOut=[]):
+ """Set current group filter."""
+
+ # set filters
+ self.filterIn = filterIn
+ self.filterOut = filterOut
+
+ # update list
+ self.updateMonomerList()
+ # ----
+
+
+ def enableDnD(self, enable):
+ """Enable / disable drag and drop."""
+ self.DnD = enable
+ # ----
+
+
+ def updateMonomerMap(self):
+ """Update items map."""
+
+ self.monomerMap = []
+
+ # get search
+ search = self.search_value.GetValue().lower().split()
+
+ # make map
+ for abbr, monomer in sorted(mspy.monomers.items()):
+
+ # check filters
+ if self.filterIn and not monomer.category in self.filterIn:
+ continue
+ elif self.filterOut and monomer.category in self.filterOut:
+ continue
+
+ # check search
+ if search and not (
+ all(map(lambda x: x in monomer.abbr.lower(), search)) or
+ all(map(lambda x: x in monomer.name.lower(), search))
+ ):
+ continue
+
+ # append item
+ self.monomerMap.append((abbr, monomer.name))
+ # ----
+
+
+ def updateMonomerList(self):
+ """Update items list."""
+
+ # clear previous data and set new
+ self.updateMonomerMap()
+ self.monomerList.DeleteAllItems()
+ self.monomerList.setDataMap(self.monomerMap)
+
+ # check data
+ if not self.monomerMap:
+ return
+
+ # add new data
+ for row, item in enumerate(self.monomerMap):
+ self.monomerList.InsertStringItem(row, item[0])
+ self.monomerList.SetStringItem(row, 1, item[1])
+ self.monomerList.SetItemData(row, row)
+
+ # sort
+ self.monomerList.sort()
+ # ----
+
diff -Nru mmass-3.12.1/gui/panel_peak_differences.py mmass-4.0.0/gui/panel_peak_differences.py
--- mmass-3.12.1/gui/panel_peak_differences.py 2011-04-14 18:14:46.000000000 +0000
+++ mmass-4.0.0/gui/panel_peak_differences.py 2011-11-28 16:24:40.000000000 +0000
@@ -425,6 +425,12 @@
def searchAll(self):
"""Search differences for specified value, aminoacids or dipeptides."""
+ # get amino acids
+ aminoacids = []
+ for abbr in mspy.monomers:
+ if mspy.monomers[abbr].category == '_InternalAA':
+ aminoacids.append(abbr)
+
# get maxima
aaMin = 0
aaMax = 0
@@ -432,8 +438,8 @@
dipMax = 0
if config.differences['aminoacids'] or config.differences['dipeptides']:
masses = []
- for aa in mspy.aminoacids:
- masses.append(mspy.aminoacids[aa].mass[config.differences['massType']])
+ for aa in aminoacids:
+ masses.append(mspy.monomers[aa].mass[config.differences['massType']])
aaMin = min(masses) - config.differences['tolerance']
aaMax = max(masses) + config.differences['tolerance']
dipMin = min(masses)*2 - config.differences['tolerance']
@@ -467,8 +473,8 @@
# search for aminoacids
if not matched and config.differences['aminoacids'] and aaMin <= diff <= aaMax:
- for aa in mspy.aminoacids:
- if diffMin <= mspy.aminoacids[aa].mass[config.differences['massType']] <= diffMax:
+ for aa in aminoacids:
+ if diffMin <= mspy.monomers[aa].mass[config.differences['massType']] <= diffMax:
self.currentDifferences[x][y][1] = 'amino'
matched = True
@@ -486,6 +492,12 @@
self.currentMatches = []
+ # get amino acids
+ aminoacids = []
+ for abbr in mspy.monomers:
+ if mspy.monomers[abbr].category == '_InternalAA':
+ aminoacids.append(abbr)
+
# search for value
if self.difference:
error = diff - self.difference
@@ -494,8 +506,8 @@
# search for aminoacids
if config.differences['aminoacids']:
- for aa in mspy.aminoacids:
- error = diff - mspy.aminoacids[aa].mass[config.differences['massType']]
+ for aa in aminoacids:
+ error = diff - mspy.monomers[aa].mass[config.differences['massType']]
if abs(error) <= config.differences['tolerance']:
self.currentMatches.append([aa, error])
@@ -531,16 +543,21 @@
def calcDipeptides(self):
"""Calculate dipeptides masses."""
+ # get amino acids
+ aminoacids = []
+ for abbr in mspy.monomers:
+ if mspy.monomers[abbr].category == '_InternalAA':
+ aminoacids.append(abbr)
+
self.dipeptides = {}
- symbols = mspy.aminoacids.keys()
- for x in range(len(symbols)):
- for y in range(x, len(symbols)):
+ for x in range(len(aminoacids)):
+ for y in range(x, len(aminoacids)):
- aX = symbols[x]
- aY = symbols[y]
+ aX = aminoacids[x]
+ aY = aminoacids[y]
- massX = mspy.aminoacids[aX].mass
- massY = mspy.aminoacids[aY].mass
+ massX = mspy.monomers[aX].mass
+ massY = mspy.monomers[aY].mass
mass = (massX[0] + massY[0], massX[1] + massY[1])
if aX != aY:
diff -Nru mmass-3.12.1/gui/panel_peaklist.py mmass-4.0.0/gui/panel_peaklist.py
--- mmass-3.12.1/gui/panel_peaklist.py 2011-06-30 11:28:37.000000000 +0000
+++ mmass-4.0.0/gui/panel_peaklist.py 2011-10-21 14:05:37.000000000 +0000
@@ -424,6 +424,11 @@
def onDelete(self, evt):
"""Minus button pressed."""
+ # check document
+ if self.currentDocument == None:
+ wx.Bell()
+ return
+
# popup menu
menuDeleteSelectedID = wx.NewId()
menuDeleteByThresholdID = wx.NewId()
@@ -547,7 +552,7 @@
elif thresholdType == 'Relative Intensity':
threshold /= 100
for i, peak in enumerate(self.currentDocument.spectrum.peaklist):
- if peak.relIntensity < threshold:
+ if peak.ri < threshold:
indexes.append(i)
# use s/n
@@ -676,7 +681,7 @@
elif column == 'int':
row.append(peak.intensity)
elif column == 'rel':
- row.append(peak.relIntensity*100)
+ row.append(peak.ri*100)
elif column == 'sn':
row.append(peak.sn)
elif column == 'z':
@@ -911,7 +916,7 @@
if 'int' in config.export['peaklistColumns']:
line += str(peak.intensity) + '\t'
if 'rel' in config.export['peaklistColumns']:
- line += str(peak.relIntensity*100) + '\t'
+ line += str(peak.ri*100) + '\t'
if 'sn' in config.export['peaklistColumns']:
line += str(peak.sn) + '\t'
if 'z' in config.export['peaklistColumns']:
@@ -1032,6 +1037,7 @@
+
class dlgCopy(wx.Dialog):
"""Set coumns to copy."""
@@ -1151,6 +1157,7 @@
config.export['peaklistColumns'].append('group')
# ----
+
class fileDropTarget(wx.FileDropTarget):
diff -Nru mmass-3.12.1/gui/panel_processing.py mmass-4.0.0/gui/panel_processing.py
--- mmass-3.12.1/gui/panel_processing.py 2011-07-01 11:31:42.000000000 +0000
+++ mmass-4.0.0/gui/panel_processing.py 2011-11-30 14:29:17.000000000 +0000
@@ -184,18 +184,17 @@
self.updateAvailableDocuments()
mathOperation_label = wx.StaticText(panel, -1, "Operation:")
- self.mathOperationAdd_radio = wx.RadioButton(panel, -1, "A + B ", style=wx.RB_GROUP)
+ self.mathOperationNorm_radio = wx.RadioButton(panel, -1, "Normalize", style=wx.RB_GROUP)
+ self.mathOperationAdd_radio = wx.RadioButton(panel, -1, "A + B ")
self.mathOperationSub_radio = wx.RadioButton(panel, -1, "A - B ")
- self.mathOperationMul_radio = wx.RadioButton(panel, -1, "A * X")
- self.mathOperationNorm_radio = wx.RadioButton(panel, -1, "Normalize")
- self.mathOperationAdd_radio.SetValue(True)
+ self.mathOperationMul_radio = wx.RadioButton(panel, -1, "A x")
+ self.mathOperationNorm_radio.SetValue(True)
+ self.mathOperationNorm_radio.Bind(wx.EVT_RADIOBUTTON, self.onMathChanged)
self.mathOperationAdd_radio.Bind(wx.EVT_RADIOBUTTON, self.onMathChanged)
self.mathOperationSub_radio.Bind(wx.EVT_RADIOBUTTON, self.onMathChanged)
self.mathOperationMul_radio.Bind(wx.EVT_RADIOBUTTON, self.onMathChanged)
- self.mathOperationNorm_radio.Bind(wx.EVT_RADIOBUTTON, self.onMathChanged)
- mathMul_label = wx.StaticText(panel, -1, "Multiplier X:")
self.mathMul_value = wx.TextCtrl(panel, -1, '1', size=(70, -1), validator=mwx.validator('floatPos'))
self.mathMul_value.Bind(wx.EVT_TEXT, self.onMathChanged)
self.mathMul_value.Disable()
@@ -203,14 +202,13 @@
# pack elements
grid = wx.GridBagSizer(mwx.GRIDBAG_VSPACE, mwx.GRIDBAG_HSPACE)
grid.Add(mathOperation_label, (0,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
- grid.Add(self.mathOperationAdd_radio, (0,1))
- grid.Add(self.mathOperationSub_radio, (1,1))
- grid.Add(self.mathOperationMul_radio, (2,1))
- grid.Add(self.mathOperationNorm_radio, (3,1))
+ grid.Add(self.mathOperationNorm_radio, (0,1), (1,2))
+ grid.Add(self.mathOperationAdd_radio, (1,1), (1,2))
+ grid.Add(self.mathOperationSub_radio, (2,1), (1,2))
+ grid.Add(self.mathOperationMul_radio, (3,1))
+ grid.Add(self.mathMul_value, (3,2), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
grid.Add(mathSpectrumB_label, (4,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
- grid.Add(self.mathSpectrumB_combo, (4,1), (1,3))
- grid.Add(mathMul_label, (5,0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
- grid.Add(self.mathMul_value, (5,1), (1,3))
+ grid.Add(self.mathSpectrumB_combo, (4,1), (1,2))
mainSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer.Add(grid, 0, wx.ALIGN_CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
@@ -298,10 +296,12 @@
# make elements
smoothingMethod_label = wx.StaticText(panel, -1, "Method:")
- self.smoothingMethod_combo = wx.ComboBox(panel, -1, choices=['Moving Average', 'Savitzky-Golay'], size=(150, mwx.COMBO_HEIGHT), style=wx.CB_READONLY)
+ self.smoothingMethod_combo = wx.ComboBox(panel, -1, choices=['Moving Average', 'Gaussian', 'Savitzky-Golay'], size=(150, mwx.COMBO_HEIGHT), style=wx.CB_READONLY)
self.smoothingMethod_combo.Select(0)
- if config.processing['smoothing']['method']=='SG':
+ if config.processing['smoothing']['method']=='GA':
self.smoothingMethod_combo.Select(1)
+ elif config.processing['smoothing']['method']=='SG':
+ self.smoothingMethod_combo.Select(2)
self.smoothingMethod_combo.Bind(wx.EVT_COMBOBOX, self.onSmoothingChanged)
smoothingWindow_label = wx.StaticText(panel, -1, "Window size:")
@@ -441,9 +441,9 @@
self.deisotopingRemoveUnknown_check.SetValue(bool(config.processing['deisotoping']['removeUnknown']))
deisotopingLabelEnvelopeTool_label = wx.StaticText(panel, -1, "Label envelope tool:")
- self.deisotopingLabelEnvelopeTool_combo = wx.ComboBox(panel, -1, choices=['Monoisotopic Mass', 'Envelope Centroid', 'All Isotopes'], size=(160, mwx.COMBO_HEIGHT), style=wx.CB_READONLY)
+ self.deisotopingLabelEnvelopeTool_combo = wx.ComboBox(panel, -1, choices=['1st Selected', 'Monoisotopic Mass', 'Envelope Centroid', 'All Isotopes'], size=(160, mwx.COMBO_HEIGHT), style=wx.CB_READONLY)
self.deisotopingLabelEnvelopeTool_combo.Select(1)
- choices=['monoisotopic', 'centroid', 'isotopes']
+ choices=['1st', 'monoisotope', 'centroid', 'isotopes']
if config.processing['deisotoping']['labelEnvelope'] in choices:
self.deisotopingLabelEnvelopeTool_combo.Select(choices.index(config.processing['deisotoping']['labelEnvelope']))
self.deisotopingLabelEnvelopeTool_combo.Bind(wx.EVT_COMBOBOX, self.getParams)
@@ -764,10 +764,12 @@
self.baselineOffset_slider.SetValue(presets['baseline']['offset']*100)
# set smoothing
- if presets['smoothing']['method']=='MA':
+ if presets['smoothing']['method'] == 'MA':
self.smoothingMethod_combo.Select(0)
- else:
+ elif presets['smoothing']['method'] == 'GA':
self.smoothingMethod_combo.Select(1)
+ else:
+ self.smoothingMethod_combo.Select(2)
self.smoothingWindow_value.SetValue(str(presets['smoothing']['windowSize']))
self.smoothingCycles_slider.SetValue(presets['smoothing']['cycles'])
@@ -791,7 +793,7 @@
self.deisotopingRemoveUnknown_check.SetValue(bool(presets['deisotoping']['removeUnknown']))
self.deisotopingSetAsMonoisotopic_check.SetValue(bool(presets['deisotoping']['setAsMonoisotopic']))
- choices=['monoisotopic', 'centroid', 'isotopes']
+ choices=['1st', 'monoisotope', 'centroid', 'isotopes']
if presets['deisotoping']['labelEnvelope'] in choices:
self.deisotopingLabelEnvelopeTool_combo.Select(choices.index(presets['deisotoping']['labelEnvelope']))
else:
@@ -849,7 +851,10 @@
return
# disable / enable items
- if self.mathOperationAdd_radio.GetValue():
+ if self.mathOperationNorm_radio.GetValue():
+ self.mathSpectrumB_combo.Disable()
+ self.mathMul_value.Disable()
+ elif self.mathOperationAdd_radio.GetValue():
self.mathSpectrumB_combo.Enable()
self.mathMul_value.Disable()
elif self.mathOperationSub_radio.GetValue():
@@ -858,9 +863,6 @@
elif self.mathOperationMul_radio.GetValue():
self.mathSpectrumB_combo.Disable()
self.mathMul_value.Enable()
- elif self.mathOperationNorm_radio.GetValue():
- self.mathSpectrumB_combo.Disable()
- self.mathMul_value.Disable()
# ----
@@ -880,10 +882,10 @@
return
# get baseline
- baseline = self.currentDocument.spectrum.baseline(\
- window=(1./config.processing['baseline']['precision']), \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ baseline = self.currentDocument.spectrum.baseline(
+ window = (1./config.processing['baseline']['precision']),
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# make tmp spectrum
@@ -1079,7 +1081,9 @@
try:
# math operations
- if self.mathOperationAdd_radio.GetValue():
+ if self.mathOperationNorm_radio.GetValue():
+ config.processing['math']['operation'] = 'norm'
+ elif self.mathOperationAdd_radio.GetValue():
config.processing['math']['operation'] = 'add'
config.processing['math']['spectrumB'] = self.mathSpectrumB_combo.GetValue()
elif self.mathOperationSub_radio.GetValue():
@@ -1088,8 +1092,6 @@
elif self.mathOperationMul_radio.GetValue():
config.processing['math']['operation'] = 'mul'
config.processing['math']['multiplier'] = float(self.mathMul_value.GetValue())
- elif self.mathOperationNorm_radio.GetValue():
- config.processing['math']['operation'] = 'norm'
# crop
config.processing['crop']['lowMass'] = float(self.cropLowMass_value.GetValue())
@@ -1104,7 +1106,9 @@
config.processing['smoothing']['cycles'] = int(self.smoothingCycles_slider.GetValue())
config.processing['smoothing']['method'] = 'MA'
- if self.smoothingMethod_combo.GetValue() == 'Savitzky-Golay':
+ if self.smoothingMethod_combo.GetValue() == 'Gaussian':
+ config.processing['smoothing']['method'] = 'GA'
+ elif self.smoothingMethod_combo.GetValue() == 'Savitzky-Golay':
config.processing['smoothing']['method'] = 'SG'
# peak picking
@@ -1127,8 +1131,10 @@
config.processing['deisotoping']['setAsMonoisotopic'] = bool(self.deisotopingSetAsMonoisotopic_check.GetValue())
labelEnvelope = self.deisotopingLabelEnvelopeTool_combo.GetValue()
- if labelEnvelope == 'Monoisotopic Mass':
- config.processing['deisotoping']['labelEnvelope'] = 'monoisotopic'
+ if labelEnvelope == '1st Selected':
+ config.processing['deisotoping']['labelEnvelope'] = '1st'
+ elif labelEnvelope == 'Monoisotopic Mass':
+ config.processing['deisotoping']['labelEnvelope'] = 'monoisotope'
elif labelEnvelope == 'Envelope Centroid':
config.processing['deisotoping']['labelEnvelope'] = 'centroid'
elif labelEnvelope == 'All Isotopes':
@@ -1193,11 +1199,11 @@
try:
# correct baseline
- self.previewData = mspy.correctBaseline(\
- points=self.currentDocument.spectrum.points, \
- window=(1./config.processing['baseline']['precision']), \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ self.previewData = mspy.correctBaseline(
+ points = self.currentDocument.spectrum.points,
+ window = (1./config.processing['baseline']['precision']),
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# task canceled
@@ -1214,20 +1220,29 @@
# smooth data by MA
if config.processing['smoothing']['method']=='MA':
+
+ self.previewData = mspy.smoothMA(
+ points = self.currentDocument.spectrum.points,
+ window = config.processing['smoothing']['windowSize'],
+ cycles = config.processing['smoothing']['cycles']
+ )
- self.previewData = mspy.smoothMA(\
- points=self.currentDocument.spectrum.points, \
- window=config.processing['smoothing']['windowSize'], \
- cycles=config.processing['smoothing']['cycles']\
+ # smooth data by GA
+ elif config.processing['smoothing']['method']=='GA':
+
+ self.previewData = mspy.smoothGA(
+ points = self.currentDocument.spectrum.points,
+ window = config.processing['smoothing']['windowSize'],
+ cycles = config.processing['smoothing']['cycles']
)
# smooth data by SG
elif config.processing['smoothing']['method']=='SG':
-
- self.previewData = mspy.smoothSG(\
- points=self.currentDocument.spectrum.points, \
- window=config.processing['smoothing']['windowSize'], \
- cycles=config.processing['smoothing']['cycles']\
+
+ self.previewData = mspy.smoothSG(
+ points = self.currentDocument.spectrum.points,
+ window = config.processing['smoothing']['windowSize'],
+ cycles = config.processing['smoothing']['cycles']
)
# task canceled
@@ -1256,7 +1271,10 @@
return
# process spectrum
- if config.processing['math']['operation'] == 'add':
+ if config.processing['math']['operation'] == 'norm':
+ self.currentDocument.spectrum.normalize()
+
+ elif config.processing['math']['operation'] == 'add':
self.currentDocument.spectrum.concatenate(spectrumB)
elif config.processing['math']['operation'] == 'sub':
@@ -1265,9 +1283,6 @@
elif config.processing['math']['operation'] == 'mul':
self.currentDocument.spectrum.multiply(config.processing['math']['multiplier'])
- elif config.processing['math']['operation'] == 'norm':
- self.currentDocument.spectrum.normalize()
-
# remove notations
del self.currentDocument.annotations[:]
for sequence in self.currentDocument.sequences:
@@ -1326,10 +1341,10 @@
self.currentDocument.backup(('spectrum', 'notations'))
# correct baseline
- self.currentDocument.spectrum.correctBaseline(\
- window=(1./config.processing['baseline']['precision']), \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ self.currentDocument.spectrum.correctBaseline(
+ window = (1./config.processing['baseline']['precision']),
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# remove notations
@@ -1353,10 +1368,10 @@
self.currentDocument.backup(('spectrum', 'notations'))
# smooth spectrum
- self.currentDocument.spectrum.smooth(\
- method=config.processing['smoothing']['method'], \
- window=config.processing['smoothing']['windowSize'], \
- cycles=config.processing['smoothing']['cycles'] \
+ self.currentDocument.spectrum.smooth(
+ method = config.processing['smoothing']['method'],
+ window = config.processing['smoothing']['windowSize'],
+ cycles = config.processing['smoothing']['cycles']
)
# remove notations
@@ -1390,18 +1405,18 @@
smoothMethod = config.processing['smoothing']['method']
# label spectrum
- self.currentDocument.spectrum.labelScan(\
- pickingHeight=config.processing['peakpicking']['pickingHeight'], \
- absThreshold=config.processing['peakpicking']['absIntThreshold'], \
- relThreshold=config.processing['peakpicking']['relIntThreshold'], \
- snThreshold=config.processing['peakpicking']['snThreshold'], \
- baselineWindow=baselineWindow, \
- baselineSmooth=True, \
- baselineOffset=config.processing['baseline']['offset'], \
- smoothMethod=smoothMethod, \
- smoothWindow=config.processing['smoothing']['windowSize'], \
- smoothCycles=config.processing['smoothing']['cycles'] \
- )
+ self.currentDocument.spectrum.labelScan(
+ pickingHeight = config.processing['peakpicking']['pickingHeight'],
+ absThreshold = config.processing['peakpicking']['absIntThreshold'],
+ relThreshold = config.processing['peakpicking']['relIntThreshold'],
+ snThreshold = config.processing['peakpicking']['snThreshold'],
+ baselineWindow = baselineWindow,
+ baselineSmooth = True,
+ baselineOffset = config.processing['baseline']['offset'],
+ smoothMethod = smoothMethod,
+ smoothWindow = config.processing['smoothing']['windowSize'],
+ smoothCycles = config.processing['smoothing']['cycles']
+ )
# remove shoulder peaks
if config.processing['peakpicking']['removeShoulders']:
@@ -1409,11 +1424,11 @@
# find isotopes and calculate charges
if config.processing['peakpicking']['deisotoping']:
- self.currentDocument.spectrum.findIsotopes(\
- maxCharge=config.processing['deisotoping']['maxCharge'], \
- mzTolerance=config.processing['deisotoping']['massTolerance'], \
- intTolerance=config.processing['deisotoping']['intTolerance'], \
- isotopeShift=config.processing['deisotoping']['isotopeShift'] \
+ self.currentDocument.spectrum.findIsotopes(
+ maxCharge = config.processing['deisotoping']['maxCharge'],
+ mzTolerance = config.processing['deisotoping']['massTolerance'],
+ intTolerance = config.processing['deisotoping']['intTolerance'],
+ isotopeShift = config.processing['deisotoping']['isotopeShift']
)
# remove isotopes
@@ -1445,11 +1460,11 @@
self.currentDocument.backup(('spectrum', 'notations'))
# find isotopes and calculate charges
- self.currentDocument.spectrum.findIsotopes(\
- maxCharge=config.processing['deisotoping']['maxCharge'], \
- mzTolerance=config.processing['deisotoping']['massTolerance'], \
- intTolerance=config.processing['deisotoping']['intTolerance'], \
- isotopeShift=config.processing['deisotoping']['isotopeShift'] \
+ self.currentDocument.spectrum.findIsotopes(
+ maxCharge = config.processing['deisotoping']['maxCharge'],
+ mzTolerance = config.processing['deisotoping']['massTolerance'],
+ intTolerance = config.processing['deisotoping']['intTolerance'],
+ isotopeShift = config.processing['deisotoping']['isotopeShift']
)
# remove isotopes
@@ -1491,14 +1506,13 @@
del sequence.matches[:]
# deconvolute peaklist
- massType = ['mo', 'av']
- docData.spectrum.deconvolute(massType=massType[config.processing['deconvolution']['massType']])
+ docData.spectrum.deconvolute(massType=config.processing['deconvolution']['massType'])
# group peaks
if config.processing['deconvolution']['groupPeaks']:
docData.spectrum.groupPeaks(
- window=config.processing['deconvolution']['groupWindow'], \
- forceWindow=config.processing['deconvolution']['forceGroupWindow']
+ window = config.processing['deconvolution']['groupWindow'],
+ forceWindow = config.processing['deconvolution']['forceGroupWindow']
)
# append new document
@@ -1561,11 +1575,11 @@
window = 1./config.processing['baseline']['precision']
# get curent baseline
- baseline = self.currentDocument.spectrum.baseline(\
- window=window, \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
- )
+ baseline = self.currentDocument.spectrum.baseline(
+ window = window,
+ smooth = True,
+ offset = config.processing['baseline']['offset']
+ )
# get basepeak (approx. only)
index = self.currentDocument.spectrum.points.argmax(axis=0)[1]
diff -Nru mmass-3.12.1/gui/panel_sequence.py mmass-4.0.0/gui/panel_sequence.py
--- mmass-3.12.1/gui/panel_sequence.py 2011-06-13 09:59:39.000000000 +0000
+++ mmass-4.0.0/gui/panel_sequence.py 2011-11-30 10:59:51.000000000 +0000
@@ -29,6 +29,7 @@
import mspy
from gui.panel_match import panelMatch
+from gui.panel_monomer_library import panelMonomerLibrary
# FLOATING PANEL WITH SEQUENCE TOOLS
@@ -37,11 +38,12 @@
class panelSequence(wx.MiniFrame):
"""Sequence tools."""
- def __init__(self, parent, tool='sequence'):
+ def __init__(self, parent, tool='editor'):
wx.MiniFrame.__init__(self, parent, -1, 'Sequence', size=(500, 300), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BOX | wx.MAXIMIZE_BOX))
self.parent = parent
self.matchPanel = None
+ self.monomerLibraryPanel = None
self.processing = None
@@ -164,8 +166,21 @@
"""Make toolbar for sequence panel."""
# make elements
- self.sequenceInfo_label = wx.StaticText(panel, -1, "", size=(330,-1))
- self.sequenceInfo_label.SetFont(wx.SMALL_FONT)
+ self.monomerLibrary_butt = wx.BitmapButton(panel, -1, images.lib['toolsLibrary'], size=(mwx.TOOLBAR_TOOLSIZE), style=wx.BORDER_NONE)
+ self.monomerLibrary_butt.SetToolTip(wx.ToolTip("Monomer library"))
+ self.monomerLibrary_butt.Bind(wx.EVT_BUTTON, self.onMonomerLibrary)
+
+ sequenceType_label = wx.StaticText(panel, -1, "Sequence type:")
+ sequenceType_label.SetFont(wx.SMALL_FONT)
+
+ self.sequenceType_combo = wx.ComboBox(panel, -1, choices=['Regular amino acids', 'Custom'], size=(-1, mwx.SMALL_COMBO_HEIGHT), style=wx.CB_READONLY)
+ self.sequenceType_combo.SetFont(wx.SMALL_FONT)
+ self.sequenceType_combo.Select(0)
+ self.sequenceType_combo.Bind(wx.EVT_COMBOBOX, self.onSequenceType)
+
+ self.sequenceCyclic_check = wx.CheckBox(panel, -1, "Cyclic")
+ self.sequenceCyclic_check.SetFont(wx.SMALL_FONT)
+ self.sequenceCyclic_check.Bind(wx.EVT_CHECKBOX, self.onSequenceCyclic)
self.pattern_butt = wx.Button(panel, -1, "Pattern", size=(-1, mwx.SMALL_BUTTON_HEIGHT))
self.pattern_butt.SetFont(wx.SMALL_FONT)
@@ -174,7 +189,12 @@
# pack elements
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.AddSpacer(20)
- sizer.Add(self.sequenceInfo_label, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.Add(self.monomerLibrary_butt, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(sequenceType_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sizer.Add(self.sequenceType_combo, 0, wx.ALIGN_CENTER_VERTICAL)
+ sizer.AddSpacer(20)
+ sizer.Add(self.sequenceCyclic_check, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.AddStretchSpacer()
sizer.AddSpacer(20)
sizer.Add(self.pattern_butt, 0, wx.ALIGN_CENTER_VERTICAL)
@@ -380,10 +400,16 @@
def makeSequencePanel(self):
"""Make compound summary panel."""
+ # init panels
+ ctrlPanel = mwx.bgrPanel(self, -1, images.lib['bgrControlbar'], size=(-1, mwx.CONTROLBAR_HEIGHT))
panel = wx.Panel(self, -1)
+ # make controls
+ self.sequenceInfo_label = wx.StaticText(ctrlPanel, -1, "Sequence Info", size=(600,-1))
+ self.sequenceInfo_label.SetFont(wx.SMALL_FONT)
+
# make elements
- self.sequenceTitle_value = wx.TextCtrl(panel, -1, self.currentSequence.title, size=(250, -1))
+ self.sequenceTitle_value = wx.TextCtrl(panel, -1, self.currentSequence.title, size=(420, -1))
self.sequenceTitle_value.Bind(wx.EVT_TEXT, self.onSequenceTitle)
sequenceAccession_label = wx.StaticText(panel, -1, "Acc.:")
@@ -398,21 +424,40 @@
self.sequenceCanvas.Bind(wx.EVT_RIGHT_DOWN, self.onSequence)
self.sequenceCanvas.Bind(wx.EVT_MOTION, self.onSequence)
+ self.sequenceGrid = sequenceGrid(self, panel, sequence=self.currentSequence, items=config.sequence['editor']['gridSize'])
+
+ # pack controls
+ controls = wx.BoxSizer(wx.HORIZONTAL)
+ controls.AddSpacer(mwx.CONTROLBAR_LSPACE)
+ controls.Add(self.sequenceInfo_label, 0, wx.ALIGN_CENTER_VERTICAL)
+ controls.AddSpacer(mwx.CONTROLBAR_RSPACE)
+ controls.Fit(ctrlPanel)
+ ctrlPanel.SetSizer(controls)
+
# pack elements
- sizer = wx.BoxSizer(wx.HORIZONTAL)
- sizer.Add(self.sequenceTitle_value, 1, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
- sizer.Add(sequenceAccession_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- sizer.Add(self.sequenceAccession_value, 0)
+ sequenceTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
+ sequenceTitleSizer.Add(self.sequenceTitle_value, 1, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10)
+ sequenceTitleSizer.Add(sequenceAccession_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
+ sequenceTitleSizer.Add(self.sequenceAccession_value, 0)
- mainSizer = wx.BoxSizer(wx.VERTICAL)
- mainSizer.Add(sizer, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
- mainSizer.Add(self.sequenceCanvas, 1, wx.EXPAND|wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT|wx.BOTTOM, mwx.PANEL_SPACE_MAIN)
+ self.sequenceEditorSizer = wx.BoxSizer(wx.VERTICAL)
+ if wx.Platform == '__WXMAC__':
+ self.sequenceEditorSizer.Add(sequenceTitleSizer, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, mwx.PANEL_SPACE_MAIN)
+ else:
+ self.sequenceEditorSizer.Add(sequenceTitleSizer, 0, wx.EXPAND|wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT|wx.BOTTOM, mwx.PANEL_SPACE_MAIN)
+ self.sequenceEditorSizer.Add(self.sequenceCanvas, 1, wx.EXPAND|wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT|wx.BOTTOM, mwx.PANEL_SPACE_MAIN)
+ self.sequenceEditorSizer.Add(self.sequenceGrid, 1, wx.EXPAND|wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT|wx.BOTTOM, mwx.PANEL_SPACE_MAIN)
+ self.sequenceEditorSizer.Hide(2)
- # fit layout
- mainSizer.Fit(panel)
- panel.SetSizer(mainSizer)
+ self.sequenceEditorSizer.Fit(panel)
+ panel.SetSizer(self.sequenceEditorSizer)
- return panel
+ # pack main
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(ctrlPanel, 0, wx.EXPAND)
+ mainSizer.Add(panel, 1, wx.EXPAND)
+
+ return mainSizer
# ----
@@ -426,7 +471,7 @@
modsPosition_label = wx.StaticText(ctrlPanel, -1, "Position:")
modsPosition_label.SetFont(wx.SMALL_FONT)
- self.modsResidue_combo = wx.ComboBox(ctrlPanel, -1, choices=['Glutamic acid'], size=(130, mwx.SMALL_COMBO_HEIGHT), style=wx.CB_READONLY)
+ self.modsResidue_combo = wx.ComboBox(ctrlPanel, -1, choices=[], size=(130, mwx.SMALL_COMBO_HEIGHT), style=wx.CB_READONLY)
self.modsResidue_combo.SetFont(wx.SMALL_FONT)
self.modsResidue_combo.Bind(wx.EVT_COMBOBOX, self.onResidueSelected)
@@ -550,11 +595,16 @@
"""Make controls for peptide fragmentation."""
# init panel
- ctrlPanel = mwx.bgrPanel(self, -1, images.lib['bgrControlbar'], size=(-1, mwx.CONTROLBAR_HEIGHT))
+ ctrlPanel = mwx.bgrPanel(self, -1, images.lib['bgrControlbarDouble'], size=(-1, mwx.CONTROLBAR_DOUBLE_HEIGHT))
# make controls
- fragmentIons_label = wx.StaticText(ctrlPanel, -1, "Ions:")
- fragmentIons_label.SetFont(wx.SMALL_FONT)
+ self.fragmentM_check = wx.CheckBox(ctrlPanel, -1, "M")
+ self.fragmentM_check.SetFont(wx.SMALL_FONT)
+ self.fragmentM_check.SetValue(config.sequence['fragment']['fragments'].count('M'))
+
+ self.fragmentIm_check = wx.CheckBox(ctrlPanel, -1, "im")
+ self.fragmentIm_check.SetFont(wx.SMALL_FONT)
+ self.fragmentIm_check.SetValue(config.sequence['fragment']['fragments'].count('im'))
self.fragmentA_check = wx.CheckBox(ctrlPanel, -1, "a")
self.fragmentA_check.SetFont(wx.SMALL_FONT)
@@ -580,74 +630,102 @@
self.fragmentZ_check.SetFont(wx.SMALL_FONT)
self.fragmentZ_check.SetValue(config.sequence['fragment']['fragments'].count('z'))
- self.fragmentIm_check = wx.CheckBox(ctrlPanel, -1, "im")
- self.fragmentIm_check.SetFont(wx.SMALL_FONT)
- self.fragmentIm_check.SetValue(config.sequence['fragment']['fragments'].count('im'))
-
- self.fragmentIntB_check = wx.CheckBox(ctrlPanel, -1, "int-b")
- self.fragmentIntB_check.SetFont(wx.SMALL_FONT)
- self.fragmentIntB_check.SetValue(config.sequence['fragment']['fragments'].count('int'))
-
self.fragmentIntA_check = wx.CheckBox(ctrlPanel, -1, "int-a")
self.fragmentIntA_check.SetFont(wx.SMALL_FONT)
- self.fragmentIntA_check.SetValue(config.sequence['fragment']['fragments'].count('int-CO'))
+ self.fragmentIntA_check.SetValue(config.sequence['fragment']['fragments'].count('int-a'))
- fragmentLoss_label = wx.StaticText(ctrlPanel, -1, 'Loss:')
- fragmentLoss_label.SetFont(wx.SMALL_FONT)
-
- self.fragmentH2O_check = wx.CheckBox(ctrlPanel, -1, "-H2O")
- self.fragmentH2O_check.SetFont(wx.SMALL_FONT)
- self.fragmentH2O_check.SetValue(config.sequence['fragment']['fragments'].count('-H2O'))
-
- self.fragmentNH3_check = wx.CheckBox(ctrlPanel, -1, "-NH3")
- self.fragmentNH3_check.SetFont(wx.SMALL_FONT)
- self.fragmentNH3_check.SetValue(config.sequence['fragment']['fragments'].count('-NH3'))
-
- self.fragmentH3PO4_check = wx.CheckBox(ctrlPanel, -1, "-H3PO4")
- self.fragmentH3PO4_check.SetFont(wx.SMALL_FONT)
- self.fragmentH3PO4_check.SetValue(config.sequence['fragment']['fragments'].count('-H3PO4'))
-
- fragmentLadder_label = wx.StaticText(ctrlPanel, -1, 'Ladder:')
- fragmentLadder_label.SetFont(wx.SMALL_FONT)
+ self.fragmentIntB_check = wx.CheckBox(ctrlPanel, -1, "int-b")
+ self.fragmentIntB_check.SetFont(wx.SMALL_FONT)
+ self.fragmentIntB_check.SetValue(config.sequence['fragment']['fragments'].count('int-b'))
- self.fragmentNLadder_check = wx.CheckBox(ctrlPanel, -1, "N")
+ self.fragmentNLadder_check = wx.CheckBox(ctrlPanel, -1, "N-ladder")
self.fragmentNLadder_check.SetFont(wx.SMALL_FONT)
self.fragmentNLadder_check.SetValue(config.sequence['fragment']['fragments'].count('n-ladder'))
- self.fragmentCLadder_check = wx.CheckBox(ctrlPanel, -1, "C")
+ self.fragmentCLadder_check = wx.CheckBox(ctrlPanel, -1, "C-ladder")
self.fragmentCLadder_check.SetFont(wx.SMALL_FONT)
self.fragmentCLadder_check.SetValue(config.sequence['fragment']['fragments'].count('c-ladder'))
- self.fragmentFilter_check = wx.CheckBox(ctrlPanel, -1, "Filter")
- self.fragmentFilter_check.SetFont(wx.SMALL_FONT)
- self.fragmentFilter_check.SetValue(config.sequence['fragment']['filterFragments'])
+ self.fragmentLossH2O_check = wx.CheckBox(ctrlPanel, -1, "-H2O")
+ self.fragmentLossH2O_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossH2O_check.SetValue(config.sequence['fragment']['fragments'].count('-H2O'))
+
+ self.fragmentLossNH3_check = wx.CheckBox(ctrlPanel, -1, "-NH3")
+ self.fragmentLossNH3_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossNH3_check.SetValue(config.sequence['fragment']['fragments'].count('-NH3'))
+
+ self.fragmentLossCO_check = wx.CheckBox(ctrlPanel, -1, "-CO")
+ self.fragmentLossCO_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossCO_check.SetValue(config.sequence['fragment']['fragments'].count('-CO'))
+
+ self.fragmentLossH3PO4_check = wx.CheckBox(ctrlPanel, -1, "-H3PO4")
+ self.fragmentLossH3PO4_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossH3PO4_check.SetValue(config.sequence['fragment']['fragments'].count('-H3PO4'))
+
+ self.fragmentLossDefined_check = wx.CheckBox(ctrlPanel, -1, "Defined losses")
+ self.fragmentLossDefined_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossDefined_check.SetValue(config.sequence['fragment']['fragments'].count('losses'))
+ self.fragmentLossDefined_check.SetToolTip(wx.ToolTip("Apply specific losses from monomer library."))
+
+ self.fragmentLossCombi_check = wx.CheckBox(ctrlPanel, -1, "Combinations")
+ self.fragmentLossCombi_check.SetFont(wx.SMALL_FONT)
+ self.fragmentLossCombi_check.SetValue(config.sequence['fragment']['fragments'].count('losscombi'))
+
+ self.fragmentGainH2O_check = wx.CheckBox(ctrlPanel, -1, "+H2O")
+ self.fragmentGainH2O_check.SetFont(wx.SMALL_FONT)
+ self.fragmentGainH2O_check.SetValue(config.sequence['fragment']['fragments'].count('+H2O'))
+ self.fragmentGainH2O_check.SetToolTip(wx.ToolTip("Allowed for 'b' ions only."))
+
+ self.fragmentGainCO_check = wx.CheckBox(ctrlPanel, -1, "+CO")
+ self.fragmentGainCO_check.SetFont(wx.SMALL_FONT)
+ self.fragmentGainCO_check.SetValue(config.sequence['fragment']['fragments'].count('+CO'))
+ self.fragmentGainCO_check.SetToolTip(wx.ToolTip("Allowed for 'b' and 'c' ions only."))
+
+ self.fragmentScrambling_check = wx.CheckBox(ctrlPanel, -1, "Allow scrambling")
+ self.fragmentScrambling_check.SetFont(wx.SMALL_FONT)
+ self.fragmentScrambling_check.SetValue(config.sequence['fragment']['fragments'].count('scrambling'))
+ self.fragmentScrambling_check.SetToolTip(wx.ToolTip("Allow non-direct sequencing."))
+ self.fragmentScrambling_check.Bind(wx.EVT_CHECKBOX, self.updateAvailableFragments)
+
+ self.fragmentRemoveFiltered_check = wx.CheckBox(ctrlPanel, -1, "Remove filtered")
+ self.fragmentRemoveFiltered_check.SetFont(wx.SMALL_FONT)
+ self.fragmentRemoveFiltered_check.SetValue(config.sequence['fragment']['filterFragments'])
self.makeFragmentsList()
# pack controls
+ grid = wx.GridBagSizer(mwx.GRIDBAG_VSPACE, mwx.GRIDBAG_HSPACE)
+ grid.Add(self.fragmentM_check, (0,0))
+ grid.Add(self.fragmentIm_check, (1,0))
+
+ grid.Add(self.fragmentA_check, (0,2))
+ grid.Add(self.fragmentB_check, (0,3))
+ grid.Add(self.fragmentC_check, (0,4))
+ grid.Add(self.fragmentX_check, (1,2))
+ grid.Add(self.fragmentY_check, (1,3))
+ grid.Add(self.fragmentZ_check, (1,4))
+
+ grid.Add(self.fragmentIntA_check, (0,6))
+ grid.Add(self.fragmentIntB_check, (1,6))
+ grid.Add(self.fragmentNLadder_check, (0,7))
+ grid.Add(self.fragmentCLadder_check, (1,7))
+
+ grid.Add(self.fragmentLossH2O_check, (0,9))
+ grid.Add(self.fragmentLossNH3_check, (1,9))
+ grid.Add(self.fragmentLossCO_check, (0,10))
+ grid.Add(self.fragmentLossH3PO4_check, (1,10))
+ grid.Add(self.fragmentLossDefined_check, (0,11))
+ grid.Add(self.fragmentLossCombi_check, (1,11))
+
+ grid.Add(self.fragmentGainH2O_check, (0,13))
+ grid.Add(self.fragmentGainCO_check, (1,13))
+
+ grid.Add(self.fragmentScrambling_check, (0,15))
+ grid.Add(self.fragmentRemoveFiltered_check, (1,15))
+
controls = wx.BoxSizer(wx.HORIZONTAL)
controls.AddSpacer(mwx.CONTROLBAR_LSPACE)
- controls.Add(fragmentIons_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentA_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentB_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentC_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentX_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentY_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentZ_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentIm_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentIntB_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentIntA_check, 0, wx.ALIGN_CENTER_VERTICAL)
- controls.AddSpacer(20)
- controls.Add(fragmentLoss_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentH2O_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentNH3_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentH3PO4_check, 0, wx.ALIGN_CENTER_VERTICAL)
- controls.AddSpacer(20)
- controls.Add(fragmentLadder_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentNLadder_check, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
- controls.Add(self.fragmentCLadder_check, 0, wx.ALIGN_CENTER_VERTICAL)
- controls.AddSpacer(20)
- controls.Add(self.fragmentFilter_check, 0, wx.ALIGN_CENTER_VERTICAL)
+ controls.Add(grid, 0, wx.ALIGN_CENTER_VERTICAL)
controls.AddSpacer(mwx.CONTROLBAR_RSPACE)
controls.Fit(ctrlPanel)
ctrlPanel.SetSizer(controls)
@@ -781,7 +859,7 @@
"""Make digest list."""
# init peaklist
- self.digestList = mwx.sortListCtrl(self, -1, size=(738, 300), style=mwx.LISTCTRL_STYLE_SINGLE)
+ self.digestList = mwx.sortListCtrl(self, -1, size=(778, 300), style=mwx.LISTCTRL_STYLE_SINGLE)
self.digestList.SetFont(wx.SMALL_FONT)
self.digestList.setSecondarySortColumn(2)
self.digestList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
@@ -796,7 +874,7 @@
self.digestList.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onListRMU)
# make columns
- self.digestList.InsertColumn(0, "range", wx.LIST_FORMAT_CENTER)
+ self.digestList.InsertColumn(0, "slice", wx.LIST_FORMAT_CENTER)
self.digestList.InsertColumn(1, "mis.", wx.LIST_FORMAT_CENTER)
self.digestList.InsertColumn(2, "m/z", wx.LIST_FORMAT_RIGHT)
self.digestList.InsertColumn(3, "z", wx.LIST_FORMAT_CENTER)
@@ -804,7 +882,7 @@
self.digestList.InsertColumn(5, "error", wx.LIST_FORMAT_RIGHT)
# set column widths
- for col, width in enumerate((80,47,90,40,400,60)):
+ for col, width in enumerate((80,47,90,40,440,60)):
self.digestList.SetColumnWidth(col, width)
# ----
@@ -813,9 +891,9 @@
"""Make fragments list."""
# init peaklist
- self.fragmentsList = mwx.sortListCtrl(self, -1, size=(816, 300), style=mwx.LISTCTRL_STYLE_SINGLE)
+ self.fragmentsList = mwx.sortListCtrl(self, -1, size=(801, 300), style=mwx.LISTCTRL_STYLE_SINGLE)
self.fragmentsList.SetFont(wx.SMALL_FONT)
- self.fragmentsList.setSecondarySortColumn(2)
+ self.fragmentsList.setSecondarySortColumn(1)
self.fragmentsList.setAltColour(mwx.LISTCTRL_ALTCOLOUR)
# set events
@@ -828,16 +906,15 @@
self.fragmentsList.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onListRMU)
# make columns
- self.fragmentsList.InsertColumn(0, "ion", wx.LIST_FORMAT_CENTER)
- self.fragmentsList.InsertColumn(1, "#", wx.LIST_FORMAT_CENTER)
- self.fragmentsList.InsertColumn(2, "range", wx.LIST_FORMAT_CENTER)
- self.fragmentsList.InsertColumn(3, "m/z", wx.LIST_FORMAT_RIGHT)
- self.fragmentsList.InsertColumn(4, "z", wx.LIST_FORMAT_CENTER)
- self.fragmentsList.InsertColumn(5, "sequence", wx.LIST_FORMAT_LEFT)
- self.fragmentsList.InsertColumn(6, "error", wx.LIST_FORMAT_RIGHT)
+ self.fragmentsList.InsertColumn(0, "ion", wx.LIST_FORMAT_LEFT)
+ self.fragmentsList.InsertColumn(1, "slice", wx.LIST_FORMAT_CENTER)
+ self.fragmentsList.InsertColumn(2, "m/z", wx.LIST_FORMAT_RIGHT)
+ self.fragmentsList.InsertColumn(3, "z", wx.LIST_FORMAT_CENTER)
+ self.fragmentsList.InsertColumn(4, "sequence", wx.LIST_FORMAT_LEFT)
+ self.fragmentsList.InsertColumn(5, "error", wx.LIST_FORMAT_RIGHT)
# set column widths
- for col, width in enumerate((80,40,70,90,40,415,60)):
+ for col, width in enumerate((120,130,90,40,340,60)):
self.fragmentsList.SetColumnWidth(col, width)
# ----
@@ -861,7 +938,7 @@
self.searchList.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onListRMU)
# make columns
- self.searchList.InsertColumn(0, "range", wx.LIST_FORMAT_CENTER)
+ self.searchList.InsertColumn(0, "slice", wx.LIST_FORMAT_CENTER)
self.searchList.InsertColumn(1, "m/z", wx.LIST_FORMAT_RIGHT)
self.searchList.InsertColumn(2, "sequence", wx.LIST_FORMAT_LEFT)
self.searchList.InsertColumn(3, "error", wx.LIST_FORMAT_RIGHT)
@@ -884,6 +961,10 @@
if self.matchPanel:
self.matchPanel.Close()
+ # close library panel
+ if self.monomerLibraryPanel:
+ self.monomerLibraryPanel.Close()
+
# close self
self.Destroy()
# ----
@@ -999,6 +1080,29 @@
elif evt and evt.GetId() == ID_sequenceSearch:
tool = 'search'
+ # block some tools for cyclic or custom sequence
+ if tool == 'editor':
+ pass
+ elif self.currentSequence == None:
+ wx.Bell()
+ return
+ elif self.currentSequence.chainType != 'aminoacids' and not tool in ('editor', 'fragment'):
+ wx.Bell()
+ title = "Selected tool is not available for custom-type sequences."
+ message = "To enable this tool, check the sequence type specified in the editor\nand if possible, convert your sequence to use regular amino acids."
+ dlg = mwx.dlgMessage(self, title, message)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+ elif self.currentSequence.cyclic and not tool in ('editor', 'modifications','fragment'):
+ wx.Bell()
+ title = "Selected tool is not available for cyclic sequences."
+ message = "To enable this tool, linearize the sequence in the editor."
+ dlg = mwx.dlgMessage(self, title, message)
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+
# set current tool
self.currentTool = tool
@@ -1030,7 +1134,7 @@
self.toolbar.Show(1)
self.mainSizer.Show(1)
- if tool == 'modifications':
+ elif tool == 'modifications':
self.SetTitle("Sequence Modifications")
self.modifications_butt.SetBitmapLabel(images.lib['sequenceModificationsOn'])
self.toolbar.Show(2)
@@ -1059,6 +1163,116 @@
# ----
+ def onMonomerLibrary(self, evt):
+ """Show monomers library."""
+
+ # destroy panel
+ if self.monomerLibraryPanel:
+ self.monomerLibraryPanel.Close()
+ return
+
+ # set filters
+ filterIn = []
+ filterOut = []
+ if self.currentSequence == None or self.currentSequence.chainType == 'aminoacids':
+ filterIn = ['_InternalAA']
+ DnD = False
+ else:
+ filterOut = ['_InternalAA']
+ DnD = True
+
+ # init library panel
+ if not self.monomerLibraryPanel:
+ self.monomerLibraryPanel = panelMonomerLibrary(self, filterIn=filterIn, filterOut=filterOut, DnD=DnD)
+ pos = self.GetPosition()
+ size = self.monomerLibraryPanel.GetSize()
+ self.monomerLibraryPanel.SetPosition((pos[0]-size[0]-20, pos[1]+50))
+ self.monomerLibraryPanel.Show(True)
+
+ # raise panel
+ self.monomerLibraryPanel.Raise()
+ # ----
+
+
+ def onSequenceType(self, evt=None, chainType='aminoacids'):
+ """Change sequence editor and chain type."""
+
+ # switch sequence type
+ if evt != None:
+
+ # get chain type
+ if self.sequenceType_combo.GetValue() == 'Regular amino acids':
+ chainType = 'aminoacids'
+ before = 'Custom'
+ elif self.sequenceType_combo.GetValue() == 'Custom':
+ chainType = 'custom'
+ before = 'Regular amino acids'
+
+ # ask to process
+ if len(self.currentSequence):
+ title = 'Do you really want to change the sequence type?'
+ message = 'Current sequence definition will be lost.'
+ buttons = [(wx.ID_CANCEL, "Cancel", 80, False, 15), (wx.ID_OK, "Change", 80, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ if dlg.ShowModal() == wx.ID_OK:
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+ self.sequenceType_combo.SetValue(before)
+ return
+
+ # reset sequence
+ del self.currentSequence[:]
+ self.currentSequence.chainType = chainType
+
+ # set editors
+ if chainType == 'aminoacids':
+ self.sequenceCanvas.setData(self.currentSequence)
+ self.sequenceGrid.setData(None)
+ self.sequenceGrid.setModified(True)
+ self.sequenceEditorSizer.Hide(2)
+ self.sequenceEditorSizer.Show(1)
+ elif chainType == 'custom':
+ self.sequenceGrid.setData(self.currentSequence)
+ self.sequenceCanvas.setData(None)
+ self.sequenceCanvas.setModified(True)
+ self.sequenceEditorSizer.Hide(1)
+ self.sequenceEditorSizer.Show(2)
+
+ # update sequence info
+ self.onSequenceChanged()
+
+ # set monomer filter to library
+ if self.monomerLibraryPanel and chainType == 'aminoacids':
+ self.monomerLibraryPanel.setFilter(filterIn=['_InternalAA'])
+ self.monomerLibraryPanel.enableDnD(False)
+ elif self.monomerLibraryPanel and chainType == 'custom':
+ self.monomerLibraryPanel.setFilter(filterOut=['_InternalAA'])
+ self.monomerLibraryPanel.enableDnD(True)
+
+ # fit layout
+ mwx.layout(self, self.mainSizer)
+ # ----
+
+
+ def onSequenceCyclic(self, evt):
+ """Set current sequence cyclic or linear."""
+
+ # make sequence cyclic/linear
+ value = self.sequenceCyclic_check.IsChecked()
+ self.currentSequence.cyclize(value)
+
+ # set editor as modified
+ if self.currentSequence.chainType != 'aminoacids':
+ self.sequenceGrid.setModified(True)
+ else:
+ self.sequenceCanvas.setModified(True)
+
+ # update sequence info
+ self.onSequenceChanged()
+ # ----
+
+
def onSequenceTitle(self, evt):
"""Update sequence title."""
@@ -1088,27 +1302,37 @@
# update sequence info
self.updateSequenceInfo()
+ # check sequence
+ if self.currentSequence == None:
+ return
+
+ # set editor
+ editor = self.sequenceCanvas
+ if self.currentSequence.chainType != 'aminoacids':
+ editor = self.sequenceGrid
+
# skip if sequence has not changed - cursor move only
- if self.sequenceCanvas.ismodified():
- self.sequenceCanvas.setModified(False)
+ if editor.ismodified():
+ editor.setModified(False)
# update modifications panel
self.updateAvailableResidues()
self.updateModificationsList()
# update digest panel
- if self.currentDigest !=None:
+ if self.currentDigest != None:
self.currentDigest = None
self.updateDigestList()
self.updateCoverage()
# update fragment panel
- if self.currentFragments !=None:
+ self.updateAvailableFragments()
+ if self.currentFragments != None:
self.currentFragments = None
self.updateFragmentsList()
# update search panel
- if self.currentSearch !=None:
+ if self.currentSearch != None:
self.currentSearch = None
self.updateSearchList()
@@ -1129,7 +1353,7 @@
"""Show isotopic pattern for whole sequence."""
# get formula
- if len(self.currentSequence) != 0:
+ if self.currentSequence:
formula = self.currentSequence.formula()
else:
wx.Bell()
@@ -1239,7 +1463,7 @@
if self.currentTool=='digest':
mz = self.currentDigest[evt.GetData()][2]
elif self.currentTool=='fragment':
- mz = self.currentFragments[evt.GetData()][3]
+ mz = self.currentFragments[evt.GetData()][2]
elif self.currentTool=='search':
mz = self.currentSearch[evt.GetData()][1]
@@ -1250,26 +1474,151 @@
def onItemActivated(self, evt):
"""Show isotopic pattern for selected peptide/fragment."""
+ self.onItemSendToMassCalculator(evt)
+ # ----
+
+
+ def onItemSendToMassCalculator(self, evt):
+ """Send selected item to Mass Calculator panel."""
- # get formula and charge
- if self.currentTool=='digest':
- item = self.currentDigest[evt.GetData()]
- formula = item[6].formula()
- charge = item[3]
- elif self.currentTool=='fragment':
- item = self.currentFragments[evt.GetData()]
- formula = item[7].formula()
- charge = item[4]
- elif self.currentTool=='search':
- item = self.currentSearch[evt.GetData()]
- formula = item[5].formula()
- charge = item[2]
+ # get data
+ if self.currentTool == 'digest':
+ selected = self.digestList.getSelected()
+ if selected:
+ index = self.digestList.GetItemData(selected[0])
+ formula = self.currentDigest[index][6].formula()
+ charge = self.currentDigest[index][3]
- # send to masscalc
+ elif self.currentTool == 'fragment':
+ selected = self.fragmentsList.getSelected()
+ if selected:
+ index = self.fragmentsList.GetItemData(selected[0])
+ formula = self.currentFragments[index][6].formula()
+ charge = self.currentFragments[index][3]
+
+ elif self.currentTool == 'search':
+ selected = self.searchList.getSelected()
+ if selected:
+ index = self.searchList.GetItemData(selected[0])
+ formula = self.currentSearch[index][5].formula()
+ charge = self.currentSearch[index][2]
+
+ # check selection
+ if not selected:
+ wx.Bell()
+ return
+
+ # send data to masscalc
self.parent.onToolsMassCalculator(formula=formula, charge=charge, agentFormula='H', agentCharge=1)
# ----
+ def onItemSendToEnvelopeFit(self, evt):
+ """Send selected item to envelope fit panel."""
+
+ # get data
+ if self.currentTool == 'digest':
+ selected = self.digestList.getSelected()
+ if selected:
+ index = self.digestList.GetItemData(selected[0])
+ sequence = self.currentDigest[index][6]
+ charge = self.currentDigest[index][3]
+
+ elif self.currentTool == 'fragment':
+ selected = self.fragmentsList.getSelected()
+ if selected:
+ index = self.fragmentsList.GetItemData(selected[0])
+ sequence = self.currentFragments[index][6]
+ charge = self.currentFragments[index][3]
+
+ elif self.currentTool == 'search':
+ selected = self.searchList.getSelected()
+ if selected:
+ index = self.searchList.GetItemData(selected[0])
+ sequence = self.currentSearch[index][5]
+ charge = self.currentSearch[index][2]
+
+ # send data to envelope fit
+ self.parent.onToolsEnvelopeFit(sequence=sequence, charge=charge)
+ # ----
+
+
+ def onItemCopySequence(self, evt):
+ """Copy selected sequence into clipboard."""
+
+ # get list
+ if self.currentTool == 'digest':
+ selected = self.digestList.getSelected()
+ if selected:
+ index = self.digestList.GetItemData(selected[0])
+ sequence = self.currentDigest[index][6].format('S')
+
+ elif self.currentTool == 'fragment':
+ selected = self.fragmentsList.getSelected()
+ if selected:
+ index = self.fragmentsList.GetItemData(selected[0])
+ sequence = self.currentFragments[index][6].format('S')
+
+ elif self.currentTool == 'search':
+ selected = self.searchList.getSelected()
+ if selected:
+ index = self.searchList.GetItemData(selected[0])
+ sequence = self.currentSearch[index][5].format('S')
+
+ # check selection
+ if not selected:
+ wx.Bell()
+ return
+
+ # make text object for data
+ obj = wx.TextDataObject()
+ obj.SetText(sequence)
+
+ # paste to clipboard
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(obj)
+ wx.TheClipboard.Close()
+ # ----
+
+
+ def onItemCopyFormula(self, evt):
+ """Copy selected sequence formula into clipboard."""
+
+ # get list
+ if self.currentTool == 'digest':
+ selected = self.digestList.getSelected()
+ if selected:
+ index = self.digestList.GetItemData(selected[0])
+ formula = self.currentDigest[index][6].formula()
+
+ elif self.currentTool == 'fragment':
+ selected = self.fragmentsList.getSelected()
+ if selected:
+ index = self.fragmentsList.GetItemData(selected[0])
+ formula = self.currentFragments[index][6].formula()
+
+ elif self.currentTool == 'search':
+ selected = self.searchList.getSelected()
+ if selected:
+ index = self.searchList.GetItemData(selected[0])
+ formula = self.currentSearch[index][5].formula()
+
+ # check selection
+ if not selected:
+ wx.Bell()
+ return
+
+ # make text object for data
+ obj = wx.TextDataObject()
+ obj.SetText(formula)
+
+ # paste to clipboard
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(obj)
+ wx.TheClipboard.Close()
+ # ----
+
+
def onListKey(self, evt):
"""Export list if Ctrl+C."""
@@ -1296,7 +1645,12 @@
menu.Append(ID_listViewMatched, "Show Matched Only", "", wx.ITEM_RADIO)
menu.Append(ID_listViewUnmatched, "Show Unmatched Only", "", wx.ITEM_RADIO)
menu.AppendSeparator()
- menu.Append(ID_listCopySequence, "Copy Selected Sequence", "")
+ menu.Append(ID_listSendToMassCalculator, "Show Isotopic Pattern...", "")
+ if self.currentTool in ('digest', 'search'):
+ menu.Append(ID_listSendToEnvelopeFit, "Send to Envelope Fit...", "")
+ menu.AppendSeparator()
+ menu.Append(ID_listCopySequence, "Copy Sequence", "")
+ menu.Append(ID_listCopyFormula, "Copy Formula", "")
menu.Append(ID_listCopy, "Copy List")
# check item
@@ -1310,11 +1664,13 @@
menu.Check(ID_listViewAll, True)
# bind events
- if self.currentTool in ('digest', 'fragment'):
- self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewAll)
- self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewMatched)
- self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewUnmatched)
- self.Bind(wx.EVT_MENU, self.onListCopySequence, id=ID_listCopySequence)
+ self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewAll)
+ self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewMatched)
+ self.Bind(wx.EVT_MENU, self.onListFilter, id=ID_listViewUnmatched)
+ self.Bind(wx.EVT_MENU, self.onItemSendToMassCalculator, id=ID_listSendToMassCalculator)
+ self.Bind(wx.EVT_MENU, self.onItemSendToEnvelopeFit, id=ID_listSendToEnvelopeFit)
+ self.Bind(wx.EVT_MENU, self.onItemCopySequence, id=ID_listCopySequence)
+ self.Bind(wx.EVT_MENU, self.onItemCopyFormula, id=ID_listCopyFormula)
self.Bind(wx.EVT_MENU, self.onListCopy, id=ID_listCopy)
# show menu
@@ -1362,44 +1718,6 @@
# ----
- def onListCopySequence(self, evt):
- """Copy selected sequence into clipboard."""
-
- # get list
- if self.currentTool=='digest':
- selected = self.digestList.getSelected()
- if selected:
- index = self.digestList.GetItemData(selected[0])
- sequence = self.currentDigest[index][6].format('S')
-
- elif self.currentTool=='fragment':
- selected = self.fragmentsList.getSelected()
- if selected:
- index = self.fragmentsList.GetItemData(selected[0])
- sequence = self.currentFragments[index][7].format('S')
-
- elif self.currentTool=='search':
- selected = self.searchList.getSelected()
- if selected:
- index = self.searchList.GetItemData(selected[0])
- sequence = self.currentSearch[index][5].format('S')
-
- # check selection
- if not selected:
- wx.Bell()
- return
-
- # make text object for data
- obj = wx.TextDataObject()
- obj.SetText(sequence)
-
- # paste to clipboard
- if wx.TheClipboard.Open():
- wx.TheClipboard.SetData(obj)
- wx.TheClipboard.Close()
- # ----
-
-
def onDigest(self, evt):
"""Digest sequence."""
@@ -1421,7 +1739,7 @@
return
# check sequence
- if len(self.currentSequence) == 0:
+ if not self.currentSequence or self.currentSequence.chainType != 'aminoacids':
wx.Bell()
return
@@ -1477,7 +1795,7 @@
return
# check sequence
- if len(self.currentSequence) == 0:
+ if not self.currentSequence:
wx.Bell()
return
@@ -1528,7 +1846,7 @@
return
# check sequence
- if len(self.currentSequence) == 0:
+ if not self.currentSequence or self.currentSequence.chainType != 'aminoacids':
wx.Bell()
return
@@ -1586,28 +1904,33 @@
buff = []
+ # get template
+ template = 'matchTemplateAmino'
+ if self.currentSequence.chainType != 'aminoacids':
+ template = 'matchTemplateCustom'
+
# get digest data
if self.currentTool == 'digest' and self.currentDigest:
for item in self.currentDigest:
obj = item[6]
- title = '%s' % (obj.format(config.sequence['digest']['matchFormat']))
+ title = obj.format(config.sequence['digest'][template])
for match in item[-1]:
match.label = title
match.charge = item[3]
match.formula = obj.formula()
- match.sequenceRange = obj.userRange[:]
+ match.sequenceRange = [obj.history[-1][1]+1, obj.history[-1][2]]
buff.append((match.mz, match.delta('Da'), match))
# get fragment data
elif self.currentTool == 'fragment' and self.currentFragments:
for item in self.currentFragments:
- obj = item[7]
- title = '%s' % (obj.format(config.sequence['fragment']['matchFormat']))
+ obj = item[6]
+ title = obj.format(config.sequence['fragment'][template])
for match in item[-1]:
match.label = title
- match.charge = item[4]
+ match.charge = item[3]
match.formula = obj.formula()
- match.sequenceRange = obj.userRange[:]
+ match.sequenceRange = [obj.history[-1][1]+1, obj.history[-1][2]]
match.fragmentSerie = obj.fragmentSerie
match.fragmentIndex = obj.fragmentIndex
buff.append((match.mz, match.delta('Da'), match))
@@ -1631,26 +1954,35 @@
def setData(self, sequence=None):
"""Set current sequence."""
+ self.currentSequence = sequence
+
# check sequence
- if sequence == None:
- sequence = mspy.sequence('')
+ if self.currentSequence == None:
+ self.sequenceType_combo.Enable(False)
+ self.sequenceCyclic_check.Enable(False)
self.sequenceTitle_value.Enable(False)
self.sequenceAccession_value.Enable(False)
- self.sequenceCanvas.Enable(False)
+ self.sequenceCyclic_check.SetValue(False)
+ self.sequenceTitle_value.ChangeValue('')
+ self.sequenceAccession_value.ChangeValue('')
else:
+ self.sequenceType_combo.Enable(True)
+ self.sequenceCyclic_check.Enable(True)
self.sequenceTitle_value.Enable(True)
self.sequenceAccession_value.Enable(True)
- self.sequenceCanvas.Enable(True)
-
- # set data
- self.currentSequence = sequence
- self.sequenceTitle_value.ChangeValue(self.currentSequence.title)
- self.sequenceAccession_value.ChangeValue(self.currentSequence.accession)
- self.sequenceCanvas.setData(self.currentSequence)
- self.sequenceCanvas.setModified(False)
-
- # update sequence info
- self.updateSequenceInfo()
+ self.sequenceCyclic_check.SetValue(self.currentSequence.cyclic)
+ self.sequenceTitle_value.ChangeValue(self.currentSequence.title)
+ self.sequenceAccession_value.ChangeValue(self.currentSequence.accession)
+
+ # select editor
+ if self.currentSequence == None or self.currentSequence.chainType == 'aminoacids':
+ self.sequenceType_combo.Select(0)
+ self.sequenceCanvas.setData(self.currentSequence)
+ self.onSequenceType(chainType='aminoacids')
+ else:
+ self.sequenceType_combo.Select(1)
+ self.sequenceGrid.setData(self.currentSequence)
+ self.onSequenceType(chainType='custom')
# update modifications panel
self.updateAvailableResidues()
@@ -1663,6 +1995,7 @@
self.updateCoverage()
# update fragment panel
+ self.updateAvailableFragments()
if self.currentFragments != None:
self.currentFragments = None
self.updateFragmentsList()
@@ -1675,6 +2008,9 @@
# clear match panel
if self.matchPanel:
self.matchPanel.Close()
+
+ # select editor tool
+ self.onToolSelected(tool='editor')
# ----
@@ -1710,6 +2046,10 @@
config.sequence['fragment']['massType'] = 1
config.sequence['fragment']['fragments'] = []
+ if self.fragmentM_check.GetValue():
+ config.sequence['fragment']['fragments'].append('M')
+ if self.fragmentIm_check.GetValue():
+ config.sequence['fragment']['fragments'].append('im')
if self.fragmentA_check.GetValue():
config.sequence['fragment']['fragments'].append('a')
if self.fragmentB_check.GetValue():
@@ -1722,24 +2062,38 @@
config.sequence['fragment']['fragments'].append('y')
if self.fragmentZ_check.GetValue():
config.sequence['fragment']['fragments'].append('z')
- if self.fragmentIm_check.GetValue():
- config.sequence['fragment']['fragments'].append('im')
- if self.fragmentIntB_check.GetValue():
- config.sequence['fragment']['fragments'].append('int')
+
if self.fragmentIntA_check.GetValue():
- config.sequence['fragment']['fragments'].append('int-CO')
- if self.fragmentH2O_check.GetValue():
- config.sequence['fragment']['fragments'].append('-H2O')
- if self.fragmentNH3_check.GetValue():
- config.sequence['fragment']['fragments'].append('-NH3')
- if self.fragmentH3PO4_check.GetValue():
- config.sequence['fragment']['fragments'].append('-H3PO4')
+ config.sequence['fragment']['fragments'].append('int-a')
+ if self.fragmentIntB_check.GetValue():
+ config.sequence['fragment']['fragments'].append('int-b')
if self.fragmentNLadder_check.GetValue():
config.sequence['fragment']['fragments'].append('n-ladder')
if self.fragmentCLadder_check.GetValue():
config.sequence['fragment']['fragments'].append('c-ladder')
- if self.fragmentFilter_check.GetValue():
+ if self.fragmentLossH2O_check.GetValue():
+ config.sequence['fragment']['fragments'].append('-H2O')
+ if self.fragmentLossNH3_check.GetValue():
+ config.sequence['fragment']['fragments'].append('-NH3')
+ if self.fragmentLossCO_check.GetValue():
+ config.sequence['fragment']['fragments'].append('-CO')
+ if self.fragmentLossH3PO4_check.GetValue():
+ config.sequence['fragment']['fragments'].append('-H3PO4')
+ if self.fragmentLossDefined_check.GetValue():
+ config.sequence['fragment']['fragments'].append('losses')
+ if self.fragmentLossCombi_check.GetValue():
+ config.sequence['fragment']['fragments'].append('losscombi')
+
+ if self.fragmentGainH2O_check.GetValue():
+ config.sequence['fragment']['fragments'].append('+H2O')
+ if self.fragmentGainCO_check.GetValue():
+ config.sequence['fragment']['fragments'].append('+CO')
+
+ if self.fragmentScrambling_check.GetValue():
+ config.sequence['fragment']['fragments'].append('scrambling')
+
+ if self.fragmentRemoveFiltered_check.GetValue():
config.sequence['fragment']['filterFragments'] = 1
else:
config.sequence['fragment']['filterFragments'] = 0
@@ -1773,24 +2127,30 @@
def updateSequenceInfo(self):
"""Update sequence info."""
- # make label
label = ''
- length = len(self.currentSequence)
- if length > 0:
+ # check sequence
+ if not self.currentSequence:
+ self.sequenceInfo_label.SetLabel('No sequence defined')
+ return
+
+ # get mass
+ if len(self.currentSequence):
format = '%0.' + `config.main['mzDigits']` + 'f'
mass = self.currentSequence.mass()
+ label += 'Mo. mass: '+format % mass[0]
+ label += ' Av. mass: '+format % mass[1]
+
+ # get length
+ label += ' Length: %d' % len(self.currentSequence)
+
+ # get cursor position
+ if len(self.currentSequence) and self.currentSequence.chainType == 'aminoacids':
selection = self.sequenceCanvas.getSequenceSelection()
-
- label += 'Mo: '+format % mass[0]
- label += ' Av: '+format % mass[1]
-
- if selection[0]==selection[1]:
- label += ' Position: %s/%s' % (selection[0]+1,length)
- elif selection[1] > length:
- label += ' Selection: %s-%s' % ((selection[0]+1), selection[1]-1)
+ if selection[0] == selection[1]:
+ label += ' Cursor: %s' % (selection[0]+1)
else:
- label += ' Selection: %s-%s' % ((selection[0]+1), selection[1])
+ label += ' Cursor: %s-%s' % ((selection[0]+1), min(selection[1], len(self.currentSequence)))
self.sequenceInfo_label.SetLabel(label)
# ----
@@ -1804,10 +2164,14 @@
self.modsPosition_combo.Clear()
self.modsMod_combo.Clear()
+ # check sequence type
+ if not self.currentSequence or self.currentSequence.chainType != 'aminoacids':
+ return
+
# get residues
residues = []
- for amino in self.currentSequence:
- name = '%s (%s)' % (mspy.aminoacids[amino].name, amino)
+ for monomer in self.currentSequence:
+ name = '%s (%s)' % (mspy.monomers[monomer].name, monomer)
if not name in residues:
residues.append(name)
@@ -1947,6 +2311,45 @@
# ----
+ def updateAvailableFragments(self, evt=None):
+ """Update available fragments."""
+
+ # no sequence defined
+ if self.currentSequence == None:
+ self.fragmentIntA_check.Enable()
+ self.fragmentIntB_check.Enable()
+ self.fragmentNLadder_check.Enable()
+ self.fragmentCLadder_check.Enable()
+ self.fragmentGainCO_check.SetValue(False)
+ self.fragmentGainCO_check.Disable()
+
+ # cyclic sequence
+ elif self.currentSequence.cyclic:
+ self.fragmentIntA_check.SetValue(False)
+ self.fragmentIntB_check.SetValue(False)
+ self.fragmentNLadder_check.SetValue(False)
+ self.fragmentCLadder_check.SetValue(False)
+ self.fragmentIntA_check.Disable()
+ self.fragmentIntB_check.Disable()
+ self.fragmentNLadder_check.Disable()
+ self.fragmentCLadder_check.Disable()
+ self.fragmentGainCO_check.Enable()
+
+ # linear sequence
+ else:
+ self.fragmentIntA_check.Enable()
+ self.fragmentIntB_check.Enable()
+ self.fragmentNLadder_check.Enable()
+ self.fragmentCLadder_check.Enable()
+ self.fragmentGainCO_check.SetValue(False)
+ self.fragmentGainCO_check.Disable()
+
+ # scrambling enabled
+ if self.fragmentScrambling_check.IsChecked():
+ self.fragmentGainCO_check.Enable()
+ # ----
+
+
def updateDigestList(self):
"""Update digest list."""
@@ -1975,7 +2378,7 @@
continue
# format data
- userRange = '[%s-%s]' % tuple(item[0])
+ section = item[6].format('h')
mz = mzFormat % (item[2])
error = ''
@@ -1984,7 +2387,7 @@
# add data
row += 1
- self.digestList.InsertStringItem(row, userRange)
+ self.digestList.InsertStringItem(row, section)
self.digestList.SetStringItem(row, 1, str(item[1]))
self.digestList.SetStringItem(row, 2, mz)
self.digestList.SetStringItem(row, 3, str(item[3]))
@@ -2029,43 +2432,37 @@
for index, item in enumerate(self.currentFragments):
# filter data
- if self._fragmentsFilter == 1 and item[6] == None:
+ if self._fragmentsFilter == 1 and item[5] == None:
continue
- elif self._fragmentsFilter == -1 and item[6] != None:
+ elif self._fragmentsFilter == -1 and item[5] != None:
continue
# format data
- if type(item[1]) == int:
- idx = str(item[1])
- else:
- idx = '-'
-
- urange = '[%s-%s]' % tuple(item[2])
- mz = mzFormat % (item[3])
+ section = item[6].format('h')
+ mz = mzFormat % (item[2])
error = ''
- if item[6] != None:
- error = errFormat % (item[6])
+ if item[5] != None:
+ error = errFormat % (item[5])
# add data
row += 1
self.fragmentsList.InsertStringItem(row, item[0])
- self.fragmentsList.SetStringItem(row, 1, idx)
- self.fragmentsList.SetStringItem(row, 2, urange)
- self.fragmentsList.SetStringItem(row, 3, mz)
- self.fragmentsList.SetStringItem(row, 4, str(item[4]))
- self.fragmentsList.SetStringItem(row, 5, item[5])
- self.fragmentsList.SetStringItem(row, 6, error)
+ self.fragmentsList.SetStringItem(row, 1, section)
+ self.fragmentsList.SetStringItem(row, 2, mz)
+ self.fragmentsList.SetStringItem(row, 3, str(item[3]))
+ self.fragmentsList.SetStringItem(row, 4, item[4])
+ self.fragmentsList.SetStringItem(row, 5, error)
self.fragmentsList.SetItemData(row, index)
# mark filtered and matched fragments
- if item[7].fragmentFiltered and item[6] == None:
+ if item[6].fragmentFiltered and item[5] == None:
self.fragmentsList.SetItemTextColour(row, (150,150,150))
self.fragmentsList.SetItemFont(row, fontFiltered)
- elif item[7].fragmentFiltered and item[6] != None:
+ elif item[6].fragmentFiltered and item[5] != None:
self.fragmentsList.SetItemTextColour(row, (0,200,0))
self.fragmentsList.SetItemFont(row, fontFiltered)
- elif item[6] != None:
+ elif item[5] != None:
self.fragmentsList.SetItemTextColour(row, (0,200,0))
self.fragmentsList.SetItemFont(row, fontMatched)
@@ -2099,13 +2496,13 @@
for index, item in enumerate(self.currentSearch):
# format data
- userRange = '[%s-%s]' % tuple(item[0])
+ section = item[5].format('h')
mz = mzFormat % (item[1])
error = errFormat % (item[4])
# add data
row += 1
- self.searchList.InsertStringItem(row, userRange)
+ self.searchList.InsertStringItem(row, section)
self.searchList.SetStringItem(row, 1, mz)
self.searchList.SetStringItem(row, 2, item[3])
self.searchList.SetStringItem(row, 3, error)
@@ -2150,16 +2547,17 @@
totalRanges = []
matchedRanges = []
for peptide in self.currentDigest:
- totalRanges.append(peptide[0])
+ section = [peptide[6].history[-1][1]+1, peptide[6].history[-1][2]]
+ totalRanges.append(section)
if peptide[5] != None:
- matchedRanges.append(peptide[0])
+ matchedRanges.append(section)
# get coverages
totalCoverage = mspy.coverage(totalRanges, len(self.currentSequence))
matchedCoverage = mspy.coverage(matchedRanges, len(self.currentSequence))
# set new label
- label = 'Cov.: %0.0f/%0.0f' % (matchedCoverage, totalCoverage)
+ label = 'Coverage: %0.0f/%0.0f' % (matchedCoverage, totalCoverage)
label += ' %'
self.digestCoverage_label.SetLabel(label)
# ----
@@ -2172,7 +2570,7 @@
presets = libs.presets['modifications'][name]
# check sequence
- if len(self.currentSequence) == 0:
+ if not self.currentSequence:
wx.Bell()
dlg = mwx.dlgMessage(self, title="No sequence defined.", message='Modifications cannot be applied on empty sequence.')
dlg.ShowModal()
@@ -2189,22 +2587,30 @@
dlg.Destroy()
return
- # remove current modifications
- self.currentSequence.unmodify(None)
+ # remove previous modifications if empty presets
+ if not presets:
+ self.currentSequence.unmodify(None)
+
+ # ask to replace previous modifications
+ if self.currentSequence.modifications:
+ title = 'Modifications already applied!'
+ message = "There are some modifications already applied to the sequence\nyou can either replace previous or append new."
+ buttons = [(ID_dlgReplace, "Replace", 80, False, 15), (ID_dlgAppend, "Append", 80, True, 0)]
+ dlg = mwx.dlgMessage(self, title, message, buttons)
+ if dlg.ShowModal() == ID_dlgReplace:
+ self.currentSequence.unmodify(None)
# check and apply modifications
valid = True
for mod in presets:
- if not mod[1] in self.currentSequence:
- continue
- elif self.checkModifications(self.currentSequence, [mod[0], mod[1], mod[2]], config.sequence['digest']['maxMods']):
+ if self.checkModifications(self.currentSequence, [mod[0], mod[1], mod[2]], config.sequence['digest']['maxMods']):
self.currentSequence.modify(mod[0], mod[1], mod[2])
else:
valid = False
if not valid:
wx.Bell()
- dlg = mwx.dlgMessage(self, title="Some of your modifications cannot be applied.", message='Maximum number of fixed modification is already applied\nto a single position.')
+ dlg = mwx.dlgMessage(self, title="Some of your modifications cannot be applied.", message='Maximum number of fixed modifications per single position\nis already applied.')
dlg.ShowModal()
dlg.Destroy()
@@ -2222,36 +2628,55 @@
presets = libs.presets['fragments'][name]
# set fragments
+ self.fragmentM_check.SetValue(presets.count('M'))
+ self.fragmentIm_check.SetValue(presets.count('im'))
self.fragmentA_check.SetValue(presets.count('a'))
self.fragmentB_check.SetValue(presets.count('b'))
self.fragmentC_check.SetValue(presets.count('c'))
self.fragmentX_check.SetValue(presets.count('x'))
self.fragmentY_check.SetValue(presets.count('y'))
self.fragmentZ_check.SetValue(presets.count('z'))
- self.fragmentIm_check.SetValue(presets.count('im'))
- self.fragmentIntB_check.SetValue(presets.count('int'))
- self.fragmentIntA_check.SetValue(presets.count('int-CO'))
- self.fragmentH2O_check.SetValue(presets.count('-H2O'))
- self.fragmentNH3_check.SetValue(presets.count('-NH3'))
- self.fragmentH3PO4_check.SetValue(presets.count('-H3PO4'))
+
+ self.fragmentIntB_check.SetValue(presets.count('int-b'))
+ self.fragmentIntA_check.SetValue(presets.count('int-a'))
self.fragmentNLadder_check.SetValue(presets.count('n-ladder'))
self.fragmentCLadder_check.SetValue(presets.count('c-ladder'))
+
+ self.fragmentLossH2O_check.SetValue(presets.count('-H2O'))
+ self.fragmentLossNH3_check.SetValue(presets.count('-NH3'))
+ self.fragmentLossCO_check.SetValue(presets.count('-CO'))
+ self.fragmentLossH3PO4_check.SetValue(presets.count('-H3PO4'))
+ self.fragmentLossDefined_check.SetValue(presets.count('losses'))
+ self.fragmentLossCombi_check.SetValue(presets.count('losscombi'))
+
+ self.fragmentGainCO_check.SetValue(presets.count('+CO'))
+ self.fragmentGainH2O_check.SetValue(presets.count('+H2O'))
+
+ self.fragmentScrambling_check.SetValue(presets.count('scrambling'))
+
+ # enable/disable some fragments
+ self.updateAvailableFragments()
# ----
def saveModificationsPresets(self):
"""Save applied global modifications as presets."""
+ # check sequence
+ if not self.currentSequence:
+ wx.Bell()
+ return
+
# get modifications
modifications = []
for mod in self.currentSequence.modifications:
- if type(mod[1]) in (str, unicode):
+ if type(mod[1]) in (str, unicode) or mod[1] == 0:
modifications.append(mod)
# check presets
if not modifications:
wx.Bell()
- dlg = mwx.dlgMessage(self, title="Global modifications not found.", message='Global modifications only can be saved in presets.')
+ dlg = mwx.dlgMessage(self, title="Presets cannot be saved.", message='Global and N-terminal modifications can only be saved in presets.')
dlg.ShowModal()
dlg.Destroy()
return
@@ -2333,7 +2758,13 @@
self.currentDigest = []
# digest sequence
- peptides = self.currentSequence.digest(enzyme=config.sequence['digest']['enzyme'], miscleavage=config.sequence['digest']['miscl'], allowMods=config.sequence['digest']['allowMods'], strict=False)
+ peptides = mspy.digest(
+ sequence = self.currentSequence,
+ enzyme = config.sequence['digest']['enzyme'],
+ miscleavage = config.sequence['digest']['miscl'],
+ allowMods = config.sequence['digest']['allowMods'],
+ strict = False
+ )
# do not cleave if modified
enzyme = config.sequence['digest']['enzyme']
@@ -2352,6 +2783,11 @@
polarity = -1
maxCharge = abs(config.sequence['digest']['maxCharge'])+1
+ # get list template
+ template = config.sequence['digest']['listTemplateAmino']
+ if self.currentSequence.chainType != 'aminoacids':
+ template = config.sequence['digest']['listTemplateCustom']
+
# calculate mz and check limits
buff = []
for peptide in peptides:
@@ -2362,11 +2798,11 @@
mz = peptide.mz(z*polarity)[config.sequence['digest']['massType']]
if mz >= config.sequence['digest']['lowMass'] and mz <= config.sequence['digest']['highMass']:
buff.append([
- peptide.userRange,
+ peptide.history,
peptide.miscleavages,
mz,
z*polarity,
- peptide.format(config.sequence['digest']['listFormat']),
+ peptide.format(template),
None,
peptide,
[],
@@ -2388,45 +2824,84 @@
self.currentFragments = []
- # get fragment types
+ # get fragment series
series = []
-
+ if 'M' in config.sequence['fragment']['fragments']:
+ series.append('M')
+ if 'im' in config.sequence['fragment']['fragments']:
+ series.append('im')
if 'a' in config.sequence['fragment']['fragments']:
series.append('a')
if 'b' in config.sequence['fragment']['fragments']:
series.append('b')
- if 'y' in config.sequence['fragment']['fragments']:
- series.append('y')
- if 'int' in config.sequence['fragment']['fragments']:
- series.append('int')
-
- for serie in series[:]:
- if '-H2O' in config.sequence['fragment']['fragments']:
- series.append(serie+'-H2O')
- if '-NH3' in config.sequence['fragment']['fragments']:
- series.append(serie+'-NH3')
- if '-H3PO4' in config.sequence['fragment']['fragments']:
- series.append(serie+'-H3PO4')
-
if 'c' in config.sequence['fragment']['fragments']:
series.append('c')
if 'x' in config.sequence['fragment']['fragments']:
series.append('x')
+ if 'y' in config.sequence['fragment']['fragments']:
+ series.append('y')
if 'z' in config.sequence['fragment']['fragments']:
series.append('z')
- if 'im' in config.sequence['fragment']['fragments']:
- series.append('im')
- if 'int-CO' in config.sequence['fragment']['fragments']:
- series.append('int-CO')
+ if 'int-b' in config.sequence['fragment']['fragments']:
+ series.append('int-b')
+ if 'int-a' in config.sequence['fragment']['fragments']:
+ series.append('int-a')
if 'n-ladder' in config.sequence['fragment']['fragments']:
series.append('n-ladder')
if 'c-ladder' in config.sequence['fragment']['fragments']:
series.append('c-ladder')
- # fragment sequence
- fragments = []
- for serie in series:
- fragments += self.currentSequence.fragment(serie)
+ # get losses
+ userLosses = []
+ definedLosses = False
+ if '-H2O' in config.sequence['fragment']['fragments']:
+ userLosses.append('H2O')
+ if '-NH3' in config.sequence['fragment']['fragments']:
+ userLosses.append('NH3')
+ if '-CO' in config.sequence['fragment']['fragments']:
+ userLosses.append('CO')
+ if '-H3PO4' in config.sequence['fragment']['fragments']:
+ userLosses.append('H3PO4')
+ if 'losses' in config.sequence['fragment']['fragments']:
+ definedLosses = True
+
+ # get gains
+ userGains = []
+ if '+H2O' in config.sequence['fragment']['fragments']:
+ userGains.append('H2O')
+ if '+CO' in config.sequence['fragment']['fragments']:
+ userGains.append('CO')
+
+ # get scrambling
+ scrambling = False
+ if 'scrambling' in config.sequence['fragment']['fragments']:
+ scrambling = True
+
+ # get loss combinations
+ maxLosses = 1
+ if 'losscombi' in config.sequence['fragment']['fragments']:
+ maxLosses = config.sequence['fragment']['maxLosses']
+
+ # generate basic fragments
+ fragments = mspy.fragment(
+ sequence = self.currentSequence,
+ series = series,
+ scrambling = scrambling
+ )
+
+ # apply neutral losses
+ fragments += mspy.fragmentLosses(
+ fragments = fragments,
+ losses = userLosses,
+ defined = definedLosses,
+ limit = maxLosses
+ )
+
+ # apply neutral gains
+ fragments += mspy.fragmentGains(
+ fragments = fragments,
+ gains = userGains,
+ )
# variate mods
buff = []
@@ -2440,7 +2915,12 @@
polarity = -1
maxCharge = abs(config.sequence['fragment']['maxCharge'])+1
- # calculate mz
+ # get list template
+ template = config.sequence['fragment']['listTemplateAmino']
+ if self.currentSequence.chainType != 'aminoacids':
+ template = config.sequence['fragment']['listTemplateCustom']
+
+ # calculate mz and store fragments
buff = []
for fragment in fragments:
for z in range(1, maxCharge):
@@ -2449,12 +2929,11 @@
if not config.sequence['fragment']['filterFragments'] or not fragment.fragmentFiltered:
buff.append([
- fragment.fragmentSerie,
- fragment.fragmentIndex,
- fragment.userRange,
+ fragment.format('f'),
+ fragment.history,
fragment.mz(z*polarity)[config.sequence['fragment']['massType']],
z*polarity,
- fragment.format(config.sequence['fragment']['listFormat']),
+ fragment.format(template),
None,
fragment,
[],
@@ -2477,26 +2956,31 @@
self.currentSearch = []
# search sequence
- peptides = self.currentSequence.search(\
- mass=config.sequence['search']['mass'], \
- charge=config.sequence['search']['charge'], \
- tolerance=config.sequence['search']['tolerance'], \
- enzyme=config.sequence['search']['enzyme'], \
- semiSpecific=config.sequence['search']['semiSpecific'], \
- tolUnits=config.sequence['search']['units'], \
- massType=config.sequence['search']['massType'], \
- maxMods=config.sequence['search']['maxMods'], \
- position=config.sequence['search']['retainPos']\
+ peptides = self.currentSequence.search(
+ mass = config.sequence['search']['mass'],
+ charge = config.sequence['search']['charge'],
+ tolerance = config.sequence['search']['tolerance'],
+ enzyme = config.sequence['search']['enzyme'],
+ semiSpecific = config.sequence['search']['semiSpecific'],
+ tolUnits = config.sequence['search']['units'],
+ massType = config.sequence['search']['massType'],
+ maxMods = config.sequence['search']['maxMods'],
+ position = config.sequence['search']['retainPos']
)
+ # get list template
+ template = config.sequence['search']['listTemplateAmino']
+ if self.currentSequence.chainType != 'aminoacids':
+ template = config.sequence['search']['listTemplateCustom']
+
buff = []
for peptide in peptides:
mz = peptide.mz(config.sequence['search']['charge'])[config.sequence['search']['massType']]
buff.append([
- peptide.userRange,
+ peptide.history,
mz,
config.sequence['search']['charge'],
- peptide.format(config.sequence['search']['listFormat']),
+ peptide.format(template),
mspy.delta(mz, config.sequence['search']['mass'], config.sequence['search']['units']),
peptide,
])
@@ -2515,19 +2999,25 @@
# ----
- def checkModifications(self, currentSequence, modification, maxMods):
+ def checkModifications(self, sequence, modification, maxMods):
"""Do not allow multiple modifications on single residue."""
+ # check same modifications
+ if str(modification[1]).isdigit():
+ modification[1] = int(modification[1])
+ if modification in sequence.modifications:
+ return False
+
# get occupied positions
occupied = []
- for mod in currentSequence.modifications:
+ for mod in sequence.modifications:
if mod[2] == 'f':
- count = max(1, currentSequence.count(str(mod[1])))
+ count = max(1, sequence.count(str(mod[1])))
occupied += [mod[1]]*count
# apply current modification
if modification[2] == 'f':
- count = max(1, currentSequence.count(str(modification[1])))
+ count = max(1, sequence.count(str(modification[1])))
occupied += [modification[1]]*count
else:
occupied.append(modification[1])
@@ -2536,14 +3026,14 @@
for x in occupied:
count = occupied.count(x)
if type(x) == int:
- if count>maxMods:
+ if count > maxMods:
return False
elif type(x) in (str, unicode):
- available = currentSequence.count(x)
+ available = sequence.count(x)
for y in occupied:
- if type(y) == int and currentSequence[y] == x:
+ if type(y) == int and sequence[y] == x:
available -= 1
- if count>(available*maxMods):
+ if count > (available*maxMods):
return False
return True
@@ -2553,7 +3043,7 @@
class sequenceCanvas(wx.TextCtrl):
- """Sequence editor canvas."""
+ """Sequence editor canvas for amino acids."""
def __init__(self, parent, id, sequence=None, size=(-1,-1), style=wx.TE_MULTILINE|wx.TE_RICH):
wx.TextCtrl.__init__(self, parent, id, size=size, style=style)
@@ -2566,8 +3056,12 @@
self.currentSequence = sequence
elif sequence == None:
self.currentSequence = mspy.sequence('')
- elif type(sequence) in (str, unicode):
- self.currentSequence = mspy.sequence(sequence)
+
+ # get regular amino acids
+ self._aminoacids = []
+ for abbr in mspy.monomers:
+ if mspy.monomers[abbr].category == '_InternalAA':
+ self._aminoacids.append(abbr)
# set events
self.Bind(wx.EVT_KEY_DOWN, self._onKey)
@@ -2581,7 +3075,7 @@
self.SetDefaultStyle(self.styles['default'])
# show current sequence
- self.updateCanvas()
+ self.refresh()
# ----
@@ -2679,9 +3173,9 @@
curSelection = self.GetSelection()
seqSelection = self._positionEditorToSequence(curSelection)
- if char in mspy.aminoacids:
+ if char in self._aminoacids:
self.currentSequence[seqSelection[0]:seqSelection[1]] = mspy.sequence(char)
- self.updateCanvas()
+ self.refresh()
self.setInsertionPoint(seqSelection[0]+1)
self.modified = True
else:
@@ -2714,10 +3208,10 @@
curSelection = self.GetSelection()
seqSelection = self._positionEditorToSequence(curSelection)
- sequence = self.getSequenceFromClipboard()
+ sequence = self._getSequenceFromClipboard()
if sequence:
self.currentSequence[seqSelection[0]:seqSelection[1]] = sequence
- self.updateCanvas()
+ self.refresh()
self.setInsertionPoint(seqSelection[0]+len(sequence))
self.modified = True
@@ -2752,7 +3246,7 @@
else:
del self.currentSequence[seqSelection[0]:seqSelection[1]]
- self.updateCanvas()
+ self.refresh()
self.setInsertionPoint(seqSelection[0])
self.modified = True
# ----
@@ -2766,12 +3260,12 @@
if seqSelection[0] == seqSelection[1] and seqSelection[0] != 0:
del self.currentSequence[seqSelection[0]-1:seqSelection[1]]
- self.updateCanvas()
+ self.refresh()
self.setInsertionPoint(seqSelection[0]-1)
self.modified = True
else:
del self.currentSequence[seqSelection[0]:seqSelection[1]]
- self.updateCanvas()
+ self.refresh()
self.setInsertionPoint(seqSelection[0])
self.modified = True
# ----
@@ -2783,6 +3277,37 @@
# ----
+ def _updateCanvas(self):
+ """Show current sequence in canvas."""
+
+ # check sequence
+ if self.currentSequence == None:
+ self.ChangeValue('')
+ return
+
+ # format sequence
+ sequence = ''
+ modifications = []
+ for x, amino in enumerate(self.currentSequence):
+ sequence += amino
+ if not (x+1) % 10:
+ sequence += ' '
+ if self.currentSequence.ismodified(x, True):
+ modifications.append(x)
+
+ # update sequence
+ self.ChangeValue(sequence)
+
+ # set default style
+ self.SetStyle(0, len(sequence), self.styles['default'])
+
+ # highlight modifications
+ for pos in modifications:
+ x, y = self._positionSequenceToEditor([pos, pos])
+ self.SetStyle(x, x+1, self.styles['modified'])
+ # ----
+
+
def _positionEditorToSequence(self, selection):
"""Get sequence coordinates for editor selection."""
@@ -2805,22 +3330,61 @@
# ----
+ def _getSequenceFromClipboard(self):
+ """Get sequence from clipboard."""
+
+ # get data from clipboard
+ success = False
+ data = wx.TextDataObject()
+ if wx.TheClipboard.Open():
+ success = wx.TheClipboard.GetData(data)
+ wx.TheClipboard.Close()
+
+ # parse sequence if data in clipboard
+ if success:
+
+ # get text from clipboard
+ data = data.GetText()
+
+ # remove whitespaces
+ for char in ('\t','\n','\r','\f','\v', ' ', '-', '*', '.'):
+ data = data.replace(char, '')
+
+ # remove numbers
+ for char in ('0','1','2','3','4','5','6','7','8','9'):
+ data = data.replace(char, '')
+
+ # make sequence object
+ try:
+ sequence = mspy.sequence(data)
+ return sequence
+ except:
+ pass
+
+ wx.Bell()
+ return False
+ # ----
+
+
def setData(self, sequence):
"""Set sequence object."""
- # make sequence
- if isinstance(sequence, mspy.sequence):
- self.currentSequence = sequence
- elif sequence == None:
- self.currentSequence = mspy.sequence('')
- elif type(sequence) in (str, unicode):
- self.currentSequence = mspy.sequence(sequence)
+ # set current sequence
+ self.currentSequence = sequence
- # set modified
- self.modified = True
+ # disable editor
+ if self.currentSequence == None:
+ self.refresh()
+ self.enable(False)
+ return
+
+ # check sequence
+ if not isinstance(sequence, mspy.sequence):
+ raise TypeError, 'Sequence must be mspy.sequence object!'
# update gui
- self.updateCanvas()
+ self.enable(True)
+ self.refresh()
# ----
@@ -2850,71 +3414,246 @@
# ----
- def getSequenceFromClipboard(self):
- """Get sequence from clipboard."""
+ def enable(self, enable=True):
+ """Enable or disable editor."""
+ self.Enable(enable)
+ # ----
+
+
+ def refresh(self):
+ """Redraw current sequence."""
+ self._updateCanvas()
+ # ----
+
+
+ def ismodified(self):
+ """Modified status."""
+ return self.modified
+ # ----
+
+
+
+
+class sequenceGrid(wx.StaticBoxSizer):
+ """Sequence editor for all monomers."""
+
+ def __init__(self, parent, panel, sequence=None, items=20):
+ wx.StaticBoxSizer.__init__(self, wx.StaticBox(panel, -1, ""), wx.VERTICAL)
- # get data from clipboard
- success = False
- data = wx.TextDataObject()
- if wx.TheClipboard.Open():
- success = wx.TheClipboard.GetData(data)
- wx.TheClipboard.Close()
+ self.parent = parent
+ self.panel = panel
+ self.modified = False
- # parse sequence if data in clipboard
- if success:
-
- # get text from clipboard
- data = data.GetText()
-
- # remove whitespaces
- for char in ('\t','\n','\r','\f','\v', ' ', '-', '*', '.'):
- data = data.replace(char, '')
-
- # remove numbers
- for char in ('0','1','2','3','4','5','6','7','8','9'):
- data = data.replace(char, '')
+ self.items = []
+
+ # make sequence
+ if isinstance(sequence, mspy.sequence):
+ self.currentSequence = sequence
+ elif sequence == None:
+ self.currentSequence = mspy.sequence('')
+
+ # make items grid
+ items = max(items, len(self.currentSequence))
+ self._makeGUI(items)
+ # --
+
+
+ def _onSequence(self, evt=None):
+ """Get current sequence from grid."""
+
+ self.modified = True
+
+ # get sequence
+ sequence = []
+ gap = False
+ for x, item in enumerate(self.items):
+ monomer = item.GetValue()
+
+ if not monomer:
+ gap = True
+ item.SetBackgroundColour(wx.NullColour)
+ elif not monomer in mspy.monomers:
+ gap = True
+ item.SetBackgroundColour((250,100,100))
+ elif not gap:
+ sequence.append(monomer)
+ item.SetBackgroundColour(wx.NullColour)
+ else:
+ item.SetBackgroundColour(wx.NullColour)
- # make sequence object
- try:
- sequence = mspy.sequence(data)
- return sequence
- except:
- pass
+ item.Refresh()
- wx.Bell()
- return False
+ # update sequence
+ self.currentSequence[:] = mspy.sequence(sequence, chainType='custom')
+
+ # lock items
+ self._lockItems()
+
+ # send notification up
+ self.parent.onSequenceChanged()
# ----
- def updateCanvas(self):
- """Show current sequence in canvas."""
+ def _makeGUI(self, items):
+ """Make monomer items."""
- # format and sequence
- sequence = ''
- modifications = []
- for x, amino in enumerate(self.currentSequence):
- sequence += amino
- if not (x+1) % 10:
- sequence += ' '
- if self.currentSequence.ismodified(x, True):
- modifications.append(x)
+ # make items grid
+ self.grid = wx.GridBagSizer(mwx.GRIDBAG_VSPACE, mwx.GRIDBAG_HSPACE)
+ self.grid.AddGrowableCol(1)
+ self.grid.AddGrowableCol(3)
+ self.grid.AddGrowableCol(5)
+ self.grid.AddGrowableCol(7)
+ self.grid.AddGrowableCol(9)
- # update sequence
- self.ChangeValue(sequence)
+ # make items
+ while len(self.items) < items:
+ self.addRow()
- # set default style
- self.SetStyle(0, len(sequence), self.styles['default'])
+ # add to self
+ self.Add(self.grid, 1, wx.EXPAND|wx.ALIGN_CENTER|wx.ALL, 10)
- # highlight modifications
- for pos in modifications:
- x, y = self._positionSequenceToEditor([pos, pos])
- self.SetStyle(x, x+1, self.styles['modified'])
+ # lock items
+ self._lockItems()
+ # ----
+
+
+ def _updateGrid(self):
+ """Show current sequence in grid."""
+
+ # clear items
+ for item in self.items:
+ item.ChangeValue('')
+ item.SetBackgroundColour(wx.NullColour)
+
+ # update items
+ if self.currentSequence != None:
+ for x, monomer in enumerate(self.currentSequence):
+ self.items[x].ChangeValue(monomer)
+
+ # lock items
+ self._lockItems()
+ # ----
+
+
+ def _lockItems(self):
+ """Disable unset items."""
+
+ # check sequence
+ if self.currentSequence == None:
+ for item in self.items:
+ item.Disable()
+ item.SetBackgroundColour((230,230,230))
+ return
+
+ # enable/disable items
+ length = len(self.currentSequence)
+ end = 0
+ for x in reversed(range(len(self.items))):
+ item = self.items[x]
+ value = self.items[x].GetValue()
+
+ # set sequence end by last specified item
+ if x > end and value:
+ end = x
+
+ # value specified
+ if value:
+ item.Enable()
+
+ # space right next to the sequence
+ elif x == length and x > end:
+ item.Enable()
+ self.items[x].SetBackgroundColour(wx.NullColour)
+
+ # space out of specified sequence
+ elif x > end:
+ item.Disable()
+ self.items[x].SetBackgroundColour((230,230,230))
+
+ # gap
+ elif x < end:
+ item.Enable()
+ self.items[x].SetBackgroundColour((240,100,100))
+ # ----
+
+
+ def setData(self, sequence):
+ """Set sequence object."""
+
+ # set current sequence
+ self.currentSequence = sequence
+
+ # disable editor
+ if self.currentSequence == None:
+ self.refresh()
+ self.enable(False)
+ return
+
+ # check sequence
+ if not isinstance(sequence, mspy.sequence):
+ raise TypeError, 'Sequence must be mspy.sequence object!'
+
+ # check number of items
+ while len(self.currentSequence) - len(self.items) > 0:
+ self.addRow()
+
+ # update gui
+ self.enable(True)
+ self.refresh()
+ # ----
+
+
+ def setModified(self, status=True):
+ """Set modified status."""
+ self.modified = status
+ # ----
+
+
+ def getData(self):
+ """Get current sequence."""
+ return self.currentSequence
+ # ----
+
+
+ def addRow(self):
+ """Append new row of items."""
+
+ length = len(self.items)
+ for x in range(5):
+
+ # make item
+ item = wx.TextCtrl(self.panel, -1, '', size=(85, -1))
+ item.Bind(wx.EVT_TEXT, self._onSequence)
+ dropTarget = monomerDropTarget(item)
+ item.SetDropTarget(dropTarget)
+ self.items.append(item)
+
+ # add to grid
+ row = (length + x) / 5
+ col = 2 * (x % 5)
+
+ label = wx.StaticText(self.panel, -1, str(length+x+1))
+ label.SetFont(wx.SMALL_FONT)
+
+ self.grid.Add(label, (row, col), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ self.grid.Add(item, (row, col+1), flag=wx.EXPAND)
+ # ----
+
+
+ def enable(self, enable=True):
+ """Enable or disable editor."""
+
+ for item in self.items:
+ item.Enable(enable)
+
+ if enable:
+ self._lockItems()
# ----
def refresh(self):
"""Redraw current sequence."""
- self.updateCanvas()
+ self._updateGrid()
# ----
@@ -2986,3 +3725,29 @@
wx.Bell()
# ----
+
+
+
+class monomerDropTarget(wx.TextDropTarget):
+ """Monomer droptarget definition."""
+
+ def __init__(self, item):
+ wx.TextDropTarget.__init__(self)
+ self.item = item
+ # ----
+
+
+ def OnDropText(self, x, y, text):
+ if not self.item.IsEnabled():
+ wx.Bell()
+ return wx.DragNone
+ elif wx.Platform == '__WXGTK__':
+ self.item.SetValue('')
+ return
+ else:
+ self.item.SetValue(text)
+ return wx.DragCopy
+ # ----
+
+
+
diff -Nru mmass-3.12.1/gui/panel_spectrum_generator.py mmass-4.0.0/gui/panel_spectrum_generator.py
--- mmass-3.12.1/gui/panel_spectrum_generator.py 2011-06-30 11:56:13.000000000 +0000
+++ mmass-4.0.0/gui/panel_spectrum_generator.py 2011-11-29 14:55:09.000000000 +0000
@@ -78,9 +78,8 @@
# fit layout
self.mainSizer.Fit(self)
self.SetSizer(self.mainSizer)
- size = self.GetSize()
- self.SetSize((size[0],size[1]+1)) # layout hack
self.SetMinSize(self.GetSize())
+ mwx.layout(self, self.mainSizer)
# ----
@@ -91,7 +90,7 @@
panel = mwx.bgrPanel(self, -1, images.lib['bgrToolbar'], size=(-1, mwx.TOOLBAR_HEIGHT))
# make elements
- fwhm_label = wx.StaticText(panel, -1, "Default FWHM:")
+ fwhm_label = wx.StaticText(panel, -1, "FWHM:")
fwhm_label.SetFont(wx.SMALL_FONT)
self.fwhm_value = wx.TextCtrl(panel, -1, str(config.generator['fwhm']), size=(60, -1), validator=mwx.validator('floatPos'))
@@ -204,6 +203,7 @@
self.spectrumCanvas.setProperties(showCurXPos=True)
self.spectrumCanvas.setProperties(showCurYPos=True)
self.spectrumCanvas.setProperties(showCurCharge=True)
+ self.spectrumCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.spectrumCanvas.setProperties(reverseDrawing=True)
self.spectrumCanvas.setLMBFunction('xDistance')
@@ -513,16 +513,17 @@
# add main profile spectrum to container
labelFont = wx.Font(config.spectrum['labelFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
- spectrum = mspy.plot.spectrum(mspy.scan(points=profile, peaks=peaklist), \
- spectrumColour=(16,71,185), \
- tickColour=(255,0,0), \
- showPoints=config.spectrum['showDataPoints'], \
- showLabels=config.spectrum['showLabels'], \
- showTicks=True, \
- labelDigits=config.main['mzDigits'], \
- labelBgr=config.spectrum['labelBgr'], \
- labelAngle=config.spectrum['labelAngle'],
- labelFont=labelFont
+ spectrum = mspy.plot.spectrum(
+ scan = mspy.scan(points=profile, peaks=peaklist),
+ spectrumColour = (16,71,185),
+ tickColour = (255,0,0),
+ showPoints = config.spectrum['showDataPoints'],
+ showLabels = config.spectrum['showLabels'],
+ showTicks = True,
+ labelDigits = config.main['mzDigits'],
+ labelBgr = config.spectrum['labelBgr'],
+ labelAngle = config.spectrum['labelAngle'],
+ labelFont = labelFont
)
self.spectrumContainer.append(spectrum)
@@ -530,11 +531,12 @@
if config.generator['showPeaks']:
if self.currentPeaks != None:
for peak in self.currentPeaks:
- spectrum = mspy.plot.points(peak, \
- lineColour=(50,140,0), \
- showLines=True, \
- showPoints=False, \
- exactFit=True
+ spectrum = mspy.plot.points(
+ points = peak,
+ lineColour = (50,140,0),
+ showLines = True,
+ showPoints = False,
+ exactFit = True
)
self.spectrumContainer.append(spectrum)
@@ -572,12 +574,12 @@
try:
# make profile spectrum
- self.currentProfile = mspy.profile( \
- peaklist=self.currentDocument.spectrum.peaklist, \
- fwhm=config.generator['fwhm'], \
- points=config.generator['points'], \
- noise=config.generator['noise'], \
- forceFwhm=config.generator['forceFwhm'] \
+ self.currentProfile = mspy.profile(
+ peaklist = self.currentDocument.spectrum.peaklist,
+ fwhm = config.generator['fwhm'],
+ points = config.generator['points'],
+ noise = config.generator['noise'],
+ forceFwhm = config.generator['forceFwhm']
)
# make peak spectra
@@ -590,11 +592,11 @@
fwhm = peak.fwhm
# calc peak
- points = mspy.gaussian( \
- mz=peak.mz, \
- ai=peak.ai, \
- base=peak.base, \
- fwhm=fwhm \
+ points = mspy.gaussian(
+ mz = peak.mz,
+ ai = peak.ai,
+ base = peak.base,
+ fwhm = fwhm
)
self.currentPeaks.append(points)
diff -Nru mmass-3.12.1/gui/panel_spectrum.py mmass-4.0.0/gui/panel_spectrum.py
--- mmass-3.12.1/gui/panel_spectrum.py 2011-06-29 11:42:48.000000000 +0000
+++ mmass-4.0.0/gui/panel_spectrum.py 2011-11-30 12:59:27.000000000 +0000
@@ -110,6 +110,8 @@
self.spectrumCanvas.setProperties(xPosDigits=config.main['mzDigits'])
self.spectrumCanvas.setProperties(yPosDigits=config.main['intDigits'])
self.spectrumCanvas.setProperties(distanceDigits=config.main['mzDigits'])
+ self.spectrumCanvas.setProperties(checkLimits=True)
+ self.spectrumCanvas.setProperties(reverseScrolling=config.main['reverseScrolling'])
self.spectrumCanvas.setProperties(reverseDrawing=True)
axisFont = wx.Font(config.spectrum['axisFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
@@ -133,10 +135,6 @@
panel = mwx.bgrPanel(self, -1, images.lib['bgrBottombar'], size=(-1, mwx.BOTTOMBAR_HEIGHT))
# make canvas toolset
- self.canvasParameters_butt = wx.BitmapButton(panel, ID_viewCanvasProperties, images.lib['spectrumParams'], size=(mwx.BOTTOMBAR_TOOLSIZE), style=wx.BORDER_NONE)
- self.canvasParameters_butt.SetToolTip(wx.ToolTip("Canvas properties..."))
- self.canvasParameters_butt.Bind(wx.EVT_BUTTON, self.onCanvasProperties)
-
image = (images.lib['spectrumLabelsOff'], images.lib['spectrumLabelsOn'])[config.spectrum['showLabels']]
self.showLabels_butt = wx.BitmapButton(panel, ID_viewLabels, image, size=(mwx.BOTTOMBAR_TOOLSIZE), style=wx.BORDER_NONE)
self.showLabels_butt.SetToolTip(wx.ToolTip("Show / hide labels"))
@@ -214,8 +212,7 @@
# pack elements
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.AddSpacer(mwx.BOTTOMBAR_LSPACE)
- sizer.Add(self.canvasParameters_butt, 0, wx.ALIGN_CENTER_VERTICAL)
- sizer.Add(self.showLabels_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, mwx.BUTTON_SIZE_CORRECTION)
+ sizer.Add(self.showLabels_butt, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(self.showTicks_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, mwx.BUTTON_SIZE_CORRECTION)
sizer.Add(self.showNotations_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, mwx.BUTTON_SIZE_CORRECTION)
sizer.Add(self.labelAngle_butt, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, mwx.BUTTON_SIZE_CORRECTION)
@@ -438,6 +435,7 @@
spectrum.setProperties(labelCharge=config.spectrum['labelCharge'])
spectrum.setProperties(labelDigits=config.main['mzDigits'])
spectrum.setProperties(labelBgr=config.spectrum['labelBgr'])
+ spectrum.setProperties(isotopeColour=None)
labelFont = wx.Font(config.spectrum['labelFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
spectrum.setProperties(labelFont=labelFont)
@@ -553,6 +551,9 @@
ppmFormat = '%0.' + `config.main['ppmDigits']` + 'f'
chargeFormat = '%d'
+ if position and abs(position[1]) > 10000:
+ intFormat = '%.2e'
+
# offset dragging
if self.currentTool == 'offset' and distance and position:
format = 'a.i.: %s dist: %s' % (intFormat, intFormat)
@@ -566,8 +567,11 @@
# distance measurement
elif distance and position:
- format = 'm/z: %s dist: %s ppm: %s' % (mzFormat, mzFormat, ppmFormat)
- label += format % (position[0], distance[0], 1e6*distance[0]/position[0])
+ charge = 0
+ if distance[0]:
+ charge = int(abs(round(1/distance[0],0)))
+ format = 'm/z: %s dist: %s ppm: %s z: %s' % (mzFormat, mzFormat, ppmFormat, chargeFormat)
+ label += format % (position[0], distance[0], 1e6*distance[0]/position[0], charge*polarity)
# no specific fce
elif position:
@@ -611,17 +615,18 @@
flipped = self.documents[self.currentDocument].flipped
# make tmp spectrum
- obj = mspy.plot.points(points, \
- normalized=config.spectrum['normalize'], \
- flipped=flipped, \
- xOffset=xOffset, \
- yOffset=yOffset, \
- showInGel=False, \
- showLines=True, \
- showPoints=False, \
- exactFit=True, \
- pointColour=config.spectrum['tmpSpectrumColour'], \
- lineColour=config.spectrum['tmpSpectrumColour'] \
+ obj = mspy.plot.points(
+ points = points,
+ normalized = config.spectrum['normalize'],
+ flipped = flipped,
+ xOffset = xOffset,
+ yOffset = yOffset,
+ showInGel = False,
+ showLines = True,
+ showPoints = False,
+ exactFit = True,
+ pointColour = config.spectrum['tmpSpectrumColour'],
+ lineColour = config.spectrum['tmpSpectrumColour']
)
# set normalization
@@ -667,22 +672,23 @@
# add points to container
labelFont = wx.Font(config.spectrum['labelFontSize'], wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0)
- obj = mspy.plot.annotations(notations, \
- normalized=config.spectrum['normalize'], \
- flipped=flipped, \
- xOffset=xOffset, \
- yOffset=yOffset, \
- exactFit=True, \
- showInGel=False, \
- showPoints=config.spectrum['notationMarks'], \
- showLabels=config.spectrum['notationLabels'], \
- showXPos=config.spectrum['notationMZ'], \
- xPosDigits=config.main['mzDigits'], \
- pointColour=config.spectrum['notationMarksColour'], \
- labelAngle=config.spectrum['labelAngle'], \
- labelBgr=config.spectrum['labelBgr'], \
- labelFont=labelFont, \
- labelMaxLength=config.spectrum['notationMaxLength'], \
+ obj = mspy.plot.annotations(
+ points = notations,
+ normalized = config.spectrum['normalize'],
+ flipped = flipped,
+ xOffset = xOffset,
+ yOffset = yOffset,
+ exactFit = True,
+ showInGel = False,
+ showPoints = config.spectrum['notationMarks'],
+ showLabels = config.spectrum['notationLabels'],
+ showXPos = config.spectrum['notationMZ'],
+ xPosDigits = config.main['mzDigits'],
+ pointColour = config.spectrum['notationMarksColour'],
+ labelAngle = config.spectrum['labelAngle'],
+ labelBgr = config.spectrum['labelBgr'],
+ labelFont = labelFont,
+ labelMaxLength = config.spectrum['notationMaxLength']
)
# set normalization
@@ -818,19 +824,19 @@
baselineWindow = 1./config.processing['baseline']['precision']
# get baseline
- baseline = self.documents[self.currentDocument].spectrum.baseline(\
- window=baselineWindow, \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ baseline = self.documents[self.currentDocument].spectrum.baseline(
+ window = baselineWindow,
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# label peak
- peak = mspy.labelPeak(\
- points=self.documents[self.currentDocument].spectrum.points, \
- minX=selection[0], \
- maxX=selection[2], \
- pickingHeight=config.processing['peakpicking']['pickingHeight'], \
- baselineData=baseline \
+ peak = mspy.labelPeak(
+ points = self.documents[self.currentDocument].spectrum.points,
+ minX = selection[0],
+ maxX = selection[2],
+ pickingHeight = config.processing['peakpicking']['pickingHeight'],
+ baselineData = baseline
)
if peak:
@@ -859,17 +865,17 @@
baselineWindow = 1./config.processing['baseline']['precision']
# get baseline
- baseline = self.documents[self.currentDocument].spectrum.baseline(\
- window=baselineWindow, \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ baseline = self.documents[self.currentDocument].spectrum.baseline(
+ window = baselineWindow,
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# label point
- peak = mspy.labelPoint(\
- points=self.documents[self.currentDocument].spectrum.points, \
- mz=mz, \
- baselineData=baseline \
+ peak = mspy.labelPoint(
+ points = self.documents[self.currentDocument].spectrum.points,
+ mz = mz,
+ baselineData = baseline
)
if peak:
@@ -898,21 +904,21 @@
baselineWindow = 1./config.processing['baseline']['precision']
# get baseline
- baseline = self.documents[self.currentDocument].spectrum.baseline(\
- window=baselineWindow, \
- smooth=True, \
- offset=config.processing['baseline']['offset'] \
+ baseline = self.documents[self.currentDocument].spectrum.baseline(
+ window = baselineWindow,
+ smooth = True,
+ offset = config.processing['baseline']['offset']
)
# label isotopes
peaks = []
buff = []
for isotope in isotopes:
- peak = mspy.labelPeak(\
- points=self.documents[self.currentDocument].spectrum.points, \
- mz=isotope, \
- pickingHeight=config.processing['peakpicking']['pickingHeight'], \
- baselineData=baseline \
+ peak = mspy.labelPeak(
+ points = self.documents[self.currentDocument].spectrum.points,
+ mz = isotope,
+ pickingHeight = config.processing['peakpicking']['pickingHeight'],
+ baselineData = baseline
)
if peak and not peak.mz in buff:
peaks.append(peak)
@@ -930,17 +936,8 @@
if self.documents[self.currentDocument].spectrum.polarity == -1:
polarity = -1
- # label all isotopes
- if config.processing['deisotoping']['labelEnvelope'] == 'isotopes':
- groupname = self.documents[self.currentDocument].spectrum.peaklist.nextGroupName()
- for x, peak in enumerate(peaks):
- peak.setIsotope(x)
- peak.setCharge(charge*polarity)
- peak.setGroup(groupname)
- self.documents[self.currentDocument].spectrum.peaklist.append(peak)
-
- # label monoisotopic peak
- elif config.processing['deisotoping']['labelEnvelope'] == 'monoisotopic':
+ # label 1st isotope
+ if config.processing['deisotoping']['labelEnvelope'] == '1st':
basepeak = peaks[0]
sumIntensity = 0
@@ -963,17 +960,25 @@
ai = base + sumIntensity / len(isotopes)
sn = (ai - base) * basepeak.sn / (basepeak.ai - basepeak.base)
- peak = mspy.peak(mz=peaks[0].mz, \
- ai=ai, \
- base=base, \
- sn=sn, \
- charge=charge*polarity, \
- isotope=0, \
- fwhm=None \
+ peak = mspy.peak(
+ mz = peaks[0].mz,
+ ai = ai,
+ base = base,
+ sn = sn,
+ charge = charge*polarity,
+ isotope = 0,
+ fwhm = None
)
self.documents[self.currentDocument].spectrum.peaklist.append(peak)
+ # label monoisotopic peak
+ elif config.processing['deisotoping']['labelEnvelope'] == 'monoisotope':
+ peak = mspy.envelopeMonoisotope(peaks, charge=charge*polarity, intensity=config.processing['deisotoping']['envelopeIntensity'])
+ if peak:
+ peak.setCharge(charge*polarity)
+ self.documents[self.currentDocument].spectrum.peaklist.append(peak)
+
# label envelope centroid
elif config.processing['deisotoping']['labelEnvelope'] == 'centroid':
peak = mspy.envelopeCentroid(peaks, height=0.5, intensity=config.processing['deisotoping']['envelopeIntensity'])
@@ -981,6 +986,15 @@
peak.setCharge(charge*polarity)
self.documents[self.currentDocument].spectrum.peaklist.append(peak)
+ # label all isotopes
+ if config.processing['deisotoping']['labelEnvelope'] == 'isotopes':
+ groupname = self.documents[self.currentDocument].spectrum.peaklist.nextGroupName()
+ for x, peak in enumerate(peaks):
+ peak.setIsotope(x)
+ peak.setCharge(charge*polarity)
+ peak.setGroup(groupname)
+ self.documents[self.currentDocument].spectrum.peaklist.append(peak)
+
# update gui
self.parent.onDocumentChanged(('spectrum'))
# ----
diff -Nru mmass-3.12.1/mspy/blocks.py mmass-4.0.0/mspy/blocks.py
--- mmass-3.12.1/mspy/blocks.py 2011-06-14 14:24:52.000000000 +0000
+++ mmass-4.0.0/mspy/blocks.py 2011-11-28 17:23:11.000000000 +0000
@@ -37,7 +37,7 @@
isotopes: (dict) dict of isotopes {mass number:(mass, abundance),...}
"""
- def __init__(self, name='', symbol='', atomicNumber='', isotopes={}):
+ def __init__(self, name, symbol, atomicNumber, isotopes={}):
self.name = name
self.symbol = symbol
@@ -62,25 +62,31 @@
-class aminoacid:
- """Amino acid object definition.
- name: (str) name
- symbol: (str) one-letter symbol
+class monomer:
+ """Monomer object definition.
+ abbr: (str) unique monomer abbreviation
formula: (str) molecular formula
- abbr: (str) three-letter abbreviation
+ losses: (list) list of applicable neutral losses
+ name: (str) name
+ category: (str) category name
"""
- def __init__(self, name='', symbol='', formula='', abbr=''):
+ def __init__(self, abbr, formula, losses=[], name='', category=''):
- self.name = name
- self.symbol = symbol
- self.formula = formula
self.abbr = abbr
+ self.formula = formula
+ self.losses = losses
+ self.name = name
+ self.category = category
# init masses and composition
cmpd = objects.compound(self.formula)
self.composition = cmpd.composition()
self.mass = cmpd.mass()
+
+ # check formulae
+ for loss in losses:
+ cmpd = objects.compound(loss)
# ----
@@ -103,6 +109,10 @@
self.cTermFormula = cTermFormula
self.modsBefore = modsBefore
self.modsAfter = modsAfter
+
+ # check formulae
+ cmpd = objects.compound(nTermFormula)
+ cmpd = objects.compound(cTermFormula)
# ----
@@ -110,25 +120,25 @@
class fragment:
"""Peptide ion fragment object definition.
name: (str) name
- teminus: (N or C on S or I) fragment type (N-terminal, C-terminal, I-internal, S-single amino)
- specifity: (str) specific amino acids for this fragment
+ teminus: (M or N or C on S or I) fragment type (M-molecular ion, N-terminal, C-terminal, I-internal, S-single amino)
nTermFormula: (str) molecular formula of N-terminal gain or loss
cTermFormula: (str) molecular formula of C-terminal gain or loss
- lossFormula: (str) molecular formula of neutral loss
nTermFilter: (bool) filter N-terminal fragment
cTermFilter: (bool) filter C-terminal fragment
"""
- def __init__(self, name='', terminus='', specifity='', nTermFormula='', cTermFormula='', lossFormula='', nTermFilter=False, cTermFilter=False):
+ def __init__(self, name='', terminus='', nTermFormula='', cTermFormula='', nTermFilter=False, cTermFilter=False):
self.name = name
self.terminus = terminus
- self.specifity = specifity
self.nTermFormula = nTermFormula
self.cTermFormula = cTermFormula
- self.lossFormula = lossFormula
self.nTermFilter = nTermFilter
self.cTermFilter = cTermFilter
+
+ # check formulae
+ cmpd = objects.compound(nTermFormula)
+ cmpd = objects.compound(cTermFormula)
# ----
@@ -282,28 +292,30 @@
'Zr': element( name='Zirconium', symbol='Zr', atomicNumber=40, isotopes={96: (95.908276000000001, 0.028000000000000001), 90: (89.904703699999999, 0.51449999999999996), 91: (90.905645000000007, 0.11219999999999999), 92: (91.905040099999994, 0.17150000000000001), 94: (93.906315800000002, 0.17380000000000001)}),
}
-aminoacids = {
- 'A': aminoacid( name='Alanine', symbol='A', formula='C3H5NO', abbr='Ala'),
- 'C': aminoacid( name='Cysteine', symbol='C', formula='C3H5NOS', abbr='Cys'),
- 'D': aminoacid( name='Aspartic Acid', symbol='D', formula='C4H5NO3', abbr='Asp'),
- 'E': aminoacid( name='Glutamic Acid', symbol='E', formula='C5H7NO3', abbr='Glu'),
- 'F': aminoacid( name='Phenylalanine', symbol='F', formula='C9H9NO', abbr='Phe'),
- 'G': aminoacid( name='Glycine', symbol='G', formula='C2H3NO', abbr='Gly'),
- 'H': aminoacid( name='Histidine', symbol='H', formula='C6H7N3O', abbr='His'),
- 'I': aminoacid( name='Isoleucine', symbol='I', formula='C6H11NO', abbr='Ile'),
- 'K': aminoacid( name='Lysine', symbol='K', formula='C6H12N2O', abbr='Lys'),
- 'L': aminoacid( name='Leucine', symbol='L', formula='C6H11NO', abbr='Leu'),
- 'M': aminoacid( name='Methionine', symbol='M', formula='C5H9NSO', abbr='Met'),
- 'N': aminoacid( name='Asparagine', symbol='N', formula='C4H6O2N2', abbr='Asn'),
- 'O': aminoacid( name='Ornithine', symbol='O', formula='C5H10N2O', abbr='Ort'),
- 'P': aminoacid( name='Proline', symbol='P', formula='C5H7NO', abbr='Pro'),
- 'Q': aminoacid( name='Glutamine', symbol='Q', formula='C5H8N2O2', abbr='Gln'),
- 'R': aminoacid( name='Arginine', symbol='R', formula='C6H12N4O', abbr='Arg'),
- 'S': aminoacid( name='Serine', symbol='S', formula='C3H5NO2', abbr='Ser'),
- 'T': aminoacid( name='Threonine', symbol='T', formula='C4H7NO2', abbr='Thr'),
- 'V': aminoacid( name='Valine', symbol='V', formula='C5H9NO', abbr='Val'),
- 'W': aminoacid( name='Tryptophan', symbol='W', formula='C11H10N2O', abbr='Trp'),
- 'Y': aminoacid( name='Tyrosine', symbol='Y', formula='C9H9NO2', abbr='Tyr'),
+monomers = {
+
+ # regular amino acids for protein and peptide sequences
+ 'A': monomer( abbr='A', name='Alanine', formula='C3H5NO', category='_InternalAA'),
+ 'C': monomer( abbr='C', name='Cysteine', formula='C3H5NOS', category='_InternalAA'),
+ 'D': monomer( abbr='D', name='Aspartic Acid', formula='C4H5NO3', losses=['H2O'], category='_InternalAA'),
+ 'E': monomer( abbr='E', name='Glutamic Acid', formula='C5H7NO3', losses=['H2O'], category='_InternalAA'),
+ 'F': monomer( abbr='F', name='Phenylalanine', formula='C9H9NO', category='_InternalAA'),
+ 'G': monomer( abbr='G', name='Glycine', formula='C2H3NO', category='_InternalAA'),
+ 'H': monomer( abbr='H', name='Histidine', formula='C6H7N3O', category='_InternalAA'),
+ 'I': monomer( abbr='I', name='Isoleucine', formula='C6H11NO', category='_InternalAA'),
+ 'K': monomer( abbr='K', name='Lysine', formula='C6H12N2O', losses=['NH3'], category='_InternalAA'),
+ 'L': monomer( abbr='L', name='Leucine', formula='C6H11NO', category='_InternalAA'),
+ 'M': monomer( abbr='M', name='Methionine', formula='C5H9NSO', category='_InternalAA'),
+ 'N': monomer( abbr='N', name='Asparagine', formula='C4H6O2N2', losses=['NH3'], category='_InternalAA'),
+ 'O': monomer( abbr='O', name='Ornithine', formula='C5H10N2O', category='_InternalAA'),
+ 'P': monomer( abbr='P', name='Proline', formula='C5H7NO', category='_InternalAA'),
+ 'Q': monomer( abbr='Q', name='Glutamine', formula='C5H8N2O2', losses=['NH3'], category='_InternalAA'),
+ 'R': monomer( abbr='R', name='Arginine', formula='C6H12N4O', losses=['NH3'], category='_InternalAA'),
+ 'S': monomer( abbr='S', name='Serine', formula='C3H5NO2', losses=['H2O','H3PO4'], category='_InternalAA'),
+ 'T': monomer( abbr='T', name='Threonine', formula='C4H7NO2', losses=['H2O','H3PO4'], category='_InternalAA'),
+ 'V': monomer( abbr='V', name='Valine', formula='C5H9NO', category='_InternalAA'),
+ 'W': monomer( abbr='W', name='Tryptophan', formula='C11H10N2O', category='_InternalAA'),
+ 'Y': monomer( abbr='Y', name='Tyrosine', formula='C9H9NO2', losses=['H3PO4'], category='_InternalAA'),
}
enzymes = {
@@ -335,29 +347,18 @@
}
fragments = {
- 'a': fragment( name='a', terminus='N', specifity='', nTermFormula='', cTermFormula='C-1O-1H-1', lossFormula='', nTermFilter=True, cTermFilter=True),
- 'a-H2O': fragment( name='a-H2O', terminus='N', specifity='STED', nTermFormula='', cTermFormula='C-1O-1H-1', lossFormula='H2O', nTermFilter=True, cTermFilter=True),
- 'a-H3PO4': fragment( name='a-H3PO4', terminus='N', specifity='STY', nTermFormula='', cTermFormula='C-1O-1H-1', lossFormula='H3PO4', nTermFilter=True, cTermFilter=True),
- 'a-NH3': fragment( name='a-NH3', terminus='N', specifity='RKQN', nTermFormula='', cTermFormula='C-1O-1H-1', lossFormula='NH3', nTermFilter=True, cTermFilter=True),
- 'b': fragment( name='b', terminus='N', specifity='', nTermFormula='', cTermFormula='H-1', lossFormula='', nTermFilter=True, cTermFilter=True),
- 'b-H2O': fragment( name='b-H2O', terminus='N', specifity='STED', nTermFormula='', cTermFormula='H-1', lossFormula='H2O', nTermFilter=True, cTermFilter=True),
- 'b-H3PO4': fragment( name='b-H3PO4', terminus='N', specifity='STY', nTermFormula='', cTermFormula='H-1', lossFormula='H3PO4', nTermFilter=True, cTermFilter=True),
- 'b-NH3': fragment( name='b-NH3', terminus='N', specifity='RKQN', nTermFormula='', cTermFormula='H-1', lossFormula='NH3', nTermFilter=True, cTermFilter=True),
- 'c': fragment( name='c', terminus='N', specifity='', nTermFormula='', cTermFormula='NH2', lossFormula='', nTermFilter=True, cTermFilter=True),
- 'c-ladder': fragment( name='c-ladder', terminus='N', specifity='', nTermFormula='', cTermFormula='OH', lossFormula='', nTermFilter=False, cTermFilter=True),
- 'im': fragment( name='im', terminus='S', specifity='', nTermFormula='H', cTermFormula='C-1O-1H-1', lossFormula='', nTermFilter=True, cTermFilter=False),
- 'int': fragment( name='int', terminus='I', specifity='', nTermFormula='H', cTermFormula='H-1', lossFormula='', nTermFilter=False, cTermFilter=False),
- 'int-CO': fragment( name='int-CO', terminus='I', specifity='', nTermFormula='H', cTermFormula='C-1O-1H-1', lossFormula='', nTermFilter=False, cTermFilter=False),
- 'int-H2O': fragment( name='int-H2O', terminus='I', specifity='STED', nTermFormula='H', cTermFormula='H-1', lossFormula='H2O', nTermFilter=False, cTermFilter=False),
- 'int-H3PO4': fragment( name='int-H3PO4', terminus='C', specifity='STY', nTermFormula='H', cTermFormula='H-1', lossFormula='H3PO4', nTermFilter=False, cTermFilter=False),
- 'int-NH3': fragment( name='int-NH3', terminus='I', specifity='RKQN', nTermFormula='H', cTermFormula='H-1', lossFormula='NH3', nTermFilter=False, cTermFilter=False),
- 'n-ladder': fragment( name='n-ladder', terminus='C', specifity='', nTermFormula='H', cTermFormula='', lossFormula='', nTermFilter=True, cTermFilter=False),
- 'x': fragment( name='x', terminus='C', specifity='', nTermFormula='COH-1', cTermFormula='', lossFormula='', nTermFilter=False, cTermFilter=True),
- 'y': fragment( name='y', terminus='C', specifity='', nTermFormula='H', cTermFormula='', lossFormula='', nTermFilter=True, cTermFilter=False),
- 'y-H2O': fragment( name='y-H2O', terminus='C', specifity='STED', nTermFormula='H', cTermFormula='', lossFormula='H2O', nTermFilter=True, cTermFilter=False),
- 'y-H3PO4': fragment( name='y-H3PO4', terminus='C', specifity='STY', nTermFormula='H', cTermFormula='', lossFormula='H3PO4', nTermFilter=True, cTermFilter=False),
- 'y-NH3': fragment( name='y-NH3', terminus='C', specifity='RKQN', nTermFormula='H', cTermFormula='', lossFormula='NH3', nTermFilter=True, cTermFilter=False),
- 'z': fragment( name='z', terminus='C', specifity='', nTermFormula='N-1H-1', cTermFormula='', lossFormula='', nTermFilter=True, cTermFilter=False),
+ 'M': fragment( name='M', terminus='M', nTermFilter=False, cTermFilter=False),
+ 'im': fragment( name='im', terminus='S', nTermFormula='H', cTermFormula='C-1O-1H-1', nTermFilter=False, cTermFilter=False),
+ 'a': fragment( name='a', terminus='N', cTermFormula='C-1O-1H-1', nTermFilter=True, cTermFilter=True),
+ 'b': fragment( name='b', terminus='N', cTermFormula='H-1', nTermFilter=True, cTermFilter=True),
+ 'c': fragment( name='c', terminus='N', cTermFormula='NH2', nTermFilter=False, cTermFilter=True),
+ 'x': fragment( name='x', terminus='C', nTermFormula='COH-1', nTermFilter=True, cTermFilter=False),
+ 'y': fragment( name='y', terminus='C', nTermFormula='H', nTermFilter=True, cTermFilter=False),
+ 'z': fragment( name='z', terminus='C', nTermFormula='N-1H-2', nTermFilter=True, cTermFilter=False),
+ 'c-ladder': fragment( name='c-ladder', terminus='N', cTermFormula='OH', nTermFilter=True, cTermFilter=True),
+ 'n-ladder': fragment( name='n-ladder', terminus='C', nTermFormula='H', nTermFilter=True, cTermFilter=False),
+ 'int-b': fragment( name='int-b', terminus='I', nTermFormula='H', cTermFormula='H-1'),
+ 'int-a': fragment( name='int-a', terminus='I', nTermFormula='H', cTermFormula='C-1O-1H-1'),
}
modifications = {
@@ -422,89 +423,49 @@
# LOAD FUNCTIONS
# --------------
-def loadElements(path=os.path.join(blocksdir, 'elements.xml'), clear=False):
- """Parse elements XML and get data."""
+def loadMonomers(path=os.path.join(blocksdir, 'monomers.xml'), clear=False, replace=False):
+ """Parse monomers XML and get data."""
container = {}
# parse XML
document = xml.dom.minidom.parse(path)
- # get elements
- elementTags = document.getElementsByTagName('element')
- for x, elementTag in enumerate(elementTags):
-
- # get symbol, name and atomic number
- name = elementTag.getAttribute('name')
- symbol = str(elementTag.getAttribute('symbol'))
- atomicNumber = elementTag.getAttribute('atomicNumber')
-
- # get masses
- massTags = elementTag.getElementsByTagName('mass')
- massMo = float(massTags[0].getAttribute('monoisotopic'))
- massAv = float(massTags[0].getAttribute('average'))
- mass = (massMo, massAv)
-
- # get isotopes
- isotopes = {}
- isotopeTags = elementTag.getElementsByTagName('isotope')
- for isotopeTag in isotopeTags:
- massNumber = int(isotopeTag.getAttribute('massNumber'))
- imass = float(isotopeTag.getAttribute('mass'))
- abundance = float(isotopeTag.getAttribute('abundance'))
- isotopes[massNumber] = (imass,abundance)
-
- # add object
- container[symbol] = element( \
- name=name, \
- symbol=symbol, \
- atomicNumber=atomicNumber, \
- isotopes=isotopes \
- )
-
- # update current lib
- if clear:
- elements.clear()
- for key in container:
- elements[key] = container[key]
-# ----
-
-
-def loadAminoacids(path=os.path.join(blocksdir, 'aminoacids.xml'), clear=False):
- """Parse amino acid XML and get data."""
-
- container = {}
-
- # parse XML
- document = xml.dom.minidom.parse(path)
-
- # get aminoacids
- aminoacidTags = document.getElementsByTagName('aminoacid')
- for x, aminoacidTag in enumerate(aminoacidTags):
+ # get monomers
+ monomerTags = document.getElementsByTagName('monomer')
+ for x, monomerTag in enumerate(monomerTags):
# get basic data
- name = aminoacidTag.getAttribute('name')
- symbol = aminoacidTag.getAttribute('symbol')
- abbr = aminoacidTag.getAttribute('abbr')
- formula = aminoacidTag.getAttribute('formula')
+ abbr = monomerTag.getAttribute('abbr')
+ name = monomerTag.getAttribute('name')
+ category = monomerTag.getAttribute('category')
+ formula = monomerTag.getAttribute('formula')
+
+ # get losses
+ losses = []
+ attr = monomerTag.getAttribute('losses')
+ if attr:
+ losses = attr.split(';')
# add object
- container[symbol] = aminoacid( \
- name=name, \
- symbol=symbol, \
- formula=formula, \
- abbr=abbr \
+ container[abbr] = monomer(
+ abbr = abbr,
+ formula = formula,
+ losses = losses,
+ name = name,
+ category = category
)
# update current lib
- if clear:
- aminoacids.clear()
+ if container and clear:
+ monomers.clear()
for key in container:
- aminoacids[key] = container[key]
+ if replace or not key in monomers:
+ monomers[key] = container[key]
# ----
-def loadEnzymes(path=os.path.join(blocksdir, 'enzymes.xml'), clear=False):
+def loadEnzymes(path=os.path.join(blocksdir, 'enzymes.xml'), clear=False, replace=True):
"""Parse enzymes XML and get data."""
container = {}
@@ -534,72 +495,25 @@
modsAfter = bool(int(allowModsTags[0].getAttribute('after')))
# add objects
- container[name] = enzyme( \
- name=name, \
- expression=expression, \
- nTermFormula=nTermFormula, \
- cTermFormula=cTermFormula, \
- modsBefore=modsBefore, \
- modsAfter=modsAfter \
+ container[name] = enzyme(
+ name = name,
+ expression = expression,
+ nTermFormula = nTermFormula,
+ cTermFormula = cTermFormula,
+ modsBefore = modsBefore,
+ modsAfter = modsAfter
)
# update current lib
- if clear:
+ if container and clear:
enzymes.clear()
for key in container:
- enzymes[key] = container[key]
-# ----
-
-
-def loadFragments(path=os.path.join(blocksdir, 'fragments.xml'), clear=False):
- """Parse fragments XML and get data."""
-
- container = {}
-
- # parse XML
- document = xml.dom.minidom.parse(path)
-
- # get fragments
- fragmentTags = document.getElementsByTagName('fragment')
- for x, fragmentTag in enumerate(fragmentTags):
-
- # get basic data
- name = fragmentTag.getAttribute('name')
- terminus = fragmentTag.getAttribute('terminus')
- specifity = fragmentTag.getAttribute('specifity')
-
- # get formula
- formulaTags = fragmentTag.getElementsByTagName('formula')
- cTermFormula = str(formulaTags[0].getAttribute('cTerm'))
- nTermFormula = str(formulaTags[0].getAttribute('nTerm'))
- lossFormula = str(formulaTags[0].getAttribute('neutralLoss'))
-
- # get filter
- termFilterTags = fragmentTag.getElementsByTagName('termFilter')
- nTermFilter = bool(int(termFilterTags[0].getAttribute('nTerm')))
- cTermFilter = bool(int(termFilterTags[0].getAttribute('cTerm')))
-
- # add object
- container[name] = fragment(
- name=name, \
- terminus=terminus, \
- specifity=specifity, \
- cTermFormula=cTermFormula, \
- nTermFormula=nTermFormula, \
- lossFormula=lossFormula, \
- nTermFilter=nTermFilter, \
- cTermFilter=cTermFilter \
- )
-
- # update current lib
- if clear:
- fragments.clear()
- for key in container:
- fragments[key] = container[key]
+ if replace or not key in enzymes:
+ enzymes[key] = container[key]
# ----
-def loadModifications(path=os.path.join(blocksdir, 'modifications.xml'), clear=False):
+def loadModifications(path=os.path.join(blocksdir, 'modifications.xml'), clear=False, replace=True):
"""Parse modifications XML and get data."""
container = {}
@@ -629,20 +543,21 @@
description = _getNodeText(descriptionTags[0])
# add object
- container[name] = modification( \
- name=name, \
- gainFormula=gainFormula, \
- lossFormula=lossFormula, \
- aminoSpecifity=aminoSpecifity, \
- termSpecifity=termSpecifity, \
- description=description \
+ container[name] = modification(
+ name = name,
+ gainFormula = gainFormula,
+ lossFormula = lossFormula,
+ aminoSpecifity = aminoSpecifity,
+ termSpecifity = termSpecifity,
+ description = description
)
# update current lib
- if clear:
+ if container and clear:
modifications.clear()
for key in container:
- modifications[key] = container[key]
+ if replace or not key in modifications:
+ modifications[key] = container[key]
# ----
@@ -662,56 +577,22 @@
# SAVE FUNCTIONS
# --------------
-def saveElements(path=os.path.join(blocksdir, 'elements.xml')):
- """Make and save elements XML."""
+def saveMonomers(path=os.path.join(blocksdir, 'monomers.xml')):
+ """Make and save monomers XML."""
- # make elements xml
+ # make monomers xml
buff = '\n'
- buff += '\n'
+ buff += '\n'
- symbols = elements.keys()
- symbols.sort()
- for symbol in symbols:
- buff += ' \n' % (elements[symbol].symbol, elements[symbol].name, elements[symbol].atomicNumber)
- buff += ' \n' % elements[symbol].mass
- buff += ' \n'
-
- isotopes = elements[symbol].isotopes.keys()
- isotopes.sort()
- for isotope in isotopes:
- buff += ' \n' % (isotope, elements[symbol].isotopes[isotope][0], elements[symbol].isotopes[isotope][1])
-
- buff += ' \n'
- buff += ' \n'
+ abbrs = monomers.keys()
+ abbrs.sort()
+ for abbr in abbrs:
+ if monomers[abbr].category != '_InternalAA':
+ buff += ' \n' % (monomers[abbr].abbr, monomers[abbr].name, monomers[abbr].formula, monomers[abbr].category, ';'.join(monomers[abbr].losses))
- buff += ''
+ buff += ''
- # save elements file
- try:
- save = file(path, 'w')
- save.write(buff.encode("utf-8"))
- save.close()
- return True
- except:
- return False
-# ----
-
-
-def saveAminoacids(path=os.path.join(blocksdir, 'aminoacids.xml')):
- """Make and save aminoacids XML."""
-
- # make aminoacids xml
- buff = '\n'
- buff += '\n'
-
- symbols = aminoacids.keys()
- symbols.sort()
- for symbol in symbols:
- buff += ' \n' % (aminoacids[symbol].symbol, aminoacids[symbol].name, aminoacids[symbol].abbr, aminoacids[symbol].formula)
-
- buff += ''
-
- # save aminoacids file
+ # save monomers file
try:
save = file(path, 'w')
save.write(buff.encode("utf-8"))
@@ -751,34 +632,6 @@
# ----
-def saveFragments(path=os.path.join(blocksdir, 'fragments.xml')):
- """Make and save fragments XML."""
-
- # make fragments xml
- buff = '\n'
- buff += '\n'
-
- names = fragments.keys()
- names.sort()
- for name in names:
- buff += ' \n' % (_escape(fragments[name].name), fragments[name].terminus, fragments[name].specifity)
- buff += ' \n' % (fragments[name].nTermFormula, fragments[name].cTermFormula, fragments[name].lossFormula)
- buff += ' \n' % (int(fragments[name].nTermFilter), int(fragments[name].cTermFilter))
- buff += ' \n'
-
- buff += ''
-
- # save fragments file
- try:
- save = file(path, 'w')
- save.write(buff.encode("utf-8"))
- save.close()
- return True
- except:
- return False
-# ----
-
-
def saveModifications(path=os.path.join(blocksdir, 'modifications.xml')):
"""Make and save modifications XML."""
diff -Nru mmass-3.12.1/mspy/envfit.py mmass-4.0.0/mspy/envfit.py
--- mmass-3.12.1/mspy/envfit.py 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/mspy/envfit.py 2011-11-29 14:55:52.000000000 +0000
@@ -0,0 +1,438 @@
+# -------------------------------------------------------------------------
+# Copyright (C) 2005-2011 Martin Strohalm
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# Complete text of GNU GPL can be found in the file LICENSE.TXT in the
+# main directory of the program
+# -------------------------------------------------------------------------
+
+# load libs
+import math
+import numpy
+from numpy.linalg import solve as solveLinEq
+
+# load stopper
+from stopper import CHECK_FORCE_QUIT
+
+# register essential objects and modules
+import objects
+import processing
+
+
+# ENVELOPE FIT
+# ------------
+
+class envelopeFit():
+ """Fit modeled profiles with exchanged atoms to acquired data."""
+
+ def __init__(self, formula, charge, scale, loss='H', gain='H{2}'):
+
+ self.error = None # 1 - no data in relevant mass range
+
+ loss = objects.compound(loss)
+ loss.negate()
+ self._lossFormula = loss.formula()
+ self._gainFormula = gain
+
+ self.formula = formula
+ self.charge = charge
+ self.scale = self._validateScale(scale)
+ self.mzRange = self._calcMZRange()
+
+ self.fwhm = 0.1
+ self.spectrum = []
+ self.data = []
+ self.model = []
+ self.params = None
+ self.composition = None
+ self.ncomposition = None
+ self.average = None
+ self.std = None
+ # ----
+
+
+ def fitToSpectrum(self, points, fwhm=0.1, forceFwhm=True, autoAlign=True, iterLimit=None, pickingHeight=0.85, relThreshold=0., baselineWindow=0.1, baselineSmooth=True, baselineOffset=0.25, baselineData=None):
+ """Fit modeled profiles to spectrum using tmp peaklist.
+ points: (numpy array) m/z - intensity pairs or raw spectrum
+ fwhm: (float) defaut fwhm
+ forceFwhm: (bool) use default fwhm
+ autoAlign: (bool) automatic m/z shift
+ iterLimit: (int) maximum number of iterations
+ pickingHeight: (float) peak picking height for centroiding
+ relThreshold: (float) relative intensity threshold
+ baselineWindow: (float) noise calculation window in %/100
+ baselineSmooth: (bool) smooth baseline
+ baselineOffset: (float) baseline intensity offset in %/100
+ baselineData: (list of [x, noiseLevel, noiseWidth]) precalculated baseline
+ """
+
+ # get spectrum baseline
+ if baselineData == None:
+ baselineData = processing.baseline(
+ points = points,
+ window = baselineWindow,
+ smooth = baselineSmooth,
+ offset = baselineOffset
+ )
+
+ # crop points to relevant m/z range
+ i1 = processing.findIndex(points, self.mzRange[0], dim=2)
+ i2 = processing.findIndex(points, self.mzRange[1], dim=2)
+ points = points[i1:i2]
+
+ # get peaklist from spectrum points
+ peaklist = processing.labelScan(
+ points = points,
+ pickingHeight = pickingHeight,
+ relThreshold = relThreshold,
+ baselineData = baselineData
+ )
+
+ # correct spectrum baseline
+ self.spectrum = processing.correctBaseline(points, baselineData=baselineData)
+
+ # fit to peaklist
+ self.fitToPeaklist(
+ peaklist = peaklist,
+ fwhm = fwhm,
+ forceFwhm = forceFwhm,
+ autoAlign = autoAlign,
+ iterLimit = iterLimit
+ )
+ # ----
+
+
+ def fitToPeaklist(self, peaklist, fwhm=0.1, forceFwhm=True, autoAlign=True, iterLimit=None):
+ """Fit modeled profiles to peaklist.
+ peaklist: (mspy.peaklist) peak list
+ fwhm: (float) defaut fwhm
+ forceFwhm: (bool) use default fwhm
+ autoAlign: (bool) automatic m/z shift
+ iterLimit: (int) maximum number of iterations
+ """
+
+ # check peaklist object
+ if not isinstance(peaklist, objects.peaklist):
+ peaklist = objects.peaklist(peaklist)
+
+ # crop peaklist to relevant m/z range
+ buff = []
+ for peak in peaklist:
+ if self.mzRange[0] <= peak.mz <= self.mzRange[1]:
+ buff.append(peak)
+ peaklist = objects.peaklist(buff)
+
+ # get fwhm from basepeak
+ if not forceFwhm and peaklist.basepeak and peaklist.basepeak.fwhm:
+ fwhm = peaklist.basepeak.fwhm
+
+ # fit to points
+ self.data = numpy.array([(p.mz, p.intensity) for p in peaklist])
+ if not autoAlign:
+ self.fitToPoints(self.data, fwhm=fwhm, iterLimit=iterLimit)
+ else:
+ self.fitToPoints(self.data, fwhm=fwhm, iterLimit=self.scale[1]/2)
+ self._alignData()
+ self.fitToPoints(self.data, fwhm=fwhm, iterLimit=iterLimit)
+ # ----
+
+
+ def fitToPoints(self, points, fwhm=0.1, iterLimit=None):
+ """Fit modeled profiles to given points.
+ points: (numpy array or list) m/z - intensity pairs
+ fwhm: (float) defaut fwhm
+ iterLimit: (int) maximum number of iterations
+ """
+
+ self.fwhm = fwhm
+
+ # crop points to relevant m/z range
+ i1 = processing.findIndex(points, self.mzRange[0], dim=2)
+ i2 = processing.findIndex(points, self.mzRange[1], dim=2)
+ self.data = numpy.array(points[i1:i2])
+
+ # check data
+ if len(self.data) == 0:
+ self.error = 1
+ return
+
+ # split data to raster and intensities
+ xAxis, yAxis = numpy.hsplit(self.data, 2)
+ raster = xAxis.flatten()
+ intensities = yAxis.flatten()
+
+ # model profiles
+ models, exchanged = self._makeModels(raster)
+
+ # fit data to model
+ self.params = self._leastSquare(intensities, models, iterLimit=iterLimit)
+
+ # calc compositions
+ self.composition = {}
+ self.ncomposition = {}
+ f = 1./sum(self.params)
+ for i, value in enumerate(self.params):
+ self.composition[exchanged[i]] = value
+ self.ncomposition[exchanged[i]] = f*value
+
+ # calc average exchange
+ self.average = 0.
+ for x in self.ncomposition:
+ self.average += x * self.ncomposition[x]
+
+ # calc standard deviation
+ self.std = 0.
+ err = 0.
+ for x in self.ncomposition:
+ err += self.ncomposition[x] * (x - self.average)**2
+ self.std = math.sqrt(err)
+
+ # calc fitted points
+ intensities = numpy.sum(models * [[x] for x in self.params], axis=0)
+ intensities.shape = (-1,1)
+ raster.shape = (-1,1)
+ self.model = numpy.concatenate((raster, intensities), axis=1).copy()
+ # ----
+
+
+ def envelope(self, points=5):
+ """Return calculated envelope for current composition."""
+
+ # check composition
+ if self.composition == None:
+ return []
+
+ # get peak width
+ width = self.fwhm/1.66
+
+ # get isotopes for all profiles
+ isotopes = []
+ for x, abundance in self.composition.items():
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, x, self._gainFormula, x)
+ compound = objects.compound(item)
+ pattern = compound.pattern(fwhm=self.fwhm, charge=self.charge)
+ isotopes += [(p[0], p[1]*abundance) for p in pattern]
+
+ # make profile from isotopes
+ profile = processing.profile(isotopes, fwhm=self.fwhm, points=points)
+
+ return profile
+ # ----
+
+
+ def _validateScale(self, scale):
+ """Check if compounds are valid for given scale."""
+
+ for x in range(scale[0], scale[1]+1):
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, x, self._gainFormula, x)
+ compound = objects.compound(item)
+ if not compound.isvalid(charge=self.charge):
+ return (scale[0], x-1)
+
+ return scale
+ # ----
+
+
+ def _calcMZRange(self):
+ """Calculate relevant m/z range for current formula and scale."""
+
+ # set additional space
+ space = .001
+
+ # get m/z range
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, self.scale[0], self._gainFormula, self.scale[0])
+ compound = objects.compound(item)
+ minX = compound.pattern(fwhm=0.5, charge=self.charge)[0][0]
+ minX -= minX * space
+
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, self.scale[1], self._gainFormula, self.scale[1])
+ compound = objects.compound(item)
+ maxX = compound.pattern(fwhm=0.5, charge=self.charge)[-1][0]
+ maxX += maxX * space
+
+ return (minX, maxX)
+ # ----
+
+
+ def _makeModels(self, raster):
+ """Make individual profiles to fit."""
+
+ # get peak width
+ width = self.fwhm/1.66
+
+ # get raster
+ rasterMin = raster[0] - self.fwhm
+ rasterMax = raster[-1] + self.fwhm
+
+ # calculate profiles
+ models = []
+ exchanged = []
+ for x in range(self.scale[0], self.scale[1]+1):
+
+ CHECK_FORCE_QUIT()
+
+ # generate new formula with H/D exchange
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, x, self._gainFormula, x)
+ compound = objects.compound(item)
+ mz = compound.mz(self.charge)
+
+ # check theoretical mass with current m/z raster
+ if mz[0] < rasterMax and mz[1] > rasterMin:
+
+ # calculate isotopic pattern
+ pattern = compound.pattern(fwhm=self.fwhm, charge=self.charge)
+
+ # calculate intensities by adding peak gaussians
+ model = numpy.zeros(raster.size, float)
+ for peak in pattern:
+ i1 = processing.findIndex(raster, (peak[0]-5*width), dim=1)
+ i2 = processing.findIndex(raster, (peak[0]+5*width), dim=1)
+ for i in range(i1, i2):
+ model[i] += peak[1]*numpy.exp(-1*(pow(raster[i]-peak[0],2))/pow(width,2))
+
+ # store data
+ if model.any():
+ models.append(model)
+ exchanged.append(x)
+
+ # convert profiles to matrix
+ models = numpy.array(models)
+
+ return models, exchanged
+ # ----
+
+
+ def _alignData(self):
+ """Re-calibrate data using theoretical envelope."""
+
+ # check composition
+ if not self.composition:
+ return
+
+ # make theoretical profile
+ width = self.fwhm/1.66
+ isotopes = []
+ for x, abundance in self.composition.items():
+ item = "%s(%s)%d(%s)%d" % (self.formula, self._lossFormula, x, self._gainFormula, x)
+ compound = objects.compound(item)
+ pattern = compound.pattern(fwhm=self.fwhm, charge=self.charge)
+ isotopes += [(p[0], p[1]*abundance) for p in pattern]
+ profile = processing.profile(isotopes, fwhm=self.fwhm, points=5)
+
+ # label peaks in profile
+ peaklist = processing.labelScan(profile, pickingHeight=0.95, relThreshold=0.01)
+
+ # find peaks within tolerance
+ calibrants = []
+ tolerance = self.fwhm/1.5
+ previous = None
+ for peak in peaklist:
+ for point in self.data:
+ delta = point[0] - peak.mz
+
+ if abs(delta) <= tolerance:
+ if previous and previous[0] == peak.mz and previous[1] < point[1]:
+ calibrants[-1] = (point[0], peak.mz)
+ else:
+ calibrants.append((point[0], peak.mz))
+ previous = (peak.mz, point[1])
+
+ elif delta > tolerance:
+ break
+
+ # calc calibration
+ if len(calibrants) > 3:
+ model, params, chi = processing.calibration(calibrants, model='quadratic')
+ elif len(calibrants) > 1:
+ model, params, chi = processing.calibration(calibrants, model='linear')
+ else:
+ return
+
+ # apply calibration to data
+ for x in range(len(self.data)):
+ self.data[x][0] = model(params, self.data[x][0])
+ for x in range(len(self.spectrum)):
+ self.spectrum[x][0] = model(params, self.spectrum[x][0])
+ # ----
+
+
+ def _leastSquare(self, data, models, iterLimit=None, chiLimit=1e-3):
+ """Least-square fitting. Adapted from the original code by Konrad Hinsen."""
+
+ normf = 100./numpy.max(data)
+ data *= normf
+
+ params = [50.] * len(models)
+ id = numpy.identity(len(params))
+ chisq, alpha = self._chiSquare(data, models, params)
+ l = 0.001
+
+ niter = 0
+ while True:
+
+ CHECK_FORCE_QUIT()
+
+ niter += 1
+ delta = solveLinEq(alpha+l*numpy.diagonal(alpha)*id,-0.5*numpy.array(chisq[1]))
+ next_params = map(lambda a,b: a+b, params, delta)
+
+ for x in range(len(next_params)):
+ if next_params[x] < 0.:
+ next_params[x] = 0.
+
+ next_chisq, next_alpha = self._chiSquare(data, models, next_params)
+ if next_chisq[0] > chisq[0]:
+ l = 5.*l
+ elif chisq[0] - next_chisq[0] < chiLimit:
+ break
+ else:
+ l = 0.5*l
+ params = next_params
+ chisq = next_chisq
+ alpha = next_alpha
+
+ if iterLimit and niter == iterLimit:
+ break
+
+ next_params /= normf
+
+ return next_params
+ # ----
+
+
+ def _chiSquare(self, data, models, params):
+ """Calculate fitting chi-square for current parameter set."""
+
+ # calculate differences and chi-square value between calculated and real data
+ differences = numpy.sum(models * [[x] for x in params], axis=0) - data
+ chisq_value = numpy.sum(differences**2)
+
+ # calculate chi-square deriv and alpha
+ cycles = len(models)
+ chisq_deriv = cycles*[0]
+ alpha = numpy.zeros((len(params), len(params)))
+ for x in range(len(data)):
+
+ deriv = cycles*[0]
+ for i in range(cycles):
+ p_deriv = cycles*[0]
+ p_deriv[i] = models[i][x]
+ deriv = map(lambda a,b: a+b, deriv, p_deriv)
+ chisq_deriv = map(lambda a,b: a+b, chisq_deriv, map(lambda x,f=differences[x]*2:f*x, deriv))
+
+ d = numpy.array(deriv)
+ alpha = alpha + d[:,numpy.newaxis]*d
+
+ return [chisq_value, chisq_deriv], alpha
+ # ----
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/mspy/__init__.py mmass-4.0.0/mspy/__init__.py
--- mmass-3.12.1/mspy/__init__.py 2011-04-29 15:17:03.000000000 +0000
+++ mmass-4.0.0/mspy/__init__.py 2011-11-28 11:20:22.000000000 +0000
@@ -23,7 +23,8 @@
# register modules
from utilities import *
from processing import *
-from mascot import *
+from proteo import *
+from envfit import *
# register parsers
from parser_xy import parseXY
diff -Nru mmass-3.12.1/mspy/objects.py mmass-4.0.0/mspy/objects.py
--- mmass-3.12.1/mspy/objects.py 2011-06-30 11:05:14.000000000 +0000
+++ mmass-4.0.0/mspy/objects.py 2011-11-29 18:34:37.000000000 +0000
@@ -28,6 +28,7 @@
# register essential modules
import processing
+import proteo
# compile basic patterns
@@ -57,47 +58,68 @@
class compound:
"""Compound object definition."""
- def __init__(self, rawFormula):
+ def __init__(self, expression):
- # user defined formula
- self.rawFormula = rawFormula
+ # check formula
+ self._checkFormula(expression)
+ self.expression = expression
# buffers
- self._formula = None
self._composition = None
+ self._formula = None
self._mass = None
# user defined params
self.userParams = {}
+ # ----
+
+
+ def __iadd__(self, other):
+ """Append formula."""
- # check formula
- if not formulaPattern.match(self.rawFormula):
- raise ValueError, 'Wrong formula! --> ' + self.rawFormula
+ # check and append value
+ if isinstance(other, compound):
+ self.expression += other.expression
+ else:
+ self._checkFormula(other)
+ self.expression += other
- # check elements and isotopes
- for atom in elementPattern.findall(self.rawFormula):
- if not atom[0] in blocks.elements:
- raise ValueError, 'Unknown element in formula! --> ' + atom[0] + ' in ' + self.rawFormula
- elif atom[1] and not int(atom[1]) in blocks.elements[atom[0]].isotopes:
- raise ValueError, 'Unknown isotope in formula! --> ' + atom[0] + atom[1] + ' in ' + self.rawFormula
+ # clear buffers
+ self.reset()
- # check brackets
- if self.rawFormula.count(')') != self.rawFormula.count('('):
- raise ValueError, 'Wrong number of brackets in formula! --> ' + self.rawFormula
+ return self
# ----
def reset(self):
"""Clear formula buffers."""
+ self._composition = None
self._formula = None
self._mass = None
- self._composition = None
# ----
# GETTERS
+ def count(self, item):
+ """Count atom in formula."""
+
+ # pre-check atom
+ if not item in self.expression:
+ return 0
+
+ # get composition
+ comp = self.composition()
+
+ # count atom
+ if item in comp:
+ return comp[item]
+ else:
+ return 0
+ # ----
+
+
def formula(self):
"""Get formula."""
@@ -121,16 +143,16 @@
def composition(self):
- """Get elemental composition as dict."""
+ """Get elemental composition."""
# check composition buffer
if self._composition != None:
return self._composition
# unfold brackets
- unfoldedFormula = self._unfoldBrackets(self.rawFormula)
+ unfoldedFormula = self._unfoldBrackets(self.expression)
- # group same elements
+ # group elements
self._composition = {}
for symbol, isotop, count in elementPattern.findall(unfoldedFormula):
@@ -161,7 +183,7 @@
# ----
- def mass(self):
+ def mass(self, massType=None):
"""Get mass."""
# get mass
@@ -185,40 +207,49 @@
else:
atomMass = blocks.elements[symbol].mass
- # multiply atom
+ # multiply atom mass
massMo += atomMass[0]*count
massAv += atomMass[1]*count
# store mass in buffer
self._mass = (massMo, massAv)
- return self._mass
+ # return mass
+ if massType == 0:
+ return self._mass[0]
+ elif massType == 1:
+ return self._mass[1]
+ else:
+ return self._mass
# ----
def mz(self, charge, agentFormula='H', agentCharge=1):
"""Get ion m/z."""
- # get current mass and calculate mz
- return processing.mz(self.mass(), charge, agentFormula=agentFormula, agentCharge=agentCharge)
+ return processing.mz(self.mass(),
+ charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge
+ )
# ----
def pattern(self, fwhm=0.1, threshold=0.01, charge=0, agentFormula='H', agentCharge=1):
"""Get isotopic pattern."""
- return processing.pattern(self, \
- fwhm=fwhm, \
- threshold=threshold, \
- charge=charge, \
- agentFormula=agentFormula, \
- agentCharge=agentCharge \
+ return processing.pattern(self,
+ fwhm = fwhm,
+ threshold = threshold,
+ charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge
)
# ----
def isvalid(self, charge=0, agentFormula='H', agentCharge=1):
- """Utility to check ion composition."""
+ """Check ion composition."""
# check agent formula
if agentFormula != 'e' and not isinstance(agentFormula, compound):
@@ -226,12 +257,12 @@
# make ion compound
if charge and agentFormula != 'e':
- ionFormula = self.rawFormula
+ ionFormula = self.expression
for atom, count in agentFormula.composition().items():
ionFormula += '%s%d' % (atom, count*(charge/agentCharge))
ion = compound(ionFormula)
else:
- ion = compound(self.rawFormula)
+ ion = compound(self.expression)
# get composition
for atom, count in ion.composition().items():
@@ -242,8 +273,47 @@
# ----
+ # MODIFIERS
+
+ def negate(self):
+ """Make all atom counts negative."""
+
+ # get composition
+ comp = self.composition()
+
+ # negate composition
+ formula = ''
+ for el in sorted(comp.keys()):
+ formula += '%s%d' % (el, -1*comp[el])
+ self.expression = formula
+
+ # clear buffers
+ self.reset()
+ # ----
+
+
# HELPERS
+ def _checkFormula(self, formula):
+ """Check given formula."""
+
+ # check formula
+ if not formulaPattern.match(formula):
+ raise ValueError, 'Wrong formula! --> ' + formula
+
+ # check elements and isotopes
+ for atom in elementPattern.findall(formula):
+ if not atom[0] in blocks.elements:
+ raise ValueError, 'Unknown element in formula! --> ' + atom[0] + ' in ' + formula
+ elif atom[1] and not int(atom[1]) in blocks.elements[atom[0]].isotopes:
+ raise ValueError, 'Unknown isotope in formula! --> ' + atom[0] + atom[1] + ' in ' + formula
+
+ # check brackets
+ if formula.count(')') != formula.count('('):
+ raise ValueError, 'Wrong number of brackets in formula! --> ' + formula
+ # ----
+
+
def _unfoldBrackets(self, string):
"""Unfold formula and count each atom."""
@@ -286,6 +356,7 @@
brackets = [0,0]
i += 1
+
return unfoldedFormula
# ----
@@ -294,18 +365,41 @@
class sequence:
"""Sequence object definition."""
- def __init__(self, chain, title='', accession='', nTermFormula='H', cTermFormula='OH', lossFormula=''):
+ def __init__(self, chain, title='', accession='', chainType='aminoacids', cyclic=False):
- # get chain
- chain = chain.upper()
- for char in ('\t','\n','\r','\f','\v', ' ', '-', '*', '.'):
- chain = chain.replace(char, '')
- self.chain = chain.upper()
-
- self.nTermFormula = nTermFormula
- self.cTermFormula = cTermFormula
- self.modifications = [] # [[name, position=[#|symbol], state[f|v]], ] (f-fixed, v-variable)
- self.labels = [] # [[name, position=[#|symbol], state[f|v]], ] (f-fixed, v-variable)
+ self.chain = []
+ self.chainType = chainType
+ self.cyclic = cyclic
+
+ # get sequence chain
+ if type(chain) == list:
+ self.chain = chain
+
+ elif self.chainType == 'aminoacids':
+ for symbol in chain.upper():
+ if not symbol in ('\t','\n','\r','\f','\v', ' ', '-', '*', '.', ''):
+ self.chain.append(symbol)
+ else:
+ for symbol in chain.split('|'):
+ symbol = symbol.strip()
+ if not symbol in ('\t','\n','\r','\f','\v', ' ', '-', '*', '.', ''):
+ self.chain.append(symbol)
+
+ for monomer in self.chain:
+ if not monomer in blocks.monomers:
+ raise KeyError, 'Unknown monomer in the sequence! --> ' + monomer
+
+ # set terminal groups
+ if self.cyclic:
+ self.nTermFormula = ''
+ self.cTermFormula = ''
+ else:
+ self.nTermFormula = 'H'
+ self.cTermFormula = 'OH'
+
+ # [[name, position=[#|symbol], state=[f|v]], ] (f->fixed, v->variable)
+ self.modifications = []
+ self.labels = []
# for proteins
self.title = title
@@ -315,29 +409,31 @@
self.score = None
# for peptides
- self.userRange = []
- self.aaBefore = ''
- self.aaAfter = ''
+ self.history = [('init', 0, len(self.chain))]
+ self.itemBefore = ''
+ self.itemAfter = ''
self.miscleavages = 0
# for fragments
self.fragmentSerie = None
self.fragmentIndex = None
+ self.fragmentLosses = []
+ self.fragmentGains = []
self.fragmentFiltered = False
- self.lossFormula = lossFormula
# buffers
self._formula = None
self._composition = None
- self._mass = None # (monoisotopic, average)
+ self._mass = None
# user defined params
self.userParams = {}
-
- # check amino acids
- for amino in self.chain:
- if not amino in blocks.aminoacids:
- raise ValueError, 'Unknown amino acid in sequence! --> ' + amino
+ # ----
+
+
+ def __nonzero__(self):
+ """Check sequence length."""
+ return bool(len(self.chain))
# ----
@@ -356,50 +452,80 @@
"""Get slice of the sequence."""
# check slice
- if stop < start:
- raise ValueError, 'Invalid sequence slice definition!'
+ if stop < start and not self.cyclic:
+ raise ValueError, 'Invalid slice!'
# break the links
parent = copy.deepcopy(self)
# check slice
start = max(start, 0)
- stop = min(stop, len(parent.chain))
+ stop = min(stop, len(parent))
# make new sequence object
- seq = parent.chain[start:stop]
- peptide = sequence(seq)
+ if start < stop:
+ seq = parent.chain[start:stop]
+ peptide = sequence(seq, chainType=parent.chainType, cyclic=False)
+ elif self.cyclic:
+ seq = parent.chain[start:] + parent.chain[:stop]
+ peptide = sequence(seq, chainType=parent.chainType, cyclic=False)
+
+ # add previous history
+ peptide.history = parent.history
+
+ # add fragment losses and gains
+ peptide.fragmentLosses = parent.fragmentLosses
+ peptide.fragmentGains = parent.fragmentGains
# add modifications
for mod in parent.modifications:
- if type(mod[1]) == int and mod[1] >= start and mod[1] < stop:
- mod[1] -= start
- peptide.modifications.append(mod)
- elif type(mod[1]) in (str, unicode) and mod[1] in peptide.chain:
+ if type(mod[1]) in (str, unicode) and mod[1] in peptide.chain:
peptide.modifications.append(mod)
+ elif type(mod[1]) == int:
+ if start <= mod[1] < stop:
+ mod[1] -= start
+ peptide.modifications.append(mod)
+ elif start >= stop and mod[1] >= start:
+ mod[1] -= start
+ peptide.modifications.append(mod)
+ elif start >= stop and mod[1] < stop:
+ mod[1] += len(parent) - start
+ peptide.modifications.append(mod)
# add labels
for mod in parent.labels:
- if type(mod[1]) == int and mod[1] >= start and mod[1] < stop:
- mod[1] -= start
- peptide.labels.append(mod)
- elif type(mod[1]) in (str, unicode) and mod[1] in peptide.chain:
+ if type(mod[1]) in (str, unicode) and mod[1] in peptide.chain:
peptide.labels.append(mod)
-
- # set range in user coordinates
- peptide.userRange = [start+1, stop]
-
- # set adjacent amino acids
- if start > 0:
- peptide.aaBefore = parent.chain[start-1]
- if stop < len(parent.chain):
- peptide.aaAfter = parent.chain[stop]
+ elif type(mod[1]) == int:
+ if start <= mod[1] < stop:
+ mod[1] -= start
+ peptide.labels.append(mod)
+ elif start >= stop and mod[1] >= start:
+ mod[1] -= start
+ peptide.labels.append(mod)
+ elif start >= stop and mod[1] < stop:
+ mod[1] += len(parent) - start
+ peptide.labels.append(mod)
# add terminal modifications
if start == 0:
peptide.nTermFormula = parent.nTermFormula
- if stop >= len(parent.chain):
+ if stop >= len(parent):
peptide.cTermFormula = parent.cTermFormula
+ if parent.cyclic:
+ peptide.nTermFormula = 'H'
+ peptide.cTermFormula = 'OH'
+
+ # set adjacent monomers
+ if start > 0 or parent.cyclic:
+ peptide.itemBefore = parent.chain[start-1]
+ if stop < len(parent):
+ peptide.itemAfter = parent.chain[stop]
+ if stop == len(parent) and parent.cyclic:
+ peptide.itemAfter = parent.chain[0]
+
+ # add to history
+ peptide.history.append(('slice', start, stop))
# ensure buffers are cleaned
peptide.reset()
@@ -419,6 +545,10 @@
if not isinstance(value, sequence):
raise TypeError, 'Invalid object to instert!'
+ # check chain type
+ if value.chainType != self.chainType:
+ raise TypeError, 'Invalid chain type to instert!'
+
# break the links
value = copy.deepcopy(value)
@@ -452,9 +582,9 @@
self.labels.append(mod)
# clear some values
- self.userRange = []
- self.aaBefore = ''
- self.aaAfter = ''
+ self.history = [('init', 0, len(self.chain))]
+ self.itemBefore = ''
+ self.itemAfter = ''
self.miscleavages = 0
# clear buffers
@@ -495,9 +625,9 @@
self.labels = keep
# clear some values
- self.userRange = []
- self.aaBefore = ''
- self.aaAfter = ''
+ self.history = [('init', 0, len(self.chain))]
+ self.itemBefore = ''
+ self.itemAfter = ''
self.miscleavages = 0
# clear buffers
@@ -505,27 +635,39 @@
#----
- def __add__(self, value):
+ def __add__(self, other):
"""Join sequences and return result (essential for sequence editor)."""
# check value
- if not isinstance(value, sequence):
- raise TypeError, 'Invalid object to join with sequence!'
+ if not isinstance(other, sequence):
+ raise TypeError, 'Invalid object to join with!'
+
+ # check chain type
+ if value.chainType != self.chainType:
+ raise TypeError, 'Invalid chain type to join with!'
+
+ # check cyclic peptides
+ if self.cyclic or other.cyclic:
+ raise TypeError, 'Cannot join cyclic peptides!'
+
+ # break the links
+ other = copy.deepcopy(other)
# join sequences
result = self[:]
- result[len(result):] = value
+ result[len(result):] = other
# set C terminus
- result.cTermFormula = value.cTermFormula
+ result.cTermFormula = other.cTermFormula
- # set neutral loss
- result.lossFormula = value.lossFormula
+ # set neutral loss and gain
+ result.fragmentLosses = other.fragmentLosses
+ result.fragmentGains = other.fragmentGains
# clear some values
- result.userRange = []
- result.aaBefore = ''
- result.aaAfter = ''
+ result.history = [('init', 0, len(self.chain))]
+ result.itemBefore = ''
+ result.itemAfter = ''
result.miscleavages = 0
# clear buffers
@@ -563,7 +705,11 @@
def duplicate(self):
"""Return copy of current sequence."""
- return copy.deepcopy(self)
+
+ dupl = copy.deepcopy(self)
+ dupl.reset()
+
+ return dupl
# ----
@@ -596,7 +742,7 @@
def composition(self):
- """Get elemental composition as dict."""
+ """Get elemental composition."""
# check composition buffer
if self._composition != None:
@@ -604,9 +750,9 @@
self._composition = {}
- # add amino acids to formula
- for amino in self.chain:
- for el, count in blocks.aminoacids[amino].composition.items():
+ # add monomers to formula
+ for monomer in self.chain:
+ for el, count in blocks.monomers[monomer].composition.items():
if el in self._composition:
self._composition[el] += count
else:
@@ -625,20 +771,31 @@
self._composition[el] = multi*count
# add terminal modifications
- termCmpd = compound(self.nTermFormula + self.cTermFormula)
- for el, count in termCmpd.composition().items():
- if el in self._composition:
- self._composition[el] += count
- else:
- self._composition[el] = count
+ if not self.cyclic:
+ termCmpd = compound(self.nTermFormula + self.cTermFormula)
+ for el, count in termCmpd.composition().items():
+ if el in self._composition:
+ self._composition[el] += count
+ else:
+ self._composition[el] = count
- # subtract neutral loss for fragments
- lossCmpd = compound(self.lossFormula)
- for el, count in lossCmpd.composition().items():
- if el in self._composition:
- self._composition[el] -= count
- else:
- self._composition[el] = -1*count
+ # subtract neutral losses for fragments
+ for loss in self.fragmentLosses:
+ lossCmpd = compound(loss)
+ for el, count in lossCmpd.composition().items():
+ if el in self._composition:
+ self._composition[el] -= count
+ else:
+ self._composition[el] = -1*count
+
+ # add neutral gains for fragments
+ for gain in self.fragmentGains:
+ gainCmpd = compound(gain)
+ for el, count in gainCmpd.composition().items():
+ if el in self._composition:
+ self._composition[el] += count
+ else:
+ self._composition[el] = count
# remove zeros
for atom in self._composition.keys():
@@ -649,37 +806,43 @@
# ----
- def mass(self):
+ def mass(self, massType=None):
"""Get mass."""
- # check mass buffer
- if self._mass != None:
- return self._mass
-
# get mass
- self._mass = compound(self.formula()).mass()
+ if self._mass == None:
+ self._mass = compound(self.formula()).mass()
- return self._mass
+ # return mass
+ if massType == 0:
+ return self._mass[0]
+ elif massType == 1:
+ return self._mass[1]
+ else:
+ return self._mass
# ----
def mz(self, charge, agentFormula='H', agentCharge=1):
"""Get ion m/z"""
- # get current mass and calculate mz
- return processing.mz(self.mass(), charge, agentFormula=agentFormula, agentCharge=agentCharge)
+ return processing.mz(self.mass(),
+ charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge
+ )
# ----
def pattern(self, fwhm=0.1, threshold=0.01, charge=0, agentFormula='H', agentCharge=1):
"""Get isotopic pattern."""
- return processing.pattern(self, \
- fwhm=fwhm, \
- threshold=threshold, \
- charge=charge, \
- agentFormula=agentFormula, \
- agentCharge=agentCharge \
+ return processing.pattern(self,
+ fwhm = fwhm,
+ threshold = threshold,
+ charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge
)
# ----
@@ -687,28 +850,53 @@
def format(self, template='S [m]'):
"""Get formated sequence."""
- # make keys
keys = {}
- keys['s'] = self.chain.lower()
- keys['S'] = self.chain
+
+ # make sequence keys
+ if self.chainType == 'aminoacids':
+ keys['S'] = ''.join(self.chain)
+ keys['s'] = ''.join(self.chain).lower()
+ keys['B'] = self.itemBefore
+ keys['A'] = self.itemAfter
+ keys['b'] = self.itemBefore.lower()
+ keys['a'] = self.itemAfter.lower()
+ else:
+ keys['S'] = ' | '.join(self.chain)
+ keys['s'] = '|'.join(self.chain)
+ keys['b'] = self.itemBefore
+ keys['a'] = self.itemAfter
+ keys['B'] = self.itemBefore
+ keys['A'] = self.itemAfter
+
+ # make terminal formula keys
keys['N'] = self.nTermFormula
keys['C'] = self.cTermFormula
- keys['b'] = self.aaBefore.lower()
- keys['B'] = self.aaBefore
- keys['a'] = self.aaAfter.lower()
- keys['A'] = self.aaAfter
+
+ # make modification keys
keys['m'] = self._formatModifications(self.modifications)
keys['M'] = self._formatModifications(self.modifications + self.labels)
keys['l'] = self._formatModifications(self.labels)
keys['p'] = self.miscleavages
- if self.userRange:
- keys['r'] = '%s-%s' % tuple(self.userRange)
-
- if self.fragmentSerie != None and self.fragmentIndex != None:
- keys['f'] = '%s %s' % (self.fragmentSerie, self.fragmentIndex)
- elif self.fragmentSerie != None:
- keys['f'] = self.fragmentSerie
+ # make history key
+ keys['h'] = ''
+ if 'h' in template:
+ for item in self.history[1:]:
+ if item[0] == 'slice':
+ keys['h'] += '[%s-%s]' % (item[1]+1, item[2])
+ elif item[0] == 'break':
+ keys['h'] += '[%s|%s]' % (item[1]+1, item[2]+1)
+
+ # make fragment name key
+ keys['f'] = ''
+ if 'f' in template and self.fragmentSerie:
+ keys['f'] = self.fragmentSerie
+ if self.fragmentIndex != None:
+ keys['f'] += str(self.fragmentIndex)
+ for gain in self.fragmentGains:
+ keys['f'] += ' +'+gain
+ for loss in self.fragmentLosses:
+ keys['f'] += ' -'+loss
# format
buff = ''
@@ -727,37 +915,7 @@
# ----
- def digest(self, enzyme, miscleavage=0, allowMods=False, strict=True):
- """Digest seuence by specified enzyme.
- enzyme: (str) enzyme name - must be defined in mspy.enzymes
- miscleavage: (int) number of allowed misscleavages
- allowMods: (bool) do not care about modifications in cleavage site
- strict: (bool) do not cleave even if variable modification is in cleavage site
- """
-
- return processing.digest(self,
- enzyme=enzyme, \
- miscleavage=miscleavage, \
- allowMods=allowMods, \
- strict=strict
- )
- # ----
-
-
- def fragment(self, serie, index=None):
- """Generate list of neutral peptide fragments from given peptide.
- serie: (str) fragment serie name - must be defined in mspy.fragments
- index: (int) fragment index
- """
-
- return processing.fragment(self, \
- serie=serie, \
- index=index \
- )
- # ----
-
-
- def search(self, mass, charge, tolerance, enzyme=None, semiSpecific=True, tolUnits='Da', massType='mo', maxMods=1, position=False):
+ def search(self, mass, charge, tolerance, enzyme=None, semiSpecific=True, tolUnits='Da', massType=0, maxMods=1, position=False):
"""Search sequence for specified ion.
mass: (float) m/z value to search for
charge: (int) charge of the m/z value
@@ -765,18 +923,16 @@
tolUnits: ('Da', 'ppm') tolerance units
enzyme: (str) enzyme used for peptides endings, if None H/OH is used
semiSpecific: (bool) semispecific cleavage is checked (enzyme must be set)
- massType: ('mo' or 'av') mass type of the mass value
+ massType: (0 or 1) mass type of the mass value, 0 = monoisotopic, 1 = average
maxMods: (int) maximum number of modifications at one residue
position: (bool) retain position for variable modifications (much slower)
"""
- matches = []
+ # check cyclic peptides
+ if self.cyclic:
+ raise TypeError, 'Search function is not supported for cyclic peptides!'
- # set mass type
- if massType == 'mo':
- massType = 0
- elif massType == 'av':
- massType = 1
+ matches = []
# set terminal modifications
if enzyme:
@@ -812,8 +968,8 @@
peptide.cTerminalFormula = cTerm
# check enzyme specifity
- if semiSpecific and peptide.aaBefore and peptide.aaAfter:
- if not expression.search(peptide.aaBefore+peptide.chain[0]) and not expression.search(peptide.chain[-1]+peptide.aaAfter):
+ if semiSpecific and peptide.itemBefore and peptide.itemAfter:
+ if not expression.search(peptide.itemBefore+peptide.chain[0]) and not expression.search(peptide.chain[-1]+peptide.itemAfter):
continue
# variate modifications
@@ -861,8 +1017,8 @@
if not position:
variableMods += [mod] * self.chain.count(mod[1])
else:
- for x, amino in enumerate(self.chain):
- if amino == mod[1]:
+ for x, symbol in enumerate(self.chain):
+ if symbol == mod[1]:
variableMods.append([mod[0], x, 'v'])
# make combinations of variable modifications
@@ -880,9 +1036,9 @@
# disable modifications at cleavage sites
if enzyme:
enz = blocks.enzymes[enzyme]
- if not enz.modsBefore and self.aaAfter:
- occupied += [len(self.chain)-1]*maxMods
- if not enz.modsAfter and self.aaBefore:
+ if not enz.modsBefore and self.itemAfter:
+ occupied += [len(self)-1]*maxMods
+ if not enz.modsAfter and self.itemBefore:
occupied += [0]*maxMods
CHECK_FORCE_QUIT()
@@ -918,10 +1074,10 @@
CHECK_FORCE_QUIT()
- variablePeptide = copy.deepcopy(self)
+ variablePeptide = self.duplicate()
variablePeptide.modifications[:] = fixedMods+combination
- variablePeptide.reset()
+ # check composition
if variablePeptide.isvalid():
variablePeptides.append(variablePeptide)
@@ -929,6 +1085,53 @@
# ----
+ def linearized(self, breakPoint=None):
+ """Return list of all linearized sequences resulted from cyclic parent."""
+
+ # ensure sequence is cyclic
+ cyclic = self.cyclic
+ self.cyclic = True
+
+ # set break points
+ breakPoints = range(len(self))
+ if breakPoint != None:
+ breakPoints = [breakPoint]
+
+ # make peptides for all break points
+ peptides = []
+ for x in breakPoints:
+ peptide = self[x:x]
+ del peptide.history[-1]
+ if x != 0:
+ peptide.history.append(('break', x-1, x))
+ else:
+ peptide.history.append(('break', len(self)-1, x))
+ peptides.append(peptide)
+
+ # revert to original cyclization
+ self.cyclic = cyclic
+
+ if breakPoint:
+ return peptides[0]
+ else:
+ return peptides
+ # ----
+
+
+ def indexes(self):
+ """Calculate parent indexes from sequence history."""
+
+ ranges = range(self.history[0][1], self.history[0][2])
+ for item in self.history[1:]:
+ if item[0] == 'slice':
+ ranges = ranges[item[1] : item[2]]
+ elif item[0] == 'break':
+ ranges = ranges[item[2]:]+ranges[:item[1]+1]
+
+ return ranges
+ # ----
+
+
def ismodified(self, position=None, strict=False):
"""Check if selected amino acid or whole sequence has any modification.
position: (int) amino acid index
@@ -955,8 +1158,14 @@
def isvalid(self, charge=0, agentFormula='H', agentCharge=1):
"""Utility to check ion composition."""
+ # make compound
formula = compound(self.formula())
- return formula.isvalid(charge=charge, agentFormula=agentFormula, agentCharge=agentCharge)
+
+ # check ion composition
+ return formula.isvalid(charge = charge,
+ agentFormula = agentFormula,
+ agentCharge = agentCharge
+ )
# ----
@@ -972,7 +1181,9 @@
# check position
try: position = int(position)
except: position = str(position)
- if type(position) == str and self.chain.count(position) == 0:
+ if type(position) == str and not position in self.chain:
+ return False
+ elif type(position) == int and (position < 0 or position >= len(self)):
return False
# add modification
@@ -997,8 +1208,7 @@
try: mod = [name, int(position), str(state)]
except: mod = [name, str(position), str(state)]
while mod in self.modifications:
- i = self.modifications.index(mod)
- del self.modifications[i]
+ del self.modifications[self.modifications.index(mod)]
# clear buffers
self.reset()
@@ -1015,7 +1225,9 @@
# check position
try: position = int(position)
except: position = str(position)
- if type(position) == str and self.chain.count(position) == 0:
+ if type(position) == str and not position in self.chain:
+ return False
+ elif type(position) == int and (position < 0 or position >= len(self)):
return False
# add label
@@ -1028,6 +1240,24 @@
# ----
+ def cyclize(self, cyclic=True):
+ """Make current sequence cyclic/linear."""
+
+ # make sequence cyclic
+ if cyclic:
+ self.cyclic = True
+ self.nTermFormula = ''
+ self.cTermFormula = ''
+ else:
+ self.cyclic = False
+ self.nTermFormula = 'H'
+ self.cTermFormula = 'OH'
+
+ # clear buffers
+ self.reset()
+ # ----
+
+
# HELPERS
def _formatModifications(self, modifications):
@@ -1130,8 +1360,8 @@
self.childScanNumber = None
# set intensity
+ self.ri = 1.
self.intensity = self.ai - self.base
- self.relIntensity = 1.
# set resolution
self.resolution = None
@@ -1139,7 +1369,7 @@
self.resolution = self.mz/self.fwhm
# set buffers
- self._mass = None # neutral mass
+ self._mass = None
# user defined params
self.userParams = {}
@@ -1174,7 +1404,7 @@
# check mass buffer
if self._mass != None:
return self._mass
-
+
# calculate neutral mass
self._mass = processing.mz(self.mz, 0, self.charge, agentFormula='H', agentCharge=1)
@@ -1313,7 +1543,7 @@
# lower than basepeak
elif self.basepeak:
- item.relIntensity = item.intensity / self.basepeak.intensity
+ item.ri = item.intensity / self.basepeak.intensity
self.peaks[i] = item
# no basepeak set
@@ -1352,11 +1582,11 @@
# ----
- def __add__(self, peaksB):
+ def __add__(self, other):
"""Return A+B."""
new = self.duplicate()
- new.concatenate(peaksB)
+ new.concatenate(other)
return new
# ----
@@ -1371,6 +1601,7 @@
def next(self):
+
if self._index < len(self.peaks):
self._index += 1
return self.peaks[self._index-1]
@@ -1401,11 +1632,11 @@
# lower than basepeak
elif self.basepeak and self.basepeak.intensity != 0:
- item.relIntensity = item.intensity / self.basepeak.intensity
+ item.ri = item.intensity / self.basepeak.intensity
# no basepeak set
else:
- item.relIntensity = 1.
+ item.ri = 1.
self._setBasepeak()
# ----
@@ -1536,14 +1767,12 @@
# ----
- def concatenate(self, peaksB):
- """Add data from given peaklist.
- peaksB: (peaklist or list of peaks) peaklist to be added
- """
+ def concatenate(self, other):
+ """Add data from given peaklist."""
# check peaks
buff = []
- for peak in copy.deepcopy(peaksB):
+ for peak in copy.deepcopy(other):
peak = self._checkPeak(peak)
buff.append(peak)
@@ -1587,18 +1816,18 @@
# find isotops
processing.findIsotopes(
- peaklist=self, \
- maxCharge=maxCharge, \
- mzTolerance=mzTolerance, \
- intTolerance=intTolerance, \
- isotopeShift=isotopeShift \
+ peaklist = self,
+ maxCharge = maxCharge,
+ mzTolerance = mzTolerance,
+ intTolerance = intTolerance,
+ isotopeShift = isotopeShift
)
# ----
- def deconvolute(self, massType='mo'):
+ def deconvolute(self, massType=0):
"""Recalculate peaklist to singly charged.
- massType: ('mo' or 'av') mass type used for m/z re-calculation
+ massType: (0 or 1) mass type used for m/z re-calculation, 0 = monoisotopic, 1 = average
"""
# check peaklist
@@ -1607,8 +1836,8 @@
# deconvolute peaklist
peaks = processing.deconvolute(
- peaklist=self, \
- massType=massType \
+ peaklist = self,
+ massType = massType
)
# store data
@@ -1795,7 +2024,7 @@
return item
# make peak from list or tuple
- elif type(item) in (list, tuple) and len(item)==2:
+ elif type(item) in (list, tuple) or len(item)==2:
return peak(item[0], item[1])
# not valid peak data
@@ -1832,10 +2061,10 @@
maxInt = self.basepeak.intensity
if maxInt:
for item in self.peaks:
- item.relIntensity = item.intensity / maxInt
+ item.ri = item.intensity / maxInt
else:
for item in self.peaks:
- item.relIntensity = 1.
+ item.ri = 1.
# ----
@@ -1881,10 +2110,9 @@
self.points = numpy.array(points)
# convert peaks to peaklist
- if isinstance(peaks, peaklist):
- self.peaklist = peaks
- else:
- self.peaklist = peaklist(peaks)
+ if not isinstance(peaks, peaklist):
+ peaks = peaklist(peaks)
+ self.peaklist = peaks
# ----
@@ -1893,20 +2121,20 @@
# ----
- def __add__(self, scanB):
+ def __add__(self, other):
"""Return A+B."""
new = self.duplicate()
- new.concatenate(peaksB)
+ new.concatenate(other)
return new
# ----
- def __sub__(self, scanB):
+ def __sub__(self, other):
"""Return A-B."""
new = self.duplicate()
- new.subtract(peaksB)
+ new.subtract(other)
return new
# ----
@@ -1945,7 +2173,12 @@
"""
# calculate noise
- return processing.noise(self.points, minX=minX, maxX=maxX, mz=mz, window=window)
+ return processing.noise(self.points,
+ minX = minX,
+ maxX = maxX,
+ mz = mz,
+ window = window
+ )
# ----
@@ -2011,11 +2244,11 @@
# check slice
if maxX < minX:
- raise ValueError, 'Invalid m/z slice definition!'
+ raise ValueError, 'Invalid slice!'
# crop points
- i1 = self._getIndex(self.points, minX)
- i2 = self._getIndex(self.points, maxX)
+ i1 = processing.findIndex(self.points, minX, dim=2)
+ i2 = processing.findIndex(self.points, maxX, dim=2)
return self.points[i1:i2]
# ----
@@ -2064,7 +2297,7 @@
def setPeaklist(self, peaks):
- """Set new point."""
+ """Set new peaklist."""
# convert peaks to peaklist
if isinstance(peaks, peaklist):
@@ -2103,8 +2336,8 @@
"""
# crop spectrum data
- i1 = self._getIndex(self.points, minX)
- i2 = self._getIndex(self.points, maxX)
+ i1 = processing.findIndex(self.points, minX, dim=2)
+ i2 = processing.findIndex(self.points, maxX, dim=2)
self.points = self.points[i1:i2]
# crop peaklist data
@@ -2155,20 +2388,18 @@
# ----
- def concatenate(self, scanB):
- """Add data from given scan.
- scanB: (scan) scan to be added
- """
+ def concatenate(self, other):
+ """Add data from given scan."""
# check scan
- if not isinstance(scanB, scan):
+ if not isinstance(other, scan):
raise TypeError, "Cannot concatenate with non-scan object!"
# use spectra only
- if len(self.points) or len(scanB.points):
+ if len(self.points) or len(other.points):
# unify raster
- data = processing.unifyRaster(self.points, scanB.points)
+ data = processing.unifyRaster(self.points, other.points)
# convert back to arrays
pointsA = numpy.array(data[0])
@@ -2184,26 +2415,26 @@
self.peaklist.empty()
# use peaklists only
- elif len(self.peaklist) or len(scanB.peaklist):
- self.peaklist.concatenate(scanB.peaklist)
+ elif len(self.peaklist) or len(other.peaklist):
+ self.peaklist.concatenate(other.peaklist)
# clear buffers
self.reset()
# ----
- def subtract(self, scanB):
+ def subtract(self, other):
"""Subtract given data points from current scan."""
# check scan
- if not isinstance(scanB, scan):
+ if not isinstance(other, scan):
raise TypeError, "Cannot subtract non-scan object!"
# use spectra only
- if len(self.points) and len(scanB.points):
+ if len(self.points) and len(other.points):
# unify raster
- data = processing.unifyRaster(self.points, scanB.points)
+ data = processing.unifyRaster(self.points, other.points)
# convert back to arrays
pointsA = numpy.array(data[0])
@@ -2225,7 +2456,7 @@
def smooth(self, method, window, cycles=1):
"""Smooth data points.
- method: ('MA' or 'SG') smoothing method, MA - moving average, SG - Savitzky-Golay
+ method: ('MA', 'GA' or 'SG') smoothing method, MA - moving average, GA - Gaussian, SG - Savitzky-Golay
window: (float) m/z window size for smoothing
cycles: (int) number of repeating cycles
"""
@@ -2234,13 +2465,17 @@
if method.upper() == 'MA':
points = processing.smoothMA(self.points, window, cycles)
+ # apply Gaussian filter
+ elif method.upper() == 'GA':
+ points = processing.smoothGA(self.points, window, cycles)
+
# apply Savitzky-Golay filter
elif method.upper() == 'SG':
points = processing.smoothSG(self.points, window, cycles)
# unknown method
else:
- raise KeyError, "Unknown smoothing method"
+ raise KeyError, "Unknown smoothing method! --> " + method
# store data
self.points = points
@@ -2277,11 +2512,11 @@
"""
# correct baseline
- points = processing.correctBaseline(\
- points=self.points, \
- window=window, \
- smooth=smooth, \
- offset=offset \
+ points = processing.correctBaseline(
+ points = self.points,
+ window = window,
+ smooth = smooth,
+ offset = offset
)
# store data
@@ -2302,23 +2537,24 @@
baselineWindow: (float) noise calculation window in %/100
baselineSmooth: (bool) smooth baseline
baselineOffset: (float) baseline intensity offset in %/100
- smoothMethod: (None or MA or SG) smoothing method, MA - moving average, SG - Savitzky-Golay
+ smoothMethod: (None, MA, GA or SG) smoothing method, MA - moving average, GA - Gaussian, SG - Savitzky-Golay
smoothWindows: (float) m/z window size for smoothing
smoothCycles: (int) number of repeating cycles
"""
# label scan
- newPeaklist = processing.labelScan(self.points, \
- pickingHeight=pickingHeight, \
- absThreshold=absThreshold, \
- relThreshold=relThreshold, \
- snThreshold=snThreshold, \
- baselineWindow=baselineWindow, \
- baselineSmooth=baselineSmooth, \
- baselineOffset=baselineOffset, \
- smoothMethod=smoothMethod, \
- smoothWindow=smoothWindow, \
- smoothCycles=smoothCycles
+ newPeaklist = processing.labelScan(
+ points = self.points,
+ pickingHeight = pickingHeight,
+ absThreshold = absThreshold,
+ relThreshold = relThreshold,
+ snThreshold = snThreshold,
+ baselineWindow = baselineWindow,
+ baselineSmooth = baselineSmooth,
+ baselineOffset = baselineOffset,
+ smoothMethod = smoothMethod,
+ smoothWindow = smoothWindow,
+ smoothCycles = smoothCycles
)
# update peaklist
@@ -2343,15 +2579,16 @@
"""
# label peak
- newPeak = processing.labelPeak(self.points, \
- mz=mz, \
- minX=minX, \
- maxX=maxX, \
- pickingHeight=pickingHeight, \
- baselineWindow=baselineWindow, \
- baselineSmooth=baselineSmooth, \
- baselineOffset=baselineOffset, \
- baselineData=baselineData \
+ newPeak = processing.labelPeak(
+ points = self.points,
+ mz = mz,
+ minX = minX,
+ maxX = maxX,
+ pickingHeight = pickingHeight,
+ baselineWindow = baselineWindow,
+ baselineSmooth = baselineSmooth,
+ baselineOffset = baselineOffset,
+ baselineData = baselineData
)
# append peak
@@ -2373,12 +2610,13 @@
"""
# label point
- newPeak = processing.labelPoint(self.points, \
- mz=mz, \
- baselineWindow=baselineWindow, \
- baselineSmooth=baselineSmooth, \
- baselineOffset=baselineOffset, \
- baselineData=baselineData \
+ newPeak = processing.labelPoint(
+ points = self.points,
+ mz = mz,
+ baselineWindow = baselineWindow,
+ baselineSmooth = baselineSmooth,
+ baselineOffset = baselineOffset,
+ baselineData = baselineData
)
# append peak
@@ -2400,17 +2638,17 @@
# find istopes
self.peaklist.findIsotopes(
- maxCharge=maxCharge, \
- mzTolerance=mzTolerance, \
- intTolerance=intTolerance, \
- isotopeShift=isotopeShift \
+ maxCharge = maxCharge,
+ mzTolerance = mzTolerance,
+ intTolerance = intTolerance,
+ isotopeShift = isotopeShift
)
# ----
- def deconvolute(self, massType='mo'):
+ def deconvolute(self, massType=0):
"""Recalculate peaklist to singly charged.
- massType: ('mo' or 'av') mass type used for m/z re-calculation
+ massType: (0 or 1) mass type used for m/z re-calculation, 0 = monoisotopic, 1 = average
"""
# delete spectrum points
@@ -2430,10 +2668,9 @@
forceWindow: (bool) use default window for all peaks instead of fwhm
"""
- # group near peaks
self.peaklist.groupPeaks(
- window=window, \
- forceWindow=forceWindow \
+ window = window,
+ forceWindow = forceWindow
)
# ----
@@ -2445,12 +2682,11 @@
snThreshold: (float) signal to noise threshold
"""
- # remove peaks below threshold
- self.peaklist.removeBelow( \
- absThreshold=absThreshold, \
- relThreshold=relThreshold, \
- snThreshold=snThreshold \
- )
+ self.peaklist.removeBelow(
+ absThreshold = absThreshold,
+ relThreshold = relThreshold,
+ snThreshold = snThreshold
+ )
# ----
@@ -2461,68 +2697,24 @@
fwhm: (float) default peak width if not set in peak
"""
- # remove shoulder peaks
- self.peaklist.removeShoulders(\
- window=window, \
- relThreshold=relThreshold, \
- fwhm=fwhm \
- )
+ self.peaklist.removeShoulders(
+ window = window,
+ relThreshold = relThreshold,
+ fwhm = fwhm
+ )
# ----
def removeIsotopes(self):
"""Remove isotopes from current peaklist."""
-
- # remove isotopes
self.peaklist.removeIsotopes()
# ----
def removeUnknown(self):
"""Remove unknown peaks (no charge set) from current peaklist."""
-
- # remove unknowns
self.peaklist.removeUnknown()
# ----
- # HELPERS
-
- def _getIndex(self, points, x):
- """Get nearest higher index for selected point."""
-
- lo = 0
- hi = len(points)
- while lo < hi:
- mid = (lo + hi) / 2
- if x < points[mid][0]:
- hi = mid
- else:
- lo = mid + 1
-
- return lo
- # ----
-
-
- def _interpolateLine(self, p1, p2, x=None, y=None):
- """Get line interpolated X or Y value."""
-
- # check points
- if p1[0] == p2[0] and x!=None:
- return max(p1[1], p2[1])
- elif p1[0] == p2[0] and y!=None:
- return p1[0]
-
- # get equation
- m = (p2[1] - p1[1])/(p2[0] - p1[0])
- b = p1[1] - m * p1[0]
-
- # get point
- if x != None:
- return m * x + b
- elif y != None:
- return (y - b) / m
- # ----
-
-
diff -Nru mmass-3.12.1/mspy/plot/canvas.py mmass-4.0.0/mspy/plot/canvas.py
--- mmass-3.12.1/mspy/plot/canvas.py 2011-06-23 12:16:48.000000000 +0000
+++ mmass-4.0.0/mspy/plot/canvas.py 2011-11-28 15:25:57.000000000 +0000
@@ -69,6 +69,7 @@
'yScaleFactor': 0.1,
'maxZoom': 0.001,
'checkLimits': True,
+ 'reverseScrolling': False,
'reverseDrawing': False,
'canvasColour': (255, 255, 255),
'plotColour': (255, 255, 255),
@@ -162,7 +163,10 @@
minX = rangeXmin
if maxX > rangeXmax:
maxX = rangeXmax
-
+ if minX > maxX:
+ minX = rangeXmin
+ maxX = rangeXmax
+
# draw plot
self.draw(self.lastDraw[0], (minX, maxX), (minY, maxY))
else:
@@ -549,13 +553,15 @@
direction = 1
if evt.GetWheelRotation() < 0:
direction = -1
+ if self.properties['reverseScrolling']:
+ direction *= -1
# set new charge and count for isotope ruler
if self.mouseFce == 'isotoperuler' and evt.ShiftDown():
if evt.AltDown() or evt.ControlDown():
- self.currentIsotopeLines = min(50, self.currentIsotopeLines + 1*direction)
+ self.currentIsotopeLines = min(50, self.currentIsotopeLines + direction)
else:
- self.currentCharge = max(1, self.currentCharge + 1*direction)
+ self.currentCharge = max(1, self.currentCharge + direction)
self.currentCharge = min(50, self.currentCharge)
self.drawMouseTracker()
return
@@ -1466,7 +1472,7 @@
xFormat = '%0.'+`self.properties['xPosDigits']`+'f'
yFormat = '%0.'+`self.properties['yPosDigits']`+'f'
xText = xFormat % (self.cursorPosition[0])
- if self.cursorPosition[1] > 10000:
+ if abs(self.cursorPosition[1]) > 10000:
yFormat = '%.2e'
yText = yFormat % (self.cursorPosition[1])
diff -Nru mmass-3.12.1/mspy/plot/objects.py mmass-4.0.0/mspy/plot/objects.py
--- mmass-3.12.1/mspy/plot/objects.py 2011-07-12 12:33:08.000000000 +0000
+++ mmass-4.0.0/mspy/plot/objects.py 2011-08-23 07:55:59.000000000 +0000
@@ -871,7 +871,7 @@
# draw points
if self.properties['showPoints']:
pencolour = [max(x-70,0) for x in self.properties['pointColour']]
- pen = wx.Pen(pencolour, 1*printerScale['drawings'], wx.SOLID)
+ pen = wx.Pen(pencolour, self.properties['lineWidth']*printerScale['drawings'], wx.SOLID)
brush = wx.Brush(self.properties['pointColour'], wx.SOLID)
dc.SetPen(pen)
dc.SetBrush(brush)
@@ -1725,7 +1725,7 @@
def _getIndex(points, x):
- """Get nearest index for selected point."""
+ """Get nearest lower index for selected point."""
lo = 0
hi = len(points)
diff -Nru mmass-3.12.1/mspy/plot/viewer.py mmass-4.0.0/mspy/plot/viewer.py
--- mmass-3.12.1/mspy/plot/viewer.py 2011-07-04 07:19:16.000000000 +0000
+++ mmass-4.0.0/mspy/plot/viewer.py 2011-11-29 14:56:46.000000000 +0000
@@ -57,14 +57,15 @@
]
# init plot canvas
- self.plotCanvas = canvas.canvas(self, size=(700,400), \
- xLabel='m/z', \
- yLabel='a.i.', \
- showPosBar=True, \
- showIntBar=True, \
- posBarHeight=6, \
- intBarHeight=6, \
- xPosDigits=4, \
+ self.plotCanvas = canvas.canvas(self,
+ size = (700,400),
+ xLabel = 'm/z',
+ yLabel = 'a.i.',
+ showPosBar = True,
+ showIntBar = True,
+ posBarHeight = 6,
+ intBarHeight = 6,
+ xPosDigits = 4
)
self.plotCanvas.setProperties(**attr)
self.plotCanvas.setMFunction('cross')
@@ -75,7 +76,11 @@
# append data sets
for x, item in enumerate(data):
- if isinstance(item, mspy.scan):
+ if isinstance(item, mspy.plot.points):
+ obj = item
+ elif isinstance(item, mspy.plot.spectrum):
+ obj = item
+ elif isinstance(item, mspy.scan):
obj = objects.spectrum(item)
else:
obj = objects.points(item)
diff -Nru mmass-3.12.1/mspy/processing.py mmass-4.0.0/mspy/processing.py
--- mmass-3.12.1/mspy/processing.py 2011-08-28 19:11:39.000000000 +0000
+++ mmass-4.0.0/mspy/processing.py 2011-11-30 12:58:29.000000000 +0000
@@ -16,17 +16,14 @@
# -------------------------------------------------------------------------
# load libs
-import re
-import os.path
import copy
import numpy
-import math
from numpy.linalg import solve as solveLinEq
# load stopper
from stopper import CHECK_FORCE_QUIT
-# register essential objects
+# register essential objects and modules
import objects
import blocks
@@ -61,24 +58,16 @@
# ----
-def mz(mass, charge, currentCharge=0, agentFormula='H', agentCharge=1, massType='mo'):
+def mz(mass, charge, currentCharge=0, agentFormula='H', agentCharge=1, massType=0):
"""Calculate m/z value for given mass and charge.
mass: (tuple of (Mo,Av) or float)
charge: (int) desired charge of ion
currentCharge: (int) if mass is charged already
agentFormula: (str or formula) charging agent formula
agentCharge: (int) charging agent charge
- massType: ('mo' or 'av') used mass type if mass value is float
+ massType: (0 or 1) used mass type if mass value is float, 0 = monoisotopic, 1 = average
"""
- # set mass type
- if massType == 'mo':
- massType = 0
- elif massType == 'av':
- massType = 1
- else:
- raise ValueError, "Mass type must be 'mo' or 'av' --> " + massType
-
# check agent formula
if agentFormula != 'e' and not isinstance(agentFormula, objects.compound):
agentFormula = objects.compound(agentFormula)
@@ -113,33 +102,6 @@
# ----
-def coverage(ranges, length, trueIndexes=False):
- """Calculate sequence coverage.
- ranges: (list of mspy.sequence or list of user ranges (start,stop))
- length: (int) parent sequence length
- """
-
- # check data
- if not ranges:
- return 0.
-
- # make a blank sequence
- blank = length*[0]
-
- # list of ranges
- for r in ranges:
- if trueIndexes:
- for x in range(r[0], r[1]):
- blank[x]=(1)
- else:
- for x in range(r[0]-1, r[1]):
- blank[x]=(1)
-
- # get sequence coverage
- return 100.0*blank.count(1)/length
-# ----
-
-
# ISOTOPIC PATTERN
# ----------------
@@ -297,11 +259,10 @@
peakWidth = fwhm/1.66
# calulate peak
- x = _getIndex1D(raster, (peak.mz-5*peakFwhm))
- i2 = _getIndex1D(raster, (peak.mz+5*peakFwhm))
- while x < i2:
- intensities[x] += peak.intensity*numpy.exp(-1*(pow(raster[x]-peak.mz,2))/pow(peakWidth,2))
- x += 1
+ i1 = findIndex(raster, (peak.mz-5*peakFwhm), dim=1)
+ i2 = findIndex(raster, (peak.mz+5*peakFwhm), dim=1)
+ for i in xrange(i1, i2):
+ intensities[i] += peak.intensity*numpy.exp(-1*(pow(raster[i]-peak.mz,2))/pow(peakWidth,2))
# add random noise
if noise:
@@ -353,36 +314,34 @@
# ----
-def averagine(mass, composition, threshold=0.005, fwhm=0.2):
- """Calculate isotopic distribution for given mass and building block.
+def averagine(mass, charge=0, composition=AVERAGE_AMINO):
+ """Calculate average formula for given mass and building block composition.
mass: (float) neutral mass to be modeled
+ charge: (int) charge to be calculated
composition: (dict) building block composition
- relIntThreshold: (float) peak intensity threshold
- fwhm: (float) peak fwhm
"""
- # get number of possible blocks for given m/z value
- blockFormula = ''
+ # get average mass of block
+ blockMass = 0
for element in composition:
- blockFormula += '%s%0.f' % (element, composition[element]*100)
- blockMass = objects.compound(blockFormula).mass()
- count = int(max(1, (round(mass/blockMass[0]*100))))
+ blockMass += blocks.elements[element].mass[1] * composition[element]
+
+ # get block count
+ neutralMass = mz(mass, charge=0, currentCharge=charge, massType=1)
+ count = max(1, neutralMass/blockMass)
# make formula
formula = ''
for element in composition:
- formula += '%s%0.f' % (element, composition[element]*count)
+ formula += '%s%d' % (element, int(composition[element]*count))
formula = objects.compound(formula)
- # calc pattern
- distribution = []
- pattern = formula.pattern(threshold=threshold, fwhm=fwhm)
-
- # make distribution
- for peak in pattern:
- distribution.append(peak[1])
+ # add some hydrogens
+ hydrogens = int(round((neutralMass - formula.mass(1)) / blocks.elements['H'].mass[1]))
+ hydrogens = max(hydrogens, -1*formula.count('H'))
+ formula += 'H%d' % hydrogens
- return distribution
+ return formula
# ----
@@ -416,8 +375,8 @@
m = (rasterRange[1] - rasterRange[0]) / (mzRange[1] - mzRange[0])
b = rasterRange[0] - m * mzRange[0]
- size = int((mzRange[1] - mzRange[0]) / rasterRange[0]) + 1
- raster = numpy.zeros(size, float)
+ size = ((mzRange[1] - mzRange[0]) / rasterRange[0]) + 2
+ raster = numpy.zeros(int(size), float)
i = 0
x = mzRange[0]
@@ -447,12 +406,12 @@
pass
elif mz != None:
window = mz*window
- i1 = _getIndex2D(points, mz-window)
- i2 = _getIndex2D(points, mz+window)
+ i1 = findIndex(points, mz-window, dim=2)
+ i2 = findIndex(points, mz+window, dim=2)
points = points[i1:i2]
elif minX != None and maxX != None:
- i1 = _getIndex2D(points, minX)
- i2 = _getIndex2D(points, maxX)
+ i1 = findIndex(points, minX, dim=2)
+ i2 = findIndex(points, maxX, dim=2)
# check indexes
if i1 == i2:
@@ -507,22 +466,26 @@
levels = []
widths = []
for x in raster:
- i1 = _getIndex2D(points, x-x*window)
- i2 = _getIndex2D(points, x+x*window)
+ i1 = findIndex(points, x-x*window, dim=2)
+ i2 = findIndex(points, x+x*window, dim=2)
if i1 == i2:
noiseLevel = 0.0
noiseWidth = 1.0
else:
noiseLevel = numpy.median(intArr[i1:i2])
- noiseWidth = float(numpy.median(numpy.absolute(intArr[i1:i2] - noiseLevel)))*2
+ noiseWidth = abs(float(numpy.median(numpy.absolute(intArr[i1:i2] - noiseLevel)))*2)
levels.append([x, noiseLevel])
widths.append([x, noiseWidth])
# smooth baseline
if smooth:
- window = 5 * window * (points[-1][0]-points[0][0])
+ window = 5 * window * (points[-1][0] - points[0][0])
levels = smoothSG(numpy.array(levels), window, 2)
- widths = smoothSG(numpy.array(widths), window, 2)
+ widths = smoothGA(numpy.array(widths), window, 2)
+
+ # ensure there are positive values in widths
+ for i in range(len(widths)):
+ widths[i][1] = abs(widths[i][1])
# apply relative offset and add widths to baseline
buff = []
@@ -533,7 +496,7 @@
# ----
-def smoothMA(points, window, cycles=1):
+def smoothMA(points, window, cycles=1, style='flat'):
"""Return data points smoothed by moving average.
points: (numpy.array) points to be smoothed
window: (float) m/z window size for smoothing
@@ -542,10 +505,11 @@
# approximate number of points within window
window = int(window*len(points)/(points[-1][0]-points[0][0]))
- if window < 2:
+ window = min(window, len(points))
+ if window < 3:
return points.copy()
if not window % 2:
- window += 1
+ window -= 1
# unpack mz and intensity
xAxis, yAxis = numpy.hsplit(points,2)
@@ -557,9 +521,16 @@
CHECK_FORCE_QUIT()
- s=numpy.r_[2*yAxis[0]-yAxis[window:1:-1],yAxis,2*yAxis[-1]-yAxis[-1:-window:-1]]
- w=numpy.ones(window,'f')
- y=numpy.convolve(w/w.sum(),s,mode='same')
+ if style == 'flat':
+ w = numpy.ones(window,'f')
+ elif style == 'gaussian':
+ r = numpy.array([(i-(window-1)/2.) for i in range(window)])
+ w = numpy.exp(-(r**2/(window/4.)**2))
+ else:
+ w = eval('numpy.'+style+'(window)')
+
+ s = numpy.r_[yAxis[window-1:0:-1], yAxis, yAxis[-2:-window-1:-1]]
+ y = numpy.convolve(w/w.sum(), s, mode='same')
yAxis = y[window-1:-window+1]
cycles -=1
@@ -572,6 +543,22 @@
# ----
+def smoothGA(points, window, cycles=1):
+ """Return data points smoothed by Gaussian filter.
+ points: (numpy.array) points to be smoothed
+ window: (float) m/z window size for smoothing
+ cycles: (int) number of repeating cycles
+ """
+
+ return smoothMA(
+ points = points,
+ window = window,
+ cycles = cycles,
+ style = 'gaussian'
+ )
+# ----
+
+
def smoothSG(points, window, cycles=1, order=3):
"""Return data points smoothed by Savitzky-Golay filter.
points: (numpy.array) points to be smoothed
@@ -638,12 +625,12 @@
return False
# get mz index
- index = _getIndex2D(points, mz)
+ index = findIndex(points, mz, dim=2)
if not index or index == len(points):
return False
# get intensity
- intens = _interpolateLine(points[index-1], points[index], x=mz)
+ intens = interpolateLine(points[index-1], points[index], x=mz)
return intens
# ----
@@ -661,11 +648,11 @@
return None
# get indexes
- index = _getIndex2D(points, mz)
- if index < 1:
+ index = findIndex(points, mz, dim=2)
+ if index < 1 or index == len(points):
return None
- leftIndx = index-1
+ leftIndx = index - 1
while leftIndx >= 0:
if points[leftIndx][1] <= intensity:
break
@@ -679,10 +666,10 @@
rightIndx += 1
# get mz
- leftMZ = _interpolateLine(points[leftIndx], points[leftIndx+1], y=intensity)
- rightMZ = _interpolateLine(points[rightIndx-1], points[rightIndx], y=intensity)
+ leftMZ = interpolateLine(points[leftIndx], points[leftIndx+1], y=intensity)
+ rightMZ = interpolateLine(points[rightIndx-1], points[rightIndx], y=intensity)
- return rightMZ - leftMZ
+ return abs(rightMZ - leftMZ)
# ----
@@ -715,10 +702,13 @@
# get peak baseline and s/n
i = 0
- while baselineData[i][0] < mz:
+ while i < len(baselineData)-1 and baselineData[i][0] < mz:
i += 1
- base = _interpolateLine((baselineData[i-1][0], baselineData[i-1][1]), (baselineData[i][0], baselineData[i][1]), x=mz)
- sn = (intens - base) / _interpolateLine((baselineData[i-1][0], baselineData[i-1][2]), (baselineData[i][0], baselineData[i][2]), x=mz)
+ base = interpolateLine((baselineData[i-1][0], baselineData[i-1][1]), (baselineData[i][0], baselineData[i][1]), x=mz)
+ noiseWidth = interpolateLine((baselineData[i-1][0], baselineData[i-1][2]), (baselineData[i][0], baselineData[i][2]), x=mz)
+ sn = None
+ if noiseWidth:
+ sn = (intens - base) / interpolateLine((baselineData[i-1][0], baselineData[i-1][2]), (baselineData[i][0], baselineData[i][2]), x=mz)
# check peak intensity
if intens <= base:
@@ -762,14 +752,14 @@
return False
# get left index
- i1 = _getIndex2D(points, minX)
+ i1 = findIndex(points, minX, dim=2)
indexMax = i1
if not (0 < i1 < len(points)):
return False
# get right index
if maxX != None:
- i2 = _getIndex2D(points, maxX)
+ i2 = findIndex(points, maxX, dim=2)
if not (0 < i2 < len(points)):
return False
@@ -785,9 +775,9 @@
# get picking height
i = 0
mzMax = points[indexMax][0]
- while baselineData[i][0] < mzMax:
+ while i < len(baselineData)-1 and baselineData[i][0] < mzMax:
i += 1
- noiseLevel = _interpolateLine((baselineData[i-1][0], baselineData[i-1][1]), (baselineData[i][0], baselineData[i][1]), x=mzMax)
+ noiseLevel = interpolateLine((baselineData[i-1][0], baselineData[i-1][1]), (baselineData[i][0], baselineData[i][1]), x=mzMax)
height = ((points[indexMax][1] - noiseLevel) * pickingHeight) + noiseLevel
# get centroided m/z
@@ -796,44 +786,46 @@
if points[leftIndx][1] <= height:
break
leftIndx -= 1
- leftMZ = _interpolateLine(points[leftIndx], points[leftIndx+1], y=height)
+ leftMZ = interpolateLine(points[leftIndx], points[leftIndx+1], y=height)
rightIndx = indexMax
while rightIndx < (len(points)-1):
if points[rightIndx][1] <= height:
break
rightIndx += 1
- rightMZ = _interpolateLine(points[rightIndx-1], points[rightIndx], y=height)
+ rightMZ = interpolateLine(points[rightIndx-1], points[rightIndx], y=height)
# check range
- if mz == None and (leftMZ < minX or rightMZ > maxX):
+ if mz == None and (leftMZ < minX or rightMZ > maxX) and (leftMZ != rightMZ):
return False
# label peak in the newly found selection
- if mz != None:
- peak = labelPeak(\
- points=points, \
- minX=leftMZ, \
- maxX=rightMZ, \
- pickingHeight=pickingHeight, \
- baselineData=baselineData \
+ if mz != None and leftMZ != rightMZ:
+ peak = labelPeak(
+ points = points,
+ minX = leftMZ,
+ maxX = rightMZ,
+ pickingHeight = pickingHeight,
+ baselineData = baselineData
)
return peak
# label current point
else:
- peak = labelPoint(\
- points=points, \
- mz=((leftMZ + rightMZ)/2), \
- baselineData=baselineData \
+ peak = labelPoint(
+ points = points,
+ mz = ((leftMZ + rightMZ)/2),
+ baselineData = baselineData
)
return peak
# ----
-def labelScan(points, pickingHeight=0.75, absThreshold=0., relThreshold=0., snThreshold=0., baselineWindow=0.1, baselineSmooth=True, baselineOffset=0., smoothMethod=None, smoothWindow=0.2, smoothCycles=1):
+def labelScan(points, minX=None, maxX=None, pickingHeight=0.75, absThreshold=0., relThreshold=0., snThreshold=0., baselineWindow=0.1, baselineSmooth=True, baselineOffset=0., baselineData=None, smoothMethod=None, smoothWindow=0.2, smoothCycles=1):
"""Return centroided peaklist for given data points.
points: (numpy array) spectrum data points
+ minX: (float) starting m/z value
+ maxX: (float) ending m/z value
pickingHeight: (float) peak picking height for centroiding
absThreshold: (float) absolute intensity threshold
relThreshold: (float) relative intensity threshold
@@ -841,7 +833,8 @@
baselineWindow: (float) noise calculation window in %/100
baselineSmooth: (bool) smooth baseline
baselineOffset: (float) baseline intensity offset in %/100
- smoothMethod: (None or MA or SG) smoothing method, MA - moving average, SG - Savitzky-Golay
+ baselineData: (list of [x, noiseLevel, noiseWidth]) precalculated baseline
+ smoothMethod: (None, MA GA or SG) smoothing method, MA - moving average, GA - Gaussian, SG - Savitzky-Golay
smoothWindows: (float) m/z window size for smoothing
smoothCycles: (int) number of repeating cycles
"""
@@ -850,14 +843,23 @@
if len(points) == 0:
return objects.peaklist()
- # get original baseline
- oribase = baseline(points, window=baselineWindow, smooth=baselineSmooth, offset=baselineOffset)
+ # get baseline data
+ if baselineData == None:
+ baselineData = baseline(points, window=baselineWindow, smooth=baselineSmooth, offset=baselineOffset)
CHECK_FORCE_QUIT()
+ # crop data
+ if minX != None and maxX != None:
+ i1 = findIndex(points, minX, dim=2)
+ i2 = findIndex(points, maxX, dim=2)
+ points = points[i1:i2]
+
# apply smoothing
if smoothMethod and smoothMethod.upper() == 'MA':
points = smoothMA(points, smoothWindow, smoothCycles)
+ elif smoothMethod and smoothMethod.upper() == 'GA':
+ points = smoothGA(points, smoothWindow, smoothCycles)
elif smoothMethod and smoothMethod.upper() == 'SG':
points = smoothSG(points, smoothWindow, smoothCycles)
@@ -885,13 +887,15 @@
i = 0
basepeak = 0
for peak in buff:
- while oribase[i][0] < peak[0]:
+ while i < len(baselineData)-1 and baselineData[i][0] < peak[0]:
i += 1
- b1 = oribase[i-1]
- b2 = oribase[i]
- peak[2] = _interpolateLine((b1[0], b1[1]), (b2[0], b2[1]), x=peak[0])
+ b1 = baselineData[i-1]
+ b2 = baselineData[i]
+ peak[2] = interpolateLine((b1[0], b1[1]), (b2[0], b2[1]), x=peak[0])
intens = peak[1] - peak[2]
- peak[3] = intens/_interpolateLine((b1[0], b1[2]), (b2[0], b2[2]), x=peak[0])
+ noiseWidth = interpolateLine((b1[0], b1[2]), (b2[0], b2[2]), x=peak[0])
+ if noiseWidth:
+ peak[3] = intens/noiseWidth
if intens > basepeak:
basepeak = intens
@@ -901,7 +905,7 @@
threshold = max(basepeak * relThreshold, absThreshold)
localMaxima = []
for peak in buff:
- if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and peak[3] >= snThreshold:
+ if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and (not peak[3] or peak[3] >= snThreshold):
localMaxima.append(peak)
# make centroides
@@ -918,7 +922,7 @@
height = ((peak[1]-peak[2]) * pickingHeight) + peak[2]
# get peak indexes
- index = _getIndex2D(points, peak[0])
+ index = findIndex(points, peak[0], dim=2)
if not (0 < index < len(points)):
continue
@@ -936,8 +940,8 @@
rightIndx += 1
# get mz
- leftMZ = _interpolateLine(points[leftIndx], points[leftIndx+1], y=height)
- rightMZ = _interpolateLine(points[rightIndx-1], points[rightIndx], y=height)
+ leftMZ = interpolateLine(points[leftIndx], points[leftIndx+1], y=height)
+ rightMZ = interpolateLine(points[rightIndx-1], points[rightIndx], y=height)
peak[0] = (leftMZ + rightMZ)/2
# get intensity
@@ -962,13 +966,15 @@
i = 0
basepeak = 0
for peak in buff:
- while oribase[i][0] < peak[0]:
+ while i < len(baselineData)-1 and baselineData[i][0] < peak[0]:
i += 1
- b1 = oribase[i-1]
- b2 = oribase[i]
- peak[2] = _interpolateLine((b1[0], b1[1]), (b2[0], b2[1]), x=peak[0])
+ b1 = baselineData[i-1]
+ b2 = baselineData[i]
+ peak[2] = interpolateLine((b1[0], b1[1]), (b2[0], b2[1]), x=peak[0])
intens = peak[1] - peak[2]
- peak[3] = intens/_interpolateLine((b1[0], b1[2]), (b2[0], b2[2]), x=peak[0])
+ noiseWidth = interpolateLine((b1[0], b1[2]), (b2[0], b2[2]), x=peak[0])
+ if noiseWidth:
+ peak[3] = intens/noiseWidth
peak[4] = peakWidth(points, peak[0], (peak[2] + intens * 0.5))
if intens > basepeak:
basepeak = intens
@@ -979,7 +985,7 @@
threshold = max(basepeak * relThreshold, absThreshold)
centroides = []
for peak in buff:
- if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and peak[3] >= snThreshold:
+ if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and (not peak[3] or peak[3] >= snThreshold):
centroides.append(objects.peak(mz=peak[0], ai=peak[1], base=peak[2], sn=peak[3], fwhm=peak[4]))
# return peaklist object
@@ -1000,39 +1006,35 @@
elif len(isotopes) == 1:
return isotopes[0]
+ # check peaklist object
+ if not isinstance(isotopes, objects.peaklist):
+ isotopes = objects.peaklist(isotopes)
+
# get sums
sumMZ = 0
sumIntensity = 0
- sumBase = 0
for isotope in isotopes:
sumMZ += isotope.mz * isotope.intensity
sumIntensity += isotope.intensity
- sumBase += isotope.base
- # get m/z
+ # get average m/z
mz = sumMZ / sumIntensity
- # get basepeak
- basepeak = isotopes[0]
- for isotope in isotopes:
- if isotope.intensity > basepeak.intensity:
- basepeak = isotope
-
# get ai, base and sn
- base = basepeak.base
- ai = basepeak.ai
- sn = basepeak.sn
+ base = isotopes.basepeak.base
+ sn = isotopes.basepeak.sn
+ fwhm = isotopes.basepeak.fwhm
if intensity == 'sum':
- base = sumBase / len(isotopes)
ai = base + sumIntensity
- sn = (ai - base) * basepeak.sn / (basepeak.ai - basepeak.base)
elif intensity == 'average':
- base = sumBase / len(isotopes)
ai = base + sumIntensity / len(isotopes)
- sn = (ai - base) * basepeak.sn / (basepeak.ai - basepeak.base)
+ else:
+ ai = isotopes.basepeak.ai
+ if isotopes.basepeak.sn:
+ sn = (ai - base) * isotopes.basepeak.sn / (isotopes.basepeak.ai - base)
# get envelope width
- minInt = basepeak.intensity * height
+ minInt = isotopes.basepeak.intensity * height
i1 = None
i2 = None
for x, isotope in enumerate(isotopes):
@@ -1044,17 +1046,78 @@
mz1 = isotopes[i1].mz
mz2 = isotopes[i2].mz
if i1 != 0:
- mz1 = _interpolateLine((isotopes[i1-1].mz, isotopes[i1-1].ai), (isotopes[i1].mz, isotopes[i1].ai), y=minInt)
+ mz1 = interpolateLine((isotopes[i1-1].mz, isotopes[i1-1].ai), (isotopes[i1].mz, isotopes[i1].ai), y=minInt)
if i2 < len(isotopes)-1:
- mz2 = _interpolateLine((isotopes[i2].mz, isotopes[i2].ai), (isotopes[i2+1].mz, isotopes[i2+1].ai), y=minInt)
+ mz2 = interpolateLine((isotopes[i2].mz, isotopes[i2].ai), (isotopes[i2+1].mz, isotopes[i2+1].ai), y=minInt)
+ if mz1 != mz2:
+ fwhm = abs(mz2 - mz1)
+
+ # make peak
+ peak = objects.peak(mz=mz, ai=ai, base=base, sn=sn, fwhm=fwhm)
+
+ return peak
+# ----
+
+
+def envelopeMonoisotope(isotopes, charge, intensity='maximum'):
+ """Calculate envelope centroid for given isotopes.
+ isotopes: (mspy.peaklist or list of peaks)
+ charge: (int) peak charge
+ intensity: (maximum | sum | average) haw to calculate envelope label intensity
+ """
+
+ # check isotopes
+ if len(isotopes) == 0:
+ return False
+
+ # check peaklist object
+ if not isinstance(isotopes, objects.peaklist):
+ isotopes = objects.peaklist(isotopes)
+
+ # calc averagine
+ avFormula = averagine(isotopes.basepeak.mz, charge=charge, composition=AVERAGE_AMINO)
+ avPattern = avFormula.pattern(fwhm=0.1, threshold=0.001, charge=charge)
+ avPattern = objects.peaklist(avPattern)
+
+ # get envelope centroid
+ points = numpy.array([(p.mz, p.intensity) for p in isotopes])
+ baseline = numpy.array([(points[0][0], 0., 0.), (points[-1][0], 0., 0.)])
+ centroid = labelPeak(points, mz=isotopes.basepeak.mz, pickingHeight=0.8, baselineData=baseline)
+ if not centroid:
+ centroid = isotopes.basepeak
+
+ # get averagine centroid
+ points = numpy.array([(p.mz, p.intensity) for p in avPattern])
+ baseline = numpy.array([(points[0][0], 0., 0.), (points[-1][0], 0., 0.)])
+ avCentroid = labelPeak(points, mz=avPattern.basepeak.mz, pickingHeight=0.8, baselineData=baseline)
+ if not avCentroid:
+ avCentroid = avPattern.basepeak
+
+ # align profiles and get monoisotopic mass
+ shift = centroid.mz - avCentroid.mz
+ errors = [(abs(p.mz - avPattern.basepeak.mz - shift), p.mz) for p in isotopes]
+ mz = min(errors)[1] - (avPattern.basepeak.mz - avFormula.mz(charge)[0])
+
+ # sum intensities
+ sumIntensity = 0
+ for isotope in isotopes:
+ sumIntensity += isotope.intensity
- if mz1 == mz2:
- fwhm = basepeak.fwhm
+ # get ai, base and sn
+ base = isotopes.basepeak.base
+ sn = isotopes.basepeak.sn
+ fwhm = isotopes.basepeak.fwhm
+ if intensity == 'sum':
+ ai = base + sumIntensity
+ elif intensity == 'average':
+ ai = base + sumIntensity / len(isotopes)
else:
- fwhm = mz2 - mz1
+ ai = isotopes.basepeak.ai
+ if isotopes.basepeak.sn:
+ sn = (ai - base) * isotopes.basepeak.sn / (isotopes.basepeak.ai - base)
# make peak
- peak = objects.peak(mz=mz, ai=ai, base=base, sn=sn, fwhm=fwhm)
+ peak = objects.peak(mz=mz, ai=ai, base=base, sn=sn, fwhm=fwhm, isotope=0)
return peak
# ----
@@ -1161,10 +1224,10 @@
# ----
-def deconvolute(peaklist, massType='mo'):
+def deconvolute(peaklist, massType=0):
"""Recalculate peaklist to singly charged.
peaklist: (mspy.peaklist) peak list to deconvolute
- massType: ('mo' or 'av') mass type used for m/z re-calculation
+ massType: (0 or 1) mass type used for m/z re-calculation, 0 = monoisotopic, 1 = average
"""
# recalculate peaks
@@ -1226,6 +1289,10 @@
baselineData: (list of [x, noiseLevel]) precalculated baseline
"""
+ # check points
+ if len(points) == 0:
+ return points
+
# get baseline
if baselineData == None:
baselineData = baseline(points, window=window, smooth=smooth, offset=offset)
@@ -1301,12 +1368,12 @@
break
if pointsA[i][0] < pointsB[i][0]:
- intens = _interpolateLine(pointsB[i-1], pointsB[i], x=pointsA[i][0])
+ intens = interpolateLine(pointsB[i-1], pointsB[i], x=pointsA[i][0])
pointsB.insert(i, [pointsA[i][0], intens])
countB += 1
elif pointsA[i][0] > pointsB[i][0]:
- intens = _interpolateLine(pointsA[i-1], pointsA[i], x=pointsB[i][0])
+ intens = interpolateLine(pointsA[i-1], pointsA[i], x=pointsB[i][0])
pointsA.insert(i, [pointsB[i][0], intens])
countA += 1
@@ -1390,7 +1457,7 @@
# ----
-def _leastSquaresFit(model, parameters, data, max_iterations=None, stopping_limit=1e-7):
+def _leastSquaresFit(model, parameters, data, maxIterations=None, limit=1e-7):
"""General non-linear least-squares fit using the
Levenberg-Marquardt algorithm and automatic derivatives."""
@@ -1404,355 +1471,166 @@
l = 0.001
chi_sq, alpha = _chiSquare(model, p, data)
niter = 0
- while 1:
+
+ while True:
+ niter += 1
+
delta = solveLinEq(alpha+l*numpy.diagonal(alpha)*id,-0.5*numpy.array(chi_sq[1]))
next_p = map(lambda a,b: a+b, p, delta)
+
next_chi_sq, next_alpha = _chiSquare(model, next_p, data)
if next_chi_sq > chi_sq:
l = 10.*l
+ elif chi_sq[0] - next_chi_sq[0] < limit:
+ break
else:
l = 0.1*l
- if chi_sq[0] - next_chi_sq[0] < stopping_limit: break
p = next_p
chi_sq = next_chi_sq
alpha = next_alpha
- niter = niter + 1
- if max_iterations is not None and niter == max_iterations:
- pass
+
+ if maxIterations and niter == maxIterations:
+ break
+
return map(lambda p: p[0], next_p), next_chi_sq[0]
# ----
-def _isDerivVar(x):
- """Returns 1 if |x| is a DerivVar object."""
- return hasattr(x,'value') and hasattr(x,'deriv')
-# ----
-
-
def _chiSquare(model, parameters, data):
- """ Count Chi-square. """
+ """Count chi-square."""
n_param = len(parameters)
- chi_sq = 0.
alpha = numpy.zeros((n_param, n_param))
+
+ chi_sq = _DerivVar(0., [])
for point in data:
- sigma = 1
- if len(point) == 3:
- sigma = point[2]
f = model(parameters, point[0])
- chi_sq = chi_sq + ((f-point[1])/sigma)**2
- d = numpy.array(f[1])/sigma
+ chi_sq += (f-point[1])**2
+ d = numpy.array(f[1])
alpha = alpha + d[:,numpy.newaxis]*d
- return chi_sq, alpha
-# ----
-
-
-def _mapderiv(func, a, b):
- """ Map a binary function on two first derivative lists. """
- nvars = max(len(a), len(b))
- a = a + (nvars-len(a))*[0]
- b = b + (nvars-len(b))*[0]
- return map(func, a, b)
+ return chi_sq, alpha
# ----
class _DerivVar:
"""This module provides automatic differentiation for functions with any number of variables."""
- def __init__(self, value, index=0, order=1):
- if order > 1:
- raise ValueError, 'Only first-order derivatives'
+ def __init__(self, value, index=0):
self.value = value
- if order == 0:
- self.deriv = []
- elif type(index) == type([]):
+ if type(index) == type([]):
self.deriv = index
else:
self.deriv = index*[0] + [1]
+ def _mapderiv(self, func, a, b):
+ nvars = max(len(a), len(b))
+ a = a + (nvars-len(a))*[0]
+ b = b + (nvars-len(b))*[0]
+ return map(func, a, b)
+
def __getitem__(self, item):
- if item < 0 or item > 1:
- raise ValueError, 'Index out of range'
if item == 0:
return self.value
- else:
+ elif item == 1:
return self.deriv
-
- def __coerce__(self, other):
- if _isDerivVar(other):
- return self, other
else:
- return self, _DerivVar(other, [])
+ raise IndexError
def __cmp__(self, other):
- return cmp(self.value, other.value)
+ if isinstance(other, _DerivVar):
+ return cmp(self.value, other.value)
+ else:
+ return cmp(self.value, other)
def __add__(self, other):
- return _DerivVar(self.value + other.value, _mapderiv(lambda a,b: a+b, self.deriv, other.deriv))
- __radd__ = __add__
+ if isinstance(other, _DerivVar):
+ return _DerivVar(self.value + other.value, self._mapderiv(lambda a,b: a+b, self.deriv, other.deriv))
+ else:
+ return _DerivVar(self.value + other, self.deriv)
+
+ def __radd__(self, other):
+ if isinstance(other, _DerivVar):
+ self.value += other.value
+ self.deriv = self._mapderiv(lambda a,b: a+b, self.deriv, other.deriv)
+ return self
+ else:
+ self.value += other
+ return self
def __sub__(self, other):
- return _DerivVar(self.value - other.value, _mapderiv(lambda a,b: a-b, self.deriv, other.deriv))
+ if isinstance(other, _DerivVar):
+ return _DerivVar(self.value - other.value, self._mapderiv(lambda a,b: a-b, self.deriv, other.deriv))
+ else:
+ return _DerivVar(self.value - other, self.deriv)
- def __mul__(self, other):
- return _DerivVar(self.value*other.value,
- _mapderiv(lambda a,b: a+b,
- map(lambda x,f=other.value:f*x, self.deriv),
- map(lambda x,f=self.value:f*x, other.deriv)))
+ def __rsub__(self, other):
+ if isinstance(other, _DerivVar):
+ self.value -= other.value
+ self.deriv = self._mapderiv(lambda a,b: a-b, self.deriv, other.deriv)
+ return self
+ else:
+ self.value -= other
+ return self
- __rmul__ = __mul__
+ def __mul__(self, other):
+ if isinstance(other, _DerivVar):
+ return _DerivVar(self.value * other.value, self._mapderiv(lambda a,b: a+b, map(lambda x,f=self.value:f*x, other.deriv), map(lambda x,f=other.value:f*x, self.deriv)))
+ else:
+ return _DerivVar(self.value * other, map(lambda x,f=other:f*x, self.deriv))
def __div__(self, other):
- if not other.value:
- raise ZeroDivisionError, 'DerivVar division'
- inv = 1./other.value
- return _DerivVar(self.value*inv,
- _mapderiv(lambda a,b: a-b,
- map(lambda x,f=inv: f*x, self.deriv),
- map(lambda x,f=self.value*inv*inv: f*x,
- other.deriv)))
-
- def __rdiv__(self, other):
- return other/self
-
- def __pow__(self, other, z=None):
- if z is not None:
- raise TypeError, 'DerivVar does not support ternary pow()'
- val1 = pow(self.value, other.value-1)
- val = val1*self.value
- deriv1 = map(lambda x,f=val1*other.value: f*x, self.deriv)
- if _isDerivVar(other) and len(other.deriv) > 0:
- deriv2 = map(lambda x, f=val*numpy.log(self.value): f*x,
- other.deriv)
- return _DerivVar(val,_mapderiv(lambda a,b: a+b, deriv1, deriv2))
+ if isinstance(other, _DerivVar):
+ inv = 1./other.value
+ return _DerivVar(self.value * inv, self._mapderiv(lambda a,b: a-b, map(lambda x,f=inv: f*x, self.deriv), map(lambda x,f=self.value*inv*inv: f*x, other.deriv)))
else:
- return _DerivVar(val,deriv1)
+ inv = 1./value
+ return _DerivVar(self.value * inv, map(lambda x,f=inv:f*x, self.deriv))
+
+ def __pow__(self, other):
+ val1 = pow(self.value, other-1)
+ deriv1 = map(lambda x,f=val1*other: f*x, self.deriv)
+ return _DerivVar(val1*self.value, deriv1)
+
+ def __abs__(self):
+ absvalue = abs(self.value)
+ return _DerivVar(absvalue, map(lambda a, d=self.value/absvalue: d*a, self.deriv))
- def __rpow__(self, other):
- return pow(other, self)
-
# ----
-# SEQUENCE PROCESSING
-# -------------------
+# HELPERS
+# -------
-def digest(sequence, enzyme, miscleavage=0, allowMods=False, strict=True):
- """Digest seuence by specified enzyme.
- sequence: (sequence) mspy sequence object
- enzyme: (str) enzyme name - must be defined in mspy.enzymes
- miscleavage: (int) number of allowed misscleavages
- allowMods: (bool) do not care about modifications in cleavage site
- strict: (bool) do not cleave even if variable modification is in cleavage site
- """
-
- # check sequence object
- if not isinstance(sequence, objects.sequence):
- raise TypeError, "Cannot digest non-sequence object!"
- elif not sequence.chain:
- return []
-
- # get enzyme
- if enzyme in blocks.enzymes:
- enzyme = blocks.enzymes[enzyme]
- expression = re.compile(enzyme.expression+'$')
- else:
- raise KeyError, 'Unknown enzyme! -> ' + enzyme
-
- # get digest indices
- slices = [] # from | to | miscl
- lastIndex = 0
- peptide = ''
- for x, aa in enumerate(sequence.chain):
-
- # check expression
- peptide += aa
- if expression.search(peptide):
-
- # skip not allowed modifications
- if not allowMods and sequence.ismodified(x-1, strict) and not enzyme.modsBefore:
- continue
- elif not allowMods and sequence.ismodified(x, strict) and not enzyme.modsAfter:
- continue
- else:
- slices.append((lastIndex, x, 0))
- lastIndex = x
+def findIndex(points, x, dim=1):
+ """Get nearest lower index for selected point."""
- # add last peptide
- slices.append((lastIndex, x+1, 0))
+ lo = 0
+ hi = len(points)
- # add indices for partials
- indices = len(slices)
- for x in range(indices):
- for y in range(1, miscleavage+1):
- if x+y < indices:
- slices.append((slices[x][0], slices[x+y][1], y))
+ # 1D array
+ if dim == 1:
+ while lo < hi:
+ mid = (lo + hi) / 2
+ if x < points[mid]:
+ hi = mid
else:
- break
-
- # get peptides slices from protein
- peptides = []
- for indices in slices:
-
- CHECK_FORCE_QUIT()
-
- # get peptide
- peptide = sequence[indices[0]:indices[1]]
- peptide.miscleavages = indices[2]
-
- # add terminal groups
- if indices[0] != 0:
- peptide.nTermFormula = enzyme.nTermFormula
- if indices[1] != len(sequence.chain):
- peptide.cTermFormula = enzyme.cTermFormula
-
- peptides.append(peptide)
-
- return peptides
-# ----
-
-
-def fragment(sequence, serie, index=None):
- """Generate list of neutral peptide fragments from given peptide.
- sequence: (sequence) mspy sequence object
- serie: (str) fragment serie name - must be defined in mspy.fragments
- index: (int) fragment index
- """
-
- # check sequence object
- if not isinstance(sequence, objects.sequence):
- raise TypeError, "Cannot fragment non-sequence object!"
-
- frags = []
- length = len(sequence.chain)
-
- # get serie definition
- if serie in blocks.fragments:
- serie = blocks.fragments[serie]
- else:
- raise KeyError, 'Unknown fragment type! -> ' + serie
-
- # N-terminal fragments
- if serie.terminus == 'N':
- if index != None:
- frag = sequence[:index]
- frag.cTermFormula = serie.cTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = index
- frags.append(frag)
- else:
- for x in range(length):
-
- CHECK_FORCE_QUIT()
-
- frag = sequence[:x+1]
- frag.cTermFormula = serie.cTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = (x+1)
- frags.append(frag)
-
- # C-terminal fragments
- elif serie.terminus == 'C':
- if index != None:
- frag = sequence[length-index:]
- frag.nTermFormula = serie.nTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = index
- frags.append(frag)
- else:
- for x in range(length):
-
- CHECK_FORCE_QUIT()
-
- frag = sequence[length-(x+1):]
- frag.nTermFormula = serie.nTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = (x+1)
- frags.append(frag)
-
- # singlet fragments
- elif serie.terminus == 'S':
- if index != None:
- frag = sequence[index-1:index]
- frag.nTermFormula = serie.nTermFormula
- frag.cTermFormula = serie.cTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = index
- frags.append(frag)
- else:
- for x in range(length):
-
- CHECK_FORCE_QUIT()
-
- frag = sequence[x:x+1]
- frag.nTermFormula = serie.nTermFormula
- frag.cTermFormula = serie.cTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frag.fragmentIndex = (x+1)
- frags.append(frag)
-
- # internal fragments
- elif serie.terminus == 'I':
- if index != None:
- raise ValueError, 'No index allowed for this serie! -> ' + serie.name
- else:
- for x in range(1,length-1):
- for y in range(2,length-x):
-
- CHECK_FORCE_QUIT()
-
- frag = sequence[x:x+y]
- frag.nTermFormula = serie.nTermFormula
- frag.cTermFormula = serie.cTermFormula
- frag.lossFormula = serie.lossFormula
- frag.fragmentSerie = serie.name
- frags.append(frag)
- else:
- raise ValueError, 'Unknown fragment terminus! -> ' + serie.terminus
-
- # check fragment specifity
- if serie.specifity:
- for x in range(len(frags)):
- frags[x].fragmentFiltered = True
- for aa in serie.specifity:
- if aa in frags[x].chain:
- frags[x].fragmentFiltered = False
- break
-
- # filter nonsense fragments
- if frags and serie.terminus == 'N':
- if serie.nTermFilter and (index==None or index==1):
- frags[0].fragmentFiltered = True
- if serie.cTermFilter and (index==None or index==len(sequence.chain)):
- frags[-1].fragmentFiltered = True
- elif frags and serie.terminus == 'C':
- if serie.nTermFilter and (index==None or index==len(sequence.chain)):
- frags[-1].fragmentFiltered = True
- if serie.cTermFilter and (index==None or index==1):
- frags[0].fragmentFiltered = True
- elif frags and serie.terminus == 'S':
- if serie.nTermFilter and (index==None or index==1):
- frags[0].fragmentFiltered = True
- if serie.cTermFilter and (index==None or index==len(sequence.chain)):
- frags[-1].fragmentFiltered = True
+ lo = mid + 1
+ # 2D array
+ if dim == 2:
+ while lo < hi:
+ mid = (lo + hi) / 2
+ if x < points[mid][0]:
+ hi = mid
+ else:
+ lo = mid + 1
- return frags
+ return lo
# ----
-
-# HELPERS
-# -------
-
-def _interpolateLine(p1, p2, x=None, y=None):
+def interpolateLine(p1, p2, x=None, y=None):
"""Get line interpolated X or Y value."""
# check points
@@ -1773,40 +1651,6 @@
# ----
-def _getIndex1D(points, x):
- """Get nearest index for selected point."""
-
- lo = 0
- hi = len(points)
-
- while lo < hi:
- mid = (lo + hi) / 2
- if x < points[mid]:
- hi = mid
- else:
- lo = mid + 1
-
- return lo
-# ----
-
-
-def _getIndex2D(points, x):
- """Get nearest index for selected point."""
-
- lo = 0
- hi = len(points)
-
- while lo < hi:
- mid = (lo + hi) / 2
- if x < points[mid][0]:
- hi = mid
- else:
- lo = mid + 1
-
- return lo
-# ----
-
-
# PATTERN LOOKUP TABLE
# --------------------
@@ -1815,10 +1659,11 @@
"""Print pattern lookup table."""
for mass in range(0, highmass, step):
+ formula = averagine(mass, composition=composition)
pattern = ''
- for isotope in averagine(mass, composition=composition, threshold=0.001):
- pattern += '%.3f, ' % isotope
+ for mz, abundance in formula.pattern(fwhm=0.1, threshold=0.001):
+ pattern += '%.3f, ' % abundance
if table == 'tuple':
print '(%s), #%d' % (pattern[:-2], mass)
diff -Nru mmass-3.12.1/mspy/proteo.py mmass-4.0.0/mspy/proteo.py
--- mmass-3.12.1/mspy/proteo.py 1970-01-01 00:00:00.000000000 +0000
+++ mmass-4.0.0/mspy/proteo.py 2011-11-28 11:19:48.000000000 +0000
@@ -0,0 +1,438 @@
+# -------------------------------------------------------------------------
+# Copyright (C) 2005-2011 Martin Strohalm
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# Complete text of GNU GPL can be found in the file LICENSE.TXT in the
+# main directory of the program
+# -------------------------------------------------------------------------
+
+# load libs
+import re
+import itertools
+
+# load stopper
+from stopper import CHECK_FORCE_QUIT
+
+# register essential objects and modules
+import objects
+import blocks
+
+
+# SEQUENCE DIGESTION
+# ------------------
+
+def digest(sequence, enzyme, miscleavage=0, allowMods=False, strict=True):
+ """Digest seuence by specified enzyme.
+ sequence: (sequence) mspy sequence object
+ enzyme: (str) enzyme name - must be defined in mspy.enzymes
+ miscleavage: (int) number of allowed misscleavages
+ allowMods: (bool) do not care about modifications in cleavage site
+ strict: (bool) do not cleave even if variable modification is in cleavage site
+ """
+
+ # check sequence object
+ if not isinstance(sequence, objects.sequence):
+ raise TypeError, "Cannot digest non-sequence object!"
+
+ # check cyclic peptides
+ if sequence.chainType != 'aminoacids':
+ raise TypeError, 'Digest function is not supported for non-amino sequences!'
+
+ # check cyclic peptides
+ if sequence.cyclic:
+ raise TypeError, 'Digest function is not supported for cyclic peptides!'
+
+ # check sequence
+ if not sequence.chain:
+ return []
+
+ # get enzyme
+ if enzyme in blocks.enzymes:
+ enzyme = blocks.enzymes[enzyme]
+ expression = re.compile(enzyme.expression+'$')
+ else:
+ raise KeyError, 'Unknown enzyme! -> ' + enzyme
+
+ # get digest indices
+ slices = [] # from | to | miscl
+ lastIndex = 0
+ peptide = ''
+ for x, aa in enumerate(sequence):
+
+ # check expression
+ peptide += aa
+ if expression.search(peptide):
+
+ # skip not allowed modifications
+ if not allowMods and sequence.ismodified(x-1, strict) and not enzyme.modsBefore:
+ continue
+ elif not allowMods and sequence.ismodified(x, strict) and not enzyme.modsAfter:
+ continue
+ else:
+ slices.append((lastIndex, x, 0))
+ lastIndex = x
+
+ # add last peptide
+ slices.append((lastIndex, x+1, 0))
+
+ # add indices for partials
+ indices = len(slices)
+ for x in range(indices):
+ for y in range(1, miscleavage+1):
+ if x+y < indices:
+ slices.append((slices[x][0], slices[x+y][1], y))
+ else:
+ break
+
+ # get peptides slices from protein
+ peptides = []
+ for indices in slices:
+
+ CHECK_FORCE_QUIT()
+
+ # get peptide
+ peptide = sequence[indices[0]:indices[1]]
+ peptide.miscleavages = indices[2]
+
+ # add terminal groups
+ if indices[0] != 0:
+ peptide.nTermFormula = enzyme.nTermFormula
+ if indices[1] != len(sequence):
+ peptide.cTermFormula = enzyme.cTermFormula
+
+ peptides.append(peptide)
+
+ return peptides
+# ----
+
+
+def coverage(ranges, length, trueIndexes=False):
+ """Calculate sequence coverage.
+ ranges: (list of mspy.sequence or list of user ranges (start,stop))
+ length: (int) parent sequence length
+ """
+
+ # check data
+ if not ranges:
+ return 0.
+
+ # make a blank sequence
+ blank = length*[0]
+
+ # list of ranges
+ for r in ranges:
+ if trueIndexes:
+ for x in range(r[0], r[1]):
+ blank[x]=(1)
+ else:
+ for x in range(r[0]-1, r[1]):
+ blank[x]=(1)
+
+ # get sequence coverage
+ return 100.0*blank.count(1)/length
+# ----
+
+
+
+# SEQUENCE FRAGMENTATION
+# ----------------------
+
+def fragment(sequence, series, scrambling=False):
+ """Generate list of neutral peptide fragments from given peptide.
+ sequence: (sequence) mspy sequence object
+ series: (list) list of fragment serie names - must be defined in mspy.fragments
+ scrambling: (int) allow sequence scrambling
+ """
+
+ frags = []
+ scramblingFilter = ('M')
+
+ # check sequence object
+ if not isinstance(sequence, objects.sequence):
+ raise TypeError, "Cannot fragment non-sequence object!"
+
+ # generate fragments for linear peptide
+ if not sequence.cyclic:
+ for serie in series:
+ frags += fragmentSerie(sequence, serie)
+
+ # generate fragments for cyclic peptide
+ else:
+ for peptide in sequence.linearized():
+ for serie in series:
+ frags += fragmentSerie(peptide, serie, cyclicParent=True)
+
+ # generate scrambling fragments
+ if scrambling:
+ buff = []
+ for frag in frags:
+ if frag.fragmentSerie == 'b' and len(frag) > 3:
+ for peptide in frag.linearized():
+ for serie in series:
+ if not serie in scramblingFilter:
+ buff += fragmentSerie(peptide, serie, cyclicParent=sequence.cyclic)
+
+ frags += buff
+
+ # remove same fragments
+ buff = []
+ have = []
+ for frag in frags:
+ frhash = [frag.fragmentSerie] + frag.indexes()
+ if frag.fragmentSerie == 'M':
+ frhash.sort()
+ if not frhash in have:
+ buff.append(frag)
+ have.append(frhash)
+
+ frags = buff
+
+ return frags
+# ----
+
+
+def fragmentSerie(sequence, serie, cyclicParent=False):
+ """Generate list of neutral peptide fragments from given peptide.
+ sequence: (sequence) mspy sequence object
+ serie: (str) fragment serie name - must be defined in mspy.fragments
+ """
+
+ # check sequence object
+ if not isinstance(sequence, objects.sequence):
+ raise TypeError, "Cannot fragment non-sequence object!"
+
+ # check cyclic peptides
+ if sequence.cyclic:
+ raise TypeError, 'Direct fragmentation of cyclic peptides is not supported!'
+
+ frags = []
+ length = len(sequence)
+
+ # get serie definition
+ serie = blocks.fragments[serie]
+
+ # molecular ion
+ if serie.terminus == 'M':
+ frag = sequence[:]
+ frag.fragmentSerie = serie.name
+ frags.append(frag)
+
+ # N-terminal fragments
+ elif serie.terminus == 'N':
+ for x in range(length):
+ frag = sequence[:x+1]
+ frag.fragmentSerie = serie.name
+ frag.fragmentIndex = (x+1)
+ frag.cTermFormula = serie.cTermFormula
+ frags.append(frag)
+
+ CHECK_FORCE_QUIT()
+
+ # C-terminal fragments
+ elif serie.terminus == 'C':
+ for x in range(length):
+ frag = sequence[length-(x+1):]
+ frag.fragmentSerie = serie.name
+ frag.fragmentIndex = (x+1)
+ frag.nTermFormula = serie.nTermFormula
+ frags.append(frag)
+
+ CHECK_FORCE_QUIT()
+
+ # singlet fragments
+ elif serie.terminus == 'S':
+ for x in range(length):
+ frag = sequence[x:x+1]
+ frag.fragmentSerie = serie.name
+ frag.fragmentIndex = (x+1)
+ frag.nTermFormula = serie.nTermFormula
+ frag.cTermFormula = serie.cTermFormula
+ frags.append(frag)
+
+ CHECK_FORCE_QUIT()
+
+ # internal fragments
+ elif serie.terminus == 'I':
+ for x in range(1,length-1):
+ for y in range(2,length-x):
+ frag = sequence[x:x+y]
+ frag.fragmentSerie = serie.name
+ frag.nTermFormula = serie.nTermFormula
+ frag.cTermFormula = serie.cTermFormula
+ frags.append(frag)
+
+ CHECK_FORCE_QUIT()
+
+ # correct termini for cyclic peptides
+ if cyclicParent:
+ for frag in frags:
+ if serie.terminus == 'M':
+ frag.nTermFormula = ''
+ frag.cTermFormula = ''
+ elif serie.terminus == 'N':
+ frag.nTermFormula = 'H'
+ elif serie.terminus == 'C':
+ frag.cTermFormula = 'H-1'
+
+ # remove nonsense terminal fragments
+ if serie.terminus == 'N':
+ if frags and serie.nTermFilter:
+ del frags[0]
+ if frags and serie.cTermFilter:
+ del frags[-1]
+ elif serie.terminus == 'C':
+ if frags and serie.nTermFilter:
+ del frags[-1]
+ if frags and serie.cTermFilter:
+ del frags[0]
+ elif serie.terminus == 'S':
+ if frags and serie.nTermFilter:
+ del frags[0]
+ if frags and serie.cTermFilter:
+ del frags[-1]
+
+ return frags
+# ----
+
+
+def fragmentLosses(fragments, losses=[], defined=False, limit=1, filterIn={}, filterOut={}):
+ """Apply specified neutral losses to fragments.
+ fragments: (list) list of sequence fragments
+ losses: (list) list of neutral losses
+ defined: (bool) use monomer-defined neutral losses
+ limit: (int) max length of loss combination
+ filterIn: (dic) allowed series for specified losses
+ filterOut: (dic) not allowed series for specified losses
+ """
+
+ # make losses combinations
+ combinations = []
+ for x in range(1, min(len(losses), limit) + 1):
+ for c in itertools.combinations(losses, x):
+ combinations.append(list(c))
+
+ # generate fragments
+ buff = []
+ for frag in fragments:
+
+ CHECK_FORCE_QUIT()
+
+ # get monomer-defined losses to check specifity
+ definedLosses = []
+ for monomer in frag:
+ definedLosses += blocks.monomers[monomer].losses
+
+ # append new combinations with monomer-defined losses
+ lossesToApply = combinations[:]
+ if defined:
+ for monomer in frag:
+ for item in ([[]] + lossesToApply[:]):
+ for loss in blocks.monomers[monomer].losses:
+ newItem = item + [loss]
+ newItem.sort()
+
+ if not [loss] in lossesToApply:
+ lossesToApply.append([loss])
+ if len(newItem) <= limit and not newItem in lossesToApply:
+ lossesToApply.append(newItem)
+
+
+ # make fragment
+ for combination in lossesToApply:
+ newFrag = frag.duplicate()
+ skip = False
+
+ # apply losses
+ for loss in combination:
+ newFrag.fragmentLosses.append(loss)
+
+ # check neutral gains
+ if loss in frag.fragmentGains:
+ skip = True
+ break
+
+ # check fragment type filter
+ if (loss in filterOut and frag.fragmentSerie in filterOut[loss]) \
+ or (loss in filterIn and not frag.fragmentSerie in filterIn[loss]):
+ skip = True
+ break
+
+ # check fragment composition
+ if not newFrag.isvalid():
+ skip = True
+ break
+
+ # filter non-specific losses
+ if not loss in definedLosses:
+ newFrag.fragmentFiltered = True
+
+ # store fragment
+ if not skip:
+ buff.append(newFrag)
+
+ return buff
+# ----
+
+
+def fragmentGains(fragments, gains=[], filterIn={'H2O':['b'], 'CO':['b', 'c', 'break']}, filterOut={}):
+ """Apply specified neutral gains to fragments.
+ fragments: (list) list of sequence fragments
+ gains: (list) list of neutral gains
+ filterIn: (dic) allowed series for specified gains
+ filterOut: (dic) not allowed series for specified gains
+ """
+
+ # generate fragments
+ buff = []
+ for frag in fragments:
+
+ CHECK_FORCE_QUIT()
+
+ # is parent cyclic?
+ cyclicParent = False
+ for item in frag.history:
+ if 'break' in item:
+ cyclicParent = True
+ break
+
+ # apply gains
+ for gain in gains:
+
+ # check neutral losses
+ if gain in frag.fragmentLosses:
+ continue
+
+ # check fragment type filters
+ if (gain in filterOut and frag.fragmentSerie in filterOut[gain]) \
+ or (gain in filterIn and not frag.fragmentSerie in filterIn[gain]):
+ continue
+
+ # check break (cyclic parent)
+ if gain in filterIn and 'break' in filterIn[gain] and not cyclicParent:
+ continue
+
+ # make fragment
+ newFrag = frag.duplicate()
+ newFrag.fragmentGains.append(gain)
+
+ # check fragment composition
+ if not newFrag.isvalid():
+ continue
+
+ # store fragment
+ buff.append(newFrag)
+
+ return buff
+# ----
+
+
+
\ No newline at end of file
diff -Nru mmass-3.12.1/setup.py mmass-4.0.0/setup.py
--- mmass-3.12.1/setup.py 2011-05-02 18:43:09.000000000 +0000
+++ mmass-4.0.0/setup.py 2011-12-01 16:33:06.000000000 +0000
@@ -13,7 +13,7 @@
# list additional files
additionalFiles = [
("configs",[
- "configs/aminoacids.xml",
+ "configs/monomers.xml",
"configs/compounds.xml",
"configs/config.xml",
"configs/enzymes.xml",
@@ -68,7 +68,8 @@
"gui/images/mac/icon_doc_mzxml.icns",
"gui/images/mac/icon_doc_mzml.icns",
"gui/images/mac/icon_doc_fid.icns",
- "configs"
+ "configs",
+ "User Guide.pdf"
]
# py2app options