Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

ADD: First version of InVesalius 3 code by Tati, Paulo & Thiago.

git-svn-id: http://svn.softwarepublico.gov.br/svn/invesalius/invesalius3/trunk@675 e1d098d0-f32f-0410-9823-cb12c6f6c872
  • Loading branch information...
commit 776fe3e23512d2c44e5c7b238f1bb0e8ade9bdf0 0 parents
tatiana.alchueyr@gmail.com authored
Showing with 12,326 additions and 0 deletions.
  1. +28 −0 AUTHORS.txt
  2. +32 −0 HEADER.txt
  3. +23 −0 INSTALL.txt
  4. +378 −0 LICENSE-pt.txt
  5. +340 −0 LICENSE.txt
  6. +22 −0 NEWS.txt
  7. +34 −0 README.txt
  8. +97 −0 TODO.txt
  9. +21 −0 docs/devel/example_closure.py
  10. +80 −0 docs/devel/example_pubsub.py
  11. +54 −0 docs/devel/example_singleton.py
  12. +62 −0 docs/devel/example_singleton_pubsub.py
  13. +42 −0 docs/devel/sendmessages.txt
  14. +92 −0 docs/devel/subscribes.txt
  15. BIN  icons/brush_circle.jpg
  16. BIN  icons/brush_square.jpg
  17. BIN  icons/invesalius.ico
  18. BIN  icons/object_colour.jpg
  19. BIN  icons/object_invisible.jpg
  20. BIN  icons/object_visible.jpg
  21. +80 −0 invesalius/constants.py
  22. +76 −0 invesalius/control.py
  23. +1 −0  invesalius/data/__init__.py
  24. +251 −0 invesalius/data/editor.py
  25. +77 −0 invesalius/data/imagedata_utils.py
  26. +15 −0 invesalius/data/mask.py
  27. +122 −0 invesalius/data/orientation.py
  28. +86 −0 invesalius/data/polydata_utils.py
  29. +312 −0 invesalius/data/slice_.py
  30. +179 −0 invesalius/data/styles.py
  31. +234 −0 invesalius/data/surface.py
  32. 0  invesalius/data/viewer.py
  33. +194 −0 invesalius/data/viewer_slice.py
  34. +112 −0 invesalius/data/viewer_volume.py
  35. +32 −0 invesalius/data/volume.py
  36. +144 −0 invesalius/data/volume_widgets.py
  37. +50 −0 invesalius/data/vtk_utils.py
  38. +1 −0  invesalius/gui/__init__.py
  39. +462 −0 invesalius/gui/data_notebook.py
  40. +213 −0 invesalius/gui/default_tasks.py
  41. +165 −0 invesalius/gui/default_viewers.py
  42. +267 −0 invesalius/gui/frame.py
  43. +354 −0 invesalius/gui/import_data_wizard.py
  44. +26 −0 invesalius/gui/task_exporter.py
  45. +26 −0 invesalius/gui/task_generic.py
  46. +276 −0 invesalius/gui/task_importer.py
  47. +520 −0 invesalius/gui/task_slice.py
  48. +464 −0 invesalius/gui/task_surface.py
  49. +168 −0 invesalius/gui/task_tools.py
  50. +1 −0  invesalius/gui/widgets/__init__.py
  51. +1,918 −0 invesalius/gui/widgets/foldpanelbar.py
  52. +632 −0 invesalius/gui/widgets/gradient.py
  53. +915 −0 invesalius/gui/widgets/listctrl.py
  54. +85 −0 invesalius/invesalius.py
  55. +76 −0 invesalius/presets.py
  56. +109 −0 invesalius/project.py
  57. +1 −0  invesalius/reader/__init__.py
  58. +37 −0 invesalius/reader/analyze_reader.py
  59. +1,619 −0 invesalius/reader/dicom.py
  60. +526 −0 invesalius/reader/dicom_grouper.py
  61. +132 −0 invesalius/reader/dicom_reader.py
  62. +63 −0 invesalius/utils.py
28 AUTHORS.txt
@@ -0,0 +1,28 @@
+InVesalius was originally created in late 2002 at CenPRA,the Renato Archer
+Research Centre, of the Ministry of Science and Technology in Campinas, Brazil. Since November 2008, InVesalius 3 has been written from 0. This list represents only people involved with this development on.
+
+The PRIMARY AUTHORS of InVesalius 3 are (and/or have been):
+
+ * Tatiana Al-Chueyr Pereira Martins
+ * Paulo Henrique Junqueira Amorim
+ * Thiago Franco de Moraes
+
+More information on the main contributors to InVesalius can be found in
+docs/internals/committers.txt.
+
+And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS:
+people who have submitted patches, reported bugs, added translations, helped
+answer newbie questions, and generally made InVesalius that much better:
+
+ Mathieu Malaterre <mathieu.malaterre@gmail.com>
+
+A big THANK YOU goes to:
+
+ CTI Renato Archer directors for letting us open-source InVesalius.
+
+ Glauber Costa de Oliveira and Corinto Meffe for free software advices.
+
+ Robin Dunn for the marriage of the Python programming language and the
+ wxWindows, in the form of wxPython
+
+ Guido van Rossum for creating Python.
32 HEADER.txt
@@ -0,0 +1,32 @@
+#--------------------------------------------------------------------------
+# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
+# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
+# Homepage: http://www.softwarepublico.gov.br
+# Contact: invesalius@cti.gov.br
+# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
+#--------------------------------------------------------------------------
+# Este programa e software livre; voce pode redistribui-lo e/ou
+# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
+# publicada pela Free Software Foundation; de acordo com a versao 2
+# da Licenca.
+#
+# Este programa eh distribuido na expectativa de ser util, mas SEM
+# QUALQUER GARANTIA; sem mesmo a garantia implicita de
+# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
+# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
+# detalhes.
+#--------------------------------------------------------------------------
+
+
+esta sendo discutida a possibilidade de insercao do cabecalho em ingles tambem... por enquanto nao colocar.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#----------------------------------------------------------------------------
+
23 INSTALL.txt
@@ -0,0 +1,23 @@
+# TODO: FUTURE!!!
+
+Thanks for downloading InVesalius.
+
+To install it, make sure you have Python 2.5 or greater installed. Then run
+this command from the command prompt:
+
+ python setup.py install
+
+Note this requires a working Internet connection if you don't already have the
+Python utility "setuptools" installed.
+
+AS AN ALTERNATIVE, you can just copy the entire "invesalius" directory to Python's
+site-packages directory, which is located wherever your Python installation
+lives. Some places you might check are:
+
+ /usr/lib/python2.5/site-packages (Unix, Python 2.5)
+ C:\\PYTHON\site-packages (Windows)
+
+This second solution does not require a working Internet connection; it
+bypasses "setuptools" entirely.
+
+For more detailed instructions, see docs/intro/install.txt.
378 LICENSE-pt.txt
@@ -0,0 +1,378 @@
+LICEN�A P�BLICA GERAL GNU
+Vers�o 2, junho de 1991
+
+ This is an unofficial translation of the GNU General Public License into
+ Portuguese. It was not published by the Free Software Foundation, and does not
+ legally state the distribution terms for software that uses the GNU GPL -- only
+ the original English text of the GNU GPL does that. However, we hope that this
+ translation will help Portuguese speakers understand the GNU GPL better.
+
+ Esta � uma tradu��o n�o-oficial da Licen�a P�blica Geral GNU ("GPL GNU") para
+ Portugu�s. N�o foi publicada pela Free Software Foundation, e legalmente n�o
+ afirma os termos de distribui��o de software que utilize a GPL GNU -- apenas o
+ texto original da GPL GNU, em ingl�s, faz isso. Contudo, esperamos que esta
+ tradu��o ajude aos que falam portugu�s a entender melhor a GPL GNU.
+
+Para sugest�es ou correc��es a esta tradu��o, contacte:
+
+miguel.andrade@neoscopio.com
+
+
+--- Tradu��o do documento original a partir desta linha ---
+
+
+LICEN�A P�BLICA GERAL GNU
+Vers�o 2, junho de 1991
+
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+ Cambridge, MA 02139, USA
+
+ A qualquer pessoa � permitido copiar e distribuir c�pias deste documento de
+ licen�a, desde que sem qualquer altera��o.
+
+Introdu��o
+
+ As licen�as de software s�o normalmente desenvolvidas para restringir a
+ liberdade de compartilh�-lo e modifica-lo. Pelo contr�rio, a Licen�a P�blica
+ Geral GNU pretende garantir a sua liberdade de compartilhar e modificar o
+ software livre -- garantindo que o software ser� livre para os seus
+ utilizadores. Esta Licen�a P�blica Geral aplica-se � maioria do software da
+ Free Software Foundation e a qualquer outro programa ao qual o seu autor decida
+ aplic�-la. (Algum software da FSF � cobertos pela Licen�a P�blica Geral de
+ Bibliotecas.) Tamb�m poder� aplic�-la aos seus programas.
+
+ Quando nos referimos a software livre, estamo-nos a referir � liberdade e n�o
+ ao pre�o. A Licen�a P�blica Geral (GPL - General Public Licence - em Ingl�s.)
+ foi desenvolvida para garantir a sua liberdade de distribuir c�pias de software
+ livre (e cobrar por isso, se quiser); receber o c�digo-fonte ou ter acesso a
+ ele, se quiser; poder modificar o software ou utilizar partes dele em novos
+ programas livres; e que saiba que est� no seu direito de o fazer.
+
+ Para proteger seus direitos, precisamos fazer restri��es que impe�am a qualquer
+ um negar estes direitos ou solicitar que voc� abdique deles. Estas restri��es
+ traduzem-se em certas responsabilidades para si, caso venha a distribuir c�pias
+ do software, ou modific�-lo.
+
+ Por exemplo, se voc� distribuir c�pias de um programa sobre este tipo de
+ licenciamento, gratuitamente ou por alguma quantia, tem que fornecer igualmente
+ todos os direitos que possui sobre ele. Tem igualmente que garantir que os
+ destinat�rios recebam ou possam obter o c�digo-fonte. Al�m disto, tem que
+ fornecer-lhes estes termos para que possam conhecer seus direitos.
+
+ N�s protegemos seus direitos por duas formas que se completam: (1) com
+ copyright do software e (2) com a oferta desta licen�a, que lhe d� permiss�o
+ legal para copiar, distribuir e/ou modificar o software.
+
+ Al�m disso, tanto para a protec��o do autor quanto a nossa, gostar�amos de
+ certificar-nos de que todos entendam que n�o h� qualquer garantia sobre o
+ software livre. Se o software � modificado por algu�m e redistribu�do, queremos
+ que seus destinat�rios saibam que o que eles obtiveram n�o � original, de forma
+ que qualquer problema introduzido por terceiros n�o interfira na reputa��o do
+ autor original.
+
+ Finalmente, qualquer programa � amea�ado constantemente por patentes de
+ software. Queremos evitar o perigo de que distribuidores de software livre
+ obtenham patentes individuais sobre o software, o que teria o efeito de tornar
+ o software propriet�rio. Para prevenir isso, deixamos claro que qualquer
+ patente tem que ser licenciada para uso livre e gratuito por qualquer pessoa,
+ ou ent�o que nem necessite ser licenciada.
+
+ Os termos e condi��es precisas para c�pia, distribui��o e modifica��o
+ encontram-se abaixo:
+
+LICEN�A P�BLICA GERAL GNU TERMOS E CONDI��ES PARA C�PIA, DISTRIBUI��O E
+MODIFICA��O
+
+ 0. Esta licen�a aplica-se a qualquer programa ou outro trabalho que contenha um
+ aviso colocado pelo detentor dos direitos autorais informando que aquele pode
+ ser distribu�do sob as condi��es desta Licen�a P�blica Geral. O "Programa"
+ abaixo refere-se a qualquer programa ou trabalho e "trabalho baseado no
+ Programa" significa tanto o Programa em si, como quaisquer trabalhos derivados,
+ de acordo com a lei de direitos de autor: isto quer dizer um trabalho que
+ contenha o Programa ou parte dele, tanto na forma original ou modificado, e/ou
+ tradu��o para outros idiomas. ***(Doravante o termo "modifica��o" ou sin�nimos
+ ser�o usados livremente.) *** Cada licenciado � mencionado como "voc�".
+
+ Actividades outras que a c�pia, a distribui��o e modifica��o n�o est�o cobertas
+ por esta Licen�a; elas est�o fora do seu �mbito. O acto de executar o Programa
+ n�o � restringido e o resultado do Programa � coberto pela licen�a apenas se o
+ seu conte�do contenha trabalhos baseados no Programa (independentemente de
+ terem sido gerados pela execu��o do Programa). Este �ltimo ponto depende das
+ funcionalidades espec�ficas de cada programa.
+
+ 1. Voc� pode copiar e distribuir c�pias fi�is do c�digo-fonte do Programa da
+ mesma forma que voc� o recebeu, usando qualquer meio, deste que inclua em cada
+ c�pia um aviso de direitos de autor e uma declara��o de inexist�ncia de
+ garantias; mantenha intactos todos os avisos que se referem a esta Licen�a e �
+ aus�ncia total de garantias; e forne�a aos destinat�rios do Programa uma c�pia
+ desta Licen�a, em conjunto com o Programa.
+
+ Voc� pode cobrar pelo acto f�sico de transferir uma c�pia e pode,
+ opcionalmente, oferecer garantias em troca de pagamento.
+
+ 2. Voc� pode modificar sua c�pia ou c�pias do Programa, ou qualquer parte dele,
+ gerando assim um trabalho derivado, copiar e distribuir essas modifica��es ou
+ trabalhos sob os termos da sec��o 1 acima, desde que se enquadre nas seguintes
+ condi��es:
+
+ a) Os arquivos modificados devem conter avisos proeminentes afirmando que voc�
+ alterou os arquivos, incluindo a data de qualquer altera��o.
+
+ b) Deve ser licenciado, sob os termos desta Licen�a, integralmente e sem custo
+ algum para terceiros, qualquer trabalho seu que contenha ou seja derivado do
+ Programa ou de parte dele.
+
+ c) Se qualquer programa modificado, quando executado, l� normalmente comandos
+ interactivamente, tem que fazer com que, quando iniciado o uso interactivo,
+ seja impresso ou mostrado um an�ncio de que n�o h� qualquer garantia (ou ent�o
+ que voc� fornece a garantia) e que os utilizadores podem redistribuir o
+ programa sob estas condi��es, ainda informando os utilizadores como consultar
+ uma c�pia desta Licen�a. (Excep��o: se o Programa em si � interactivo mas
+ normalmente n�o imprime estes tipos de an�ncios, ent�o o seu trabalho derivado
+ n�o precisa imprimir um an�ncio.)
+
+ Estas exig�ncias aplicam-se ao trabalho derivado como um todo. Se sec��es
+ identific�veis de tal trabalho n�o s�o derivadas do Programa, e podem ser
+ razoavelmente consideradas trabalhos independentes e separados por si s�, ent�o
+ esta Licen�a, e seus termos, n�o se aplicam a estas sec��es caso as distribua
+ como um trabalho separado. Mas se distribuir as mesmas sec��es como parte de um
+ todo que constitui trabalho derivado, a distribui��o como um todo tem que
+ enquadrar-se nos termos desta Licen�a, cujos direitos para outros licenciados
+ se estendem ao todo, portanto tamb�m para toda e qualquer parte do programa,
+ independente de quem a escreveu.
+
+ Desta forma, esta sec��o n�o tem a inten��o de reclamar direitos ou contestar
+ seus direitos sobre o trabalho escrito completamente por si; ao inv�s disso, a
+ inten��o � a de exercitar o direito de controlar a distribui��o de trabalhos,
+ derivados ou colectivos, baseados no Programa.
+
+ Adicionalmente, a mera adi��o ao Programa (ou a um trabalho derivado deste) de
+ um outro trabalho num volume de armazenamento ou meio de distribui��o n�o faz
+ esse outro trabalho seja inclu�do no �mbito desta Licen�a.
+
+ 3. Voc� pode copiar e distribuir o Programa (ou trabalho derivado, conforme
+ descrito na Sec��o 2) em c�digo-objecto ou em forma execut�vel sob os termos
+ das Sec��es 1 e 2 acima, desde que cumpra uma das seguintes alienas:
+
+ a) O fa�a acompanhar com o c�digo-fonte completo e em forma acess�vel por
+ m�quinas, c�digo esse que tem que ser distribu�do sob os termos das Sec��es 1 e
+ 2 acima e em meio normalmente utilizado para o interc�mbio de software; ou,
+
+ b) O acompanhe com uma oferta escrita, v�lida por pelo menos tr�s anos, de
+ fornecer a qualquer um, com um custo n�o superior ao custo de distribui��o
+ f�sica do material, uma c�pia do c�digo-fonte completo e em forma acess�vel por
+ m�quinas, c�digo esse que tem que ser distribu�do sob os termos das Sec��es 1
+ e 2 acima e em meio normalmente utilizado para o interc�mbio de software; ou,
+
+ c) O acompanhe com a informa��o que voc� recebeu em rela��o � oferta de
+ distribui��o do c�digo-fonte correspondente. (Esta alternativa � permitida
+ somente em distribui��o n�o comerciais, e apenas se voc� recebeu o programa em
+ forma de c�digo-objecto ou execut�vel, com uma oferta de acordo com a Subsec��o
+ b) acima.)
+
+ O c�digo-fonte de um trabalho corresponde � forma de trabalho preferida para se
+ fazer modifica��es. Para um trabalho em forma execut�vel, o c�digo-fonte
+ completo significa todo o c�digo-fonte de todos os m�dulos que ele cont�m, mais
+ quaisquer arquivos de defini��o de "interface", mais os "scripts" utilizados
+ para se controlar a compila��o e a instala��o do execut�vel. Contudo, como
+ excep��o especial, o c�digo-fonte distribu�do n�o precisa incluir qualquer
+ componente normalmente distribu�do (tanto em forma original quanto bin�ria) com
+ os maiores componentes (o compilador, o "kernel" etc.) do sistema operativo sob
+ o qual o execut�vel funciona, a menos que o componente em si acompanhe o
+ execut�vel.
+
+ Se a distribui��o do execut�vel ou c�digo-objecto � feita atrav�s da oferta de
+ acesso a c�pias em algum lugar, ent�o oferecer o acesso equivalente a c�pia, no
+ mesmo lugar, do c�digo-fonte, equivale � distribui��o do c�digo-fonte, mesmo
+ que terceiros n�o sejam compelidos a copiar o c�digo-fonte em conjunto com o
+ c�digo-objecto.
+
+ 4. Voc� n�o pode copiar, modificar, sublicenciar ou distribuir o Programa,
+ excepto de acordo com as condi��es expressas nesta Licen�a. Qualquer outra
+ tentativa de c�pia, modifica��o, sublicenciamento ou distribui��o do Programa
+ n�o � valida, e cancelar� automaticamente os direitos que lhe foram fornecidos
+ por esta Licen�a. No entanto, terceiros que receberam de si c�pias ou direitos,
+ fornecidos sob os termos desta Licen�a, n�o ter�o a sua licen�a terminada,
+ desde que permane�am em total concord�ncia com ela.
+
+ 5. Voc� n�o � obrigado a aceitar esta Licen�a j� que n�o a assinou. No entanto,
+ nada mais lhe dar� permiss�o para modificar ou distribuir o Programa ou
+ trabalhos derivados deste. Estas ac��es s�o proibidas por lei, caso voc� n�o
+ aceite esta Licen�a. Desta forma, ao modificar ou distribuir o Programa (ou
+ qualquer trabalho derivado do Programa), voc� estar� a indicar a sua total
+ concord�ncia com os termos desta Licen�a, nomeadamente os termos e condi��es
+ para copiar, distribuir ou modificar o Programa, ou trabalhos baseados nele.
+
+ 6. Cada vez que redistribuir o Programa (ou qualquer trabalho derivado), os
+ destinat�rios adquirir�o automaticamente do autor original uma licen�a para
+ copiar, distribuir ou modificar o Programa, sujeitos a estes termos e
+ condi��es. Voc� n�o poder� impor aos destinat�rios qualquer outra restri��o ao
+ exerc�cio dos direitos ent�o adquiridos. Voc� n�o � respons�vel em garantir a
+ concord�ncia de terceiros a esta Licen�a.
+
+ 7. Se, em consequ�ncia de decis�es judiciais ou alega��es de viola��o de
+ patentes ou quaisquer outras raz�es (n�o limitadas a assuntos relacionados a
+ patentes), lhe forem impostas condi��es (por ordem judicial, acordos ou outras
+ formas) e que contradigam as condi��es desta Licen�a, elas n�o o livram das
+ condi��es desta Licen�a. Se n�o puder distribuir de forma a satisfazer
+ simultaneamente suas obriga��es para com esta Licen�a e para com as outras
+ obriga��es pertinentes, ent�o como consequ�ncia voc� n�o poder� distribuir o
+ Programa. Por exemplo, se uma licen�a de patente n�o permitir a redistribui��o,
+ sem obriga��o ao pagamento de "royalties", por todos aqueles que receberem
+ c�pias directa ou indirectamente de si, ent�o a �nica forma de voc� satisfazer
+ a licen�a de patente e a esta Licen�a seria a de desistir completamente de
+ distribuir o Programa.
+
+ Se qualquer parte desta sec��o for considerada inv�lida ou n�o aplic�vel em
+ qualquer circunst�ncia particular, o restante da sec��o aplica-se, e a sec��o
+ como um todo aplicar-se-� em outras circunst�ncias.
+
+ O prop�sito desta sec��o n�o � o de induzi-lo a infringir quaisquer patentes ou
+ reivindica��o de direitos de propriedade de outros, ou a contestar a validade
+ de quaisquer dessas reivindica��es; esta sec��o tem como �nico prop�sito
+ proteger a integridade dos sistemas de distribui��o de software livre, que �
+ implementado pela pr�tica de licen�as p�blicas. V�rias pessoas t�m contribu�do
+ generosamente e em grande escala para software distribu�do usando este sistema,
+ na certeza de que sua aplica��o � feita de forma consistente; fica a crit�rio
+ do autor/doador decidir se ele ou ela est� disposto(a) a distribuir software
+ utilizando outro sistema, e um outro detentor de uma licen�a n�o pode impor
+ esta ou qualquer outra escolha.
+
+ Esta sec��o destina-se a tornar bastante claro o que se acredita ser
+ consequ�ncia do restante desta Licen�a.
+
+ 8. Se a distribui��o e/ou uso do Programa s�o restringidos em certos pa�ses por
+ patentes ou direitos de autor, o detentor dos direitos de autor original, que
+ colocou o Programa sob esta Licen�a, pode incluir uma limita��o geogr�fica de
+ distribui��o, excluindo aqueles pa�ses, de forma a apenas permitir a
+ distribui��o nos pa�ses n�o exclu�dos. Nestes casos, esta Licen�a incorpora a
+ limita��o como se a mesma constasse escrita nesta Licen�a.
+
+ 9. A Free Software Foundation pode publicar vers�es revistas e/ou novas da
+ Licen�a P�blica Geral de tempos em tempos. Estas novas vers�es ser�o similares
+ em esp�rito � vers�o actual, mas podem diferir em detalhes que resolvam novos
+ problemas ou situa��es.
+
+ A cada vers�o � dada um n�mero distinto. Se o Programa especifica um n�mero de
+ vers�o espec�fico desta Licen�a que se aplica a ele e a "qualquer nova vers�o",
+ voc� tem a op��o de aceitar os termos e condi��es daquela vers�o ou de qualquer
+ outra vers�o posterior publicada pela Free Software Foundation. Se o programa
+ n�o especificar um n�mero de vers�o desta Licen�a, poder� escolher qualquer
+ vers�o publicada pela Free Software Foundation.
+
+ 10. Se voc� pretende incorporar partes do Programa em outros programas livres
+ cujas condi��es de distribui��o sejam diferentes, escreva ao autor e solicite
+ permiss�o para tal. Para o software que a Free Software Foundation det�m
+ direitos de autor, escreva � Free Software Foundation; �s vezes n�s permitimos
+ excep��es para estes casos. A nossa decis�o ser� guiada por dois objectivos: o
+ de preservar a condi��o de liberdade de todas os trabalhos derivados do nosso
+ software livre, e o de promover a partilha e reutiliza��o de software de um
+ modo geral.
+
+
+AUS�NCIA DE GARANTIAS
+
+ 11. UMA VEZ QUE O PROGRAMA � LICENCIADO SEM �NUS, N�O H� QUALQUER GARANTIA PARA
+ O PROGRAMA, NA EXTENS�O PERMITIDA PELAS LEIS APLIC�VEIS. EXCEPTO QUANDO
+ EXPRESSO DE FORMA ESCRITA, OS DETENTORES DOS DIREITOS AUTORAIS E/OU TERCEIROS
+ DISPONIBILIZAM O PROGRAMA "COMO ESTA", SEM QUALQUER TIPO DE GARANTIAS,
+ EXPRESSAS OU IMPL�CITAS, INCLUINDO, MAS N�O LIMITADO A, �S GARANTIAS IMPL�CITAS
+ DE COMERCIALIZA��O E �S DE ADEQUA��O A QUALQUER PROP�SITO. O RISCO COM A
+ QUALIDADE E DESEMPENHO DO PROGRAMA � TOTALMENTE SEU. CASO O PROGRAMA SE REVELE
+ DEFEITUOSO, VOC� ASSUME OS CUSTOS DE TODAS AS MANUTEN��ES, REPAROS E CORREC��ES
+ QUE JULGUE NECESS�RIAS.
+
+ 12. EM NENHUMA CIRCUNST�NCIA, A MENOS QUE EXIGIDO PELAS LEIS APLIC�VEIS OU
+ ACORDO ESCRITO, OS DETENTORES DOS DIREITOS DE AUTOR, OU QUALQUER OUTRA PARTE
+ QUE POSSA MODIFICAR E/OU REDISTRIBUIR O PROGRAMA CONFORME PERMITIDO ACIMA,
+ SER�O RESPONSABILIZADOS POR SI OU POR SEU INTERM�DIO, POR DANOS, INCLUINDO
+ QUALQUER DANO EM GERAL, ESPECIAL, ACIDENTAL OU CONSEQUENTE, RESULTANTES DO USO
+ OU INCAPACIDADE DE USO DO PROGRAMA (INCLUINDO, MAS N�O LIMITADO A, A PERDA DE
+ DADOS OU DADOS TORNADOS INCORRECTOS, OU PERDAS SOFRIDAS POR SI OU POR OUTRAS
+ PARTES, OU FALHAS DO PROGRAMA AO OPERAR COM QUALQUER OUTRO PROGRAMA), MESMO QUE
+ TAIS DETENTORES OU PARTES TENHAM SIDO AVISADOS DA POSSIBILIDADE DE TAIS DANOS.
+
+FIM DOS TERMOS E CONDI��ES
+
+---------------------
+
+
+
+Como Aplicar Estes Termos aos Seus Novos Programas
+
+ Se voc� desenvolver um novo programa, e quer que ele seja utilizado amplamente
+ pelo p�blico, a melhor forma de alcan�ar este objectivo � torn�-lo software
+ livre, software que qualquer um pode redistribuir e alterar, sob estes termos.
+
+ Para tal, inclua os seguintes avisos no programa. � mais seguro inclui-los logo
+ no in�cio de cada arquivo-fonte para refor�ar mais efectivamente a inexist�ncia
+ de garantias; e cada arquivo deve conter pelo menos a linha de "copyright" e
+ uma indica��o sobre onde encontrar o texto completo da licen�a.
+
+Exemplo:
+
+
+ <uma linha que forne�a o nome do programa e uma ideia do que ele faz.>
+ Copyright (C) <ano> <nome do autor>
+
+ Este programa � software livre; voc� pode redistribu�-lo e/ou modific�-lo sob
+ os termos da Licen�a P�blica Geral GNU, conforme publicada pela Free Software
+ Foundation; tanto a vers�o 2 da Licen�a como (a seu crit�rio) qualquer vers�o
+ mais actual.
+
+ Este programa � distribu�do na expectativa de ser �til, mas SEM QUALQUER
+ GARANTIA; incluindo as garantias impl�citas de COMERCIALIZA��O ou de ADEQUA��O
+ A QUALQUER PROP�SITO EM PARTICULAR. Consulte a Licen�a P�blica Geral GNU para
+ obter mais detalhes.
+
+ Voc� deve ter recebido uma c�pia da Licen�a P�blica Geral GNU em conjunto com
+ este programa; caso contr�rio, escreva para a Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+
+ Inclua tamb�m informa��es sobre como contact�-lo electronicamente e por carta.
+
+ Se o programa � interactivo, fa�a-o mostrar um aviso breve como este, ao
+ iniciar um modo interactivo:
+
+Exemplo:
+
+
+ Gnomovision vers�o 69, Copyright (C) <ano> <nome do autor> O Gnomovision n�o
+ possui QUALQUER GARANTIA; para obter mais detalhes escreva `mostrar g'. �
+ software livre e voc� est� convidado a redistribui-lo sob certas condi��es;
+ digite `mostrar c' para obter detalhes.
+
+ Os comandos hipot�ticos `mostrar g e `mostrar c' devem mostrar as partes
+ apropriadas da Licen�a P�blica Geral. � claro que os comandos que escolher usar
+ podem ser activados de outra forma que `mostrar g' e `mostrar c'; podem ser
+ cliques do rato ou itens de um menu -- o que melhor se adequar ao seu programa.
+
+ Voc� tamb�m deve obter da sua entidade patronal (se trabalhar como
+ programador) ou escola, conforme o caso, uma "declara��o de aus�ncia de
+ direitos autorais" sobre o programa, se necess�rio. Aqui est� um exemplo:
+
+
+ Neoscopio Lda., declara a aus�ncia de quaisquer direitos autorais sobre o
+ programa `Gnomovision' escrito por Jorge Andrade.
+
+10 de Junho de 2004
+ <assinatura de Miguel Nunes>,
+
+Miguel Nunes, Gerente de Neoscopio Lda.
+
+
+
+ Esta Licen�a P�blica Geral n�o permite incorporar o seu programa em programas
+ propriet�rios. Se o seu programa � uma biblioteca de sub-rotinas, poder�
+ considerar mais �til permitir ligar aplica��es propriet�rias com a biblioteca.
+ Se � isto que pretende, use a Licen�a P�blica Geral de Bibliotecas GNU, em vez
+ desta Licen�a.
+
+
+
+
+
+
340 LICENSE.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
22 NEWS.txt
@@ -0,0 +1,22 @@
+3.0 (2008-11-17)
+=================
+
+Improvements
+------------
+ - New GUI
+ - New 3D measures feature
+ - New slice editor feature
+ - Open Lossless DICOM
+ - Open large studies (over 500 slices) without resampling
+
+Bug fixes
+---------
+ - None yet
+
+API Changes
+-----------
+Changes are not backwards compatible. There were some incompatible
+changes which will affect InVesalius 2 projects backends.
+
+2.9 (2008-01-28)
+=================
34 README.txt
@@ -0,0 +1,34 @@
+InVesalius is a free 3D Medical Reconstruction Software that encourages 3D
+visualization and rapid prototyping based on 2D CT DICOM files.
+
+All documentation is in the "docs" directory and online at
+--- TODO: HTTP ---. If you're just getting started, here's
+how we recommend you read the docs:
+
+ * First, read docs/intro/install.txt for instructions on installing InVesalius.
+
+ * Next, work through the tutorials in order (docs/intro/tutorial01.txt,
+ docs/intro/tutorial02.txt, etc.).
+
+ * You'll probably want to read through the topical guides (in docs/topics)
+ next; from there you can jump to the HOWTOs (in docs/howto) for specific
+ problems, and check out the reference (docs/ref) for gory details.
+
+Docs are updated rigorously. If you find any problems in the docs, or think they
+should be clarified in any way, please take 30 seconds to fill out a ticket
+here:
+
+http://svn.softwarepublico.gov.br/trac/invesalius/report?action=new
+
+To get more help:
+
+ * Join the #invesalius channel on irc.freenode.net. Lots of helpful people
+ hang out there. Read the archives at --- TODO: HTTP ---.
+
+ * Join the django-users mailing list, or read the archives, at
+ --- TODO: HTTP ---.
+
+To contribute to InVesalius:
+
+ * Check out --- TODO: HTTP ---/community/ for information
+ about getting involved.
97 TODO.txt
@@ -0,0 +1,97 @@
+TODO LIST
+=============
+
+# Contact ITK mail list to see why warning is happening when we import Analyze
+files (noticed both under Windows and MacOS). Appears to be something related to
+wrapper.
+
+# Presets do Analyze
+Pensar sobre como estruturá-los
+
+# List Ctrl - Notebook data
+organizar decentemente classe pai
+? colocar em coluna separada a cor?
+verificar questão de ordenação - no windows e no linux nao funciona, no mac sim
+
+# Import - 0013
+1st file is corrupted
+---> InVesalius 3 quits
+todo: simply ignore corrupted file and check other!
+
+# Import
+dcm_reader.py
+-> change current structure to class
+-> force return "axial" imagedata always
+
+# GUI - insert acquistion modality
+where?
+
+# GUI / mask
+When editing a mask name in notebook -> change combobox and change info inside mask
+Update combo-box related to threshold mode (Bone / etc) to go to custom when user sets another mask or changes the threshold range
+
+# Progress bar
+implement both cursor and progress bar
+
+# Gradient
+never, ever, can min > max or max < min
+
+# After editting mask name in notebook, change Mask instance ando combobox
+
+# Change icon used in inner fold panel (invert upword arrow / dowward arrow)
+
+# Change combo_thresh value according to mask selected / define a good treatment
+# for "Custom"
+
+# Develop tool similar to mimics, in order to show where user has clicked
+both on volume, axial, coronal and sagital
+
+# Develop import interface - see how mimics, osirix and others behave
+# a good start could be a sort of wizard, similar to wifi on macos
+
+# Change references of AXIAL, SAGITAL, etc.. for constants
+
+#-----------------------------------------------------------------------------
+
+Version 3.0
+=============
+ - Totally new GUI
+ - New 3D measures feature
+ - New slice editor feature
+ - New threshold control feature
+ - Threshold presets
+ - New import DICOM process (slice reader, slice grouper)
+ - Reads JPEG lossless DICOM data
+ - New volume surface (polydata) creation pipeline - optimal quality
+ - Does not use Slicer 3D lib anymore
+ - Uses GDCM library for reading DICOM
+
+Operations in volume:
+linear measure
+angular measure
+annotation
+cut
+3d presets
+MIP ou volume rendering
+
+Operations in 2D
+linear measure
+angular measure
+area measure
+
+Generate 3D Surface
+[Preparing 3d Surface]
+- Resolution : low - high (slider 10 units)
+- Decimate: resolution (0.1 ... 1.0) default: 0.5
+- Smooth: iteration(1 ..100) default: 20
+- Pixel value (default: 300) -- (skin: -500, bone: 500, 2000) # threshold min
+- Transparency: slider
+- color: botao
+
+Export 3D
+botao com setinha
+Export as STL (.stl)
+Export as WaveFront (.obj)
+Export as Renderman (.rib)
+Export as VRML (.vrml)
+Export as Inventor (.iv)
21 docs/devel/example_closure.py
@@ -0,0 +1,21 @@
+# Python closure example
+
+def OuterCount(start):
+ counter = [start] # counter is 1-element array
+ print "passei por fora"
+ def InnerCount():
+ counter[0] = counter[0] + 1
+ print "passei por dentro"
+ return counter[0]
+ return InnerCount
+
+print "Init counter at 5"
+count = OuterCount(5)
+print "\nRun counter 3 times"
+print count()
+print count()
+print count()
+
+print "**********"
+count = OuterCount(0)
+print count()
80 docs/devel/example_pubsub.py
@@ -0,0 +1,80 @@
+# Publisher and subscriber design pattern example.
+
+# More information about this design pattern can be found at:
+# http://wiki.wxpython.org/ModelViewController
+# http://wiki.wxpython.org/PubSub
+import wx.lib.pubsub as ps
+# The maintainer of Pubsub module is Oliver Schoenborn.
+# Since the end of 2006 Pubsub is now maintained separately on SourceForge at:
+# http://pubsub.sourceforge.net/
+
+class Student():
+ def __init__(self, name):
+ self.name = name
+ self.mood = ":|"
+ self.__bind_events()
+
+ def __bind_events(self):
+ ps.Publisher().subscribe(self.ReceiveProject,
+ 'Set Student Project')
+ ps.Publisher().subscribe(self.ReceiveGrade,
+ 'Set Student Grade')
+
+ def ReceiveProject(self, pubsub_evt):
+ projects_dict = pubsub_evt.data
+ self.project = projects_dict[self.name]
+ print "%s: I've received the project %s" %(self.name,
+ self.project)
+
+ def ReceiveGrade(self, pubsub_evt):
+ grades_dict = pubsub_evt.data
+ self.grade = grades_dict[self.name]
+ if (self.grade > 6):
+ self.mood = ":)"
+ else:
+ self.mood = ":("
+ print "%s: I've received the grade %d %s" %(self.name,
+ self.grade,
+ self.mood)
+
+class Teacher():
+ def __init__(self, name, course):
+ self.name = name
+ self.course = course
+
+ def SendMessage(self):
+ print "%s: Telling students the projects" %(self.name)
+ ps.Publisher().sendMessage('Set Student Project',
+ self.course.projects_dict)
+
+ print "\n%s: Telling students the grades" %(self.name)
+ ps.Publisher().sendMessage('Set Student Grade',
+ self.course.grades_dict)
+
+class Course():
+ def __init__(self, subject):
+ self.subject = subject
+ self.grades_dict = {}
+ self.projects_dict = {}
+
+# Create students:
+s1 = Student("Coelho")
+s2 = Student("Victor")
+s3 = Student("Thomaz")
+
+# Create subject:
+cs102 = Course("InVesalius")
+cs102.projects_dict = {"Coelho":"wxPython",
+ "Victor":"VTK",
+ "Thomaz":"PIL"}
+cs102.grades_dict = {"Coelho":7,
+ "Victor":6.5,
+ "Thomaz":4}
+
+# Create teacher:
+andre = Teacher("Andre", cs102)
+
+
+
+
+andre.SendMessage()
54 docs/devel/example_singleton.py
@@ -0,0 +1,54 @@
+# Singleton design pattern example.
+
+# For more information on singleton:
+# http://en.wikipedia.org/wiki/Singleton_pattern
+# http://www.vincehuston.org/dp/singleton.html
+
+class Singleton(type):
+ # This is a Gary Robinson implementation:
+ # http://www.garyrobinson.net/2004/03/python_singleto.html
+ def __init__(cls,name,bases,dic):
+ super(Singleton,cls).__init__(name,bases,dic)
+ cls.instance=None
+
+ def __call__(cls,*args,**kw):
+ if cls.instance is None:
+ cls.instance=super(Singleton,cls).__call__(*args,**kw)
+ return cls.instance
+
+class Bone(object):
+ # Only one project will be initialized per time. Therefore, we use
+ # Singleton design pattern for implementing it
+ __metaclass__= Singleton
+
+ def __init__(self):
+ self.size = 100
+
+ def RemovePart(self, part_size):
+ self.size -= part_size # self.size = self.size - part_size
+
+class Dog():
+ def __init__(self, name):
+ self.name = name
+ self.bone = Bone()
+
+ def EatBonePart(self, part_size):
+ self.bone.RemovePart(part_size)
+
+print "Initial state:"
+d1 = Dog("Nina")
+d2 = Dog("Tang")
+print "Bone size of %s: %d"%(d1.name, d1.bone.size)
+print "Bone size of %s: %d\n"%(d2.name, d2.bone.size)
+
+print "Only Nina eats:"
+d1.EatBonePart(5)
+print "Bone size of %s: %d"%(d1.name, d1.bone.size)
+print "Bone size of %s: %d\n"%(d2.name, d2.bone.size)
+
+print "Tang eats after Nina:"
+d2.EatBonePart(20)
+print "Bone size of %s: %d"%(d1.name, d1.bone.size)
+print "Bone size of %s: %d"%(d2.name, d2.bone.size)
+
+
62 docs/devel/example_singleton_pubsub.py
@@ -0,0 +1,62 @@
+# Singleton and Publisher-Subscriber design patterns example.
+
+import wx.lib.pubsub as ps
+
+class Singleton(type):
+ # This is a Gary Robinson implementation:
+ # http://www.garyrobinson.net/2004/03/python_singleto.html
+
+ def __init__(cls,name,bases,dic):
+ super(Singleton,cls).__init__(name,bases,dic)
+ cls.instance=None
+
+ def __call__(cls,*args,**kw):
+ if cls.instance is None:
+ cls.instance=super(Singleton,cls).__call__(*args,**kw)
+ return cls.instance
+
+class Pizza(object):
+ # Only one project will be initialized per time. Therefore, we use
+ # Singleton design pattern for implementing it
+ __metaclass__= Singleton
+
+ def __init__(self):
+ self.npieces = 8
+ self.__bind_events()
+
+ def __bind_events(self):
+ ps.Publisher().subscribe(self.RemovePiece,
+ 'Eat piece of pizza')
+
+ def RemovePiece(self, pubsub_evt):
+ person = pubsub_evt.data
+ if self.npieces:
+ self.npieces -= 1
+ print "%s ate pizza!"%(person.name)
+ else:
+ print "%s is hungry!"%(person.name)
+
+class Person():
+ def __init__(self, name):
+ self.name = name
+ self.pizza = Pizza()
+
+ def EatPieceOfPizza(self):
+ ps.Publisher.sendMessage('Eat piece of pizza',(self))
+
+
+print "Initial state:"
+p1 = Person("Paulo ")
+p2 = Person("Thiago")
+p3 = Person("Andre ")
+people = [p1, p2, p3]
+
+print "Everyone eats 2 pieces:"
+for i in xrange(2):
+ for person in people:
+ person.EatPieceOfPizza()
+
+print "Everyone tries to eat another piece:"
+for person in people:
+ person.EatPieceOfPizza()
+
42 docs/devel/sendmessages.txt
@@ -0,0 +1,42 @@
+Arquivo binário ./gui/frame.pyc casa com o padrão
+./gui/editor.py:105: ps.Publisher().sendMessage('Update images', self.image)
+./gui/editor.py:106: ps.Publisher().sendMessage('Update viewer', None)
+./gui/task_data/notebook.py:83: # ps.Publisher().sendMessage('Set mask threshold in notebook',
+./gui/task_slice/task.py:167: ps.Publisher().sendMessage('Create surface from index',
+./gui/task_slice/task.py:180: ps.Publisher().sendMessage('Create new mask', mask_name)
+./gui/task_slice/task.py:374: ps.Publisher().sendMessage('Change mask selected', mask_index)
+./gui/task_slice/task.py:386: ps.Publisher().sendMessage('Set threshold values',
+./gui/task_slice/task.py:394: ps.Publisher().sendMessage('Change mask colour', colour)
+./gui/task_slice/task.py:498: ps.Publisher().sendMessage('Set edition threshold values',
+Arquivo binário ./gui/task_slice/task.pyc casa com o padrão
+./gui/frame.py:158: Publisher().sendMessage(('NEW PROJECT'))
+Arquivo binário ./data/slice_.pyc casa com o padrão
+./data/slice_.py.orig:55: ps.Publisher().sendMessage('Set mask threshold in notebook',
+./data/slice_.py.orig:58: ps.Publisher().sendMessage('Set threshold values',
+./data/slice_.py.orig:60: ps.Publisher().sendMessage('Update slice viewer')
+./data/slice_.py.orig:76: ps.Publisher().sendMessage('Change mask colour in notebook',
+./data/slice_.py.orig:78: ps.Publisher().sendMessage('Set GUI items colour', colour_wx)
+./data/slice_.py.orig:79: ps.Publisher().sendMessage('Update slice viewer')
+./data/slice_.py.orig:107: ps.Publisher().sendMessage('Update threshold limits list', (thresh_min,
+./data/slice_.py.orig:163: ps.Publisher().sendMessage('Add mask',
+./data/slice_.py.orig:252: ps.Publisher().sendMessage('Set mask threshold in notebook',
+./data/slice_.py.orig:255: ps.Publisher().sendMessage('Update slice viewer')
+Arquivo binário ./data/.slice_.py.swp casa com o padrão
+./data/slice_.py:55: ps.Publisher().sendMessage('Set mask threshold in notebook',
+./data/slice_.py:59: ps.Publisher().sendMessage('Set threshold values in gradient',
+./data/slice_.py:62: ps.Publisher().sendMessage('Update slice viewer')
+./data/slice_.py:78: ps.Publisher().sendMessage('Change mask colour in notebook',
+./data/slice_.py:80: ps.Publisher().sendMessage('Set GUI items colour', colour_wx)
+./data/slice_.py:81: ps.Publisher().sendMessage('Update slice viewer')
+./data/slice_.py:109: ps.Publisher().sendMessage('Update threshold limits list', (thresh_min,
+./data/slice_.py:165: ps.Publisher().sendMessage('Add mask',
+./data/slice_.py:253: ps.Publisher().sendMessage('Set mask threshold in notebook',
+./data/slice_.py:256: ps.Publisher().sendMessage('Update slice viewer')
+./presets.py:67: ps.Publisher().sendMessage('Update threshold limits', (thresh_min,
+./invesalius.py:68: ps.Publisher().sendMessage('Import directory', import_dir)
+Arquivo binário ./presets.pyc casa com o padrão
+Arquivo binário ./control.pyc casa com o padrão
+./control.py:36: Publisher().sendMessage('Create surface', (imagedata,colour,threshold))
+./control.py:60: Publisher().sendMessage('Load slice to viewer', (imagedata))
+./control.py:66: Publisher().sendMessage('Show content panel')
+./control.py:73: Publisher().sendMessage('Set threshold modes',(thresh_modes,const.THRESHOLD_PRESETS_INDEX))
92 docs/devel/subscribes.txt
@@ -0,0 +1,92 @@
+Arquivo binário ./gui/frame.pyc casa com o padrão
+Arquivo binário ./gui/task_data/notebook.pyc casa com o padrão
+./gui/task_data/notebook.py:77: ps.Publisher().subscribe(self.AddMask, 'Add mask')
+./gui/task_data/notebook.py:78: ps.Publisher().subscribe(self.EditMaskThreshold,
+./gui/task_data/notebook.py:80: ps.Publisher().subscribe(self.EditMaskColour,
+Arquivo binário ./gui/viewer_volume.pyc casa com o padrão
+./gui/task_slice/task.py:318: ps.Publisher().subscribe(self.AddMask, 'Add mask')
+./gui/task_slice/task.py:319: ps.Publisher().subscribe(self.SetThresholdBounds,
+./gui/task_slice/task.py:321: ps.Publisher().subscribe(self.SetThresholdModes, 'Set threshold modes')
+./gui/task_slice/task.py:322: ps.Publisher().subscribe(self.SetItemsColour, 'Set GUI items colour')
+./gui/task_slice/task.py:323: ps.Publisher().subscribe(self.SetThresholdValues,
+./gui/task_slice/task.py:473: ps.Publisher().subscribe(self.SetThresholdBounds,
+./gui/task_slice/task.py:475: ps.Publisher().subscribe(self.SetThresholdValues,
+./gui/task_slice/task.py:477: ps.Publisher().subscribe(self.ChangeMaskColour, 'Change mask colour')
+Arquivo binário ./gui/task_slice/task.pyc casa com o padrão
+./gui/frame.py:94: ps.Publisher().subscribe(self.ShowContentPanel, 'Show content panel')
+./gui/viewer_slice.py:76: ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer')
+./gui/viewer_slice.py:77: ps.Publisher().subscribe(self.SetColour, 'Change mask colour')
+./gui/viewer_slice.py:78: ps.Publisher().subscribe(self.UpdateRender, 'Update slice viewer')
+Arquivo binário ./gui/viewer_slice.pyc casa com o padrão
+./gui/viewer_volume.py:68: #ps.Publisher().subscribe(self.LoadImagedata, 'Load imagedata')
+./gui/viewer_volume.py:69: ps.Publisher().subscribe(self.LoadImagedata, 'Create surface')
+Arquivo binário ./gui/widgets/gradient.pyc casa com o padrão
+./gui/widgets/gradient.py.orig:100: ps.Publisher().subscribe(self.SetMinValue, "ChangeMinValue")
+./gui/widgets/gradient.py.orig:101: ps.Publisher().subscribe(self.SetMaxValue, "ChangeMaxValue")
+./gui/widgets/gradient.py.orig:168: ps.Publisher().subscribe(self.SetMinValue, "SetMinValue")
+./gui/widgets/gradient.py.orig:472: #ps.Publisher().subscribe(self.SetMinValue, ('SetMinValue'))
+./gui/widgets/gradient.py.orig:477: ps.Publisher().subscribe(self.SetColour, 'Change Gradient Colour')
+./gui/widgets/gradient.py.orig:478: ps.Publisher().subscribe(self.SetMinValue, 'Change Gradient MinValue')
+./gui/widgets/gradient.py.orig:479: ps.Publisher().subscribe(self.SetMaxValue, 'Change Gradient MaxValue')
+./gui/widgets/gradient.py:100: ps.Publisher().subscribe(self.SetMinValue, "ChangeMinValue")
+./gui/widgets/gradient.py:101: ps.Publisher().subscribe(self.SetMaxValue, "ChangeMaxValue")
+./gui/widgets/gradient.py:168: ps.Publisher().subscribe(self.SetMinValue, "SetMinValue")
+./gui/widgets/gradient.py:471: #ps.Publisher().subscribe(self.SetMinValue, ('SetMinValue'))
+./gui/widgets/gradient.py:476: ps.Publisher().subscribe(self.SetColour, 'Change Gradient Colour')
+./gui/widgets/gradient.py:477: ps.Publisher().subscribe(self.SetMinValue, 'Change Gradient MinValue')
+./gui/widgets/gradient.py:478: ps.Publisher().subscribe(self.SetMaxValue, 'Change Gradient MaxValue')
+Arquivo binário ./data/slice_.pyc casa com o padrão
+./data/slice_.py.orig:22: ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values')
+./data/slice_.py.orig:23: ps.Publisher().subscribe(self.SetEditionThresholdRange,
+./data/slice_.py.orig:25: ps.Publisher().subscribe(self.OnChangeCurrentMaskColour,
+./data/slice_.py.orig:27: ps.Publisher().subscribe(self.AddMask, 'Create new mask')
+./data/slice_.py.orig:28: ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected')
+Arquivo binário ./data/.slice_.py.swp casa com o padrão
+./data/slice_.py:22: ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values')
+./data/slice_.py:23: ps.Publisher().subscribe(self.SetEditionThresholdRange,
+./data/slice_.py:25: ps.Publisher().subscribe(self.OnChangeCurrentMaskColour,
+./data/slice_.py:27: ps.Publisher().subscribe(self.AddMask, 'Create new mask')
+./data/slice_.py:28: ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected')
+./presets.py:46: ps.Publisher.subscribe(self.UpdateThresholdModes,
+./invesalius.py:59: ps.Publisher().subscribe(print_events, ps.ALL_TOPICS)
+Arquivo binário ./presets.pyc casa com o padrão
+./subscribes.txt:3:./gui/task_data/notebook.py:77: ps.Publisher().subscribe(self.AddMask, 'Add mask')
+./subscribes.txt:4:./gui/task_data/notebook.py:78: ps.Publisher().subscribe(self.EditMaskThreshold,
+./subscribes.txt:5:./gui/task_data/notebook.py:80: ps.Publisher().subscribe(self.EditMaskColour,
+./subscribes.txt:7:./gui/task_slice/task.py:318: ps.Publisher().subscribe(self.AddMask, 'Add mask')
+./subscribes.txt:8:./gui/task_slice/task.py:319: ps.Publisher().subscribe(self.SetThresholdBounds,
+./subscribes.txt:9:./gui/task_slice/task.py:321: ps.Publisher().subscribe(self.SetThresholdModes, 'Set threshold modes')
+./subscribes.txt:10:./gui/task_slice/task.py:322: ps.Publisher().subscribe(self.SetItemsColour, 'Set GUI items colour')
+./subscribes.txt:11:./gui/task_slice/task.py:323: ps.Publisher().subscribe(self.SetThresholdValues,
+./subscribes.txt:12:./gui/task_slice/task.py:473: ps.Publisher().subscribe(self.SetThresholdBounds,
+./subscribes.txt:13:./gui/task_slice/task.py:475: ps.Publisher().subscribe(self.SetThresholdValues,
+./subscribes.txt:14:./gui/task_slice/task.py:477: ps.Publisher().subscribe(self.ChangeMaskColour, 'Change mask colour')
+./subscribes.txt:16:./gui/frame.py:94: ps.Publisher().subscribe(self.ShowContentPanel, 'Show content panel')
+./subscribes.txt:17:./gui/viewer_slice.py:76: ps.Publisher().subscribe(self.LoadImagedata, 'Load slice to viewer')
+./subscribes.txt:18:./gui/viewer_slice.py:77: ps.Publisher().subscribe(self.SetColour, 'Change mask colour')
+./subscribes.txt:19:./gui/viewer_slice.py:78: ps.Publisher().subscribe(self.UpdateRender, 'Update slice viewer')
+./subscribes.txt:21:./gui/viewer_volume.py:68: #ps.Publisher().subscribe(self.LoadImagedata, 'Load imagedata')
+./subscribes.txt:22:./gui/viewer_volume.py:69: ps.Publisher().subscribe(self.LoadImagedata, 'Create surface')
+./subscribes.txt:24:./gui/widgets/gradient.py.orig:100: ps.Publisher().subscribe(self.SetMinValue, "ChangeMinValue")
+./subscribes.txt:25:./gui/widgets/gradient.py.orig:101: ps.Publisher().subscribe(self.SetMaxValue, "ChangeMaxValue")
+./subscribes.txt:26:./gui/widgets/gradient.py.orig:168: ps.Publisher().subscribe(self.SetMinValue, "SetMinValue")
+./subscribes.txt:27:./gui/widgets/gradient.py.orig:472: #ps.Publisher().subscribe(self.SetMinValue, ('SetMinValue'))
+./subscribes.txt:28:./gui/widgets/gradient.py.orig:477: ps.Publisher().subscribe(self.SetColour, 'Change Gradient Colour')
+./subscribes.txt:29:./gui/widgets/gradient.py.orig:478: ps.Publisher().subscribe(self.SetMinValue, 'Change Gradient MinValue')
+./subscribes.txt:30:./gui/widgets/gradient.py.orig:479: ps.Publisher().subscribe(self.SetMaxValue, 'Change Gradient MaxValue')
+./subscribes.txt:31:./gui/widgets/gradient.py:100: ps.Publisher().subscribe(self.SetMinValue, "ChangeMinValue")
+./subscribes.txt:32:./gui/widgets/gradient.py:101: ps.Publisher().subscribe(self.SetMaxValue, "ChangeMaxValue")
+./subscribes.txt:33:./gui/widgets/gradient.py:168: ps.Publisher().subscribe(self.SetMinValue, "SetMinValue")
+./subscribes.txt:34:./gui/widgets/gradient.py:471: #ps.Publisher().subscribe(self.SetMinValue, ('SetMinValue'))
+./subscribes.txt:35:./gui/widgets/gradient.py:476: ps.Publisher().subscribe(self.SetColour, 'Change Gradient Colour')
+./subscribes.txt:36:./gui/widgets/gradient.py:477: ps.Publisher().subscribe(self.SetMinValue, 'Change Gradient MinValue')
+./subscribes.txt:37:./gui/widgets/gradient.py:478: ps.Publisher().subscribe(self.SetMaxValue, 'Change Gradient MaxValue')
+./subscribes.txt:39:./data/slice_.py.orig:22: ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values')
+./subscribes.txt:40:./data/slice_.py.orig:23: ps.Publisher().subscribe(self.SetEditionThresholdRange,
+./subscribes.txt:41:./data/slice_.py.orig:25: ps.Publisher().subscribe(self.OnChangeCurrentMaskColour,
+./subscribes.txt:42:./data/slice_.py.orig:27: ps.Publisher().subscribe(self.AddMask, 'Create new mask')
+./subscribes.txt:43:./data/slice_.py.orig:28: ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected')
+./subscribes.txt:45:./data/slice_.py:22: ps.Publisher().subscribe(self.Set
+Arquivo binário ./control.pyc casa com o padrão
+./control.py:24: Publisher().subscribe(self.ImportDirectory, 'Import directory')
+./control.py:25: Publisher().subscribe(self.CreateSurfaceFromIndex, 'Create surface from index')
BIN  icons/brush_circle.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icons/brush_square.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icons/invesalius.ico
Binary file not shown
BIN  icons/object_colour.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icons/object_invisible.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  icons/object_visible.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 invesalius/constants.py
@@ -0,0 +1,80 @@
+from project import Project
+
+AXIAL = 0
+CORONAL = 1
+SAGITAL = 2
+
+
+proj = Project()
+
+THRESHOLD_RANGE = proj.threshold_modes["Bone"]
+
+THRESHOLD_PRESETS_INDEX = 0 #Bone
+
+THRESHOLD_HUE_RANGE = (0, 0.6667)
+THRESHOLD_INVALUE = 5000
+THRESHOLD_OUTVALUE = 0
+
+MASK_NAME_PATTERN = "Mask %d"
+
+MASK_COLOUR = [(0.33, 1, 0.33),
+ (1, 1, 0.33),
+ (0.33, 0.91, 1),
+ (1, 0.33, 1),
+ (1, 0.68, 0.33),
+ (1, 0.33, 0.33),
+ (0.33333333333333331, 0.33333333333333331, 1.0),
+ #(1.0, 0.33333333333333331, 0.66666666666666663),
+ (0.74901960784313726, 1.0, 0.0),
+ (0.83529411764705885, 0.33333333333333331, 1.0)]#,
+ #(0.792156862745098, 0.66666666666666663, 1.0),
+ #(1.0, 0.66666666666666663, 0.792156862745098), # too "light"
+ #(0.33333333333333331, 1.0, 0.83529411764705885),#],
+ #(1.0, 0.792156862745098, 0.66666666666666663),
+ #(0.792156862745098, 1.0, 0.66666666666666663), # too "light"
+ #(0.66666666666666663, 0.792156862745098, 1.0)]
+
+MASK_OPACITY = 0.3
+
+OP_ADD = 0
+OP_DEL = 1
+OP_THRESH =2
+
+# Surface creation default values. List contains:
+# 0: imagedata reformat ratio
+# 1: smooth_iterations
+# 2: smooth_relaxation_factor
+# 3: decimate_reduction
+
+SURFACE_QUALITY = {
+ "Low": (3, 2, 0.3000, 0.4),
+ "Medium": (2, 2, 0.3000, 0.4),
+ "High": (0, 1, 0.3000, 0.1),
+ "Optimal": (0, 2, 0.3000, 0.4),
+ "Custom": (None, None, None, None)
+}
+
+DEFAULT_SURFACE_QUALITY = "Optimal"
+
+
+SURFACE_TRANSPARENCY = 0.0
+SURFACE_NAME_PATTERN = "Surface %d"
+
+WINDOW_LEVEL = ({"Abdomen":(350,50),
+ "Bone":(2000, 300),
+ "Brain Posterior Fossa":(120,40),
+ "Brain":(80,40),
+ "Emphysema":(500,-850),
+ "Ischemia - Hard Non Contrast":(15,32),
+ "Ischemia - Soft Non Contrast":(80,20),
+ "Larynx":(180, 80),
+ "Liver":(2000, -500),
+ "Lung - Soft":(1600,-600),
+ "Lung - Hard":(1000,-600),
+ "Lung":(1500,-6550),
+ "Mediastinum":(350,25),
+ "Pelvis": (450,50),
+ "Sinus":(4000, 400),
+ "Vasculature - Hard":(240,80),
+ "Vasculature - Soft":(650,160)
+ })
76 invesalius/control.py
@@ -0,0 +1,76 @@
+import wx.lib.pubsub as ps
+
+import constants as const
+import project as prj
+
+import data.imagedata_utils as utils
+import data.surface as surface
+import reader.dicom_reader as dicom
+import reader.analyze_reader as analyze
+
+DEFAULT_THRESH_MODE = 0
+
+class Controller():
+
+ def __init__(self, frame):
+ self.surface_manager = surface.SurfaceManager()
+ self.__bind_events()
+
+ def __bind_events(self):
+ ps.Publisher().subscribe(self.ImportDirectory, 'Import directory')
+
+ def ImportDirectory(self, pubsub_evt=None, dir_=None):
+ """
+ Import medical images (if any) and generate vtkImageData, saving data
+ inside Project instance.
+ """
+
+ if not dir_:
+ dir_ = pubsub_evt.data
+
+ # Select medical images from directory and generate vtkImageData
+ output = dicom.LoadImages(dir_)
+
+ if output:
+ imagedata, acquisition_modality, tilt_value = output
+ if (tilt_value):
+ #TODO: Show dialog so user can set not other value
+ tilt_value *= -1
+ imagedata = utils.FixGantryTilt(imagedata, tilt_value)
+ print "Fixed Gantry Tilt", str(tilt_value)
+ else:
+ "No DICOM files were found. Trying to read with ITK..."
+ imagedata = analyze.ReadDirectory(dir_)
+ acquisition_modality = "MRI"
+
+ if not imagedata:
+ print "Sorry, but there are no medical images supported on this dir."
+ else:
+ # Create new project
+ proj = prj.Project()
+ proj.name = "Untitled"
+ proj.SetAcquisitionModality(acquisition_modality)
+ proj.imagedata = imagedata
+
+ # Based on imagedata, load data to GUI
+ ps.Publisher().sendMessage('Load slice to viewer', (imagedata))
+
+ # TODO: where to insert!!!
+ self.LoadImagedataInfo()
+
+ # Call frame so it shows slice and volume related panels
+ ps.Publisher().sendMessage('Show content panel')
+
+ def LoadImagedataInfo(self):
+ proj = prj.Project()
+
+ thresh_modes = proj.threshold_modes.keys()
+ thresh_modes.sort()
+ ps.Publisher().sendMessage('Set threshold modes',
+ (thresh_modes,const.THRESHOLD_PRESETS_INDEX))
+
+ # Set default value into slices' default mask
+ key= thresh_modes[const.THRESHOLD_PRESETS_INDEX]
+ (min_thresh, max_thresh) = proj.threshold_modes.get_value(key)
+
+
1  invesalius/data/__init__.py
@@ -0,0 +1 @@
+#
251 invesalius/data/editor.py
@@ -0,0 +1,251 @@
+import math
+
+import wx.lib.pubsub as ps
+import vtk
+
+AXIAL = 2
+CORONAL = 1
+SAGITAL = 0
+
+class Editor:
+ """
+ To Use:
+
+ editor = Editor()
+ editor.SetInteractor(self.interector)
+ editor.SetOperationType(2, (50,1200)) #threshold 50, 1200
+ editor.SetInput(img_original.GetOutput(), img_threshold.GetOutput())
+ editor.Render()
+ """
+
+ def __init__(self):
+
+ self.interactor = None
+ self.image_original = None
+ self.image_threshold = None
+ self.render = None
+
+ self.lut = vtk.vtkLookupTable()
+ self.lut_original = vtk.vtkLookupTable()
+ self.image_color = vtk.vtkImageMapToColors()
+ self.blend = blend = vtk.vtkImageBlend()
+ self.map = map = vtk.vtkImageMapper()
+
+ self.actor = actor = vtk.vtkImageActor()
+ self.actor2 = actor2 = vtk.vtkImageActor()
+ self.actor3 = actor3 = vtk.vtkImageActor()
+
+ self.image_color_o = vtk.vtkImageMapToColors()
+
+ self.operation_type = 0
+ self.w = None
+
+ self.slice = 0
+ self.clicked = 0
+ self.orientation = AXIAL
+
+ self.w = (200, 1200)
+
+ #self.plane_widget_x = vtk.vtkImagePlaneWidget()
+
+ #self.actor.PickableOff()
+
+ def SetInteractor(self, interactor):
+
+ self.interactor = interactor
+ self.render = interactor.GetRenderWindow().GetRenderers().GetFirstRenderer()
+
+ istyle = vtk.vtkInteractorStyleImage()
+ istyle.SetInteractor(interactor)
+ istyle.AutoAdjustCameraClippingRangeOn()
+ interactor.SetInteractorStyle(istyle)
+
+ istyle.AddObserver("LeftButtonPressEvent", self.Click)
+ istyle.AddObserver("LeftButtonReleaseEvent", self.Release)
+ istyle.AddObserver("MouseMoveEvent",self.Moved)
+
+ pick = self.pick = vtk.vtkCellPicker()
+
+ def SetActor(self, actor):
+ self.actor = actor
+
+ def SetImage(self, image):
+ self.image = image
+
+ def SetCursor(self, cursor):
+ self.cursor = cursor
+ self.cursor.CursorCircle(self.render)
+
+ def SetOrientation(self, orientation):
+ self.orientation = orientation
+
+ def Click(self, obj, evt):
+ self.clicked = 1
+
+ def Release(self, obj, evt):
+ self.clicked = 0
+
+ def Moved(self, obj, evt):
+ pos = self.interactor.GetEventPosition()
+ wx = pos[0] #- last[0]
+ wy = pos[1] #- last[1]
+ self.pick.Pick(wx, wy, 0, self.render)
+ x,y,z = self.pick.GetPickPosition()
+
+ self.cursor.SetPosition(x, y, z)
+ self.cursor.Update()
+ if self.clicked == 1:
+ # op = self.rbOptions.GetSelection()
+ # a = (int(self.txtThresI.GetValue()), int(self.txtThresF.GetValue()))
+ # self.editor.SetOperationType(op, a)
+ wx, wy, wz = self.From3dToImagePixel(pos, (x, y, z))
+ print "Comecei"
+ self.DoOperation(wx, wy, wz)
+ print "Terminei"
+ ps.Publisher().sendMessage('Update images', self.image)
+ ps.Publisher().sendMessage('Update viewer', None)
+
+ #self.cursor.Update()
+ obj.OnMouseMove()
+
+ self.interactor.Render()
+
+ def From3dToImagePixel(self, mPos, pPos):
+ """
+ mPos - The mouse position in the screen position.
+ pPos - the pick position in the 3d world
+ """
+ x, y, z = pPos
+ bounds = self.actor.GetBounds()
+ print bounds
+
+ #c = vtk.vtkCoordinate()
+ #c.SetCoordinateSystemToWorld()
+ #c.SetValue(bounds[::2])
+ #xi, yi = c.GetComputedViewportValue(self.render)
+
+ #c.SetValue(bounds[1::2])
+ #xf, yf = c.GetComputedViewportValue(self.render)
+
+ xi, xf, yi, yf, zi, zf = bounds
+ #c.SetValue(x, y, z)
+ #wx, wy = c.GetComputedViewportValue(self.render)
+
+ wx = x - xi
+ wy = y - yi
+ wz = z - zi
+
+ dx = xf - xi
+ dy = yf - yi
+ dz = zf - zi
+
+ try:
+ wx = (wx * self.image.GetDimensions()[0]) / dx
+ except ZeroDivisionError:
+ wx = self.slice
+ try:
+ wy = (wy * self.image.GetDimensions()[1]) / dy
+ except ZeroDivisionError:
+ wy = self.slice
+ try:
+ wz = (wz * self.image.GetDimensions()[2]) / dz
+ except ZeroDivisionError:
+ wz = self.slice
+
+ return wx, wy, wz
+
+ def SetInput(self, image_original, image_threshold):
+
+ self.image_original = image_original
+ self.image_threshold = image_threshold
+
+ def SetSlice(self, a):
+ self.slice = a
+
+ def ChangeShowSlice(self, value):
+ self.map.SetZSlice(value)
+ self.interactor.Render()
+
+ def ErasePixel(self, x, y, z):
+ """
+ Deletes pixel, it is necessary to pass x, y and z.
+ """
+ self.image.SetScalarComponentFromDouble(x, y, z, 0, 0)
+ self.image.Update()
+
+ def FillPixel(self, x, y, z, colour = 3200):
+ """
+ Fill pixel, it is necessary to pass x, y and z
+ """
+
+ self.image.SetScalarComponentFromDouble(x, y, z, 0, colour)
+
+ def PixelThresholdLevel(self, x, y, z):
+ """
+ Erase or Fill with Threshold level
+ """
+ pixel_colour = self.image.GetScalarComponentAsDouble(x, y, z, 0)
+
+ thres_i = self.w[0]
+ thres_f = self.w[1]
+
+ if (pixel_colour >= thres_i) and (pixel_colour <= thres_f):
+
+ if (pixel_colour <= 0):
+ self.FillPixel(x, y, z, 1)
+ else:
+ self.FillPixel(x, y, z, pixel_colour)
+
+ else:
+ self.ErasePixel(x, y, z)
+
+
+ def DoOperation(self, xc, yc, zc):
+ """
+ This method scans the circle line by line.
+ Extracted equation.
+ http://www.mathopenref.com/chord.html
+ """
+ extent = self.image.GetWholeExtent()
+ cursor = self.cursor
+ b = [0,0,0,0,0,0]
+ self.actor.GetDisplayBounds(b)
+ print "To Paint", xc, yc, zc
+ print "Bounds", b
+ print "dimensions", self.image.GetDimensions()
+ xs, ys, zs = self.image.GetSpacing()
+ try:
+ zs = (b[-1]-b[-2]) / self.image.GetDimensions()[2]
+ except ZeroDivisionError:
+ pass
+ print xs, ys, zs
+ if self.orientation == AXIAL:
+ o = lambda x, y: (xc + x, y + yc, zc)
+ elif self.orientation == CORONAL:
+ o = lambda x, y: (xc + x, yc, zc + y/zs)
+ elif self.orientation == SAGITAL:
+ o = lambda x, y: (xc, yc + x, zc + y/zs)
+
+ if (self.operation_type == 0):
+ operation = self.ErasePixel
+ elif(self.operation_type == 1):
+ operation = self.FillPixel
+ else:
+ operation = self.PixelThresholdLevel
+ try:
+ [operation(*o(k, yi)) for k, yi in cursor.GetPoints()]
+ except:
+ pass
+ #if extent[0] <= k+xc <= extent[1] \
+ #and extent[2] <= yi+yc <=extent[3]]
+
+ def SetOperationType(self, operation_type = 0,
+ w = (100,1200)):
+ """
+ Set Operation Type
+ 0 -> Remove
+ 1 -> Add
+ 2 -> Add or Remove with Threshold Level
+ """
+ self.operation_type = operation_type
+ self.w = w #threshold_value
77 invesalius/data/imagedata_utils.py
@@ -0,0 +1,77 @@
+import math
+import vtk
+
+# TODO: Test cases which are originally in sagittal/coronal orientation
+# and have gantry
+
+def ResampleMatrix(imagedata, value):
+ """
+ Resample vtkImageData matrix.
+ """
+ spacing = imagedata.GetSpacing()
+ extent = imagedata.GetExtent()
+ size = imagedata.GetDimensions()
+
+ width = float(size[0])
+ height = float(size[1]/value)
+
+ resolution = (height/(extent[1]-extent[0])+1)*spacing[1]
+
+ resample = vtk.vtkImageResample()
+ resample.SetInput(imagedata)
+ resample.SetAxisMagnificationFactor(0, resolution)
+ resample.SetAxisMagnificationFactor(1, resolution)
+
+ return resample.GetOutput()
+
+def FixGantryTilt(imagedata, tilt):
+ """
+ Fix gantry tilt given a vtkImageData and the tilt value. Return new
+ vtkImageData.
+ """
+
+ # Retrieve data from original imagedata
+ extent = [int(value) for value in imagedata.GetExtent()]
+ origin = imagedata.GetOrigin()
+ spacing = [float(value) for value in imagedata.GetSpacing()]
+
+ n_slices = int(extent[5])
+ new_zspacing = math.cos(tilt*(math.acos(-1.0)/180.0)) * spacing[2] #zspacing
+ translate_coef = math.tan(tilt*math.pi/180.0)*new_zspacing*(n_slices-1)
+
+ # Class responsible for translating data
+ reslice = vtk.vtkImageReslice()
+ reslice.SetInput(imagedata)
+ reslice.SetInterpolationModeToLinear()
+ # Translation will create new pixels. Let's set new pixels' colour to black.
+ reslice.SetBackgroundLevel(imagedata.GetScalarRange()[0])
+
+ # Class responsible for append translated data
+ append = vtk.vtkImageAppend()
+ append.SetAppendAxis(2)
+
+ # Translate and append each slice
+ for i in xrange(n_slices+1):
+ slice_imagedata = vtk.vtkImageData()
+ value = math.tan(tilt*math.pi/180.0) * new_zspacing * i
+ new_origin1 = origin[1] + value - translate_coef
+ # Translate data
+ reslice.SetOutputOrigin(origin[0], new_origin1, origin[2])
+ reslice.SetOutputExtent(extent[0], extent[1], extent[2], extent[3], i,i)
+ reslice.Update()
+ # Append data
+ slice_imagedata.DeepCopy(reslice.GetOutput())
+ slice_imagedata.UpdateInformation()
+
+ append.AddInput(slice_imagedata)
+
+ append.Update()
+
+ # Final imagedata
+ imagedata = vtk.vtkImageData()
+ imagedata.DeepCopy(append.GetOutput())
+ imagedata.SetSpacing(spacing[0], spacing[1], new_zspacing)
+ imagedata.SetExtent(extent)
+ imagedata.UpdateInformation()
+
+ return imagedata
15 invesalius/data/mask.py
@@ -0,0 +1,15 @@
+import random
+import constants as const
+
+class Mask():
+ general_index = -1
+ def __init__(self):
+ Mask.general_index += 1
+ self.index = Mask.general_index
+ self.imagedata = None # vtkImageData
+ self.colour = random.choice(const.MASK_COLOUR)
+ self.opacity = const.MASK_OPACITY
+ self.threshold_range = const.THRESHOLD_RANGE
+ self.name = const.MASK_NAME_PATTERN %(Mask.general_index+1)
+ self.edition_threshold_range = const.THRESHOLD_RANGE
+
122 invesalius/data/orientation.py
@@ -0,0 +1,122 @@
+AXIAL = 2
+CORONAL = 1
+SAGITAL = 0
+
+class Orientation(object):
+ def __init__(self, interactor, actor):
+ self.interactor = interactor
+ self.actor = actor
+ self.image = actor.GetInput()
+ self.ren = interactor.GetRenderWindow().GetRenderers().GetFirstRenderer()
+ self.slice = 0
+
+ def SetOrientation(self, orientation):
+ cam = self.ren.GetActiveCamera()
+ self.orientation = orientation
+ extent = self.image.GetWholeExtent()
+
+ if orientation == AXIAL:
+ print "AXIAL"
+ cam.SetFocalPoint(0, 0, 0)
+ cam.SetPosition(0, 0, 1)
+ cam.ComputeViewPlaneNormal()
+ cam.SetViewUp(0, 1, 0)
+
+ xs = extent[1] - extent[0] + 1
+ ys = extent[3] - extent[2] + 1
+
+ elif orientation == CORONAL:
+ print "Coronal"
+ cam.SetFocalPoint(0, 0, 0)
+ cam.SetPosition(0, -1, 0)
+ cam.ComputeViewPlaneNormal()
+ cam.SetViewUp(0, 0, 1)
+
+ xs = extent[1] - extent[0] + 1
+ ys = extent[5] - extent[4] + 1
+
+ elif orientation == SAGITAL:
+ print "Sagital"
+ cam.SetFocalPoint(0, 0, 0)
+ cam.SetPosition(1, 0, 0)
+ cam.ComputeViewPlaneNormal()
+ cam.SetViewUp(0, 0, 1)
+
+ xs = extent[3] - extent[2] + 1
+ ys = extent[5] - extent[4] + 1
+
+ if xs < 150:
+ scale = 75
+ else:
+
+ scale = (xs - 1)/2.0
+
+
+ cam.OrthogonalizeViewUp()
+ self.UpdateDisplayExtent()
+ #self.ren.ResetCamera()
+ cam.ParallelProjectionOn()
+ cam.SetParallelScale(scale)
+ self.ren.AddActor(self.actor)
+ self.ren.ResetCamera()
+ #cam.SetParallelScale(130)
+
+ self.ren.Render()
+
+
+ def UpdateDisplayExtent(self):
+ extent = self.image.GetWholeExtent()
+ if self.orientation == AXIAL:
+ xs = extent[1] - extent[0] + 1
+ ys = extent[3] - extent[2] + 1
+
+ actor = self.actor
+ actor.SetInput(self.image)
+ actor.SetDisplayExtent(extent[0], extent[1],
+ extent[2], extent[3],
+ self.slice, self.slice)
+
+ elif self.orientation == CORONAL:
+ xs = extent[1] - extent[0] + 1
+ ys = extent[5] - extent[4] + 1
+
+ actor = self.actor
+ actor.SetInput(self.image)
+ actor.SetDisplayExtent(extent[0], extent[1],
+ self.slice, self.slice,
+ extent[4], extent[5])
+
+ elif self.orientation == SAGITAL:
+ xs = extent[3] - extent[2] + 1
+ ys = extent[5] - extent[4] + 1
+
+ actor = self.actor
+ actor.SetInput(self.image)
+ actor.SetDisplayExtent(self.slice, self.slice,
+ extent[2], extent[3],
+ extent[4], extent[5])
+
+ self.ren.AddActor(self.actor)
+
+ self.ren.ResetCameraClippingRange()
+
+ cam = self.ren.GetActiveCamera()
+
+ bounds = self.actor.GetBounds()
+ spos = bounds[self.orientation*2]
+ cpos = cam.GetPosition()[self.orientation]
+ range = abs(spos - cpos)
+ spacing = self.actor.GetInput().GetSpacing()
+ avg_spacing = sum(spacing)/3.0
+ cam.SetClippingRange(range - avg_spacing * 3.0, range +\
+ avg_spacing * 3.0)
+
+ self.ren.Render()
+
+ def SetSlice(self, slice):
+ self.slice = slice
+ self.UpdateDisplayExtent()
+
+ def GetMaxSlice(self):
+
+ return self.actor.GetSliceNumberMax()
86 invesalius/data/polydata_utils.py
@@ -0,0 +1,86 @@
+import vtk
+import wx.lib.pubsub as ps
+
+import vtk_utils as vu
+
+# Update progress value in GUI
+UpdateProgress = vu.ShowProgress()
+
+def ApplyDecimationFilter(polydata, reduction_factor):
+ """
+ Reduce number of triangles of the given vtkPolyData, based on
+ reduction_factor.
+ """
+ # Important: vtkQuadricDecimation presented better results than
+ # vtkDecimatePro
+ decimation = vtk.vtkQuadricDecimation()
+ decimation.SetInput(polydata)
+ decimation.SetTargetReduction(reduction_factor)
+ decimation.GetOutput().ReleaseDataFlagOn()
+ decimation.AddObserver("ProgressEvent", lambda obj, evt:
+ UpdateProgress(decimation, "Reducing number of triangles..."))
+ return decimation.GetOutput()
+
+def ApplySmoothFilter(polydata, iterations, relaxation_factor):
+ """
+ Smooth given vtkPolyData surface, based on iteration and relaxation_factor.
+ """
+ smoother = vtk.vtkSmoothPolyDataFilter()
+ smoother.SetInput(polydata)
+ smoother.SetNumberOfIterations(iterations)
+ smoother.SetFeatureAngle(80)
+ smoother.SetRelaxationFactor(relaxation_factor)
+ smoother.FeatureEdgeSmoothingOn()
+ smoother.BoundarySmoothingOn()
+ smoother.GetOutput().ReleaseDataFlagOn()
+ smoother.AddObserver("ProgressEvent", lambda obj, evt:
+ UpdateProgress(smoother, "Smoothing surface..."))
+
+ return smoother.GetOutput()
+
+def SelectLargestSurface(polydata):
+ """
+ """
+ pass
+ return polydata
+
+def SplitDisconectedSurfaces(polydata):
+ """
+ """
+ return []
+
+# TODO: style?
+def SelectSurfaceByCell(polytada, list_index = []):
+ """
+ """
+ pass
+ return []
+
+def FillSurfaceHole(polydata):
+ """
+ Fill holes in the given polydata.
+ """
+ # Filter used to detect and fill holes. Only fill
+ print "Filling polydata"
+ filled_polydata = vtk.vtkFillHolesFilter()
+ filled_polydata.SetInput(polydata)
+ filled_polydata.SetHoleSize(500)
+ return filled_polydata.GetOutput()
+
+def CalculateSurfaceVolume(polydata):
+ """
+ Calculate the volume from the given polydata
+ """
+ # Filter used to calculate volume and area from a polydata
+ measured_polydata = vtk.vtkMassProperties()
+ measured_polydata.SetInput(polydata)
+ return measured_polydata.GetVolume()
+
+def CalculateSurfaceArea(polydata):
+ """
+ Calculate the volume from the given polydata
+ """
+ # Filter used to calculate volume and area from a polydata
+ measured_polydata = vtk.vtkMassProperties()
+ measured_polydata.SetInput(polydata)
+ return measured_polydata.GetSurfaceArea()
312 invesalius/data/slice_.py
@@ -0,0 +1,312 @@
+import random
+
+import vtk
+import wx.lib.pubsub as ps
+
+import constants as const
+from mask import Mask
+from project import Project
+from utils import Singleton
+
+
+class Slice(object):
+ __metaclass__= Singleton
+ # Only one project will be initialized per time. Therefore, we use
+ # Singleton design pattern for implementing it
+
+ def __init__(self):
+ self.imagedata = None
+ self.__bind_events()
+
+ def __bind_events(self):
+ ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values')
+ #ps.Publisher().subscribe(self.SetEditionThresholdRange,
+ # 'Set edition threshold values')
+ ps.Publisher().subscribe(self.OnChangeCurrentMaskColour,
+ 'Change mask colour')
+ ps.Publisher().subscribe(self.AddMask, 'Create new mask')
+ ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected')
+ ps.Publisher().subscribe(self.CreateSurfaceFromIndex,
+ 'Create surface from index')
+
+ def CreateSurfaceFromIndex(self, pubsub_evt):
+ mask_index = pubsub_evt.data
+
+ proj = Project()
+ mask = proj.mask_dict[mask_index]
+
+ # This is very important. Do not use masks' imagedata. It would mess up
+ # surface quality event when using contour
+ imagedata = self.imagedata
+
+ colour = mask.colour
+ threshold = mask.threshold_range
+
+ ps.Publisher().sendMessage('Create surface', (imagedata,colour,threshold))
+
+ def OnChangeCurrentMaskColour(self, pubsub_evt):
+ colour_wx = pubsub_evt.data
+ colour_vtk = [c/255.0 for c in colour_wx]
+ self.ChangeCurrentMaskColour(colour_vtk)
+
+ def OnChangeCurrentMask(self, pubsub_evt):
+
+ mask_index = pubsub_evt.data
+
+ # This condition is not necessary in Linux, only under mac and windows
+ # in these platforms, because the combobox event is binded when the
+ # same item is selected again.
+ if mask_index != self.current_mask.index:
+ proj = Project()
+ future_mask = proj.GetMask(mask_index)
+
+ self.current_mask = future_mask
+
+ colour = future_mask.colour
+ self.ChangeCurrentMaskColour(colour)
+
+ imagedata = future_mask.imagedata
+ self.img_colours_mask.SetInput(imagedata)
+
+ ps.Publisher().sendMessage('Set mask threshold in notebook',
+ (self.current_mask.index,
+ self.current_mask.threshold_range))
+ ps.Publisher().sendMessage('Set threshold values in gradient',
+ self.current_mask.threshold_range)
+ ps.Publisher().sendMessage('Update slice viewer')
+
+ def ChangeCurrentMaskColour(self, colour):
+ try:
+ self.current_mask
+ except AttributeError:
+ pass
+ else:
+ (r,g,b) = colour
+ scalar_range = int(self.imagedata.GetScalarRange()[1])
+ self.current_mask.colour = colour
+
+ self.lut_mask.SetTableValue(1, r, g, b, 1.0)
+ self.lut_mask.SetTableValue(scalar_range - 1, r, g, b, 1.0)
+
+ colour_wx = [r*255, g*255, b*255]
+ ps.Publisher().sendMessage('Change mask colour in notebook',
+ (self.current_mask.index, (r,g,b)))
+ ps.Publisher().sendMessage('Set GUI items colour', colour_wx)
+ ps.Publisher().sendMessage('Update slice viewer')
+
+
+ def GetOutput(self):
+ return self.blend_imagedata.GetOutput()
+
+ def SetInput(self, imagedata):
+ self.imagedata = imagedata
+ self.extent = imagedata.GetExtent()
+
+ imagedata_bg = self.__create_background(imagedata)
+ imagedata_mask = self.__create_mask(imagedata)
+
+ mask_opacity = self.current_mask.opacity
+
+ # blend both imagedatas, so it can be inserted into viewer
+ blend_imagedata = vtk.vtkImageBlend()
+ blend_imagedata.SetBlendModeToNormal()
+ blend_imagedata.SetOpacity(0, 1)
+ blend_imagedata.SetOpacity(1, mask_opacity)
+ blend_imagedata.SetInput(0, imagedata_bg)
+ blend_imagedata.SetInput(1, imagedata_mask)
+ blend_imagedata.SetBlendModeToNormal()
+ blend_imagedata.GetOutput().ReleaseDataFlagOn()
+ self.blend_imagedata = blend_imagedata
+
+ def __create_background(self, imagedata):
+
+ thresh_min, thresh_max = imagedata.GetScalarRange()
+ ps.Publisher().sendMessage('Update threshold limits list', (thresh_min,
+ thresh_max))
+
+ # map scalar values into colors
+ lut_bg = vtk.vtkLookupTable()
+ lut_bg.SetTableRange(thresh_min, thresh_max)
+ lut_bg.SetSaturationRange(0, 0)
+ lut_bg.SetHueRange(0, 0)
+ lut_bg.SetValueRange(0, 1)
+ lut_bg.Build()
+
+ # map the input image through a lookup table
+ img_colours_bg = vtk.vtkImageMapToColors()
+ img_colours_bg.SetOutputFormatToRGBA()
+ img_colours_bg.SetLookupTable(lut_bg)
+ img_colours_bg.SetInput(imagedata)
+
+ return img_colours_bg.GetOutput()
+
+ def AddMask(self, pubsub_evt):
+ mask_name = pubsub_evt.data
+ self.CreateMask(name=mask_name)
+ self.ChangeCurrentMaskColour(self.current_mask.colour)
+
+ def CreateMask(self, imagedata=None, name=None):
+
+ future_mask = Mask()
+
+ # this is not the first mask, so we will import data from old imagedata
+ if imagedata is None:
+
+ old_mask = self.current_mask
+
+ imagedata = old_mask.imagedata
+
+ future_mask.threshold_range = old_mask.threshold_range
+
+ # if not defined in the method call, this will have been computed on
+ # previous if
+ #future_mask.imagedata = imagedata
+ future_mask.imagedata = vtk.vtkImageData()
+ future_mask.imagedata.DeepCopy(imagedata)
+ future_mask.imagedata.Update()
+
+ # when this is not the first instance, user will have defined a name
+ if name is not None:
+ future_mask.name = name
+
+ # insert new mask into project and retrieve its index
+ proj = Project()
+ proj.AddMask(future_mask.index, future_mask)
+
+
+ imagedata1 = proj.mask_dict[0].imagedata
+
+ # update gui related to mask
+ ps.Publisher().sendMessage('Add mask',
+ (future_mask.index,
+ future_mask.name,
+ future_mask.threshold_range,
+ future_mask.colour))
+
+ self.current_mask = future_mask
+
+
+
+ def __create_mask(self, imagedata):
+ # create new mask instance and insert it into project
+ self.CreateMask(imagedata=imagedata)
+ current_mask = self.current_mask
+
+ # properties to be inserted into pipeline
+ scalar_range = int(imagedata.GetScalarRange()[1])
+ r,g,b = current_mask.colour
+
+ # map scalar values into colors
+ lut_mask = vtk.vtkLookupTable()
+ lut_mask.SetNumberOfTableValues(1)
+ lut_mask.SetNumberOfColors(1)
+ lut_mask.SetHueRange(const.THRESHOLD_HUE_RANGE)
+ lut_mask.SetSaturationRange(1, 1)
+ lut_mask.SetValueRange(1, 1)
+ lut_mask.SetNumberOfTableValues(scalar_range)
+ lut_mask.SetTableValue(1, r, g, b, 1.0)
+ lut_mask.SetTableValue(scalar_range - 1, r, g, b, 1.0)
+ lut_mask.SetRampToLinear()
+ lut_mask.Build()
+ self.lut_mask = lut_mask
+
+ # threshold pipeline
+ mask_thresh_imagedata = self.__create_mask_threshold(imagedata)
+ current_mask.imagedata.DeepCopy(mask_thresh_imagedata)
+
+ #import time
+ #viewer = vtk.vtkImageViewer()
+ #viewer.SetInput(mask_thresh_imagedata)
+ #viewer.SetColorWindow(400)
+ #viewer.SetColorLevel(200)
+ #viewer.Render()
+ #time.sleep(5)
+
+
+ # map the input image through a lookup table
+ img_colours_mask = vtk.vtkImageMapToColors()
+ img_colours_mask.SetOutputFormatToRGBA()
+ img_colours_mask.SetLookupTable(lut_mask)
+ img_colours_mask.SetInput(mask_thresh_imagedata)
+ self.img_colours_mask = img_colours_mask
+
+ return img_colours_mask.GetOutput()
+
+
+ def __create_mask_threshold(self, imagedata):
+ thresh_min, thresh_max = self.current_mask.threshold_range
+
+ # flexible threshold
+ img_thresh_mask = vtk.vtkImageThreshold()
+ img_thresh_mask.SetInValue(const.THRESHOLD_INVALUE)
+ img_thresh_mask.SetInput(imagedata)
+ img_thresh_mask.SetOutValue(const.THRESHOLD_OUTVALUE)
+ img_thresh_mask.ThresholdBetween(float(thresh_min), float(thresh_max))
+ img_thresh_mask.Update()
+ self.img_thresh_mask = img_thresh_mask
+
+ # copy of threshold output
+ imagedata_mask = vtk.vtkImageData()
+ imagedata_mask.DeepCopy(img_thresh_mask.GetOutput())
+ imagedata_mask.Update()
+
+ return imagedata_mask
+
+ def SetThresholdRange(self, evt_pubsub):
+ thresh_min, thresh_max = evt_pubsub.data
+
+ self.img_thresh_mask.SetInput(self.imagedata)
+ self.img_thresh_mask.ThresholdBetween(float(thresh_min),
+ float(thresh_max))
+ self.img_thresh_mask.Update()
+
+ imagedata = self.img_thresh_mask.GetOutput()
+
+ self.current_mask.imagedata.DeepCopy(imagedata)
+
+ self.img_colours_mask.SetInput(self.current_mask.imagedata)
+
+ # save new data inside current mask
+ self.current_mask.threshold_range = (thresh_min, thresh_max)
+
+ ps.Publisher().sendMessage('Set mask threshold in notebook',
+ (self.current_mask.index,
+ self.current_mask.threshold_range))
+ ps.Publisher().sendMessage('Update slice viewer')
+
+ #def SetEditionThresholdRange(self, evt):
+ # thresh_min, thresh_max = evt.data
+ # self.current_mask.edition_threshold_range = thresh_min, thresh_max
+
+ def ErasePixel(self, x, y, z):
+ """
+ Delete pixel, based on x, y and z position coordinates.
+ """
+ colour = imagedata.GetScalarRange()[0]
+ self.imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour)
+ self.imagedata.Update()
+
+ def DrawPixel(self, x, y, z, colour=None):
+ """
+ Draw pixel, based on x, y and z position coordinates.
+ """
+ if colour is None:
+ colour = imagedata.GetScalarRange()[1]
+ self.imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour)
+
+ def EditPixelBasedOnThreshold(self, x, y, z):
+ """
+ Erase or draw pixel based on edition threshold range.
+ """
+ pixel_colour = self.imagedata.GetScalarComponentAsDouble(x, y, z, 0)
+ thresh_min, thresh_max = self.current_mask.edition_threshold_range
+
+ if (pixel_colour >= thresh_min) and (pixel_colour <= thresh_max):
+ self.DrawPixel(x, y, z, pixel_colour)
+ # TODO: See if the code bellow is really necessary
+ #if (pixel_colour <= 0):
+ # self.DrawPixel(x, y, z, 1)
+ #else:
+ # self.DrawPixel(x, y, z, pixel_colour)
+ else:
+ self.ErasePixel(x, y, z)
179 invesalius/data/styles.py
@@ -0,0 +1,179 @@
+import vtk
+
+import constants as const
+
+class ViewerStyle:
+ def __init__(self):
+ self.interactor = None
+ self.style = None
+ self.render = None
+
+ def SetInteractor(self, interactor):
+
+ # Setting style already defined in VTK
+ if (self.style is None):
+ self.style = vtk.vtkInteractorStyle()
+ #self.style.SetInteractor(interactor)
+ self.SetStyleConfig()
+ interactor.SetInteractorStyle(style)
+
+ # Saving data into attributes
+ self.render = interactor.GetRenderWindow().GetRenderer()
+ self.interactor = interactor
+
+ # Call events
+ self.__init_evt()
+
+ def SetStyleConfig(self):
+ print "calling parent"
+ pass
+
+ def __init_evt(self):
+ style = self.style
+ style.AddObserver("LeftButtonPressEvent", self.OnLeftButtonDown)
+ style.AddObserver("LeftButtonReleaseEvent", self.OnLeftButtonUp)
+ style.AddObserver("MiddleButtonPressEvent", self.OnMiddleButtonDown)
+ style.AddObserver("MiddleButtonReleaseEvent", self.OnMiddleButtonUp)
+ style.AddObserver("RightButtonPressEvent", self.OnRightButtonDown)
+ style.AddObserver("RightButtonReleaseEvent", self.OnRightButtonUp)
+ style.AddObserver("MouseWheelForwardEvent", self.OnScroll)
+ style.AddObserver("MouseWheelBackwardEvent", self.OnScroll)
+
+ style.AddObserver("MouseMoveEvent",self.OnMouseMove)
+
+ def OnScroll(self, evt, str_evt):
+ pass
+
+ def OnLeftButtonDown(self, evt, str_evt):
+ pass
+
+ def OnLeftButtonUp(self, evt, str_evt):
+ pass
+
+ def OnMiddleButtonDown(self, evt, str_evt):
+ pass
+
+ def OnMiddleButtonUp(self, evt, str_evt):
+ pass
+
+ def OnRightButtonDown(self, evt, str_evt):
+ pass
+
+ def OnRightButtonUp(self, evt, str_evt):
+ pass
+
+ def OnMouseMove(self, evt, str_evt):
+ pass
+
+class ViewerStyleSlice(ViewerStyle):
+ def __init__(self):
+ ViewerStyle.__init__(self)
+ self.orientation = 'AXIAL'
+
+ self.style = vtk.vtkInteractorStyleImage()
+ self.style.AutoAdjustCameraClippingRangeOn()
+
+ def SetOrientation(self, orientation='AXIAL'):
+ self.orientation = orientation
+
+ def OnScroll(self, evt, evt_string):
+ if evt_string == "MouseWheelForwardEvent":
+ value = 1
+ else: # elif evt_string =="MouseWheelBackwardEvent":
+ value = -1
+ ps.Publisher().sendMessage(('Set scroll position', self.orientation), value)
+
+class ViewerStyleSliceEditor(ViewerStyleSlice):
+
+ def __init__(self):
+ # FIXME: the idea is not using Slice from here...!
+ #self.slice_ = slc.Slice()
+
+ self.picker = vtk.vtkCellPicker() # define position where user clicked
+
+ self.mouse_pressed = 0 # define if operation will executed run or not
+
+ self.style = const.OP_ADD # define brush operation .OP_DEL, .OP_THRESH
+
+
+ def SetData(self, actor_bounds, imagedata_dimensions):
+ self.pos_converter = ViewerToImagedataPosConverter(actor_bounds,
+ imagedata_dimensions,
+ self.renderer)
+
+ def SetStyleConfig(self):
+ print "calling son"
+
+ def SetOrientation(self, orient):
+
+ def OnLeftButtonDown(self, evt, str_evt):
+ self.mouse_pressed = 1
+
+ def OnLeftButtonUp(self, evt, str_evt):
+ self.mouse_pressed = 0
+
+ def OnMouseMove(self, evt, str_evt):
+ pos = self.interactor.GetEventPosition()
+ wx = pos[0]
+ wy = pos[1]
+
+ self.pick.Pick(wx, wy, 0, self.render)
+ x, y, z = self.picker.GetPickPosition()
+
+ if self.mouse_pressed:
+ #wx, wy = self.From3dToImagePixel(pos, (x, y, z))
+ wx, wy = self.pos_converter.GetImagedataCoordinates(x, y, z)
+ #self.CircleOperation(wx, wy, self.slice_) # TODO!
+ ps.Publisher().sendMessage('Update edited imagedata', self.image)
+ ps.Publisher().sendMessage('Update slice viewer', None)
+
+ # update cursor
+ self.cursor.SetPosition(x, y, z)
+ self.cursor.Update()
+
+ obj.OnMouseMove()
+
+ self.interactor.Render()
+
+class ViewerToImagedataPosConverter():
+ def __init__(self, actor_bounds, imagedata_dimensions, renderer):
+ self.actor_bounds = actor_bounds
+ self.imagedata_dimensions = imagedata_dimensions
+ self.renderer = renderer
+
+ def GetImagedataCoordinates(self, picker_position):
+ x, y, z = picker_position
+
+ c = vtk.vtkCoordinate()
+ c.SetCoordinateSystemToWorld()
+ c.SetValue(bounds[::2])
+ xi, yi = c.GetComputedViewportValue(self.render)
+
+ c.SetValue(bounds[1::2])
+ xf, yf = c.GetComputedViewportValue(self.render)
+
+ c.SetValue(x, y, z)
+ wx, wy = c.GetComputedViewportValue(self.render)
+
+ wx = wx - xi
+ wy = wy - yi
+
+ xf = xf - xi
+ yf = yf - yi
+
+ wx = (wx * self.imagedata_dimensions[0]) / xf
+ wy = (wy * self.imagedata_dimensions[1]) / yf
+
+ return wx, wy
+
+################################################################################
+
+# style = vtk.vtkInteractorStyleImage()
+# style.SetInteractor(interactor)
+
+# interactor.SetInteractorStyle(style)
+# self.style = style
+
+#self.interactor.SetCursor(cursors.ZOOM_IN_CURSOR)
+
+################################################################################
234 invesalius/data/surface.py
@@ -0,0 +1,234 @@
+import vtk
+import wx.lib.pubsub as ps
+
+import constants as const
+import imagedata_utils as iu
+from project import Project
+import vtk_utils as vu
+
+class Surface():
+ """