#%SF_Element_n; #enthält die Summenformel #und zwar mit dem Element als Schlüssel und dessen Anzahl als Wert #C50 erfordert schon 2-hoch-50 Berechnungen ( das sind 1 Million mal 1,13 Milliarden!) #, insofern ist es nötig, Elemente zu Blöcken zusammen zu fassen. #So zerlege ich C60 in 2xC5 und 2xC25 (immer in 5er-Schritten). #Die Datenbank enthält dann für C5, C25, C125 u.s.w. ein neues Isotopen-Muster, als wäre es nur ein neues Element. #In die Datenbank fließen nur Isotope mit einem Vorkommen ab 0,1% ein. Da maximal 5 Atome einer Art #berechnet werden, bevor wieder ein neuer Block benutzt wird, hält sich der Fehler in engen Grenzen. # Diese Routine erledigt die Spaltung in 5er-Blöcke (125, 625 und 3125 habe ich weg gelassen) foreach(@SF_keys_Elemente){ $temp=$SF_Element_n{$_}; $temp5=$_."5"; $temp25=$_."25"; if ($temp >= 5 && $temp < 25){ $SF_Element_n{$_}=$temp%5;#% = Rest der Division $SF_Element_n{$temp5}=int($temp/5); if ($temp >= 25 && $temp < 125){ $SF_Element_n{$_}=$temp %5; $SF_Element_n{$temp5}=int($temp/5)-int($temp/25)*5; $SF_Element_n{$temp25}=int($temp/25); } # Jetzt folgt die eigneltiche Routine: # Jede Verbindung z.B. CH3-CH2-CSSH fasst man als lineare Kette auf: # hier: C-C-C-H-H-H-H-H-H-S-S #An jedem Element der Kette gibt es n Wahrscheinlichkeiten für ein Isotop des jeweiligen Elementes. # n ist die Anzahl der Isotope des jeweiligen Elementes. # Daraus lässt sich nun leicht ein Wahrscheinlichkeitsbaum bilden. # Mit jedem Abzweig in dem Baum muss auch verfolgt werden, wie sich die Masse durch das jeweilige #Isotop/Abzweig ändert. #Nehmen wir CS als hypotetisches Beispiel: C hat 2 Isotope, S 3 #Dann müssen folgende Zweige durchlaufen werden. # C-S # 1-2 # 0-1 # 1-0 # 0-2 # 1-1 # 0-0 #so wird aus C2S4 #CCSS #1122 #Dieses Muster 1122 muss bis 0000 herunter gezählt werden. Jede Kombination repräsentiert dann eine Möglichkeit #der Isotopen-Anordnung. # Dabei können durchaus mehrere Zweige am Ende der Rechnung zur selben Masse führen. # Die Wahrscheinlichkeiten der Zweige mit selber Masse müssen nachher addiert werden. # Mit einer for-next-Schleife ist es also nicht getan. Es ist eine Art Zahl, bei der jede Stelle eben nicht dezimal, oder binär #sondern einem Zahlensystem mit Anzahl der Isotope des jeweiligen Elementes entsprich. #@max enthält die höchste Kombinationszsahl (hier 1122) #@Kombi die aktuelle Kombination in der Schleife @Kombi = @max; #Initialisierung von @Kombi auf Maximalwert $Kombi[0]++;#Nötig, da direkt zu Beginn der Schleife $Kombi[0] wieder um 1 erniedrigt wird... for($k=1;$k<=$Kombinationen;$k++){ #$Kombinationen wurde vorher berechnet, da for Schleifen viel schneller als Alternativen sind $Kombi[0]--; #erste Stelle wird erniedrigt if($Kombi[0]<0){ # wenn diese dabei kleiner 0 wird $Kombi[0]=$max[0]; # wird sie wieder auf Maximum gesetzt $Kombi[1]--; # dafür die nächste Stelle um 1 erniedrigt for($i=1;$i<$nAtome;$i++){#dann muss diese und folgende natürlich auch kontrolliert werden if($Kombi[$i]<0){#wenn die Stelle kleiner 0 ist $Kombi[$i]=$max[$i];#wird sie zurück gesetzt $Kombi[$i+1]--;#und die folgende um 1 erniedrigt } } } #bis hier werden einfach alle Kombinationen nacheinander generiert (eine Art mechanisches Zählwerk) #Dabei muss die Anzahl der möglichen Kombinationen exakt bekannt sein, #da der Zähler sonst ins Negative läuft. #eine do-until oder while Schliefe wäre logischer, aber viel langsamer als die for-Schleife (s.o.) $Wahrscheinlichkeit=1;#Initialisierung der Wahrscheinlichkeit für einen Zweig $Masse=0; # Initialisierung der Massen-Abweichung von M-0 für einen Zweig #$Masse enthält am Ende der Schleife nur die Abweichung von M+0, nicht die tatsächliche Masse for($j=0;$j<=$nAtome;$j++){ #jetzt werden einfach alle Atome = alle Abzeige nacheinander durchmultipliziert $temp="Z".$Position_OZ[$j]."W".$Kombi[$j]; # @Position_OZ enthält das ElementSymbol der hypotetischen linearen Atomkette # z.B. nacheinander C-C-C-H-H-H-H-H-H-S-S (s.o.) # %Element_Werte enthält folgende Daten nach folgendem Schlüssel: # Z-ElementSymbol-W-Isotop-Nr W=Wahrscheinlichkeit von 0-1 # Z-ElementSymbol-M-Isotop-Nr M=MassenAbweichung zum häufigsten Isotop (M+0) # Beispiel: # Z-C-W-0 = 98,9% bzw. 0.989 # Z-C-W-1 = 1.1% bzw. 0.011 # Z-C-M-0 = 0 (da häufigstes Element) # Z-C-M-1 = 1 (da 13C 1 schwerer als das häufigste 12C) # $temp enthält den Schlüssel für die aktuelle Position $Wahrscheinlichkeit=$Wahrscheinlichkeit*$Element_Werte{$temp}; $temp=~s/W/M/g; # Ändert den Schlüssel von Wahrscheinlichkeit auf Masse $Masse=$Masse+$Element_Werte{$temp}; } #Ich habe auch probiert, die Berechnung abzubrechen, wenn die Wahrscheinlichkeit #unter z.B. 1/1000 % fällt, einfach um Rechenschritte und so Zeit zu sparen. #Tatsächlich summieren sich die Fehler aber sehr deutlich, auch wenn man den Wert extrem klein hält. #denn offensichtlich macht "auch Kleinvieh Mist". #FehlerKontrolle siehe weiter unten #Jetzt enthält $Masse die Abweichung von M+0 also der Kette, die nur aus den jeweils #häufigsten Isotopen besteht. #ACHTUNG: z.B. Fe hat Isotope, die leichter als das häufigste Isotope sind. #Die Massendifferenz zu M+0 kann also negativ sein. #Um dieses Problem zu umgehen, wird temporär einfach 100 addiert. $Masse=$Masse+100; if($Masse<0){$Masse=0;}#$Masse darf nicht negativ sein. #Falls z.B. durch viel Fe ein Zweig unter M-100 fällt, muss eingegriffen werden #damit das Programm nicht abstürtzt. Ja, das ist sehr unsauber! #Aber M-100 sind schon sehr sehr unwahrscheinlich. $Wahrscheinlichkeit[$Masse]=$Wahrscheinlichkeit[$Masse]+$Wahrscheinlichkeit; #Jetzt werden einfach alle Zweige, die in der selben Massendifferenz enden, in einer Liste #nach und nach aufaddiert ($Masse+100) dient hier als Index, deswegen darf hier kein negativer #Wert auftreten... } ################ Ausgabe: ################## $Kontrolle = -1; for ($i = 0; $i < @Wahrscheinlichkeit; $i++){ $Kontrolle = $Kontrolle +$Wahrscheinlichkeit[$i]; } } #Summiert man alle Wahrscheinlichkeiten auf, muss sich am Ende 1 ergeben, dann weiß man, dass #alle Möglichkeiten durchprobiert wurden. #Wird mit -1 angefangen, später mit 100 multipliziert hat man am Ende einen Wert in % #der Möglichkeiten die ausgelassen wurden. #Hier hat sich auch gezeigt, dass ein Abbruch nicht praktikabel ist, sondern wirklich alle Zweige #durchgerechnet werden müssen. #Sehr deutlich findet man so auch Tipp-Fehler in der Isotopen-Datenbank... #So, das wars, jetzt kann man einfach @Wahrscheinlichkeit nach und nach durchgehen #@Wahrscheinlichkeit enthält mit der Massen-Abweichung zu M+0 als Index #die Wahrscheinlichkeit für das Auftreten dieser Masse (Korrektur um 100 nicht vergessen)