Einführung zu Python und ROOT für Bachelorstudenten David Boersma Physikzentrum 28. Januar 2011; nachbearbeitet Februar 2011 1 / 59 Outline 1 Allgemeines Vorkentnisse Geschichte 2 Python Hallo Welt Rechnen Behälter und Sammlungen 3 ROOT Hallo Welt Histogramme Zufallszahlen Graphen Funktionen Dateien Trees 2 / 59 Vorkentnisse (wer ist mein Publikum) • Linuxerfahrung? • Man kann aber auch ROOT und PyROOT auf Windowsrechner machen • Programmiererfahrung (Java, C/C++, python, PHP, andere?) • Nicht strikt nötig, ist aber sehr hilfreich. • Vorlesung Datenverarbeitung: Maple? ROOT? • Maple und (Py)ROOT haben nicht soviel mit einander gemein • ROOT mit C++/CINT: gleiche ROOT-Klassen, völlig andere Skripting-Style. • Texteditor? • Ein Texteditor ist kein Wordprozessor • Es lohnt sich einen Texteditor sehr gut zu kennen • Einfache Texteditoren in Linux: kate, gedit • Kräftige Texteditoren (Linux und Windows): (g)vim, emacs 3 / 59 Vorkentnisse (wer ist mein Publikum) • Linuxerfahrung? • Man kann aber auch ROOT und PyROOT auf Windowsrechner machen • Programmiererfahrung (Java, C/C++, python, PHP, andere?) • Nicht strikt nötig, ist aber sehr hilfreich. • Vorlesung Datenverarbeitung: Maple? ROOT? • Maple und (Py)ROOT haben nicht soviel mit einander gemein • ROOT mit C++/CINT: gleiche ROOT-Klassen, völlig andere Skripting-Style. • Texteditor? • Ein Texteditor ist kein Wordprozessor • Es lohnt sich einen Texteditor sehr gut zu kennen • Einfache Texteditoren in Linux: kate, gedit • Kräftige Texteditoren (Linux und Windows): (g)vim, emacs 3 / 59 Vorkentnisse (wer ist mein Publikum) • Linuxerfahrung? • Man kann aber auch ROOT und PyROOT auf Windowsrechner machen • Programmiererfahrung (Java, C/C++, python, PHP, andere?) • Nicht strikt nötig, ist aber sehr hilfreich. • Vorlesung Datenverarbeitung: Maple? ROOT? • Maple und (Py)ROOT haben nicht soviel mit einander gemein • ROOT mit C++/CINT: gleiche ROOT-Klassen, völlig andere Skripting-Style. • Texteditor? • Ein Texteditor ist kein Wordprozessor • Es lohnt sich einen Texteditor sehr gut zu kennen • Einfache Texteditoren in Linux: kate, gedit • Kräftige Texteditoren (Linux und Windows): (g)vim, emacs 3 / 59 Vorkentnisse (wer ist mein Publikum) • Linuxerfahrung? • Man kann aber auch ROOT und PyROOT auf Windowsrechner machen • Programmiererfahrung (Java, C/C++, python, PHP, andere?) • Nicht strikt nötig, ist aber sehr hilfreich. • Vorlesung Datenverarbeitung: Maple? ROOT? • Maple und (Py)ROOT haben nicht soviel mit einander gemein • ROOT mit C++/CINT: gleiche ROOT-Klassen, völlig andere Skripting-Style. • Texteditor? • Ein Texteditor ist kein Wordprozessor • Es lohnt sich einen Texteditor sehr gut zu kennen • Einfache Texteditoren in Linux: kate, gedit • Kräftige Texteditoren (Linux und Windows): (g)vim, emacs 3 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Historisches • ∼ 1970 . . . UNIX und C (Thompson, Kernighan, Ritchie, . . .) • 1976 . . . : Microsoft (Bill Gates and Paul Allen) • 1980 . . . : Maple (Kanada) (Version 1.0 in 1982) • 1983 . . . : GNU (Richard Stallman) • 1989 . . . : Python (Guido van Rossum) • 1991: Linux (Linus Torvalds) • 1979 . . . 1998 . . .: C++ (Brian Stroustrup) • 1995 . . . : ROOT (René Brun et al.) Bilder geklaut von der ROOT Webseite (René Brun) und wikipedia (alle andere). 4 / 59 Python: Hallo Welt (4x) • • • • interaktiv: mit python interaktiv: mit ipython nicht-interaktiv: python Skript schreiben, es ausführen mit python semi-interaktiv: python Skript schreiben, es ausführen mit ipython Terminal $ python Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> print "Hallo Welt!" Hallo Welt! >>> . . . weitere Python-Befehle . . . 6 / 59 Python: Hallo Welt (4x) • • • • interaktiv: mit python interaktiv: mit ipython nicht-interaktiv: python Skript schreiben, es ausführen mit python semi-interaktiv: python Skript schreiben, es ausführen mit ipython Terminal $ ipython Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) Type "copyright", "credits" or "license" for more information. IPython 0.10 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython’s features. %quickref -> Quick reference. help -> Python’s own help system. object? -> Details about ’object’. ?object also works, ?? prints more. In [1]: print "Hallo Welt!" Hallo Welt! In [2]: . . . weitere Python-Befehle . . . 6 / 59 Python: Hallo Welt (4x) • • • • interaktiv: mit python interaktiv: mit ipython nicht-interaktiv: python Skript schreiben, es ausführen mit python semi-interaktiv: python Skript schreiben, es ausführen mit ipython Text Editor #!/usr/bin/env python # -*- coding: latin-1 -*# hier ein hallo welt befehl print "Hallo große Welt!" 6 / 59 Python: Hallo Welt (4x) • • • • interaktiv: mit python interaktiv: mit ipython nicht-interaktiv: python Skript schreiben, es ausführen mit python semi-interaktiv: python Skript schreiben, es ausführen mit ipython Terminal $ gedit hallowelt.py $ python hallowelt.py Hallo große Welt! $ . . . zurück im Shell . . . 6 / 59 Python: Hallo Welt (4x) • • • • interaktiv: mit python interaktiv: mit ipython nicht-interaktiv: python Skript schreiben, es ausführen mit python semi-interaktiv: python Skript schreiben, es ausführen mit ipython Terminal $ gedit hallowelt.py $ ipython -nobanner In [1]: %run hallowelt.py Hallo große Welt! In [2]: . . . weitere Python-Befehle . . . 6 / 59 Rechnen mit int & float & complex • int: ganze Zahlen • float: Fließkommazahlen • complex: Komplexe Zahlen # int: ganze Zahlen, pass auf bei Divisionen i=3 j=7 print "i/j=", i/j, "j/i=", j/i print "-i/j=", -i/j, "-j/i=", -j/i # int: explizit erzeugen acht=int(8.0) neun=int("9") print "acht=",acht,"neun=",neun # "modulo" rechnen m=j%i print "j modulo i = ", m m=(-j)%i print "-j modulo i = ", m # kein Limit auf Groesse gross=123456789012345678901234567890 print "gross=",gross 7 / 59 Rechnen mit int & float & complex • int: ganze Zahlen • float: Fließkommazahlen • complex: Komplexe Zahlen # floats haben einen dezimalen Komma/Punkt x=1. y=-234234.989430 c=2.99792458e8 zwoelf=float("12") # gemischte Ausdruecke von ints und floats werden float w=int(3)*float(2.71231) print "x=",x, "y=",y, "c=",c, "zwoelf=",zwoelf, "w=", w 7 / 59 Rechnen mit int & float & complex • int: ganze Zahlen • float: Fließkommazahlen • complex: Komplexe Zahlen # j ist die imaginaere Zahl z1=5.3+6.3j z2=3.1+4.2j zprod=z1*z2 zdiv=z1/z2 print "zprod=",zprod, "zdiv=",zdiv print "zprod: real=",zprod.real, "imag=", zprod.imag 7 / 59 Strings • ”Text”, ’Text’, oder ”””Text””” • Formattieren: %-Syntax • Addieren, join(), split() # "" oder ’’ Name="Higgs" xAchse=’Energie [GeV]’ KurtzerSatz="Er sagte: ’Ich bin ein Berliner.’" # """ LangerSatz=""" Wenn man gut durch geoeffnete Tueren kommen will, muss man die Tatsache achten dass sie einen festen Rahmen haben: dieser Grundsatz, nach dem der alte Professor immer gelebt hatte, ist einfach eine Forderung des Wirklichkeitssinns. """ 8 / 59 Strings • ”Text”, ’Text’, oder ”””Text””” • Formattieren: %-Syntax • Addieren, join(), split() n=33 m=8 t=13.44298347987 y=2342.323e-22 plottitle="Spektrum summiert von %d Samples" % n legendetext="Messzeit: %7.3f Sekunden" % t print "title=", plottitle, "legend=", legendtext print "dezimal: %3d und %d" % (n,m) # oktal: %o, hex: %x print "%f, %.2f, %20.4f, %g, %20.12g" % (x,x,x,y,y) 8 / 59 Strings • ”Text”, ’Text’, oder ”””Text””” • Formattieren: %-Syntax • Addieren, join(), split() # addieren, wiederholen phy="phy" sik="sik" print "addieren:",phy+sik strich=’=’*10 # ergibt "==========" # split zahlentext="23.3 28374.33 2324.32 1212.3434" zahlenliste=zahlentext.split() print "split:", zahlenliste # join: Liste zusammenfuegen zu einem String komma="," neuertext=komma.join(zahlenliste) print "join:",neuertext 8 / 59 Listen, Tuples, dictionaries • Eine Liste (eckige Klammer) ist (in Python) eine flexibele Sammlung beliebiger Objekte: • • • • Elemente hinzufügen (append) oder wegnehmen (pop()) oder ändern Sortieren Teilsammlungen bilden etc. • Eine Tuple (runde Klammer) ist wie eine Liste, aber darf nach Erzeugen nicht mehr geändert werden. • Ein Dictionary (geschweifte Klammer) wird indexiert mit beliebige Werte (z.B. Strings), nicht nur Ganzzahlen. • Ein Array hat eine feste Länge und alle Elemente sind vom gleichen Datentyp. # Liste stuff=[232,"foo","bar",2343.23423,3.0+4.1j] stuff.append(42) numbers=[4,2,6,3,5.5] numbers.pop(1) numbers.sort() numbers[0]=77 lastone=numbers[-1] 9 / 59 Listen, Tuples, dictionaries • Eine Liste (eckige Klammer) ist (in Python) eine flexibele Sammlung beliebiger Objekte: • Eine Tuple (runde Klammer) ist wie eine Liste, aber darf nach Erzeugen nicht mehr geändert werden. • Ein Dictionary (geschweifte Klammer) wird indexiert mit beliebige Werte (z.B. Strings), nicht nur Ganzzahlen. • Ein Array hat eine feste Länge und alle Elemente sind vom gleichen Datentyp. # Tupel drei=(1,2,3) #drei.append(4) GEHT NICHT, TUPLE UNVERAENDERLICH #drei.pop(1) GEHT NICHT, IDEM #drei.sort() GEHT NICHT, IDEM #drei[0]=77 GEHT NICHT, IDEM lastone=drei[-1] # GEHT! ERGIBT 3 9 / 59 Listen, Tuples, dictionaries • Eine Liste (eckige Klammer) ist (in Python) eine flexibele Sammlung beliebiger Objekte: • Eine Tuple (runde Klammer) ist wie eine Liste, aber darf nach Erzeugen nicht mehr geändert werden. • Ein Dictionary (geschweifte Klammer) wird indexiert mit beliebige Werte (z.B. Strings), nicht nur Ganzzahlen. • Ein Array hat eine feste Länge und alle Elemente sind vom gleichen Datentyp. # Dictionary telefon={} telefon["Boersma"]=27295 telefon["Wiebusch"]=27300 print telefon["Boersma"] # Gibt aus: 27295 9 / 59 Listen, Tuples, dictionaries • Eine Liste (eckige Klammer) ist (in Python) eine flexibele Sammlung beliebiger Objekte: • Eine Tuple (runde Klammer) ist wie eine Liste, aber darf nach Erzeugen nicht mehr geändert werden. • Ein Dictionary (geschweifte Klammer) wird indexiert mit beliebige Werte (z.B. Strings), nicht nur Ganzzahlen. • Ein Array hat eine feste Länge und alle Elemente sind vom gleichen Datentyp. # (Numpy) Array import numpy hundertnullen=numpy.zeros(100,’d’) # (’d’ouble precision floats) #hundertnullen.append(1) GEHT NICHT: ARRAYS HABEN FESTE LAE hundertnullen[42]=1.23456 # GEHT hunderteinsen=numpy.ones(100,’d’) hunderteinsen*=8. # jetzt hundert achten! hunderteinsen/=2. # jetzt hundert vieren! hunderteinsen[0]=3.318e1 # erstes ist jetzt 33.18 hunderteinsen*=hundertnullen # jetzt alle 0, ausser das 43. 9 / 59 Funktionen # definieren def hallo(): print "Hallo Welt!" def berechung(x,y): summe=x+y return summe def viele_optionen(x,**kwargs): if kwargs.has("name"): print "hallo %s! x=%f" % (kwargs["name"],x) else: return False return True # aufrufen hallo() z=berechung(3.3,4.4) print "z=",z wahr=viele_optionen(42.1,name="Welt") if not wahr: print "Hmmm..." 10 / 59 Python: Bedingungen I • Eine Bedingung (in Python, boolean expression) ist entweder wahr (True) oder unwahr (False). • Vergleichsoperatoren für Zahlenwerte: strikt kleiner als kleiner oder gleich >= größer oder gleich > strikt größer als == gleich != ungleich • Logische Operatoren: or (ODER), and (UND), not (NICHT). Klammern können eingesetzt werden wenn nötig, z.B. (x<3.1 or x>13.5) and i==3 < <= • Wegen Ründung sind für Fließkommazahlen die Operatoren == und != zu vermeiden. 11 / 59 Python: Bedingungen II • Zahlenwerte können auch in logische Ausdrücken eingesetzt werden; dabei gilt Null als False und Zahlen ungleich Null als True. • Strings können auch in logische Ausdrücken eingesetzt werden; dabei gilt ein leerer String als False und nicht-leere Strings als True. • Der Spezialwert None (”nicht definiert”) gilt in logischem Kontext als False. 12 / 59 Python: if, for, while • • • • Einfach bedingte Ausführung von Befehlen Mehrfach bedingte Ausführung von Befehlen Wiederholte Ausführung von Befehlen Ausführung von Befehlen für Elemente einer Liste i=42 x=3.14 filename="Higgsevents.roooooot" # Gleichheit wird mit "==" getestet if i==42: print "Die Antwort ist richtig." # Logische Ausdruecke if (x<4. and i>40) or (i<0 and not x<0): print "Zusammengestellte Bedingung erfuellt." # Substrings vergleichen if filename[0:5]=="Higgs" and filename[-5:]==".root": print "ROOT-Datei mit Higgs-Ereignissen gefunden!" 13 / 59 Python: if, for, while • Einfach bedingte Ausführung von Befehlen • Mehrfach bedingte Ausführung von Befehlen • Wiederholte Ausführung von Befehlen • Ausführung von Befehlen für Elemente einer Liste Note=1 #... if Note>5: print "Upsie." elif Note>4: print "Na schade..." elif Note<=4 and Note>=1: print "Toll!" else: print "Hae, was?" 13 / 59 Python: if, for, while • Einfach bedingte Ausführung von Befehlen • Mehrfach bedingte Ausführung von Befehlen • Wiederholte Ausführung von Befehlen • Ausführung von Befehlen für Elemente einer Liste n=0 Nmax=10 while n<Nmax: n+=1 print "Durchlauf Nr. %d" % n 13 / 59 Python: if, for, while • Einfach bedingte Ausführung von Befehlen • Mehrfach bedingte Ausführung von Befehlen • Wiederholte Ausführung von Befehlen • Ausführung von Befehlen für Elemente einer Liste Leptonen=["Elektron","Myon","Tau"] for Lepton in Leptonen: print "Ein %s ist ein Lepton." % Lepton EinsBisZehn=[1,2,3,4,5,6,7,8,9,10] for n in EinsBisZehn: print "Durchlauf Nr. %d" % n NullBisNeun=range(10) for n in NullBisNeun: print "Durchlauf Nr. %d" % (n+1) 13 / 59 Programmierterminologie I • Objekt: eine zusammenhangende Menge digitale Information, mit wohldefinierte Eigenschaften; z.B.: • Einfach: Ganzzahlen (int), Fließkommazahlen (float) • Bisschen fancier: Liste (list), dictionaries (dict), Sammlung (set), Arrays • Komplexere Objekten: z.B. ROOT Histogramme • Methode (beim Programmieren): eine Funktion die an einem Objekt gebunden ist, die also nicht nur die Funktionsargumenten nutzen kann, sondern auch die interne Daten des Objekts. Z.B.: wenn zahlen eine Liste ist, dann werden mit der sort() Methode die Elementen der Liste sortiert: zahlen.sort(). • Datentyp: Spezifiziert wie man ein Objekt benutzen kann: welche Methoden hat es, in welchen Funktionen kann ich es einsetzen. 14 / 59 Programmierterminologie II • Klasse: wie ein Datentyp, aber auch mit einer spezifischer Implementierung. In Praxis werden die Termen ”Klasse” und ”Datentyp” oft als Synonym benutzt (sind sie aber eigentlich nicht). • Modul (in Python, English: ”module”): ein Modul kann in Python (Skript, oder interaktiv) importiert werden, und damit werden dann Klassen und/oder Objekten zur Verfügung gestellt die nicht zur Basisfunktionalität von Python gehören. Z.B. mit import ROOT werden die (viele viele) Klassen und Objekten von ROOT ”geladen”. 15 / 59 Python: Dokumentation I • Gutes Buch • Für Anfänger: z.B. TODO • Schon mit Programmieren vertraut: z.B. Python, Essential Reference, Fourth Edition von David M. Beazley. (Third Edition und älter: reicht vielleicht fürs Praktikum, aber nicht empfohlen...) • Python Webseiten: • http://www.python.org (international) • http://www.python.de (Deutsch) 16 / 59 Python: Dokumentation II • Interaktiv: mit der help(irgendwas) kann man in python oder in ipython Hilfetext abfragen für sowohl Objekten als Pythonklassen und importierte Klassen: Terminal $ ipython -nobanner In [1]: z=2.1+4.55j In [2]: help(z) In [3]: help(list) In [4]: import numpy In [5]: help(numpy.array) Die Quantität und Qualität der Hilfe variiert leider stark. • Auch hilfreich: Beispielskripten und erfahrene KommilitonInnen. 17 / 59 Hallo Welt Öffnen Sie einen Terminal und versuchen Sie folgendes: Terminal $ ipython -nobanner in [1]: import root in [2]: canvas=root.tcanvas("canvas","guck mal!") in [3]: hallo=root.ttext(0.4,0.5,"hallo welt") in [4]: hallo.draw() Es sollte ein neues Fenster geöffnet sein und mit dem Text ”Hallo Welt” darauf gemalt. (Eventuell muß erst noch auf dem ”Canvas” geklickt werden.) 19 / 59 Hallo Welt • Der import ROOT Befehl lädt die ROOT Funktionalität. • Klassen, Objekten und Funktionen des ROOT-Moduls haben einen ”ROOT.” Prefix, z.B. ROOT.TCanvas. • Alternativ: from ROOT import . . ., wobei . . . eine Liste ist mit den im Skript benutzten ROOT-Klassen, z.B. from ROOT import TCanvas,TH1D,TRandom3. Wenn so importiert muß man kein ”ROOT.” Prefix mehr verwenden. • Viele ROOT Objekten (z.B. hier canvas) müssen einen Namen haben (hier: ”canvas”); der muß einheitlich sein und keine Sonder- weder Lehrzeichen enthalten. • Die Namen vieler ROOT-Klassen fangen mit ”T” an; warum das ist, weiß fast niemand. • Produktiv arbeiten: interaktiv Sachen ausprobieren, dann Skripten schreiben, usw. 21 / 59 Histogramme (Häufigkeitsverteilungen) Beispielcode: import ROOT ROOT.gStyle.SetOptStat(101) h=ROOT.TH1D("Wuerfel","Ist der Wuerfel ehrlich?",6,1.,7.) for wuerfel in [1,5,6,1,5,2,4,3,5,2,6,1]: h.Fill(wuerfel) h.GetXaxis().SetTitle("Wuerfel") h.GetYaxis().SetTitle("Haeufigkeit") h.SetLineWidth(2) h.SetLineColor(ROOT.kBlue) canvas=ROOT.TCanvas("canvas","Guck mal!") h.Draw() canvas.Print("figures/wuerfel.pdf") for i in range(0,8): print h.GetBinContent(i) 22 / 59 Histogramme (Häufigkeitsverteilungen) Wuerfel Mean 3.417 Haeufigkeit Ist der Wuerfel ehrlich? 3 2.5 2 1.5 1 1 2 3 4 5 6 7 Wuerfel 23 / 59 TH1D Histogramme I • Das Histogramm hat einen einheitlichen Namen und einen (beliebigen) Titel • Die Bins werden spezifiziert mit Anzahl der Bins und Grenzwerten. • Für jeder Bin: untere Grenze ist inklusive, obere Grenze exklusive. • Mit der Fill(x)-Methode wird den Bin gefunden worin der Wert x liegt, und die entsprechende Häufigkeit um 1 erhöht. • Wenn beim ausführen der Draw()-Methode noch kein Canvas existiert, dann wird automatisch einen erzeugt. • Das Kästchen mit Statistik läßt sich mit SetOptStat(arg) konfigurieren: die Elementen (Titel, Entries, Mean, RMS, etc.) werden mit 1 oder 0 an- bzw. ausgeschaltet. (Komischer Syntax? Ja sicher...) • Die Bins sind numeriert von 1 bis Nbins, also hier von 1 bis 6. Bins 0 und Nbins + 1, sind underflow und overflow, respektive (wieviele mit Fill(x) gegebenen Werten waren ausserhalb der Histogrammgrenzen). Also die Schleife am Ende des Beispielskripts gibt aus: 0, 3, 2, 1, 1, 3, 2, 0, respektive. 24 / 59 TH1D Histogramme II • Ein Histogramm ohne Achsenbeschriftungen ist wie ein Fahrrad ohne Räder: wertlos. • Deutsche Zeichen (Umlaut, ß) sind leider nur mit etwas holprigen Tricks teilweise unterstützt (z.B. "#ddot{a}" ergibt ä in Achsenbeschriftungen); es spart Zeit und Nerven wenn man sie einfach vermeidet. • Sonstige Tricks für Achsenbeschriftungen: • Sub- und Superskript: "T_{mean}ˆ{2}=A_{0}Bˆ{2}" √ • Grad (25◦ , Plusminus (±3.3), Wurzel ( 5), Mikrometer (µm): "25#circ, #pm3.3, #surd5, #mum" • Grieches Buchstaben: "#alpha, #beta, #gamma..." • Siehe TLatex in der Class Reference. Achtung: leider sind Sonderzeichen in gespeicherten Bildern manchmal anders dargestellt als auf dem Bildschirm: immer überprüfen! 25 / 59 2D-Histogramm Beispielcode: import ROOT ROOT.gStyle.SetOptStat(0) ROOT.gStyle.SetPalette(1) g2d=ROOT.TH2D("g2d","Gaussverteilte Zufallszahlen", \ 20,-1.5,1.5, 20, -2.5, +2.5) zzg=ROOT.TRandom3(42) n=0 while n<100000: x=zzg.Gaus(0.,1.) y=zzg.Gaus(0.,2.) g2d.Fill(x,y) n+=1 g2d.GetXaxis().SetTitle("X") g2d.GetYaxis().SetTitle("Y") g2d.GetZaxis().SetTitle("Counts") canvas1=ROOT.TCanvas("canvas1","Guck mal!") #g2d.SetMarkerStyle(ROOT.kFullCircle) g2d.Draw() canvas1.Print("figures/th2dplain.pdf") canvas=ROOT.TCanvas("canvas","Guck mal!") canvas.Divide(2,2) canvas.cd(1) g2d.Draw("LEGO") canvas.cd(2).SetRightMargin(10) g2d.Draw("ZCOL") canvas.cd(3) g2d.Draw("SURF2") canvas.cd(4) g2d.Draw("BOX") canvas.Print("figures/th2dfancy.pdf") 26 / 59 2D-Histogramm (ohne Schmuck) Y Gaussverteilte Zufallszahlen 2.5 2 1.5 1 0.5 0 -0.5 -1 -1.5 -2 -2.5 -1.5 -1 -0.5 0 0.5 1 1.5 X 27 / 59 2D-Histogramm (mit Schmuck) 2.5 Counts 2 350 1.5 300 1 250 300 250 0.5 200 150 0 100 -0.5 50 2.5 Y 2 1.5 Counts Gaussverteilte Zufallszahlen Y Gaussverteilte Zufallszahlen 200 150 -1 -1.5 10.5 0 -0.5 -1 -1.5 -2 -2.5 -1.5 -1 -0.5 0 0.5 1 1.5 X -2.5 -1.5 50 -1 -0.5 0 0.5 1 1.5 X 0 0.5 1 1.5 X Gaussverteilte Zufallszahlen Y Gaussverteilte Zufallszahlen 100 -2 2.5 Counts 2 350 1.5 300 1 250 0.5 200 150 0 100 -0.5 50 2.5 Y 2 1.5 -1 -1.5 10.5 0 -0.5 -1 -1.5 -2 -2.5 -1.5 -1 -0.5 0 0.5 1 1.5 X -2 -2.5 -1.5 -1 -0.5 28 / 59 2D-Histogramm (und Canvas) • SetPalette(1) setzt einen vernünftige Farbenskala (der Defaultskala ist grausam) • TRandom3: Zufallszahlgenerator (siehe nächsten Abschnitt) • Ein Canvas läßt sich aufteilen mit Divide(nrows,ncolums). Die Teilcanvasse sind numeriert von 1 (linksoben) bis nrows×ncolumns (rechts unten). Mit cd(nummer) wird den gewünschten Teilcanvas gewählt. Nummer 0 entspricht den gesamten Canvas. • Mit Print() wird der Canvas nicht gedruckt sondern als Bilddatei gespeichert. Unterstützte Formate sind (u.a.) EPS, PDF, PNG. Achtung: Sonderzeichen kommen manchmal leider anders im Bilddatei als auf dem Bildschirm. 29 / 59 Zufallszahlen: Generator Erzeugt man so: zzg = ROOT.TRandom3(seed), wobei seed eine nicht-negative Ganzzahl ist. • Es gibt auch noch TRandom1 und TRandom2, die sind aber weniger gut. • Mit seed größer als 0 wird eine deterministische Reihe Zufallszahlen erzeugt (”pseudorandom”), also gleiche Ergebnisse bei wiederholter Ausführung des Skripts. • Mit seed gleich 0 wird eine nicht-wiederholbare Reihe Zufallszahlen erzeugt, also bei wiederholte Ausführung gibt es unterschiedliche Ergebnisse. • Für die meisten Anwendungen reicht ein Zufallszahlengenerator für das gesamte Skript, also: OK bisschen doof falsch zzg=ROOT.TRandom(27295) for i in range(1000000): x=zzg.Uniform(-10,10) y=zzg.Uniform(-10,10) # etc zzgX=ROOT.TRandom(27295) zzgY=ROOT.TRandom(27300) for i in range(1000000): x=zzgX.Uniform(-10,10) y=zzgY.Uniform(-10,10) # etc zzgX=ROOT.TRandom(27295) zzgY=ROOT.TRandom(27295) for i in range(1000000): x=zzgX.Uniform(-10,10) y=zzgY.Uniform(-10,10) # etc 30 / 59 Zufallszahlen: Verteilungen Zum Beispiel: angenommen zzg ein ROOT.TTrandom3 Objekt, dann gibt zzg.Uniform(-3,5) eine Zufallszahl zurück, gezogen aus einer Gleichverteilung von -3 bis +5. Andere Verteilungen: • Exp(tau) • Integer(imax) • Gaus(mean,sigma) • Landau(mpv,sigma) • Poisson(mean) • Binomial(ntot,prob) 31 / 59 Graphen (ROOT.TGraph und ROOT.TGraphErrors) 32 / 59 # Methode 1 (macht dasgleiche wie 2) import ROOT # Methode 2 (macht dasgleiche wie 1) import ROOT import numpy # ohne Fehlerbalken ("graph") g=ROOT.TGraph(3) g.SetPoint(0,1.5,3.2) g.SetPoint(1,2.5,0.2) g.SetPoint(2,3.5,-0.7) # ohne Fehlerbalken ("graph") agx=numpy.array([1.5,2.5,3.5],’d’) agy=numpy.array([3.2,0.2,-0.7],’d’) g=ROOT.TGraph(3,agx,agy) # mit Fehlerbalken ("messungen") m=ROOT.TGraphErrors(3) m.SetPoint(0,1.5,2.8) m.SetPointError(0,0.25,0.4) m.SetPoint(1,2.5,0.4) m.SetPointError(1,0.25,0.6) m.SetPoint(2,3.5,-0.6) m.SetPointError(2,0.25,0.25) # mit Fehlerbalken ("messungen") agex=numpy.arange(1.5,3.51,1.0,’d’) agey=numpy.array([2.8,0.4,-0.6],’d’) agedx=numpy.ones(3,’d’)*0.25 agedy=numpy.array([0.4,0.6,0.25],’d’) m=ROOT.TGraphErrors(3,agex,agey,agedx,agedy) # Achsenbeschriftung m.GetXaxis().SetTitle("Zeit [s]") m.GetYaxis().SetTitle("Abstand [m]") m.SetTitle("Bewegung") # Achsenbeschriftung m.GetXaxis().SetTitle("Zeit [s]") m.GetYaxis().SetTitle("Abstand [m]") m.SetTitle("Bewegung") # Kosmetik g.SetLineColor(ROOT.kRed) g.SetLineWidth(2) m.SetMarkerStyle(ROOT.kFullCircle) m.SetMarkerColor(ROOT.kBlue) m.SetLineColor(ROOT.kGreen+1) # Kosmetik g.SetLineColor(ROOT.kRed) g.SetLineWidth(2) m.SetMarkerStyle(ROOT.kFullCircle) m.SetMarkerColor(ROOT.kBlue) m.SetLineColor(ROOT.kGreen+1) # Plotten canvas=ROOT.TCanvas("canvas","Guck mal!") m.Draw("ALP") g.Draw("C") canvas.Print("figures/g.pdf") # Plotten canvas=ROOT.TCanvas("canvas","Guck mal!") m.Draw("ALP") g.Draw("C") canvas.Print("figures/g.pdf") Bemerkungen zu Graphen I • Manchmal ist es praktischer mit SetPoint(...) zu arbeiten, manchmal mit arrays. • Bei arrays: aufpassen dass die Datentypen alle gleich sind: entweder alle double (’d’) oder alle single precision (’f’). • numpy.arange(xlo,xhi,dx,dtype) erzeugt einen Array mit Elementen x[i]=xlo+i*dx vom Type dtype (’f’ oder ’d’ für single oder double precision floats), x[i] ≥ xlo und x[i] < xhi. • numpy.ones(n,dtype) erzeugt einen Array mit Länge n, alle Elementen sind gleich 1. (Wenn ein numpy array mit ein Skalarwert multipliziert wird, werden alle Elementen multipliziert.) • Draw-Optionen: ”A” erzeugt neue Achsen, ”L” zieht Geraden zwischen den Punkten, ”C” eine Kurve, und ”P” Punkte (Polymarker ). 34 / 59 Bemerkungen zu Graphen II • Markers: siehe http://root.cern.ch/root/ html526/TAttMarker.html. • Linien: siehe http: //root.cern.ch/root/html526/TAttLine.html. • Farben: selektiere ”Color” im ”View”-Menü in einem Canvasfenster, das ergibt: (nächste Folie) 35 / 59 Bemerkungen zu Graphen III 36 / 59 Funktionen Auslenkung [mm] Schwung 10 5 0 -5 -10 -10 -8 -6 -4 -2 0 2 4 6 8 10 Zeit [s] 37 / 59 # Teil 1: die rote Kurve import ROOT # Funktionsbereich xmin=-10 xmax=+10 # TF1 definiert von Formel in String tf1_rot=ROOT.TF1("tf1_rot", \ "[0]*exp(x/[1])*sin([2]*x)", \ xmin, xmax ) # Parameterwertzuweisung # ([0], [1], [2] in der Formel) tf1_rot.SetParameter(0,5.) tf1_rot.SetParameter(1,10.0) tf1_rot.SetParameter(2,2.) tf1_rot.SetTitle("Schwung") # Kosmetik und Achsenbeschriftung tf1_rot.SetLineColor(ROOT.kRed+1) tf1_rot.SetLineWidth(2) tf1_rot.GetXaxis().SetTitle("Zeit [s]") tf1_rot.GetYaxis().SetTitle( \ "Auslenkung [mm]") # Plotten canvas=ROOT.TCanvas("canvas","Guck mal!") tf1_rot.Draw() # Teil 2: die blaue Kurve # (aehnlich aber anders) import ROOT from numpy import exp,sin xmin=-10 xmax=+10 def schwung(ax,apar): x=ax[0] return apar[0]*exp(x/apar[1]) \ *sin(apar[2]*x) # TF1 definiert von Python Funktion # (mit 3 freien Parametern) tf1_blau=ROOT.TF1("tf1_blau", \ schwung,xmin,xmax,3) # Parameterwertzuweisung # (apar[0], apar[1], apar[2] in schwung) tf1_blau.SetParameter(0,-5.) tf1_blau.SetParameter(1,-10.0) tf1_blau.SetParameter(2,2.) tf1_blau.SetTitle("Schwung") # Kosmetik und Achsenbeschriftung tf1_blau.SetLineColor(ROOT.kBlue+1) tf1_blau.SetLineWidth(2) tf1_blau.GetXaxis().SetTitle("Zeit [s]") tf1_blau.GetYaxis().SetTitle( \ "Auslenkung [mm]") # Plotten in gleicher Figur, und speichern tf1_blau.Draw("same") canvas=ROOT.gROOT.FindObject("canvas") canvas.Print("figures/schwung.pdf") Bemerkungen zu Funktionen I • TF1 mit String-Formel nur geeignet für sehr einfache Funktionen • Für aufwändigere Funktionen: immer mit Python-Funktion • Wie der Name TF1 schon vermuten läßt, gibt es auch ROOT-Funktionen von 2 oder 3 Variablen definieren mit TF2 (x,y) resp. TF3 (x,y,z). • Farben und Linien: wie bei Graphen. • Parameter können auch Namen bekommen, z.B. tf1_rot.SetParName(2,"Winkelfrequenz") 39 / 59 Bemerkungen zu Funktionen II • TH1D-Histogramme und Graphen können mit einer TF1-Funktion gefittet werden, z.B. wenn sm ein TGraphErrors-Objekt mit Schwingungsmessungen ist, dann sucht sm.Fit("tf1_rot") Parameterwerte so dass die tf1_rot am besten zum Graphen passt. Es ist manchmal nötig die Parameter auf ungefähr richtige Werten zu initialisieren bevor dem Fit. • Fit-Ergebnisse werden ausgegeben, sind aber auch im Skript abfragbar mit den folgenden TF1-Methoden: • GetChisquare(): gibt χ2 • GetNDF(): Anzahl der Freiheitsgraden (NPunkte − NFitparameter ) • GetProb(): Wahrscheinlichkeit eines größeres χ2 mit rein Gauß’schen Schwankungen. Sehr kleine Werte deuten meistens entweder auf einem schlechten Fit oder auf unterschätzten Fehler. Werte sehr nah zu eins deuten oft auf unterschätzte oder stark korrelierte Fehler. 40 / 59 ROOT Dateien Erzeugen eines ROOT File Objekts: f=ROOT.TFile(name,zweck) • name: Dateiname, z.B. "input.root", sollte immer ein Suffix ".root" haben. Besser keine Leerzeichen oder sonstige Sonderzeichen. • zweck ist normalerweise entweder "READ" (lesen) oder "RECREATE" (schreiben). Wenn man beim Schreiben nicht riskieren will schon existierende Dateien zu überschreiben sollte man "CREATE" verwenden. Wenn das zweck-Argument weggelassen wird, dann wird "READ" (lesen) verstanden. • Die IsZombie()-Methode gibt True zurück wenn es Probleme mit der Datei gibt: z.B. wenn eine zu lesende Datei nicht existiert. • In ROOT Dateien können beliebige (und beliebig viele) ROOT Objekten gespeichert werden; dabei ist ihr Name wichtig. 41 / 59 ROOT Dateien Beispiel Schreiben: import ROOT outputfile=ROOT.TFile("meine_Daten.root","RECREATE") histo=ROOT.TH1D("meinhisto","Versuch 1",10,0.1,3.4) # .... berechnungen, histo wird gefuellt histo.Write() outputfile.Close() Lesen: import ROOT,sys inputfile=ROOT.TFile("meine_Daten.root","READ") if rootfile.IsZombie(): print "Ups, Probleme mit Input Datei" sys.exit(1) # beendet Programm histo=rootfile.Get("meinhisto") if histo: histo.Draw() else: print "Ups, ’meinhistogramm’ nicht gefunden..." sys.exit(2) # beendet Programm # ... weitere Bearbeitungen ... 42 / 59 Trees Ein tree (Baum) in ROOT ist effektiv eine Tabelle, worin jede Reihe (”entry”) eine Messung oder Ereignis darstellt, und in jeder Spalte (”branch”) stehen die jeweilige Werten einer Variable (gemessen, simuliert, berechnet, ...). X Y N Temperatur Druck Entry Zeit 0 0.2 3.1 0.41 17 55.3 1.003 54.4 0.993 1 0.4 3.0 0.41 19 2 0.6 3.3 0.41 13 52.9 0.987 3 0.8 3.4 0.42 15 52.0 0.970 4 1.0 3.7 0.42 24 51.2 0.958 ... ... ... ... ... ... Also, etwa wie eine Excel-Tabelle, aber dann für beliebig viele Daten (Excel kann höchstens ∼ 65000 Reihen bearbeiten). 43 / 59 Trees schreiben Ein TTree Objekt erzeugen: baum=ROOT.TTree(name,titel). Spalten (Branchen) müssen definiert werden mit Namen und Datentyp (im einfachsten Fall: Ganzzahl (I) oder Fließkommazahl (single precision: F oder double precision: D). • Falls Daten schon in Textdatei vorhanden, z.B. mit 3 Zahlen pro Zeile, eine Ganzzahl und zwei Fließkommazahlen: import ROOT rootfile=ROOT.TFile("Higgs.root","RECREATE") higgs=ROOT.TTree("higgs","CMS Higss Ereignisse") higgs.ReadFile("higgs.txt","nJets/I:pT/D:Emiss/D") higgs.Write() rootfile.Close() • Allgemeineres Beispiel: siehe pyroot beispiele/tree schreiben.py 44 / 59 Trees lesen I Wenn man eine neue ROOT-Datei bekommt (nicht selber geschrieben): immer mit einem TBrowser inspizieren: $ ipython -nobanner In [1]: import ROOT In [2]: b=ROOT.TBrowser() 45 / 59 Trees lesen I Wenn man dann auf den Variablen klickt (z.B. nJets) dann werden Haeufigkeitsverteilungen gezeigt. Die Higgsdaten sind leider noch nicht zeigen, bitte Ihr Verständnis dafür. :-) Diese Beispieldatei ist sehr minimal: nur ein TTree Objekt, mit nur 3 ”Branchen” (Variablen). Eine ROOT-Datei kann viel mehr Objekten enthalten, und meistens haben die TTrees viel mehr Branchen. 51 / 59 Trees lesen II: ls, Get, Scan Terminal $ ipython -nobanner In [1]: import ROOT In [2]: f=ROOT.TFile("Higgs.root") (Bool t)1 In [3]: f.ls() TFile** Higgs.root TFile* Higgs.root KEY: TTree higgs;1 CMS Higgs Ereignisse In [4]: t=f.Get("higgs") In [5]: t.Scan("*","","",4) ************************************************ Row nJets * pT * Emiss * * * ************************************************ 0 * 2 * 2342.343 * 234545.23 * * 1 * 3 * 2342.43 * 234545.25 * * 2 * 1 * 242.343 * 245.23422 * * 3 * 0 * 2342.343 * 234545.42 * * ************************************************ Out [5]: 4L In [6]: 52 / 59 Trees lesen III: Tree::Draw Terminal $ ipython -nobanner In [1]: import ROOT In [2]: f=ROOT.TFile("Higgs.root") (Bool t)1 In [3]: t=f.Get("higgs") In [4]: t.Draw("nJets") # 1D Verteilungen In [5]: t.Draw("nJets:Emiss") # 2D Verteilungen In [6]: t.Draw("pT","nJets>1") # Selektionen In [7]: t.Draw("pT","nJets>2","same") # Plotoption 53 / 59 Trees lesen IV: Tree::GetEntry Der TTree::Draw Befehl ist bequem für schnelle Plots von Häufigkeitsverteilungen von einfachen Ausdrücken in den verfügbaren Variablen. Für ambitiösere Analysen mit aufwendigere Berechnungen möchte man eine Schleife über die Ereignisse machen und bei jeden Durchgang mehrzeilige Berechnungen in den (relevante) Variablen machen. Das erreicht man mit Hilfe der GetEntry Methode, siehe das Beispielskript pyroot beispiele/tree lesen.py. 54 / 59 Trees lesen V: Ketten Bei grosse Datenmengen wird ein tree oft nicht in einer einzelnem Datei gespeichert, sondern aufgespaltet in mehreren. Die kann man beim einlesen dann wieder zusammenketten mit einem TChain-Objekt: import ROOT # Erzeuge die Kette. Name muss Name des trees sein kette=ROOT.TChain("higgs") # Lese *alle* Files von Februar 2010 :-) (Witz!) kette.Add("/afs/cern.ch/CMS/all/2010_Feb_*/*.root") # Suche das "higgs" TTree Objekt in allen diesen # Files, und zaehle wieviele Ereignisse die insgesamt # haben. n=kette.GetEntries() # Let the data analysis session begin! kette.Draw("nJets","","",100) # die erste 100 events kette.Draw("nJets") # jetzt alle # etc Das TChain-Objekt ”benimmt” sich sonst genau so wie ein TTree-Objekt: man kann Draw(), GetEntry(i) etc. Methoden verwenden. 55 / 59 ROOT globale Variablen • gROOT, Zentralobjekt für allgemeine Sachen: • gROOT.SetStyle(’Plain’): wählt graphische Einstellungen die besser sind für z.B. gedruckten Berichte (anstatt Bildschirm). • gROOT.ls(): Liste mit ROOT Objekte (z.B. nachdem man eine Datei zum lesen geöffnet hat) • gROOT.FindObject(name): wenn es ein Objekt gibt mit dem Namen (z.B. ”canvas” in vielen meiner Beispiele) dann wird dass zurückgegeben, sonst wird den Spezialwert None zurückgegeben. • gStyle • gStyle.SetOptStat(bitpattern): Einstellungen für Statistikboxes bei Histogramme. • gStyle.SetOptFit(bitpattern): Einstellungen für Kästchen mit Fit-Ergebnissen (bei Histogrammen, Graphen) • Viele Defaultwerte können über gStyle geändert werden, z.B. gStyle.SetCanvasDefH(750) vergrößert die Standardhöhe für Canvasse. • gRandom: ein Zufallszahlgenerator, man braucht also eigentlich nicht selber einen zu erzeugen. 56 / 59 ROOT Dokumentation I http://root.cern.ch/drupal/content/documentation Leider ist alle diese Dokumentation für die C++ Variante von ROOT; vieles muß also nach Python ”übersetzt” werden, z.B.: Int_t n = 20; Double_t x[n], y[n]; for (Int_t i=0; i<n; i++) { x[i] = i*0.1; y[i] = 10*sin(x[i]+0.2); } TGraph *gr1 = new TGraph (n, x, y); from ROOT import TGraph from numpy import zeros,sin n = 20 x=zeros(n,’d’) y=zeros(n,’d’) for i in range(n): x[i] = i*0.1 y[i] = 10*sin(x[i]+0.2) gr1 = TGraph (n, x, y) 57 / 59 ROOT Dokumentation II Die User’s Guide gibt ausführliche Beschreibungen aller Aspekte in ROOT, insbesondere: • Chapter 3: Histograms • Chapter 4: Graphs • Chapter 5: Fitting Histograms • Chapter 9: Graphics and the Graphical User Interface • Das PyROOT Kapitel ist leider nur für Experten hilfreich. 58 / 59 ROOT Dokumentation III Class Reference: praktisch um für gegebene Klassen nachzuschlagen welche Methoden es gibt, was die machen, welche Argumente die brauchen. Achtung: manchmal/oft ist wichtige Funktionalität ”vererbt” von ”Basisklassen”; z.B. die TH1D Klasse vererbt von der TH1 Klasse, wo man auch gucken muß um wichtiges über TH1D zu lernen. Zum Beispiel: • TH1, TH1D, TH2D, THistPainter • Die Draw() Methoden für Histogramme und Graphen können mit einer Optons-String gesteuert werden; die Mögliche Einstellungen findet man hier: TGraphPainter, THistPainter. • ROOT-Funktionen: TF1 TF2 Auf den Linuxrechnern des Physikzentrums gibt es unter /usr/lib/root-5.26.00c/tutorials/ eine weitere Sammlung Beispielskripte. 59 / 59