mathpyx

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

mathpyx soll die Integrierung von Formeln aus allen Bereichen der Naturwissenschaft sehr stark vereinfachen und so Python für die Wissenschaft interessant machen. Die Formeln werden in speziellen XML-Dateien, XFF (xml formula file) abgespeichert um eine übersichtliche Dateistruktur zu erhalten.

mathpyx, das Modul libxff und die XFFs (nein, bitte nicht XFF-Dateien: xml formula file-Dateien ;)) sind das Herzstück vom mathpyx-Projekt. Mit mathpyx kann man XFFs lesen (--read), erstellen (--create), bestimmte Formeln berechnen (--calc), die Formeln auf Richtigkeit prüfen (--check) und in py-Dateien kompilieren (--compile).

Beispiel, --calc:

Code: Alles auswählen

remo@remuntu:~$ mathpyx --calc ./xff/biology/bmi.xff 
available variables:  bmi, m, l
Select an unknown variable: bmi

Value of m in kg: 73
Value of l in m: 1.72

bmi = 24.6755002704 kg/m^2
==========================

Installation
mathpyx benötigt "beautifulsoup" als Abhängigkeit.

In der aktuellen alpha-Version sind die XFFs nicht enthalten, und müssen separat heruntergeladen werden. weitere Infos zu "Download"

Nach dem Entpacken kann

Code: Alles auswählen

python setup.py install
(root) ausgeführt werden, um mathpyx zu installieren.

Nun läd man sich noch die XFFs herunter und entpackt sie.

Code: Alles auswählen

mathpyx --help
gibt eine Übersicht an Optionen und Kommandos.

Das Script benutzt die zwei Erweiterungsscripte von Lunar, cmdoptparse (Kommandos und Optionen parsen) und appdistutils (Installation).


Für die nächsten Versionen möchten wir die XFFs gerne direkt in die Distribution mitpacken. Allerdings können wir uns nicht entscheiden, wohin diese XFFs hinkommen sollen. Einfach nach site-packages? Ausserdem sind wir froh wenn man uns Englisch-Fehler mitteilt, denn davon gibt es ganz bestimmt viele in mathpyx ;-)

Grüsse
Pot (+ BasterTWO)
BlackJack

Besonders robust sieht das nicht aus. XML sollte man nur mit entsprechenden Bibliotheken bearbeiten und nicht per Zeichenkettenformatierung erstellen. Da braucht in der Beschreibung ja nur mal ein '<' auftauchen und schon ist das XML kaputt.

Die `__init__()` hinterlässt das Objekt nicht in einem brauchbaren Zustand.

Nach dem `read()` wird die Datei nicht geschlossen. Die Datei braucht auch nicht an das Objekt gebunden zu werden, ausserdem ist `xff_handler` ein schlechter Name für eine Datei.

Parallele Listen für zusammengehörende Informationen zu verwalten ist immer etwas unschön.

Da ist dann auch wieder ein `py_handler` als Name für eine Datei. `handler` sind Funktionen die etwas tun, keine Dateien.

Wieso bekommt die `write()`-Methode alle Angaben als Argumente die eigentlich auf dem Objekt verfügbar sind. Das Argument `name` wird gar nicht benutzt.

Beim programmatischen erstellen von Quelltext gibt's das gleiche Problem wie bei dem XML oben: Lass man jemanden eine Beschreibung eingeben, die ein " enthält.

`check()` operiert nicht auf dem Objekt sondern liest nochmal die Datei ein, wobei nicht etwa `read()` aufgerufen wird, sondern der Quelltext da *nochmal* steht.

Es wird auch unnötiger Gebrauch von ``exec()`` gemacht. Um den Namensraum zu füllen kann man auch einfach Objekte ohne den Umweg über ``exec`` in das Dictionary stecken.

Formeln in MathML und automatisches Umstellen nach den Grössen aus *einer* Formel, das wäre schön gewesen. :-)
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

BlackJack hat geschrieben:Besonders robust sieht das nicht aus. XML sollte man nur mit entsprechenden Bibliotheken bearbeiten und nicht per Zeichenkettenformatierung erstellen. Da braucht in der Beschreibung ja nur mal ein '<' auftauchen und schon ist das XML kaputt.
AFAIR wurde mir empfohlen, mit beautifulsoup zu arbeiten, Ich schau mir das mal genauer an.
Die `__init__()` hinterlässt das Objekt nicht in einem brauchbaren Zustand.
Kannst du das genauer erklären?
Nach dem `read()` wird die Datei nicht geschlossen.
Ups :oops: Danke für den Hinweis.
Die Datei braucht auch nicht an das Objekt gebunden zu werden,
Mhh.. das stimmt. Scheint wohl noch ein Überbleisel von früher zu sein. Werde ich verbessern. Danke
ausserdem ist `xff_handler` ein schlechter Name für eine Datei.
Die Variable der Datei heisst xff_file
Parallele Listen für zusammengehörende Informationen zu verwalten ist immer etwas unschön.
Vorschlag für eine Alternative?
Da ist dann auch wieder ein `py_handler` als Name für eine Datei. `handler` sind Funktionen die etwas tun, keine Dateien.

Code: Alles auswählen

py_handler = file(...)
Da wird doch die Funktion file() benutzt. Wo ist das Problem?
Wieso bekommt die `write()`-Methode alle Angaben als Argumente die eigentlich auf dem Objekt verfügbar sind.
[DURCHGESTRICHEN]Damit man write() benutzen kann, ohne gleich read() auch nutzen zu müssen. Allerdings könnte man da default-Werte zuweisen, das stimmt.[/DURCHGESTRICHEN]
Die sind nicht im Objekt verfügbar, sondern diese Tippt der Benutzer von Hand ein.
Das Argument `name` wird gar nicht benutzt.
Auch Überbleibsel. Danke.
Beim programmatischen erstellen von Quelltext gibt's das gleiche Problem wie bei dem XML oben: Lass man jemanden eine Beschreibung eingeben, die ein " enthält.
Könntest du mir eine Alternative angeben? Link zu einer Doku wie mans besser macht?
`check()` operiert nicht auf dem Objekt sondern liest nochmal die Datei ein, wobei nicht etwa `read()` aufgerufen wird, sondern der Quelltext da *nochmal* steht.
Das stimmt. Danke für den Hinweis, sinnvoll ist es wirklich nicht ;-)
Es wird auch unnötiger Gebrauch von ``exec()`` gemacht. Um den Namensraum zu füllen kann man auch einfach Objekte ohne den Umweg über ``exec`` in das Dictionary stecken.
Mir ist nicht bekannt, wie.
Formeln in MathML
Aha! Das klingt interessant. Kannst du mir mehr darüber erzählen / Wo kriege ich mehr Informationen?
und automatisches Umstellen nach den Grössen aus *einer* Formel, das wäre schön gewesen. :-)
Wie soll denn das möglich sein? :shock:


Danke für dein ehrliches Feedback, ich werde versuchen, den Code möglichst zu verbessern.

Grüsse
Pot
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

BlackJack hat geschrieben:`write()`-Methode: Das Argument `name` wird gar nicht benutzt.
Hier muss ich doch nochmals nachhaken:

Code: Alles auswählen

    def write(self, name, description, link, vars, formulae, units):
        content = """<xff>
<name>%s</name>
<description>%s</description>
<link>%s</link>

<formulas>""" % (name, description, link)
Da wird doch 'name' benutzt?

Lass man jemanden eine Beschreibung eingeben, die ein " enthält.
Das scheint zu funktionieren:

Code: Alles auswählen

remo@remuntu:~/Programmierung/Projekte/mathpyx/trunk/src/mathpyx$ python ../mathpyx_console.py --create /tmp/test
formula name: bla

Link to get more information: bli
Small description (e.g. how to use the formulae). Save with Strg-C:
"blol blo blo bli ble"

Fill in all variables, their formulae and unit, beginning with the
basic formula. If you are finished, press Strg-C.
#1variable:  bla
#1formula:  blo
#1unit:  blu

#2variable:  bli
#2formula:  ble
#2unit:  blq 

#3variable:  sdf
#3formula:  sdf
#3unit:  hg

remo@remuntu:~$ cat /tmp/test.xff 
<xff>
<name>bla</name>
<description>"blol blo blo bli ble"

</description>
<link>bli</link>

<formulas>              <formula var="bla" unit="blu">blo</formula>
                <formula var="bli" unit="blq">ble</formula>
                <formula var="sdf" unit="hg">sdf</formula>
        </formulas>
Grüsse
Pot
BlackJack

pot hat geschrieben:
Die `__init__()` hinterlässt das Objekt nicht in einem brauchbaren Zustand.
Kannst du das genauer erklären?
Mann kann zum Beispiel nicht die `compile()`-Methode aufrufen ohne einen `NameError` zu bekommen. In der `__init__` sollte ein Objekt in der Regel wirklich in einen Zustand versetzt werden, bei dem es benutzbar ist und nicht noch zwingend andere Aufrufe von Methoden in einer bestimmten Reihenfolge benötigen.
ausserdem ist `xff_handler` ein schlechter Name für eine Datei.
Die Variable der Datei heisst xff_file
Nein das ist nicht die Datei, das ist der Datei*name*. Also auch ein etwas irreführender Name.
Parallele Listen für zusammengehörende Informationen zu verwalten ist immer etwas unschön.
Vorschlag für eine Alternative?
Die Daten nicht auf drei Listen zu verteilen sondern in einer zu Speichern. Als Tupel, oder falls es Sinn macht eigene Objekte.
Da ist dann auch wieder ein `py_handler` als Name für eine Datei. `handler` sind Funktionen die etwas tun, keine Dateien.

Code: Alles auswählen

py_handler = file(...)
Da wird doch die Funktion file() benutzt. Wo ist das Problem?
Das Problem ist der Name `py_handler` für ein Dateiobjekt. Wie dieses Objekt erzeugt wurde hat damit nichts zu tun. "Handler" sind Rückruffunktionen die irgendwohin übergeben werden und/oder von irgendwoher asynchron aufgerufen werden. "Signal handler", "event handler", "interrupt handler" usw.

Bei einer Funktion, die man in `Tkinter` an das `command`-Argument eines `Button` bindet, macht ein "handler" im Namen Sinn. Bei einem Dateiobjekt, das nicht einmal aufrufbar ist, verwirrt das nur.
Wieso bekommt die `write()`-Methode alle Angaben als Argumente die eigentlich auf dem Objekt verfügbar sind.
[DURCHGESTRICHEN]Damit man write() benutzen kann, ohne gleich read() auch nutzen zu müssen. Allerdings könnte man da default-Werte zuweisen, das stimmt.[/DURCHGESTRICHEN]
Die sind nicht im Objekt verfügbar, sondern diese Tippt der Benutzer von Hand ein.
Beim Lesen sind sie am Objekt beim schreiben muss man die Datei erst wieder einlesen!? Das ist ein recht asymmetrischer Entwurf.
Es wird auch unnötiger Gebrauch von ``exec()`` gemacht. Um den Namensraum zu füllen kann man auch einfach Objekte ohne den Umweg über ``exec`` in das Dictionary stecken.
Mir ist nicht bekannt, wie.
Du weisst nicht wie man etwas in ein Dictionary steckt aber Du kannst eine Zeichenkette mit Quelltext der das tut zusammenbasteln und die ausführen!?

Code: Alles auswählen

        x = 1.0
        for var in self.vars:
            command = "namespace["" + var + ""] = " + str(x)
            exec command
            x += 1.0
Statt den Code zusammen zu basteln und dann auszuführen hättest Du ihn auch einfach *hinschreiben* können.

Code: Alles auswählen

        for x, var in enumerate(self.vars):
            namespace[var] = float(x + 1)
Den Namensraum mit den ganzen Mathefunktionen füllen geht auch ohne ``exec``:

Code: Alles auswählen

        import math
        namespace = dict(math.__dict__)
Formeln in MathML
Aha! Das klingt interessant. Kannst du mir mehr darüber erzählen / Wo kriege ich mehr Informationen?
Zum Beispiel auf der MathML-Homepage beim W3C.
und automatisches Umstellen nach den Grössen aus *einer* Formel, das wäre schön gewesen. :-)
Wie soll denn das möglich sein? :shock:
Man muss "nur" die Formeln so auf Objekte abbilden, dass man Umformungsregeln programmieren und anwenden kann. :-)

`mathomatic` kann so etwas zum Beispiel. Ist in C geschrieben und recht klein, und kann Python-Quelltext für Formeln ausspucken:

Code: Alles auswählen

bj@s8n:~$ mathomatic
Mathomatic version 12.6.7 (www.mathomatic.org)
Copyright (C) 1987-2006 George Gesslein II.
50 equation spaces available, 960KB per equation space.

1-> W = 1/2 * m * v^2

        m*(v^2)
#1: W = -------
           2

1-> code python
W = (m * (v * v) / 2.0)
1-> solve m

         2*W
#1: m = -----
        (v^2)

1-> code python
m = (2.0 * W / (v * v))
1-> solve v

         2*W 1
#1: v = (---^-)*sign1
          m  2

1-> code python
v = (((2.0 * W / m) ** (1.0 / 2.0)) * sign1)
BlackJack

*Quelltext* erzeugen geht mit " in Eingaben schief, da wird dann so etwas erzeugt wenn man z.B. 'foo " bar' eingibt:

Code: Alles auswählen

decription = "foo " bar"
link = "http..."
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

BlackJack hat geschrieben:Das Problem ist der Name `py_handler` für ein Dateiobjekt. Wie dieses Objekt erzeugt wurde hat damit nichts zu tun. "Handler" sind Rückruffunktionen die irgendwohin übergeben werden und/oder von irgendwoher asynchron aufgerufen werden. "Signal handler", "event handler", "interrupt handler" usw.
Gut, das leuchtet mir ein. Wie soll ich sie sonst nennen? py_file_object?
Wieso bekommt die `write()`-Methode alle Angaben als Argumente die eigentlich auf dem Objekt verfügbar sind.
[DURCHGESTRICHEN]Damit man write() benutzen kann, ohne gleich read() auch nutzen zu müssen. Allerdings könnte man da default-Werte zuweisen, das stimmt.[/DURCHGESTRICHEN]
Die sind nicht im Objekt verfügbar, sondern diese Tippt der Benutzer von Hand ein.
Beim Lesen sind sie am Objekt beim schreiben muss man die Datei erst wieder einlesen!? Das ist ein recht asymmetrischer Entwurf.
Siehst du den DURCHGESTRICHEN-Tag?
Es wird auch unnötiger Gebrauch von ``exec()`` gemacht. Um den Namensraum zu füllen kann man auch einfach Objekte ohne den Umweg über ``exec`` in das Dictionary stecken.
Mir ist nicht bekannt, wie.
Du weisst nicht wie man etwas in ein Dictionary steckt aber Du kannst eine Zeichenkette mit Quelltext der das tut zusammenbasteln und die ausführen!?
Du hast nie spezifiziert, welcher exec Befehl überflüssig sein soll. Ich habe mich auf einen anderen bezogen, du auf den. Aber ja, klar, das ist wirklich überflüssig. Keine Ahnung was ich da studiert habe. Danke für den Tipp, deswegen musst du mich nicht so anfahren.
Den Namensraum mit den ganzen Mathefunktionen füllen geht auch ohne ``exec``:

Code: Alles auswählen

        import math
        namespace = dict(math.__dict__)
Genau *das* meinte ich, als ich sagte "mir ist nicht bekannt, wie"! Das wollte ich wissen, vielen Dank.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und BeautifulSoup ist weniger zum Einlesen und Ausgeben von XML gedacht, sondern zum Scrapen von HTML. Um XML zu generieren, würde man eher ElementTree oder lxml verwenden.

Edit: Achja, ihr solltet euch auch für eine Sprache entscheiden. Deutsche und Englische Kommentare gleichzeitig helfen niemandem. Auch l10n wäre nützlich, da würde man alle Strings auf Englisch schreiben und mit `getttext` übersetzen.
Ich glaube auch, eure XFF-Dateien sind nicht UTF-8. Jedenfalls zeigt sie mein Browser nicht richtig an, wenn man ihn auf UTF-8 stellt.

Achja, Personen haben keine "Länge" ;) Listen und Möbel haben "Länge".
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Leonidas hat geschrieben:Edit: Achja, ihr solltet euch auch für eine Sprache entscheiden. Deutsche und Englische Kommentare gleichzeitig helfen niemandem. Auch l10n wäre nützlich, da würde man alle Strings auf Englisch schreiben und mit `getttext` übersetzen.
Das hatten wir vor. Die Kommentare müssen wir halt noch in englisch schreiben, da früher das ganze Script Deutsch war.
Ich glaube auch, eure XFF-Dateien sind nicht UTF-8. Jedenfalls zeigt sie mein Browser nicht richtig an, wenn man ihn auf UTF-8 stellt.
Welche Dateien genau? Mein Editor (vi) ist auch auf UTF-8 gestellt.
Achja, Personen haben keine "Länge" ;) Listen und Möbel haben "Länge".
Stimmt ;-) Habs geändert.

Die aktuellen Scripte sind unter https://svn.mathpyx.org/trunk/ erreichbar.
Einiges konnte ich schon verbessern, anderes mache ich später noch.

Grüsse
Pot
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

pot hat geschrieben:
Ich glaube auch, eure XFF-Dateien sind nicht UTF-8. Jedenfalls zeigt sie mein Browser nicht richtig an, wenn man ihn auf UTF-8 stellt.
Welche Dateien genau? Mein Editor (vi) ist auch auf UTF-8 gestellt.
bmi.xff, zumindest wenn man mittels Trac drauf schaut.
Hint: vi unterstützt kein UTF-8.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Okay, die XFFs könnten nicht UTF-8 kodiert sein, die Scripte jedoch sollten es.
Jaa.. ich meinte natürlich vim

edit
Das ist wohl ein Problem von Trac-Browser. Wenn du die Datei über den Subversion Link anschaust, und den Browser auf UTF-8 stellst, sollte die Darstellung korrekt sein.

Code: Alles auswählen

remo@remuntu:~/Programmierung/Projekte/mathpyx/trunk/src/mathpyx/xff/biology$ file *
bmi.xff: UTF-8 Unicode text
Grüsse
Pot
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Habe mir nun lxml angeschaut und die write()-Methode in libxff neu geschrieben. Funktioniert perfekt, allerdings hat es einen Nachteil: lxml binaries für Windows existieren nicht. Da mathpyx auch unter Windows ohne grosses pa-pi pa-po laufen soll, werden wir wohl auf eine andere Alternative zugreifen müssen.

Grüsse
Pot
Zuletzt geändert von pot am Sonntag 18. November 2007, 01:22, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ElementTree existiert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Danke.

http://mathpyx.org/changeset/39
nun wird ElementTree vollständig benutzt, BeautifulSoup wurde gekickt,
die Syntax der XFFs wurde etwas angepasst und sind nun meist ASCII
oder UTF-8 kodiert
edit
Soweit ich das sehe, ist MathML eher für die Darstellung von Formeln gedacht. Das Ziel der XFF jedoch ist es, _Informationen_ über Formeln und Gesetze zu sammeln.
Allerdings schaut mathomatic sehr interessant aus und das werde ich mir auch mal genauer anschauen bzw ein Code für Python zu schreiben versuchen.

Soweit ich nichts übersehen habe, habe ich sonst alle von euch bemängelten Codestellen überarbeitet und verbessert. Gibt es sonst noch etwas, was man verbessern könnte?

Achja: Die aktuelle Revision (40) beinhaltet auch die XFF in der Distribution. SIe werden im site-packages Ordner gespeichert. Beim nächsten Release (beta) wird es möglich sein, einfach `mathpyx --read [KATEGORIE]/[FORMEL]` angeben zu können, und es nimmt diese XFF, die in site-packages gespeichert werden.

Pot
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Python 2.5 liefert generell ElementTree mit, auch in Debian und anderen Linux Distributionen. Hat mit Gutsy nichts zu tun.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Achso, das wusse ich nicht. Danke für den Hinweis. r41

Pot
pot
User
Beiträge: 55
Registriert: Sonntag 4. März 2007, 00:57
Wohnort: Frauenfeld, CH

Da keine Verbesserungsvorschläge mehr kamen, ich jedoch mathpyx noch nicht genug reif für die Beta einschätze, habe ich mal eine preview erstellt um mathpyx ohne subversion testen zu können.

ChangeLog:

Code: Alles auswählen

Much code improvements
Included gettext and added German translation
Create ~/.mathpyx, if necessary
More Copyright information in files and configuration
Added --edit (under construction)
Added xff path parser
Much improvements in libxff module and mathpyx_console.py
Fixed: spelling errors
Much syntax improvements in XFF
Uses ElementTree now instead of BeautifulSoup to read/write XFFs
The XFFs are now a part of the distribution package
Removed --compile
Pakete v0.2.0 pre-r57: http://mathpyx.org/wiki/Download#pre-r57

Installationsanleitung findet man in der Datei INSTALL des Archivs.

Die alte Installation (falls vorhanden) kann mit folgendem Befehl entfernt werden:

Code: Alles auswählen

python setup.py uninstall
Natürlich mit dem setup-Script der Alpha-Version und nicht mit dem der pre-Version.

Grüsse
Pot
Antworten