Uma biblioteca python3 pura sem dependências destinada a facilitar a geração offline de arquivos Max patcher ( .maxpat
, .maxhelp
, .rbnopat
).
Se você estiver procurando por externos python3 para Max/MSP, verifique o projeto py-js.
Geração off-line com script de arquivos Max patcher usando objetos Python, correspondendo, individualmente, a objetos Max/MSP armazenados no formato de arquivo baseado em JSON .maxpat
.
Conversão de ida e volta entre arquivos (JSON) .maxpat
com níveis arbitrários de aninhamento e objetos Patcher
, Box
e Patchline
Python correspondentes.
Pode potencialmente lidar com qualquer objeto Max ou maxclass.
Muitos testes de unidade, cobertura de aproximadamente 99%.
Análise e modificação off-line de scripts de Max patches em termos de composição, estrutura (como gráficos de objetos), propriedades de objetos e layout (usando algoritmos de desenho de gráficos).
Permite layout e configuração precisos de objetos Max.
Os objetos Patcher
possuem métodos genéricos, como add_textbox
, e também podem ter métodos especializados, como add_coll
. Por exemplo, este método possui um argumento dictionary
para facilitar o pré-preenchimento do objeto coll
(consulte py2max/tests/test_coll.py
).
Fornece um recurso maxclassdb
que recupera configurações padrão de Max Objects.
Criação de arquivo patcher com script.
Modificação em lote de arquivos .maxpat existentes.
Use a rica biblioteca padrão e ecossistema python para ajudar a criar objetos parametrizáveis com configuração de fontes offline. Por exemplo, osciladores wavetable únicos configurados a partir de arquivos wavetable aleatórios.
Geração de casos de teste e arquivos .maxhelp
durante o desenvolvimento externo
Elimina a dificuldade de criar objetos com muitos parâmetros
Preencher previamente objetos contêineres, como objetos coll
, dict
e table
com dados
Ajude a economizar tempo criando muitos objetos com argumentos ligeiramente diferentes
Use algoritmos de desenho/layout de gráficos em patches gerados.
Geração de patch generativo (-;
etc..
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 ()
Por padrão, os objetos são retornados (incluindo patchlines) e as saídas e entradas do patchline são definidas como 0. Embora os objetos retornados sejam úteis para vinculação, os patchlines retornados não são. Portanto, o acima pode ser escrito de forma mais concisa como:
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 ()
Com aliases integrados ( .add
para métodos do tipo .add_*
e .link
para .add_line
), o exemplo acima pode ser escrito de uma forma ainda mais abreviada (e com um layout vertical) como:
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 ()
Além disso, você pode analisar arquivos .maxpat
existentes, alterá-los e salvar as alterações:
p = Patcher . from_file ( 'example1.maxpat' )
# ... make some change
p . save_as ( 'example1_mod.maxpat' )
Outro exemplo com subpatchers:
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 ()
Observe que as classes Python são basicamente wrappers simples em torno das estruturas JSON em um arquivo .maxpat, e quase todos os objetos Max/MSP e Jitter podem ser adicionados ao arquivo patcher com o .add_textbox
ou os métodos genéricos .add
. Existem também métodos especializados no formato .add_<type>
para números, parâmetros numéricos, subpatchers e objetos do tipo contêiner (consulte as notas de design abaixo para obter mais detalhes).
Maneira mais simples:
git https://github.com/shakfu/py2max.git
cd py2max
pip install . # optional
Observe que o py2max não precisa ser instalado para ser usado, então você pode pular o pip install .
parte se preferir e apenas cd
no diretório clonado e comece a usá-lo:
$ 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
tem um extenso conjunto de testes com testes na pasta py2max/tests
.
Pode-se executar todos os testes da seguinte forma:
pytest
Isso exibirá os resultados de todos os testes na pasta de outputs
.
Observe que alguns testes podem ser ignorados se um pacote necessário para o teste não puder ser importado.
Você pode verificar qual teste foi ignorado fazendo o seguinte:
pytest -v
Para verificar a cobertura do teste:
./scripts/coverage.sh
que essencialmente faz o seguinte
mkdir -p outputs
pytest --cov-report html:outputs/_covhtml --cov=py2max tests
Para executar um teste individual:
python3 -m pytest tests.test_basic
Observe que, como py2max
lida principalmente com geração e manipulação json
, a maioria dos testes não tem dependências, pois json
já está integrado ao stdlib.
Porém, vários testes exploram a aplicação de algoritmos de layout de grafos ortogonais e para isso foram utilizados vários pacotes, que vão do conhecido ao esotérico.
Conforme mencionado acima, o pytest irá pular um teste se os pacotes necessários não estiverem instalados, portanto, esses testes são totalmente opcionais.
Se você insiste em mergulhar na toca do coelho e deseja executar todos os testes você precisará dos seguintes pacotes (e suas dependências):
pip install networkx
pip install matplotlib
brew install graphviz
) - então você pode pip install pygraphviz
Os documentos da API ainda não estão disponíveis
O algoritmo de layout padrão atual é extremamente rudimentar, no entanto, existem algumas direções promissoras e você também pode ver uma comparação visual do desempenho de diferentes algoritmos de layout neste contexto.
Embora a geração não consuma os objetos py2max, infelizmente o Max não atualiza do arquivo quando ele está aberto, então você terá que fechar e reabrir o Max para ver as alterações na árvore de objetos.
Para os poucos objetos que possuem seus próprios métodos, a implementação atual diferencia objetos til de objetos não til, fornecendo um método diferente com um sufixo _tilde
:
gen = p . add_gen ()
gen_tilde = p . add_gen_tilde ()
O formato JSON .maxpat
é, na verdade, mínimo e hierárquico. Possui entradas Patcher
pai e Box
filho e também Patchlines
. Certas caixas contêm outras instâncias patcher
para representar subpatchers aninhados e patches gen~
, etc.
A estrutura acima mapeia diretamente para a implementação Python que consiste em 3 classes: Patcher
, Box
e Patchline
. Essas classes são extensíveis por meio de suas respectivas estruturas **kwds
e __dict__
internas. Na verdade, é assim que o método de classe .from_file
patcher é implementado.
Essa é a maneira mais fácil de manter e flexível para lidar com todas as diferenças entre as centenas de objetos Max, MSP e Jitter.
Uma lista crescente de métodos patcher foi implementada para especializar e facilitar a criação de certas classes de objetos que requerem configuração adicional:
.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
Esta é uma lista curta, mas o método add_textbox
sozinho pode lidar com quase todos os casos. Os outros estão lá apenas por conveniência e para economizar digitação.
Geralmente, é recomendado começar a usar py2max
por meio desses métodos add_<type>
, pois eles têm a maioria dos parâmetros necessários incorporados aos métodos e você pode obter suporte para conclusão do IDE. Quando estiver confortável com os parâmetros, use a forma abreviada genérica: add
, que é menos digitada, mas a desvantagem é que você perde o suporte à conclusão de parâmetros do IDE.
O projeto possui alguns scripts que podem ser úteis:
convert.py
: converte maxpat
em yaml
para facilitar a leitura durante o desenvolvimentocompare.py
: compare usando deepdiffcoverage.sh
: execute a cobertura pytest e gere o relatório de cobertura htmlObserve que se você deseja construir o py2max como uma roda:
pip install build
cd py2max
python3 -m build .
A roda então deve estar no diretório dist
.
Existe um ramo experimental deste projeto que é baseado no projeto pydantic2.
Esta variante tem os seguintes benefícios:
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 )]
Outra direção promissora desta variante é criar classes especializadas para objetos que possuem sua própria maxclass
exclusiva. Portanto, neste caso, o texto acima seria:
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 )]
Houve um esforço inicial para fornecer acesso a atributos baseado em propriedades e uma API aprimorada. Ele foi suplantado pelo ramo pydantic2
e não será mais desenvolvido.
Todos os direitos reservados aos respectivos autores originais:
Steve Kieffer, Tim Dwyer, Kim Marriott e Michael Wybrow. HOLA: Layout de rede ortogonal semelhante ao humano. Em Visualização e Computação Gráfica, IEEE Transactions on, Volume 22, Issue 1, páginas 349 - 358. IEEE, 2016. DOI
Aric A. Hagberg, Daniel A. Schult e Pieter J. Swart, “Explorando estrutura, dinâmica e função de rede usando NetworkX”, em Proceedings of the 7th Python in Science Conference (SciPy2008), Gäel Varoquaux, Travis Vaught e Jarrod Millman (Eds), (Pasadena, CA EUA), pp. 11–15, agosto de 2008
Uma técnica para desenhar gráficos direcionados Emden R. Gansner, Eleftherios Koutsofios, Stephen C. North, Kiem-phong Vo • IEEE TRANSACTIONS ON SOFTWARE ENGINEERING • Publicado em 1993
Gansner, ER, Koren, Y., Norte, S. (2005). Desenho de gráfico por majorização de estresse. In: Pach, J. (eds) Desenho gráfico. GD 2004. Notas de aula em ciência da computação, vol 3383. Springer, Berlim, Heidelberg. https://doi.org/10.1007/978-3-540-31843-9_25
Um sistema aberto de visualização de gráficos e suas aplicações para engenharia de software Emden R. Gansner, Stephen C. North • SOFTWARE - PRÁTICA E EXPERIÊNCIA • Publicado em 2000