Montag, 26. August 2013

Using PyQt 5 with Spyder. Some crashes and a new idea.

So after doing the stuff I posted earlier, I went on to test a simple QtQuick app.
A simple red rectangle worked okay, but everything seemed to be very unstable. I got many crashes and freezes. Something was really fucked up. After experimenting on that setup for almost a full day, I uninstalled PyQt 5 with nmake uninstall and PyQt 4 with its uninstaller. I installed the binary package of PyQt 5 and tested my qml file.

It just worked fine. No crashes, no instabilities, no nothing.

It appears that my custom built was somehow corrupted, probably from the beginning or that there are some things to do in addition. I copied the PyQt 5 folder out of the site-packages folder of python, uninstalled it, reinstalled PyQt 4 and then copied PyQt 5 back to site-packages. Updated the module name list and BANG, it works. Don't now why this didn't occur to me earlier... 

PyQt 5, Spyder and the input hook.

As mentioned in the last post, the input hook of Spyder is actually necessary to interactively edit your application while running. So how to make Spyder install its hook to PyQt 5 instead of its own PyQt 4?
The solution is a bit hacky but quite simple: Go to your Python folder, like
 C:\Python33\Lib\site-packages\spyderlib\widgets\externalshell
there is file sitecustomize.py waiting for you. For safety make copy of that file as we are going to change it a little bit.
Now open it and find the lines (should be 247 to 249):
    if os.environ.get("INSTALL_QT_INPUTHOOK", "").lower() == "true":
        if os.environ["QT_API"] == 'pyqt':
            from PyQt4 import QtCore
And change the last  from
from PyQt4 import QtCore
to
from PyQt5 import QtCore
Now Spyder imports the QtCore module from PyQt 5 instead of PyQt 4. The hook is beeing installed on the first loading of QtCore, so when Sypder launches its consoles now, everything is fine.

Happy playing!


Using PyQt 5 with Spyder.

I have a toy project where I want to go the whole scripted/interpreted way with Qt. For that I use this toolchain: Qt 5.1 with QtQuick 2.0, PyQt 5 and Python 3.3. Lately my Python-Editor of choice, Spyder, does support Python 3.3, but it is based on PyQt 4 and a release of Qt 4. That does not fit my bill, as I need some new 5.0 stuff from the QMultimedia module. (If you need just Qt 4 functionality, that toolchain works like a charm and you can stop reading.)

Just downloading a binary release of PyQt 5 and installing it, fails as it detects the PyQt 4, which needs to be uninstalled first, but doing this kills Spyder. Bummer.
Downloading the source and building it (which is actually very straightforward, just follow the instructions in the readme - don't forget to do (n)make install and update the Python module name list (in Spyder)), does the trick. Now both PyQt releases are available.
But importing QtCore from PyQt 5 causes a runtime crash:
RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap the QObject class
Obviously PyQt 4 is imported, too. A quick
import sys
sys.modules.keys()​​​
confirms that. The reason for that is that Spyder installs a special input hook, replacing the input hook of PyQt, which is said to cause problems with Spyder. Fortunately you can disable this hook under Tools > Preferences > Console > External modules. After a restart of the current console, you can now import QtCore and you can start developing your stuff.
There is a slight annoying thing regarding the hook though: you now can not interactively work with your application in the console. The solution for that comes in the next post.

Update: read my follow up post for a simpler and better solution.

Montag, 14. Januar 2013

Wie stellt man unter Windows fest ob ein Programm als Release- oder Debug-Build kompiliert wurde?

Der Dependency Walker gibt die Antwort. Bei einem Release-Build wird die MSVCRT-Bibliothek geladen und bei einem Debug-Build die MSVCRTD-Bibliothek.

Dienstag, 30. Oktober 2012

Git Extensions kann Git Hooks.

Es scheint so zu sein als würde Git Extensions seit einiger Zeit Git Hooks verstehen. Was zur Folge hat, dass man mit Git Extensions auch für Qt Gerrit Commits erzeugen kann.
(Meine bisherige Version war zumindest so alt, dass sie es nicht konnte...)
Gerrit Codereview unterstützt es auch direkt, da muss ich aber erst noch rausfinden, wie man da das jeweilige Gerrit einrichtet.

Montag, 29. Oktober 2012

Qt, Git, Gerrit, ssh und Proxy. Teil 3. (Hooks)

Hat man das alles ans Laufen gebracht, funktioniert übrigens auch:
>scp -p BENUTZER@codereview.qt-project.org:hooks/commit-msg .git/hooks
Damit bekommt man dann die Git Hooks in sein eigenes Repository, die zwingend notwendig sind, damit die Commits eine eindeutige Id bekommen. Sonst muss man die von Hand runterladen und in den richtigen Ordner kopieren.

Qt, Git, Gerrit, ssh und Proxy. Teil 2. (Push)

Kommt man dann mit:
>git push BENUTZER@codereview.qt-project.org:29418/qt/MODUL HEAD:ref/for/master
oder üblicher (sofern man sich an die Anleitung gehalten hat):
 >git push gerrit HEAD:ref/for/master
nicht durch und erhält folgenden Fehler:
ssh: connect to host codereview.qt-project.org port 22: Bad file number
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
So sollte es testweise hiermit gehen:
>git push ssh://BENUTZER@ssh.qt-project.org:443/qt/MODUL HEAD:ref/for/master  
Hängt man nämlich hinter einem Proxy, so darf man Port 29418 nicht benutzen und der Shortcut gerrit wird in der Regel mit diesem Port angelegt. Hier funktioniert es nur über den Port 443. Kommt man jetzt also durch, sollte man sich mit:
>git config --list
mal ansehen was dort unter remote.gerrit.url eingetragen ist.
Steht dort nicht der Port 443, wahrscheinlich aber sogar die URL codereview.qt-project.org, dann ändert man es so um:
>git config remote.gerrit.url ssh://BENUTZER@ssh.qt-project.org:443/qt/MODUL
Mit:
>git push gerrit HEAD:ref/for/master
sollte man dann endlich durchkommen.
Auch hier wieder Private/Public Schlüsselpaar muss erzeugt seien und Gerrit bekannt gemacht werden.
(BENUTZER: Gerrit Benutzername; MODUL: das zum Repository gehörende Qt Modul.)

Qt, Git, Gerrit, ssh und Proxy. (SSH Test)

Die testweise Verbindung mit dem Qt Codereview Gerrit mit ssh durch einen Proxy funktioniert so:
ssh -p 443 BENUTZER@ssh.qt-project.org
Dann, sofern man schön seinen Public/Private Schlüsselpaar angelegt hat, wird man nach seinem Passwort gefragt und der Server meldet:

 ****    Welcome to Gerrit Code Review    ****Hi BENUTZER, you have successfully connected over SSH. 
Unfortunately, interactive shells are disabled.
To clone a hosted Git repository, use: 
git clone ssh://egonuel@codereview.qt-project.org:29418/REPOSITORY_NAME.git
Man kommt also rein.
(BENUTZER: der Benutzername für Gerrit.)

Freitag, 26. Oktober 2012

Git und Proxy unter Windows.

Um Git (msysgit) unter Windows durch einen Proxy durchzubohren, erstellt man im Git Unterordner bin eine Textdatei mit dem Inhalt:
@echo off
set CONNECT=connect.exe
set PROXY=PROXYADDRESS:PROXYPORT


"%CONNECT%" -H %PROXY% %*
und ersetzt dort PROXYADDRESS und PROXYPORT gegen den zu durchbohrenden Proxy und speichert die Datei als bat ab, beispielsweise proxy.bat.
Dann führt man in der Git Bash Shell im Git Hauptordner folgenden Befehl aus:
git config --global core.gitproxy proxy.bat
Das wars.

Mit
git ls-remote git:://ADDRESS/REPO.git
kann man dann testen ob die Verbindung durchgeht, wobei natürlich ADDRESS und REPO durch das gewünschte Repository ersetzt werden müssen.

Sonntag, 21. August 2011

OpenCV VideoCapture and openGL glMapBuffer.

Currently I'm writting a small prove-of-concept-program, which reads avi-files using the cv::VideoCapture class of openCV and displays the frames using openGL.
(To archieve the openGL-powered frame display I walked through the excellent openGL tutorial from Joe's Blog.)
After I got this working, I changed the texture transfer to the use of pixel buffer objects.
Had I read the documentation carefully, I wouldn't had done one stupid mistake.
When you map your videomemory to your system's memory using glMapBuffer, you have to unbind it before you can use it, otherwise you get an "Invalid Operation"-error.
First attempt then was to copy the image data using memcpy, which worked just fine but required an additional copy.
Well, you can create a cv::Mat object with an already-allocated region of memory. So I used the mapped bufferpointer as the datapointer for the object.
But nothing happend and the image stayed black.

So what is going on here?
After finding out, that the memory location of the frame changed, after I read one frame with the cv::VideoCapture object, I thought that somehow the buffer memory does not match the requirements of the frame, e.g. size. But that was not the case.
Then I dug into the openCV sourcecode (second time this weekend) and found the the reason.
Inside the cv::VideoCapture class uses the old cvCapture functions, which allocate memory themself. So when you grab an image, your provided image gets this new memory and the provided memory is deallocated.
Even though this memory is only allocated at the beginning, there is no way that you can provide own memory, which should be used by the cv::VideoCapture module.
Bad news.

Funny thing is that the cvCapture code is class based and even uses cv::Mat inside.
Maybe someday the developers will rewrite the code and enable transparent memory usage.

Mittwoch, 17. August 2011

sudo port -f uninstall --follow-dependents installed

... deinstalliert alle mit MacPorts installierten Packages inklusive aller Abhängigkeiten.
Praktisch.

Dienstag, 16. August 2011

MSVCRTD.lib(crtexew.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "WinMain" in Funktion "__tmainCRTStartup".

...bekommt man diesen Fehler in Visual Studio, so weist, dies auf einen fehlerhaften Einstiegspunkt hin. Dies liegt meistens daran, dass man eine Consolen-App in einem Window-Projekt schreibt. Diese unterscheiden sich durch ihre Main-Funktion und damit eben in ihrem Einstiegspunkt.
Bei einer Consolen-App üblicherweise main und bei einer Window-App WinMain.
Um den Fehler zu beheben entweder ein neues, passendes Projekt anlegen (NOOOOT) oder in den Projekteinstellungen auf Linker gehen, dort den Unterpunkt Erweitert anwählen und den Einstiegspunkt auf mainCRTStartup setzen.
Dann klappt's auch mit dem Linken.

Montag, 1. März 2010

Visual Studio Debugger mit DLLs und Labview.

Den Visual Studio Debugger auch beim Debuggen von DLLs zu verwenden, die von einem Labview VI gerufen werden sollen, ist wünschenswert.
Geht auch ganz einfach: Die DLL im Debug-Modus kompilieren und im Call Library Node im VI eintragen. Dann den Debugger über Debuggen > An den Prozess anhängen... an den Labview Prozess anhängen (es erscheint ein Fenster mit allen laufenden Prozessen). Nun in Labview das VI ausführen und sobald das VI in die DLL springt, greift der Visual Studio Debugger ein und man kann, sofern denn Haltepunkte etc. gesetzt sind, loslegen. Danach muss die Prozessüberwachung aber manuell getrennt werden.
Angeblich soll es auch über das "normale" Debugging funktionieren, leider habe ich es bisher nicht hingekriegt, dass Labview nicht nur das VI öffnet sonderen es auch startet.
(Getestet mit Visual Studio Professional Edition 2008, die man als Student kostenlos über Microsofts Dreamspark bekommt.)

DbgPrintf: Printf mit Labview und DLLs.

DbgPrintf – öffnet ein Textfenster und schreibt die angegebene Nachricht dort hinhein, alle weiteren Nachrichten mit DbgPrinft erscheinen ebenfalls dort. DbgPrintf(NULL) schließt dieses Fenster wieder. Die Funktion verhält sich ansonsten wie printf in C.
(Using External Code in Labview, S. 81, 370109b.pdf)

Dienstag, 1. Dezember 2009

Der coole Weg auf die RAC-Server.

Im folgenden werde ich beschreiben, wie man sich mit Mac OS X sehr komfortabel über VPN und SSH auf die Rechenzentrums-Server des RheinAhrCampus einloggt. Prinzipiell lässt sich die Vorgehensweise sicher auch auf andere Server übertragen.

Teil 1 – Wie komme ich in den RAC?
Das Rechenzentrum des RACs stellt den Cisco-VPN-Client zur Verfügung. Das Programm hat mich von Anfang an so genervt, dass ich mich lieber nicht von extern eingeloggt hab, als es zu verwenden. Glücklicherweise bin ich dann auf Shimo gestoßen.

Shimo ist ein kleines Programm, das sich in der Menü-Leiste einnistet und ein hübsches, unscheinbares und komfortables Frontend für bspw. den Cisco-Client bietet. Laut dem Macher werden alle bekannten VPN-Arten unterstützt (was mir aber relativ egal ist ;)). Seit einiger Zeit ist es nicht mehr Freeware, sondern Shareware. Regulär kostet es um die 15 Euro, es gibt aber wohl Studierendenrabat. Was es dann kostet kann ich noch nicht sagen, da ich die Toolchain erst seit vorgestern wieder laufen habe und bisher noch mit dem Bezahlhinweis lebe.

So genug Vorgeplänkel, was muss man machen?
Also zunächst muss man natürlich den Cicso-VPN-Client installieren, den kriegt man auf der RZ-Seite. Wenn er schon installiert ist und ihr kürzlich Snow Leopard installiert hat, kann es notwendig sein, ihn nochmals neu zuinstallieren, das war zumindest bei mir so.

Wenn das getan ist, wird Shimo installiert, das geht straight forward. Shimo befindet sich nun im Programme-Ordner, also einfach starten. Jetzt habt ihr in der Menü-Leiste einen Torbogen, das ist Shimo. Draufklicken und auf Einstellungen. Da kann man allerhand einstellen, der wichtigste Reiter ist aber der für Profile. Jetzt auf das PLUS links unten klicken und im Bereich "Importieren aus:" "Cisco Profil" auswählen. Es poppt ein Dateiauswahl Fenster auf und ihr navigiert in den Ordner, in dem ihr die Dateien des Zip-Files vom RAC entpackt habt. Dort sind drei Profil-Dateien drin, eine für DSL-Teiltunnel, eine für DSL-Volltunnel und eine für das Studnetz. Wofür die jetzt genau da sind steht in der VPN-Broschüre, die auch im RZ-Bereich zu finden ist. Alle drei Dateien importiert ihr in Shimo.

Das war es im Prinzip schon, ihr könnt aber noch direkt über Bearbeiten euren Benutzernamen und das Kennwort eintragen, das im Schlüsselbund gespeichert wird. Einstellungen zu machen und wieder auf das Tor klicken und jetzt eine der Verbindungen anklicken, ich wähle hier Teiltunnel (Volltunnel würde wohl den gesamten Netz-Verkehr über den RAC umleiten und war bei mir furchtbar langsam), Teiltunnel reicht aber für das, was ich hier beschreibe, vollkommen aus. Nochmals auf das Tor klicken und "Verbinden", jetzt tut sich was im Tor und dann sollte (wenn ihr denn Growl installiert habt) eine Mitteilung erscheinen, dass eine Verbindung aufgebaut wurde.

Das war der erste Teil. Jetzt habt ihr schonmal eine saubere, unaufdringliche Verbindung zum RAC. Über das Terminal könnt ihr euch jetzt mit "ssh benutzername@fserver1" auf dem fserver einloggen und würdet direkt in eurem Profil landen (nach Eingabe des Passworts natürlich).
So das ist aber noch nicht so schick, denn wir haben ja einen Mac um es einfach und komfortabel zu haben.

Teil 2 – Geht es auch ohne Terminal?
Ich bin ja faul und Terminal Tipperei brauch ich auch nicht, wenn ich mal schnell eine Datei kopieren will. Da kommt jetzt MacFUSE und Macfusion ins Spiel. MacFUSE ist ein geniales Stück Software, das sehr viele Arten von Medien in das Dateisystem von OS X einbinden kann. Was wir hier brauchen ist eine Einbindung von ssh, aber man könnte auch ein Youtube-Filesystem einbinden (oO). Das Ding ist aber Kommandozeilen-basierend, sodass es noch nicht das ist, was ich will. Dafür gibt es aber Macfusion, welches ein grafisches Frontend für MacFUSE bietet. So der Reihe nach.

Zuerst installiert ihr MacFUSE, einfach das machen was von euch verlangt wird, nichts anderes. Dann installiert ihr direkt hinterher Macfusion.
Macfusion findet ihr in den Programmen, einfach starten. Es öffnet sich ein ziemlich bescheidenes Fenster. Auch hier ist es wieder ganz einfach: auf das PLUS unten links klicken und auf "SSHFS" klicken.
Im oberen Textfeld dürft ihr euch einen Namen für euren Ordner ausdenken, den ihr einbinden wollt. Also zum Beispiel "RAC/profile". (Wichtig: der Name hier hat nichts mit dem tatsächlichen Ordner zu tun, den ihr einbinden wollt. Es ist wirklich nur eine Bezeichnung für die Verbindung.) Als Host tragt ihr "fserver1.rheinahrcampus.de" ein, User Name ist eurer RAC-Profilname, Password dementsprechend euer Passwort. Path lasst ihr leer, wenn ihr euren Profil-Ordner mounten (einbinden) wollt. Um andere Ordner einzubinden könnt ihr beim Path etwas eintragen, der Root-Ordner vom fserver1 bekommt ihr mit "/", den Lehre-Server mit "/samba/lehre/".
Im Reiter "Macfusion" könnt ihr noch bei "Volume Name" angeben wie der Ordner im OS X Dateisystem heißen soll, das ist also der Name unter dem der Ordner im Finder erscheint. Es besteht dort auch die Möglichkeit auszuwählen, dass der Ordner beim Start von OS X eingebunden werden soll, das solltet ihr nicht tun, denn die Verbindung ist nur möglich wenn eine VPN-Verbindung besteht und die besteht beim Start noch nicht.

So das wars schon, "Ok" und euer Ordner steht in der Liste von Macfusion. Jetzt auf "Mount" klicken und der Ordner sollte sich nach kurzer Zeit grün verfärben. Auf dem Desktop seht ihr jetzt den Ordner und könnt ihn öffnen. Im Finder erscheint er irgendwie seit einem Versions-Update bei mir nicht mehr in der linken Leiste, man findet ihn aber, wenn man dort auf "euerName's Computer" klickt. So damit habt ihr jetzt vollen Zugriff auf eure Dateien und das nativ in OS X. Schick oder?

Teil 3 – Schluss
Eigentlich könnte es jetzt hier enden, aber zwei Punkte muss ich noch erläutern.
Wenn ihr mit eurer Arbeit auf dem Server fertig seid, "unmounted" zunächst den Ordner, das geht im Finder oder auf dem Desktop wie bei CDs oder USB-Sticks, auswerfen klicken oder auf den Papierkorb ziehen. Danach erst im Shimo-Tor auf "trennen" klicken. Wenn ihr das mit dem "unmounten" vergesst, kann es zu nervigen Verzögerungen kommen, bis OS X merkt, dass die Verbindung nicht mehr besteht.

Der letzte Punkt betrifft User von Snow Leopard. Macfusion funktioniert damit nach der Installation nicht. Also Starten und Ordner-Einrichten geht zwar, aber ihr könnt den Ordner dann nicht mounten, da gibt es einen Fehler.
Um den zu beheben, geht in den Programme-Ordner, Rechtsklick auf Macfusion und auf "Paketinhalt zeigen" klicken. Wer das noch nicht kannte: Programme die mit .app enden sind Pakete, die Ordner enthalten und in denen eine Reihe von Dateien stecken. In denen findet OS X dann die auszuführende Datei. Aber generell sollte man da nicht drin rumspielen, wenn man nicht weiß was man tut. Ihr klickt euch jetzt dort durch bis ihr hier "/Macfusion.app/Contents/PlugIns/sshfs.mfplugin/Contents/Resources/" gelandet seid. In diesem Ordner befindet sich eine Datei "sshnodelay.so", die löscht ihr. Dann macht ihr den Ordner wieder zu und startet Macfusion und siehe da: es funktioniert. Die gelöschte Datei dient wohl nur dazu, mit manchen alten Servern klar zu kommen, die RAC-Server sind aber neu und man braucht sie nicht.

So jetzt solltet ihr eine voll funktionierende Toolchain haben, mit der ihr komfortabel auf die RAC-Server zugreifen könnt. Es ist sogar deutlich angenehmer als unter Windows, wie ich finde. Das bisschen Arbeit lohnt sich also sehr.
Sowohl Shimo als auch Macfusion können mit OS X gestartet werden, Shimo kann auch bei seinem eigenen Start direkt eine VPN-Verbindung aufbauen. Bei Macfusion muss man da, wie gesagt, ein bisschen aufpassen. Wenn man will kann man also ohne ein Programm von Hand zu starten auf die Server zugreifen.
Und jetzt viel Spaß!

Links:

Dienstag, 1. September 2009

Plot und Single? Nein.

Zum Merken: der Plot-Befehl in Matlab akzeptiert nur Variablen vom Typ Double. Bei Single bringt er einen Fehler, der allerdings nicht direkt damit in Verbindung gebracht wird.

Sonntag, 30. August 2009

Safari.

Firefox nervt mich zur Zeit ultra, er ist unglaublich langsam, stürzt oft ab. Er nervt einfach.
Jetzt hab ich mal probeweise den Safari ständig an, der gefühlt deutlich flotter arbeitet und nicht abstürzt. Leider fehlen ihm wichtige Dinge, die ich jetzt mal hier auflisten will
  • es gibt kein delicious-Plugin (also es gibt eins, aber das ist nicht von delicious selber und es kostet 10 Dollar. Seh ich nicht ein.)
  • der Werbeblocker den ich verwende – AdBlock – lässt im Vergleich zum Firefox-Pendant zuviel durch. (Ich glaube er kann nicht mit iframes umgehen.) ICH WILL KEINE WERBUNG SEHEN.
  • AdBlock lässt sich nicht bei ausgewählten Seiten deaktivieren. (Zumindest hab ich die Funktion nicht gefunden, doof.)
  • alt+command+f für suchen ist doof.
  • man kann wohl RSS-Feeds nicht direkt z.B. im google Reader speichern.
  • ich glaube man kann nicht per Tastatur die Suchmaschine wechseln. Doof.
Ich will das alles für Safari haben.

Mittwoch, 26. August 2009

Project Euler.

Sehr coole Sache. Momentan 252 Aufgaben/Probleme, übergreifend mathematischer Art, die man programmierend lösen soll. (okay zum Teil gehts es auch mit Stift und Papier.)
Die Aufgaben sind so gestellt, dass am Ende immer eine Zahl rauskommt, die kann man (nach Anmeldung) beim jeweiligen Problem eingeben und wenn sie richtig ist bekommt man ein Häkchen und Zugang zum entsprechenden Forumthread. Dort findet man dann im Prinzip in jeder Programmiersprache eine Lösung, sehr interessant.
Die meisten Probleme kann man durch Brute-Force lösen, aber freiwillige Nebenbedingung ist, dass die Berechnung maximal 1 Minute dauern soll (das geht auch, man muss "nur" clever sein).
Kleines Beispiel, man hat ein Feld mit 20x20 Feldern und man soll die Anzahl der möglichen Wege über die Felderränder rausfinden, ein zulässiger Weg führt immer entweder nach rechts oder nach unten, nie zurück. Mein erster Ansatz rekursiver Natur hat das Ergebnis bis 10 Felder in akzeptabler Zeit gelöst, bei 20 Feldern hab ich nach 20 Minuten warten aufgegeben und neu überlegt. Und dann hab ich eine Formel gefunden mit der man die Anzahl berechnen kann... 10 Millisekunden.
Macht Spaß (wenn man den Spaß am Programmieren hat)!

Achso der Link.

Mathworks Webinare.

und mal wieder ein Link hier:
Mathworks Webinars
Das sind so aufgezeichnete Vorträge, also Präsentationen mit Stimme.
Die Dinger sind richtig gut, ich hab mir den "MATLAB for C/C++ Programmers" reingezogen, immerhin 70 min lang. Und hab coole neue Sachen kennengelernt. Von denen ich zwei kurz anmerken und später auch ausprobieren will:
  • Embedded MATLAB: Möglichkeit um MATLAB-Code (allerdings nur rudimentären) in C-Code umwandeln zu lassen. Finde ich sehr schick!
  • MATLAB als Engine in C-Code einbinden. Der Hammer. Man kann MATLAB von einem C-Programm aus Variablen (auch Arrays) zu schicken UND MATLAB kann dann zur C-Laufzeit damit arbeiten, also bspw. plotten. Das ist genial zum Debuggen.
So und jetzt höre ich mir noch einen an.