Eine reine Python3-Bibliothek ohne Abhängigkeiten, die die Offline-Generierung von Max-Patcher-Dateien ( .maxpat
, .maxhelp
, .rbnopat
) erleichtern soll.
Wenn Sie nach Python3-Externals für Max/MSP suchen, schauen Sie sich das py-js-Projekt an.
Geskriptete Offline- Generierung von Max-Patcher-Dateien mithilfe von Python-Objekten, die eins zu eins mit Max/MSP-Objekten korrespondieren, die im JSON-basierten Dateiformat .maxpat
gespeichert sind.
Round-Trip-Konvertierung zwischen (JSON) .maxpat
Dateien mit beliebigen Verschachtelungsebenen und entsprechenden Patcher
, Box
und Patchline
-Python-Objekten.
Kann potenziell jedes Max-Objekt oder jede Max-Klasse verarbeiten.
Viele Unit-Tests, ~99 % Abdeckung.
Analyse und Offline-Skriptmodifikation von Max-Patches in Bezug auf Zusammensetzung, Struktur (als Diagramme von Objekten), Objekteigenschaften und Layout (unter Verwendung von Diagrammzeichnungsalgorithmen).
Ermöglicht eine präzise Anordnung und Konfiguration von Max-Objekten.
Patcher
Objekte verfügen über generische Methoden wie add_textbox
und können auch spezielle Methoden wie add_coll
haben. Diese Methode verfügt beispielsweise über ein dictionary
, um das Vorabfüllen des coll
-Objekts zu erleichtern (siehe py2max/tests/test_coll.py
).
Stellt eine maxclassdb
-Funktion bereit, die Standardkonfigurationen von Max Objects abruft.
Erstellung einer geskripteten Patcher-Datei.
Batch-Änderung vorhandener .maxpat-Dateien.
Nutzen Sie die umfangreiche Python-Standardbibliothek und das Ökosystem, um parametrisierbare Objekte mit Konfiguration aus Offline-Quellen zu erstellen. Zum Beispiel einzigartige Wavetable-Oszillatoren, die aus zufälligen Wavetable-Dateien konfiguriert werden.
Generierung von Testfällen und .maxhelp
Dateien während der externen Entwicklung
Macht das Erstellen von Objekten mit vielen Parametern zum Kinderspiel
Füllen Sie Containerobjekte wie coll
, dict
und table
-Objekte vorab mit Daten aus
Sparen Sie Zeit beim Erstellen vieler Objekte mit leicht unterschiedlichen Argumenten
Verwenden Sie Diagrammzeichnungs-/Layout-Algorithmen für generierte Patches.
Generative Patch-Generierung (-;
usw..
p = Patcher ( 'my-patch.maxpat' )
osc1 = p . add_textbox ( 'cycle~ 440' )
gain = p . add_textbox ( 'gain~' )
dac = p . add_textbox ( 'ezdac~' )
osc1_gain = p . add_line ( osc1 , gain ) # osc1 outlet 0 -> gain inlet 0
gain_dac0 = p . add_line ( gain , dac , outlet = 0 , inlet = 0 )
gain_dac1 = p . add_line ( gain , dac , outlet = 0 , inlet = 1 )
p . save ()
Standardmäßig werden Objekte zurückgegeben (einschließlich Patchlines), und Patchline-Ausgänge und -Eingänge werden auf 0 gesetzt. Während zurückgegebene Objekte für die Verknüpfung nützlich sind, sind die zurückgegebenen Patchlines nicht nützlich. Daher kann das Obige prägnanter geschrieben werden als:
p = Patcher ( 'my-patch.maxpat' )
osc1 = p . add_textbox ( 'cycle~ 440' )
gain = p . add_textbox ( 'gain~' )
dac = p . add_textbox ( 'ezdac~' )
p . add_line ( osc1 , gain )
p . add_line ( gain , dac )
p . add_line ( gain , dac , inlet = 1 )
p . save ()
Mit integrierten Aliasen ( .add
für Methoden vom Typ .add_*
und .link
für .add_line
) kann das obige Beispiel in noch kürzerer Form (und mit vertikalem Layout) wie folgt geschrieben werden:
p = Patcher ( 'out_vertical.maxpat' , layout = 'vertical' )
osc = p . add ( 'cycle~ 440' )
gain = p . add ( 'gain~' )
dac = p . add ( 'ezdac~' )
p . link ( osc , gain )
p . link ( gain , dac )
p . link ( gain , dac , 1 )
p . save ()
Darüber hinaus können Sie vorhandene .maxpat
Dateien analysieren, ändern und die Änderungen anschließend speichern:
p = Patcher . from_file ( 'example1.maxpat' )
# ... make some change
p . save_as ( 'example1_mod.maxpat' )
Ein weiteres Beispiel mit Subpatchern:
p = Patcher ( 'out.maxpat' )
sbox = p . add_subpatcher ( 'p mysub' )
sp = sbox . subpatcher
in1 = sp . add ( 'inlet' )
gain = sp . add ( 'gain~' )
out1 = sp . add ( 'outlet' )
osc = p . add ( 'cycle~ 440' )
dac = p . add ( 'ezdac~' )
sp . link ( in1 , gain )
sp . link ( gain , out1 )
p . link ( osc , sbox )
p . link ( sbox , dac )
p . save ()
Beachten Sie, dass Python-Klassen im Grunde nur einfache Wrapper um die JSON-Strukturen in einer .maxpat-Datei sind und fast alle Max/MSP- und Jitter-Objekte mit der .add_textbox
oder den generischen .add
Methoden zur Patcher-Datei hinzugefügt werden können. Es gibt auch spezielle Methoden in der Form .add_<type>
für Zahlen, numerische Parameter, Subpatcher und Containertypobjekte (weitere Einzelheiten finden Sie in den Designhinweisen unten).
Einfachster Weg:
git https://github.com/shakfu/py2max.git
cd py2max
pip install . # optional
Beachten Sie, dass py2max nicht installiert sein muss, um verwendet zu werden, sodass Sie die pip install .
Teil, wenn Sie es vorziehen, und cd
einfach in das geklonte Verzeichnis und beginnen Sie mit der Verwendung:
$ cd py2max
$ ipython
In [1]: from py2max import Patcher
In [2]: p = Patcher.from_file( " tests/data/simple.maxpat " )
In [3]: p._boxes
Out[3]: [Box(id= ' obj-2 ' , maxclass= ' ezdac~ ' ), Box(id= ' obj-1 ' , maxclass= ' newobj ' )]
py2max
verfügt über eine umfangreiche Testsuite mit Tests im Ordner py2max/tests
.
Man kann alle Tests wie folgt durchführen:
pytest
Dadurch werden die Ergebnisse aller Tests im outputs
ausgegeben.
Beachten Sie, dass einige Tests möglicherweise übersprungen werden, wenn ein für den Test erforderliches Paket nicht importiert werden kann.
Sie können wie folgt überprüfen, welcher Test übersprungen wird:
pytest -v
So überprüfen Sie die Testabdeckung:
./scripts/coverage.sh
was im Wesentlichen Folgendes bewirkt
mkdir -p outputs
pytest --cov-report html:outputs/_covhtml --cov=py2max tests
So führen Sie einen einzelnen Test durch:
python3 -m pytest tests.test_basic
Beachten Sie, dass die meisten Tests keine Abhängigkeiten aufweisen, da sich py2max
hauptsächlich mit json
-Generierung und -Manipulation befasst, da json
bereits in die stdlib integriert ist.
Eine Reihe von Tests untersuchen jedoch die Anwendung orthogonaler Graph-Layout-Algorithmen und dafür wurde eine ganze Reihe von Paketen verwendet, die von altbekannt bis esoterisch reichen.
Wie oben erwähnt, überspringt pytest einen Test, wenn erforderliche Pakete nicht installiert sind, es handelt sich also um völlig optionale Tests.
Wenn Sie darauf bestehen, in den Kaninchenbau einzutauchen und alle Tests ausführen möchten, benötigen Sie die folgenden Pakete (und ihre Abhängigkeiten):
pip install networkx
pip install matplotlib
brew install graphviz
erfolgen) – dann können Sie pip install pygraphviz
API-Dokumente sind immer noch nicht verfügbar
Der aktuelle Standard-Layout-Algorithmus ist äußerst rudimentär, es gibt jedoch einige vielversprechende Richtungen und Sie können auch einen visuellen Vergleich der Leistung verschiedener Layout-Algorithmen in diesem Zusammenhang sehen.
Während die Generierung die py2max-Objekte nicht verbraucht, aktualisiert Max die Datei leider nicht, wenn sie geöffnet ist. Daher müssen Sie Max immer wieder schließen und erneut öffnen, um die Änderungen am Objektbaum zu sehen.
Für die wenigen Objekte, die über eigene Methoden verfügen, unterscheidet die aktuelle Implementierung Tilde-Objekte von Nicht-Tilde-Objekten, indem sie eine andere Methode mit dem Suffix _tilde
bereitstellt:
gen = p . add_gen ()
gen_tilde = p . add_gen_tilde ()
Das .maxpat
JSON-Format ist eigentlich ziemlich minimalistisch und hierarchisch. Es verfügt über einen übergeordneten Patcher
und untergeordnete Box
Einträge sowie Patchlines
. Bestimmte Felder enthalten andere patcher
Instanzen, um verschachtelte Subpatcher und gen~
-Patches usw. darzustellen.
Die obige Struktur lässt sich direkt auf die Python-Implementierung abbilden, die aus drei Klassen besteht: Patcher
, Box
und Patchline
. Diese Klassen sind über ihre jeweiligen **kwds
und internen __dict__
Strukturen erweiterbar. Tatsächlich ist dies die Art und Weise, wie die .from_file
Patcher-Klassenmethode implementiert wird.
Dies erweist sich als die wartbarste und flexibelste Möglichkeit, alle Unterschiede zwischen den Hunderten von Max-, MSP- und Jitter-Objekten zu bewältigen.
Eine wachsende Liste von Patcher-Methoden wurde implementiert, um die Erstellung bestimmter Objektklassen zu spezialisieren und zu erleichtern, die eine zusätzliche Konfiguration erfordern:
.add_attr
.add_beap
.add_bpatcher
.add_codebox
.add_coll
.add_comment
.add_dict
.add_floatbox
.add_floatparam
.add_gen
.add_intbox
.add_intparam
.add_itable
.add_message
.add_rnbo
.add_subpatcher
.add_table
.add_textbox
.add_umenu
Dies ist eine kurze Liste, aber die Methode add_textbox
allein kann fast alle Fälle verarbeiten. Die anderen dienen eigentlich nur der Bequemlichkeit und um das Tippen zu sparen.
Im Allgemeinen wird empfohlen, mit der Verwendung von py2max
über diese add_<type>
-Methoden zu beginnen, da die meisten erforderlichen Parameter in die Methoden integriert sind und Sie Unterstützung für die IDE-Vervollständigung erhalten können. Sobald Sie mit den Parametern vertraut sind, verwenden Sie die generische Kurzform: add
, die weniger mühsam ist, aber den Nachteil hat, dass Sie die Unterstützung für die IDE-Parametervervollständigung verlieren.
Das Projekt verfügt über einige Skripte, die nützlich sein können:
convert.py
: Konvertieren Sie maxpat
in yaml
um das Lesen während der Entwicklung zu erleichterncompare.py
: Vergleich mit DeepDiffcoverage.sh
: Führen Sie die Pytest-Abdeckung aus und generieren Sie einen HTML-AbdeckungsberichtBeachten Sie Folgendes, wenn Sie py2max als Rad erstellen möchten:
pip install build
cd py2max
python3 -m build .
Das Rad sollte sich dann im dist
-Verzeichnis befinden.
Es gibt einen experimentellen Zweig dieses Projekts, der auf dem pydantic2-Projekt basiert.
Diese Variante hat folgende Vorteile:
In [ 1 ]: from py2max import Patcher
In [ 2 ]: p = Patcher ( path = 'outputs/demo.maxpat' )
In [ 3 ]: msg = p . add_message ( 'set' )
In [ 4 ]: p . boxes
Out [ 4 ]: [ Box ( id = 'obj-1' , text = 'set' , maxclass = 'message' , numinlets = 2 , numoutlets = 1 , outlettype = [ '' ], patching_rect = Rect ( x = 48.0 , y = 48.0 , w = 66.0 , h = 22.0 ), patcher = None )]
Eine weitere vielversprechende Richtung dieser Variante besteht darin, spezialisierte Klassen für Objekte zu erstellen, die über eine eigene, einzigartige maxclass
verfügen. In diesem Fall würde das Obige also lauten:
In [ 4 ]: p . boxes
Out [ 4 ]: [ Message ( id = 'obj-1' , text = 'set' , maxclass = 'message' , numinlets = 2 , numoutlets = 1 , outlettype = [ '' ], patching_rect = Rect ( x = 48.0 , y = 48.0 , w = 66.0 , h = 22.0 ), patcher = None )]
Es gab frühe Bemühungen, einen eigenschaftsbasierten Attributzugriff und eine verbesserte API bereitzustellen. Es wurde durch den pydantic2
Zweig ersetzt und wird nicht weiterentwickelt.
Alle Rechte liegen bei den jeweiligen Originalautoren:
Steve Kieffer, Tim Dwyer, Kim Marriott und Michael Wybrow. HOLA: Menschenähnliches orthogonales Netzwerklayout. In Visualization and Computer Graphics, IEEE Transactions on, Band 22, Ausgabe 1, Seiten 349–358. IEEE, 2016. DOI
Aric A. Hagberg, Daniel A. Schult und Pieter J. Swart, „Exploring network structure, Dynamics, and Function using NetworkX“, in Proceedings of the 7th Python in Science Conference (SciPy2008), Gäel Varoquaux, Travis Vaught und Jarrod Millman (Hrsg.), (Pasadena, CA USA), S. 11–15, August 2008
Eine Technik zum Zeichnen gerichteter Graphen Emden R. Gansner, Eleftherios Koutsofios, Stephen C. North, Kiem-phong Vo • IEEE TRANSACTIONS ON SOFTWARE ENGINEERING • Veröffentlicht 1993
Gansner, ER, Koren, Y., North, S. (2005). Diagrammzeichnen durch Spannungsmajorisierung. In: Pach, J. (Hrsg.) Graph Drawing. GD 2004. Lecture Notes in Computer Science, Bd. 3383. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-540-31843-9_25
Ein offenes Graphenvisualisierungssystem und seine Anwendungen für die Softwareentwicklung Emden R. Gansner, Stephen C. North • SOFTWARE – PRAXIS UND ERFAHRUNG • Veröffentlicht 2000