def __inittoolbar(self): """Inicializa la toolbar""" self.__boton1 = QToolButton(self.Toolbar) self.__boton1.setTextLabel("Abrir fichero") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_abrir(), QIconSet.Small) self.__boton1.setOn(True) self.__boton1.setIconSet(iconos) self.__boton2 = QToolButton(self.Toolbar) self.__boton2.setTextLabel("Guardar en fichero") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_guardar(), QIconSet.Small) self.__boton2.setOn(True) self.__boton2.setIconSet(iconos) self.__boton3 = QToolButton(self.Toolbar) self.__boton3.setTextLabel("Exportar a html") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_exportar(), QIconSet.Small) self.__boton3.setOn(True) self.__boton3.setIconSet(iconos) self.__boton4 = QToolButton(self.Toolbar) self.__boton4.setTextLabel("Mostrar Ventana principal") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_nueva_ventana(), QIconSet.Small) self.__boton4.setOn(True) self.__boton4.setIconSet(iconos)
def __init_toolbar(self): """Inicializa la toolbar""" self.__boton1 = QToolButton(self.Toolbar) self.__boton1.setTextLabel("ABRIR") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_abrir(), QIconSet.Small) # iconos.setPixmap("images/flechaabajo.png", QIconSet.Automatic, QIconSet.Normal, QIconSet.Off) self.__boton1.setOn(True) self.__boton1.setIconSet(iconos) self.__boton2 = QToolButton(self.Toolbar) self.__boton2.setTextLabel("GUARDAR") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_guardar(), QIconSet.Small) self.__boton2.setOn(True) self.__boton2.setIconSet(iconos) self.__boton3 = QToolButton(self.Toolbar) self.__boton3.setTextLabel("Ventana Salida") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_nueva_ventana(), QIconSet.Small) self.__boton3.setOn(True) self.__boton3.setIconSet(iconos) self.__boton4 = QToolButton(self.Toolbar) self.__boton4.setTextLabel("Mostrar etiquetas") self.__boton4.setToggleButton(True) iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_etiquetas(), QIconSet.Small) self.__boton4.setIconSet(iconos)
class VPrincipal(vprincipal): """Ventana principal, hereda de vprincipal, que esta generado por el designer. Esta clase es padre de la mayoria de los dialogos, y es la que permite introducir los datos a el usuario""" def __init__(self, parent, config, portero, idu, gestorproyectos, gestortemas, gestoroperaciones): """Inicializador de la ventana principal""" vprincipal.__init__(self, None) #VARIABLES PUBLICAS self.parent = parent self.__config = config self.__gestortemas = gestortemas self.__idu = idu #Bloque de inicialización de dialogos self.__dbuscar = DBuscar(self, "busqueda") self.__dconfig = DConfig(config, self) self.__dfiltro = DFiltrado(self, self.__idu) self.__dayuda = DAyuda(self) self.__portero = portero self.__gestorproyectos = gestorproyectos self.grid = Grid(self, self.__idu, self.__portero) self.widgetStack1.addWidget(self.grid) self.widgetStack1.raiseWidget(self.grid) # Funciones de inicializacion de componentes self.__init_toolbar() self.mostrar_undo_redo() self.setIcon(self.__gestortemas.icono_programa()) self.__diccionarioarbolmenu = {} self.__diccionarioacciones = {} self.__colectorfunciones = [] listalistasetiquetas = [operacion.etiquetas for operacion in gestoroperaciones.values()] from Driza import categorias arbol = categorias.conv_categorias_arbol("Raiz", listalistasetiquetas) self.__conv_arbol_menu(self.Analizar, arbol, self.__diccionarioarbolmenu) listaelementosmenu = self.__lista_etiquetas_menu(self.__diccionarioarbolmenu, []) from sets import Set for operacion in gestoroperaciones.values(): for elementofinal in listaelementosmenu: if Set(operacion.etiquetas) == Set(elementofinal[1]): accion = QAction(self, "") accion.setText(unicode(operacion.nombre)) accion.addTo(elementofinal[0]) self.__diccionarioacciones[operacion.nombre] = accion self.__atajos() #FUNCIONES PUBLICAS def abrir_proyecto(self, parent = None, filename = None): """ Lanza el diálogo de apertura de fichero """ from Driza.excepciones import FicheroNoExisteException, FicheroErroneoException, FicheroTipoDesconocidoException if not parent: parent = self if not self.__dproyecto_modificado(): return if not filename: filtro = "" for fmt in SL.extensiones_fichero: filtro = filtro + "%s files (*.%s);;" % (fmt, fmt.lower()) filename = QFileDialog.getOpenFileName(QString.null, filtro, self, None, "Dialogo abrir fichero", "") filename = str(filename) if filename: try: self.__gestorproyectos.cargar(filename) except FicheroErroneoException: QMessageBox.warning(parent, u'Atención', 'El fichero no ha podido ser leido') except FicheroTipoDesconocidoException: QMessageBox.warning(parent, u'Atención', 'El fichero no ha podido ser leido') except FicheroNoExisteException: QMessageBox.warning(parent, u'Atención', 'El fichero no ha podido ser leido') except AttributeError: QErrorMessage(parent, "Error").message(u"Parece que ha intentado cargar un fichero de una versión anterior. Lo siento") LOG.exception("excepcion capturada") else: self.__myUpdate() self.grid.myUpdate() return True return False def __myUpdate(self): """Acciones de actualizacion""" from Driza import VERSION if self.__gestorproyectos.fichero: nfichero = self.__gestorproyectos.fichero else: nfichero = "Nuevo fichero" self.setCaption("Driza " + VERSION + " - " + nfichero) def showEvent(self, event): self.__myUpdate() vprincipal.showEvent(self, event) def closeEvent(self, event): """Acciones que se realizaran cuando el usuario cierre la ventana. Guarda el estado de la configuración, incluyendo los ficheros recientemente abiertos""" if not self.__dproyecto_modificado(): return QWidget.closeEvent(self, event) if not self.parent.vsalida.isVisible(): self.__config.guardar() qApp.exit(0) else: self.hide() def mostrar_undo_redo(self): """Determina que botones estan activados y cuales no del submenu de edición""" if self.__portero.puedo_undo(): self.editUndoAction.setEnabled(True) else: self.editUndoAction.setEnabled(False) if self.__portero.puedo_redo(): self.editRedoAction.setEnabled(True) else: self.editRedoAction.setEnabled(False) #FUNCIONES PRIVADAS def __importar(self): """Importa los datos de un fichero""" if not self.__dproyecto_modificado(): return self.parent.dimportartexto.show() def __dproyecto_modificado(self): """Pregunta en caso de que haya sido modificado el proyecto si desea ser guardado""" if not self.__idu.original(): returncode = QMessageBox.information(self, 'Atencion:', 'El proyecto actual ha sido modificado, desea guardarlo?', 'Guardarlo', 'No guardarlo', 'Volver', 0, 1) if returncode == 0: self.__guardar() elif returncode == 2: return False return True def __dacerca_de(self): """Mensaje acerca de""" from Driza import VERSION separador = "\n----------------------------------\n" betatesters = u"Carlos Mestre Gonzalez\n Luis de Bethencourt Guimerá" iconos = "Iconos del Tango Desktop Project: http://tango.freedesktop.org/" ristra = u"Driza %s es una interfaz estadística\n (C) Néstor Arocha Rodríguez - Tutorizado por Inmaculada luengo Merino\n Distribuido bajo licencia GPL" +\ separador + "Betatesters:\n" + betatesters + separador +\ u" Mantenedor del paquete .deb:\n Luis de Bethencourt Guimerá"+ separador + iconos QMessageBox.about(self, "Acerca de Driza", ristra % (VERSION)) def __undo(self): """Deshace el último cambio""" self.__portero.undo() self.grid.myUpdate() self.mostrar_undo_redo() def __redo(self): """Rehace el último cambio""" self.__portero.redo() self.grid.myUpdate() self.mostrar_undo_redo() def __init_toolbar(self): """Inicializa la toolbar""" self.__boton1 = QToolButton(self.Toolbar) self.__boton1.setTextLabel("ABRIR") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_abrir(), QIconSet.Small) # iconos.setPixmap("images/flechaabajo.png", QIconSet.Automatic, QIconSet.Normal, QIconSet.Off) self.__boton1.setOn(True) self.__boton1.setIconSet(iconos) self.__boton2 = QToolButton(self.Toolbar) self.__boton2.setTextLabel("GUARDAR") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_guardar(), QIconSet.Small) self.__boton2.setOn(True) self.__boton2.setIconSet(iconos) self.__boton3 = QToolButton(self.Toolbar) self.__boton3.setTextLabel("Ventana Salida") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_nueva_ventana(), QIconSet.Small) self.__boton3.setOn(True) self.__boton3.setIconSet(iconos) self.__boton4 = QToolButton(self.Toolbar) self.__boton4.setTextLabel("Mostrar etiquetas") self.__boton4.setToggleButton(True) iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_etiquetas(), QIconSet.Small) self.__boton4.setIconSet(iconos) def conexiones(self): """Funcion llamada en el constructor que almacena todas las conexiones accion-funcion""" self.connect(self.archivoSalirAction, SIGNAL("activated()"), self.__salir_programa) self.connect(self.fileNewAction, SIGNAL("activated()"), self.__nuevo) self.connect(self.fileOpenAction, SIGNAL("activated()"), self.abrir_proyecto) self.connect(self.fileSaveAsAction, SIGNAL("activated()"), self.__guardar_como) self.connect(self.fileSaveAction, SIGNAL("activated()"), self.__guardar) self.connect(self.archivoImportarAction, SIGNAL("activated()"), self.__importar) self.connect(self.archivoConfiguracinAction, SIGNAL("activated()"), self.__dconfig.show) self.connect(self.datosFiltrarAction, SIGNAL("activated()"), self.__dfiltro.show) self.connect(self.modificarCrear_nuevas_variablesAction, SIGNAL("activated()"), self.parent.dcrevar.show) self.connect(self.editFindAction, SIGNAL("activated()"), self.__dbuscar.show) self.connect(self.editCopyAction, SIGNAL("activated()"), self.__copiar) self.connect(self.editCutAction, SIGNAL("activated()"), self.__cortar) self.connect(self.editPasteAction, SIGNAL("activated()"), self.__pegar) self.connect(self.editUndoAction, SIGNAL("activated()"), self.__undo) self.connect(self.editRedoAction, SIGNAL("activated()"), self.__redo) self.connect(self.edicinBorrarAction, SIGNAL("activated()"), self.__borrar) self.connect(self.edicinInsertarAction, SIGNAL("activated()"), self.__insertar_registro) self.connect(self.acerca_deAcerca_deAction, SIGNAL("activated()"), self.__dacerca_de) self.connect(self.__boton1, SIGNAL("clicked()"), self.abrir_proyecto) self.connect(self.__boton2, SIGNAL("clicked()"), self.__guardar) self.connect(self.__boton3, SIGNAL("clicked()"), self.parent.vsalida.show) self.connect(self.__boton4, SIGNAL("clicked()"), self.__alternar_etiquetas) self.connect(self.ayudaAyudaAction, SIGNAL("activated()"), self.__mostrar_dayuda) self.connect(self.PopupMenuEditor_3, SIGNAL("aboutToShow()"), self.__actualizar_recientes) for (key, valor) in self.__diccionarioacciones.items(): self.__colectorfunciones.append(lambda k=key: self.parent.doperaciones.mostrar(k)) self.connect(valor, SIGNAL("activated()"), self.__colectorfunciones[-1]) def __atajos(self): """Establece los atajos""" self.ayudaAyudaAction.setAccel("F1") self.acciontab1 = QAction(self, "tabcasos") self.connect(self.acciontab1, SIGNAL("activated()"), self.grid.mostrar_t_reg) self.acciontab1.setAccel("F2") self.acciontab2 = QAction(self, "tabvars") self.connect(self.acciontab2, SIGNAL("activated()"), self.grid.mostrar_t_var) self.acciontab2.setAccel("F3") if self.__diccionarioacciones.has_key("Descriptivo"): self.__diccionarioacciones["Descriptivo"].setAccel("F4") self.__boton3.setAccel("F5") #Ventana salida self.archivoConfiguracinAction.setAccel("F10") self.acerca_deAcerca_deAction.setAccel("F12") self.archivoSalirAction.setAccel("Ctrl+Q") def __copiar(self): """Funcion que copia y borra la seleccion""" try: self.__copiar_privado() except AssertionError: QMessageBox.warning(self, u'Atención', 'Las operaciones de copiado, cortado y pegado no han sido implementadas') else: self.grid.borrar_seleccion() #http://www.google.com/codesearch?hl=en&q=+%22qtable%22+%22cut%22+%22paste%22+show:z9otKZeV6U8:R6dK3Cx-dYg:Gh37-3Ie27E&sa=N&cd=48&ct=rc&cs_p=http://mde.abo.fi/confluence/download/attachments/1011/coral-0.9.1.tar.gz&cs_f=coral-0.9.1/coral/modeler/property/propertyeditor.py#a0 def __cortar(self): """Copia, borra la seleccion y su contenido""" from Driza.excepciones import SeleccionIncorrectaException try: self.grid.verificar_seleccion_registros() self.__portero.guardar_estado() self.__copiar_privado() except SeleccionIncorrectaException: QMessageBox.warning(self, u'Atención', 'Solo se permite cortar registros') except AssertionError: QMessageBox.warning(self, u'Atención', 'Las operaciones de copiado, cortado y pegado no han sido implementadas') else: self.grid.borrar_seleccion(borrardatos=True) self.grid.myUpdate() def __pegar(self): """Funcion que envuelve a __pegar recogiendo sus excepciones""" #TODO Capturar otras excepciones try: self.__pegar_privado() except AssertionError: QErrorMessage(self, "Error").message(u"Error desconocido") LOG.exception("excepcion capturada en el pegado") def __pegar_privado(self): """Pega lo que haya sido copiado""" clipboard = QApplication.clipboard() registro = clipboard.text().latin1() lista = eval(registro) posrow = self.grid.table1.currentRow() poscol = self.grid.table1.currentColumn() if len(lista[0]) == self.__idu.n_var(): poscol = 0 #Copia de registro completo else: #No permitimos pegar si el pegado implica variables nuevas assert(poscol + len(lista[0]) <= self.__idu.n_var()) self.__portero.guardar_estado() #Guardamos el estado #Creamos nuevos registros hasta la posicion del cursor if posrow > self.__idu.n_reg(): for _ in range(self.__idu.n_reg(), posrow): self.__idu.ana_reg() #Hacemos el pegado efectivo i = posrow for registro in lista: if i >= self.__idu.n_reg(): self.__idu.ana_reg() j = poscol for campo in registro: if campo != None: self.__idu[i][j] = campo j += 1 i += 1 self.grid.myUpdate() def __salir_programa(self): """Funcion de salida del programa. Guarda la configuracion""" if not self.__dproyecto_modificado(): return self.__config.guardar() qApp.exit(0) def __nuevo(self): """Accion realizada cuando el usuario clickea en Nuevo""" if not self.__dproyecto_modificado(): return self.__idu.borrar_todo() self.__gestorproyectos.fichero = None self.__myUpdate() self.grid.myUpdate() def __guardar(self): """Funcion de guardado del fichero. Si el fichero no es conocido se llama a guardarcomo""" if self.__gestorproyectos.fichero: self.__gestorproyectos.guardar(sobreescribir = True) self.__idu.establecer_original() else: self.__guardar_como() def __guardar_como(self): """Abre un diálogo pidiendo el nombre de archivo y guarda en dicho archivo""" filtro = "" for fmt in SL.extensiones_fichero: filtro = filtro+ "%s files (*.%s);;" % (fmt, fmt.lower()) filename = QFileDialog.getSaveFileName(QString.null, filtro, self) filename = str(filename) if filename: from Driza.excepciones import FicheroExisteException, FicheroTipoDesconocidoException import re extension = re.compile('.*\..*') if not extension.match(filename): filename += ".driza" try: self.__gestorproyectos.guardar(filename) except FicheroExisteException, fichero: returncode = QMessageBox.information(self, 'Atencion:', 'El fichero' + fichero.fichero + ' ya existe' , 'Sobreescribir', 'Otro nombre', 'Cancelar', 0, 1) if returncode == 0: self.__gestorproyectos.guardar(filename, True) self.__idu.establecer_original() self.__myUpdate() elif returncode == 1: self.__guardarcomo() except FicheroTipoDesconocidoException: QMessageBox.warning(self, u'Atención', u'La extensión del fichero es incorrecta.\nPruebe con otra extensión') self.__gestorproyectos.fichero = None else:
def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12, 4, 4, 4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip( "If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID") self.volumeReconstructorIDSelector.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip( "If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct") self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton( " Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton( " Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton
class ProstateTRUSNavUltrasound(UltraSound): OFFLINE_VOLUME_FILENAME = "RecVol_Reference.mha" SCOUT_VOLUME_FILENAME = "ScoutScan.mha" LIVE_VOLUME_FILENAME = "LiveReconstructedVolume.mha" RECORDING_FILENAME = "Recording.mha" SCOUT_RECORDING_FILENAME = "ScoutScanRecording.mha" LIVE_RECORDING_FILENAME = LIVE_VOLUME_FILENAME SCOUT_VOLUME_NODE_NAME = "ScoutScan" OFFLINE_VOLUME_NODE_NAME = "RecVol_Reference" LIVE_VOLUME_NODE_NAME = "liveReconstruction" APPLY_HOLE_FILLING_FOR_SNAPSHOT = False SNAPSHOT_INTERVAL = 3 OUTPUT_VOLUME_SPACING = 3 LIVE_OUTPUT_VOLUME_SPACING = 1 @property def roiNode(self): return self._roiNode @roiNode.setter def roiNode(self, node): self._roiNode = node if node is not None: self.startStopLiveReconstructionButton.setEnabled(True) else: self.startStopLiveReconstructionButton.setEnabled(False) def __init__(self, guideletParent): UltraSound.__init__(self, guideletParent) self.parameterNode = guideletParent.parameterNode self.parameterNodeObserver = None self._roiNode = None self.liveOutputSpacingValue = [ self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING ] self.outputSpacing = [ self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING ] self.roiOrigin = None self.roiExtent = None self.defaultParameterNode = None self.logic = ProstateTRUSNavUltrasoundLogic() def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12, 4, 4, 4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip( "If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID") self.volumeReconstructorIDSelector.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip( "If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct") self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton( " Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton( " Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton def setupResliceDriver(self): layoutManager = slicer.app.layoutManager() # Show ultrasound in red view. redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID( self.liveUltrasoundNode_Reference.GetID()) resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') redNode.SetSliceResolutionMode( slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice( self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice( 6, redNode) # Transverse mode, default for PLUS ultrasound. else: logging.warning('Logic not found for Volume Reslice Driver') def createCollapsibleButton(self, text, collapsed=False): collapsibleButton = ctkCollapsibleButton() collapsibleButton.text = text collapsibleButton.collapsed = collapsed return collapsibleButton def createLabel(self, text, visible=True): label = QLabel() label.setText(text) label.visible = visible return label def setupConnections(self): self.startStopRecordingButton.connect( 'clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.connect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.connect( 'clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.connect( 'clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.connect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.connect( 'currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.connect( 'currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.connect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.connect( self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.connect( 'clicked(bool)', self.onConnectDisconnectButtonClicked) def disconnect(self): self.startStopRecordingButton.disconnect( 'clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.disconnect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.disconnect( 'clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.disconnect( 'clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.disconnect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.disconnect( 'currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.disconnect( 'currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.disconnect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.disconnect( self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.disconnect( 'clicked(bool)', self.onConnectDisconnectButtonClicked) def setupIcons(self): self.plusRemoteModuleDirectoryPath = slicer.modules.plusremote.path.replace( "PlusRemote.py", "") self.recordIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Record.png') self.stopIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Stop.png') self.waitIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Wait.png') self.visibleOffIcon = QIcon(":Icons\VisibleOff.png") self.visibleOnIcon = QIcon(":Icons\VisibleOn.png") def onParameterSetSelected(self): # Set up default values for new nodes if self.parameterNode: self.plusRemoteLogic.setDefaultParameters(self.parameterNode) self.updateGuiFromParameterNode() def updateGuiFromParameterNode(self): self.parameterVolumeList = { 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector } for parameter in self.parameterVolumeList: if self.parameterNode.GetParameter(parameter): self.parameterVolumeList[parameter].blockSignals(True) self.parameterVolumeList[parameter].blockSignals(False) if self.parameterNode.GetParameter('CaptureID'): self.captureIDSelector.blockSignals(True) for i in range(0, self.captureIDSelector.count): if self.parameterNode.GetParameter( 'CaptureID') == self.captureIDSelector.itemText(i): self.captureIDSelector.setCurrentIndex( int(self.parameterNode.GetParameter('CaptureIdIndex'))) self.captureIDSelector.blockSignals(False) if self.parameterNode.GetParameter('VolumeReconstructor'): self.volumeReconstructorIDSelector.blockSignals(True) for i in range(0, self.volumeReconstructorIDSelector.count): if self.parameterNode.GetParameter( 'VolumeReconstructor' ) == self.volumeReconstructorIDSelector.itemText(i): self.volumeReconstructorIDSelector.setCurrentIndex( int( self.parameterNode.GetParameter( 'VolumeReconstructorIndex'))) self.volumeReconstructorIDSelector.blockSignals(False) self.roiNode = self.parameterNode.GetNthNodeReference('ROI', 0) def updateParameterNodeFromGui(self): #Update parameter node value to save when user change value in the interface if not self.parameterNode: return self.parametersList = { 'CaptureID': self.captureIDSelector.currentText, 'CaptureIdIndex': self.captureIDSelector.currentIndex, 'VolumeReconstructor': self.volumeReconstructorIDSelector.currentText, 'VolumeReconstructorIndex': self.volumeReconstructorIDSelector.currentIndex, 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector.currentIndex } for parameter in self.parametersList: self.parameterNode.SetParameter( parameter, str(self.parametersList[parameter])) if self.roiNode: roiNodeID = self.roiNode.GetID() self.parameterNode.SetNthNodeReferenceID('ROI', 0, roiNodeID) # # Connector observation and actions # def onConnectorNodeConnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeConnected") self.connectorNodeConnected = True self.captureIDSelector.setDisabled(False) self.volumeReconstructorIDSelector.setDisabled(False) self.plusRemoteLogic.getCaptureDeviceIds( self.connectorNode.GetID(), self.onGetCaptureDeviceCommandResponseReceived) self.plusRemoteLogic.getVolumeReconstructorDeviceIds( self.connectorNode.GetID(), self.onGetVolumeReconstructorDeviceCommandResponseReceived) self.connectDisconnectButton.setText("Disconnect") def onConnectorNodeDisconnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeDisconnected") self.connectorNodeConnected = False self.startStopRecordingButton.setEnabled(False) self.startStopScoutScanButton.setEnabled(False) self.startStopLiveReconstructionButton.setEnabled(False) self.offlineReconstructButton.setEnabled(False) self.captureIDSelector.setDisabled(True) self.volumeReconstructorIDSelector.setDisabled(True) self.connectDisconnectButton.setText("Connect") def getLiveVolumeRecNode(self): liveVolumeRecNode = slicer.util.getNode(self.LIVE_VOLUME_NODE_NAME) return liveVolumeRecNode def getOfflineVolumeRecNode(self): offlineVolumeRecNode = slicer.util.getNode( self.OFFLINE_VOLUME_NODE_NAME) return offlineVolumeRecNode def getScoutVolumeNode(self): scoutScanVolumeNode = slicer.util.getNode(self.SCOUT_VOLUME_NODE_NAME) return scoutScanVolumeNode def onConnectDisconnectButtonClicked(self): if self.connectorNode.GetState( ) == slicer.vtkMRMLIGTLConnectorNode.STATE_CONNECTED: self.connectorNode.Stop() else: self.connectorNode.Start() def onStartStopRecordingButtonClicked(self): if self.startStopRecordingButton.isChecked(): self.startStopRecordingButton.setText(" Stop Recording") self.startStopRecordingButton.setIcon(self.stopIcon) self.startStopRecordingButton.setToolTip( "If clicked, stop recording") self.onStartRecording(self.generateRecordingOutputFilename()) else: self.startStopRecordingButton.setText(" Start Recording") self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setToolTip( "If clicked, start recording") self.onStopRecording(self.onVolumeRecorded) def onStartStopScoutScanButtonClicked(self): if self.startStopScoutScanButton.isChecked(): self.startStopScoutScanButton.setText( " Scout Scan\n Stop Recording and Reconstruct Recorded Volume" ) self.startStopScoutScanButton.setIcon(self.stopIcon) self.startStopScoutScanButton.setToolTip( "If clicked, stop recording and reconstruct recorded volume") self.onStartRecording(self.generateScoutRecordingOutputFilename()) else: self.onStopRecording(self.onScoutVolumeRecorded) def onStartStopLiveReconstructionButtonClicked(self): if self.startStopLiveReconstructionButton.isChecked(): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.startStopLiveReconstructionButton.setText( " Stop Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.stopIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, stop live reconstruction") self.onStartRecording(self.getLiveRecordingOutputFilename()) self.onStartReconstruction() else: self.startStopLiveReconstructionButton.setText( " Start Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction") self.onStopRecording(self.printCommandResponse) self.onStopReconstruction() def onDisplayRoiButtonClicked(self): if self.displayRoiButton.isChecked(): self.displayRoiButton.setIcon(self.visibleOnIcon) self.displayRoiButton.setToolTip("If clicked, hide ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(1) else: self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(0) def generateRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.RECORDING_FILENAME) def generateScoutRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.SCOUT_RECORDING_FILENAME) def getLiveRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.LIVE_RECORDING_FILENAME) def getLiveReconstructionOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.LIVE_VOLUME_FILENAME) def onStartRecording(self, filename): self.plusRemoteLogic.startRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, filename, self.printCommandResponse) def onStopRecording(self, callback): self.plusRemoteLogic.stopRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, callback) def onStartReconstruction(self): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.plusRemoteLogic.startVolumeReconstuction( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.liveOutputSpacingValue, self.roiOrigin, self.roiExtent, self.printCommandResponse, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) # Set up timer for requesting snapshot self.snapshotTimer.start(self.SNAPSHOT_INTERVAL * 1000) def onStopReconstruction(self): self.snapshotTimer.stop() self.plusRemoteLogic.stopVolumeReconstruction( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.onVolumeLiveReconstructed, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) def onReconstVolume(self): self.offlineReconstructButton.setIcon(self.waitIcon) self.offlineReconstructButton.setText( " Offline Reconstruction in progress ...") self.offlineReconstructButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.offlineVolumeToReconstructSelector.currentText, self.outputSpacing, self.onVolumeReconstructed, self.OFFLINE_VOLUME_FILENAME, self.OFFLINE_VOLUME_NODE_NAME) def onScoutScanReconstVolume(self): self.startStopScoutScanButton.setIcon(self.waitIcon) self.startStopScoutScanButton.setText( " Scout Scan\n Reconstruction in progress ...") self.startStopScoutScanButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.lastScoutRecordingOutputFilename, self.outputSpacing, self.onScoutVolumeReconstructed, self.SCOUT_VOLUME_FILENAME, self.SCOUT_VOLUME_NODE_NAME) def onRequestVolumeReconstructionSnapshot(self, stopFlag=""): self.plusRemoteLogic.getVolumeReconstructionSnapshot( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.LIVE_VOLUME_FILENAME, self.LIVE_VOLUME_NODE_NAME, self.APPLY_HOLE_FILLING_FOR_SNAPSHOT, self.onSnapshotAcquired) def executeCommandDelayed(self, method, delay=100): # Order of OpenIGTLink message receiving and processing is not guaranteed to be the same # therefore we wait a bit to make sure the image message is processed as well QTimer.singleShot(delay, method) def printCommandResponse(self, command, q): statusText = "Command {0} [{1}]: {2}\n".format( command.GetCommandName(), command.GetID(), command.StatusToString(command.GetStatus())) if command.GetResponseMessage(): statusText = statusText + command.GetResponseMessage() elif command.GetResponseText(): statusText = statusText + command.GetResponseText() logging.debug(statusText) def onGetCaptureDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return captureDeviceIdsListString = command.GetResponseMessage() if captureDeviceIdsListString: captureDevicesIdsList = captureDeviceIdsListString.split(",") else: captureDevicesIdsList = [] for i in range(0, len(captureDevicesIdsList)): if self.captureIDSelector.findText(captureDevicesIdsList[i]) == -1: self.captureIDSelector.addItem(captureDevicesIdsList[i]) def onGetVolumeReconstructorDeviceCommandResponseReceived( self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return volumeReconstructorDeviceIdsListString = command.GetResponseMessage() if volumeReconstructorDeviceIdsListString: volumeReconstructorDeviceIdsList = volumeReconstructorDeviceIdsListString.split( ",") else: volumeReconstructorDeviceIdsList = [] self.volumeReconstructorIDSelector.clear() self.volumeReconstructorIDSelector.addItems( volumeReconstructorDeviceIdsList) self.startStopRecordingButton.setEnabled(True) self.offlineReconstructButton.setEnabled(True) self.startStopScoutScanButton.setEnabled(True) if self.roiNode: self.startStopLiveReconstructionButton.setEnabled(True) def onVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) volumeToReconstructFileName = os.path.basename( command.GetResponseMessage()) self.offlineVolumeToReconstructSelector.insertItem( 0, volumeToReconstructFileName) self.offlineVolumeToReconstructSelector.setCurrentIndex(0) def onScoutVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) if command.GetStatus() == command.CommandExpired: logging.fatal( "Scout Volume Recording: Timeout while waiting for volume reconstruction result" ) return if command.GetStatus() == command.CommandSuccess: self.lastScoutRecordingOutputFilename = os.path.basename( command.GetResponseMessage()) self.onScoutScanReconstVolume() def onVolumeReconstructed(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setText("Offline Reconstruction") self.offlineReconstructButton.setEnabled(True) self.offlineReconstructButton.setChecked(False) if command.GetStatus() == command.CommandExpired: # volume reconstruction command timed out logging.fatal( "Volume Reconstruction: Timeout while waiting for volume reconstruction result" ) return if command.GetStatus() != command.CommandSuccess: logging.debug("Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onVolumeReconstructedFinalize) def onVolumeReconstructedFinalize(self): applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(self.getOfflineVolumeRecNode()) def onScoutVolumeReconstructed(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() == command.CommandExpired: logging.fatal( "Scout Volume Reconstruction: Timeout while waiting for scout volume reconstruction result" ) return self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setText( " Scout Scan\n Start Recording") self.startStopScoutScanButton.setEnabled(True) if command.GetStatus() != command.CommandSuccess: logging.debug("Scout Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onScoutVolumeReconstructedFinalize) def onScoutVolumeReconstructedFinalize(self): # Create and initialize ROI after scout scan because low resolution scout scan is used to set # a smaller ROI for the live high resolution reconstruction self.roiNode = self.logic.onRoiInitialization( self.SCOUT_VOLUME_NODE_NAME, self.roiNode) self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) scoutScanVolumeNode = self.getScoutVolumeNode() applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(scoutScanVolumeNode) def onSnapshotAcquired(self, command, q): self.printCommandResponse(command, q) if not self.startStopLiveReconstructionButton.isChecked(): # live volume reconstruction is not active return self.executeCommandDelayed(self.onSnapshotAcquiredFinalize) def onSnapshotAcquiredFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode()) self.snapshotTimer.start(self.SNAPSHOT_INTERVAL * 1000) def onVolumeLiveReconstructed(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() == command.CommandExpired: logging.fatal( "LIVE Volume Reconstruction: Failed to stop volume reconstruction" ) return if command.GetStatus() != command.CommandSuccess: logging.debug("LIVE Volume Reconstruction " + command.GetResponseMessage()) return self.executeCommandDelayed(self.getLiveVolumeRecNode) def onVolumeLiveReconstructedFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode())
class VSalida(VentanaSalida): """Ventana que muestra los resultados de las operaciones solicitadas. Permite al usuario exportar o guardar los resultados ya obtenidos""" def __init__(self, parent, gestorsalida, gestortemas): VentanaSalida.__init__(self) #VARIABLES PUBLICAS self.parent = parent #VARIABLES PRIVADAS self.__gestortemas = gestortemas self.__gestorsalida = gestorsalida self.__contenido = [] self.__inittoolbar() self.__conexiones() #FUNCIONES PUBLICAS def ana_res(self, objeto): """Añade un resultado al dialogo, para ser mostrado""" self.__contenido.append(objeto) def __myUpdate(self): """Actualiza el contenido de la ventana""" cadenasalida = "" i = 1 for resultado in self.__contenido: cadenasalida += "<a name=" + str(i) + "></a>" cadenasalida += resultado.html().encode('iso-8859-1', 'replace') i += 1 self.textBrowser1.setText(cadenasalida, "/tmp") self.textBrowser1.scrollToAnchor(str(len(self.__contenido))) self.__actualizar_lista() def closeEvent( self, event ): """Redefinicion del closeEvent de qt""" QWidget.closeEvent( self, event ) if not self.parent.vprincipal.isVisible(): qApp.exit(0) else: self.hide() def showEvent(self, event): """Redefinicion del método show de VentanaSalida, muestra todos los resultados almacenados""" self.__myUpdate() VentanaSalida.showEvent(self, event) #FUNCIONES PRIVADAS def __conexiones(self): """Bloque de conexiones""" self.connect(self.archivoAbrirAction, SIGNAL("activated()"), self.__dabrirfichero) self.connect(self.archivoGuardarAction, SIGNAL("activated()"), self.__dguardarfichero) self.connect(self.archivoExportarHTMLAction, SIGNAL("activated()"), self.__dexportar) self.connect(self.archivoSalirAction, SIGNAL("activated()"), self.hide) self.connect(self.__boton1, SIGNAL("clicked()"), self.__dabrirfichero) self.connect(self.__boton2, SIGNAL("clicked()"), self.__dguardarfichero) self.connect(self.__boton3, SIGNAL("clicked()"), self.__dexportar) self.connect(self.__boton4, SIGNAL("clicked()"), self.parent.vprincipal.show) self.connect(self.pushButton1, SIGNAL("clicked()"), self.__borrar_elemento) def __inittoolbar(self): """Inicializa la toolbar""" self.__boton1 = QToolButton(self.Toolbar) self.__boton1.setTextLabel("Abrir fichero") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_abrir(), QIconSet.Small) self.__boton1.setOn(True) self.__boton1.setIconSet(iconos) self.__boton2 = QToolButton(self.Toolbar) self.__boton2.setTextLabel("Guardar en fichero") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_guardar(), QIconSet.Small) self.__boton2.setOn(True) self.__boton2.setIconSet(iconos) self.__boton3 = QToolButton(self.Toolbar) self.__boton3.setTextLabel("Exportar a html") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_exportar(), QIconSet.Small) self.__boton3.setOn(True) self.__boton3.setIconSet(iconos) self.__boton4 = QToolButton(self.Toolbar) self.__boton4.setTextLabel("Mostrar Ventana principal") iconos = QIconSet() iconos.setIconSize(QIconSet.Small, QSize(100, 100)) iconos.setPixmap(self.__gestortemas.icono_nueva_ventana(), QIconSet.Small) self.__boton4.setOn(True) self.__boton4.setIconSet(iconos) def __dabrirfichero(self): """Pregunta al usuario que fichero cargar""" filterlist = "" for fmt in ["dro"]: #Candidata al fichero de listas filterlist = filterlist + "%s files (*.%s);;" % (fmt, fmt.lower()) nombrefichero = QFileDialog.getOpenFileName(QString.null, filterlist, self, None, "Dialogo abrir fichero", "") filename = str(nombrefichero) if filename: try: self.__contenido = self.__gestorsalida.cargar(filename) except AttributeError: QErrorMessage(self,"Error").message(u"Error en la carga de fichero, Probablemente versión anterior") else: self.__myUpdate() def __dguardarfichero(self): """Pregunta al usuario en que fichero guardar""" filterlist = "" for fmt in ["dro"]: #Candidata al fichero de listas filterlist = filterlist + "%s files (*.%s);;" % (fmt, fmt.lower()) nombrefichero = QFileDialog.getSaveFileName(QString.null, filterlist, self) filename = str(nombrefichero) if filename: from Driza.excepciones import FicheroExisteException, \ FicheroTipoDesconocidoException try: self.__gestorsalida.guardar(self.__contenido, filename) except FicheroExisteException,fichero: codigoretorno = QMessageBox.information(self, 'Atencion:', 'El fichero' +\ fichero.fichero + ' ya existe' , 'Sobreescribir', \ 'Otro nombre', 'Cancelar', 0, 1) if codigoretorno == 0: self.__gestorsalida.guardar(self.__contenido, filename, True) elif codigoretorno == 1: self.__dguardarfichero() except FicheroTipoDesconocidoException: QMessageBox.warning(self, u'Atención', \ u'La extensión del fichero es incorrecta.\nPruebe con otra extensión')
def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12,4,4,4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip("If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID" ) self.volumeReconstructorIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip("If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct" ) self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton(" Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton(" Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip("If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton
class ProstateTRUSNavUltrasound(UltraSound): OFFLINE_VOLUME_FILENAME = "RecVol_Reference.mha" SCOUT_VOLUME_FILENAME = "ScoutScan.mha" LIVE_VOLUME_FILENAME = "LiveReconstructedVolume.mha" RECORDING_FILENAME = "Recording.mha" SCOUT_RECORDING_FILENAME = "ScoutScanRecording.mha" LIVE_RECORDING_FILENAME = LIVE_VOLUME_FILENAME SCOUT_VOLUME_NODE_NAME = "ScoutScan" OFFLINE_VOLUME_NODE_NAME = "RecVol_Reference" LIVE_VOLUME_NODE_NAME = "liveReconstruction" APPLY_HOLE_FILLING_FOR_SNAPSHOT = False SNAPSHOT_INTERVAL = 3 OUTPUT_VOLUME_SPACING = 3 LIVE_OUTPUT_VOLUME_SPACING = 1 @property def roiNode(self): return self._roiNode @roiNode.setter def roiNode(self, node): self._roiNode=node if node is not None: self.startStopLiveReconstructionButton.setEnabled(True) else: self.startStopLiveReconstructionButton.setEnabled(False) def __init__(self, guideletParent): UltraSound.__init__(self, guideletParent) self.parameterNode = guideletParent.parameterNode self.parameterNodeObserver = None self._roiNode = None self.liveOutputSpacingValue = [self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING] self.outputSpacing = [self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING] self.roiOrigin = None self.roiExtent = None self.defaultParameterNode = None self.logic = ProstateTRUSNavUltrasoundLogic() def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12,4,4,4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip("If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID" ) self.volumeReconstructorIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip("If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct" ) self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton(" Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton(" Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip("If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton def setupResliceDriver(self): layoutManager = slicer.app.layoutManager() # Show ultrasound in red view. redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(self.liveUltrasoundNode_Reference.GetID()) resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') redNode.SetSliceResolutionMode(slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice(self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice(6, redNode) # Transverse mode, default for PLUS ultrasound. else: logging.warning('Logic not found for Volume Reslice Driver') def createCollapsibleButton(self, text, collapsed=False): collapsibleButton = ctkCollapsibleButton() collapsibleButton.text = text collapsibleButton.collapsed = collapsed return collapsibleButton def createLabel(self, text, visible=True): label = QLabel() label.setText(text) label.visible = visible return label def setupConnections(self): self.startStopRecordingButton.connect('clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.connect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.connect('clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.connect('clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.connect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.connect('currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.connect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.connect(self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.connect('clicked(bool)', self.onConnectDisconnectButtonClicked) def disconnect(self): self.startStopRecordingButton.disconnect('clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.disconnect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.disconnect('clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.disconnect('clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.disconnect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.disconnect('currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.disconnect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.disconnect(self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.disconnect('clicked(bool)', self.onConnectDisconnectButtonClicked) def setupIcons(self): self.plusRemoteModuleDirectoryPath = slicer.modules.plusremote.path.replace("PlusRemote.py", "") self.recordIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Record.png') self.stopIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Stop.png') self.waitIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Wait.png') self.visibleOffIcon = QIcon(":Icons\VisibleOff.png") self.visibleOnIcon = QIcon(":Icons\VisibleOn.png") def onParameterSetSelected(self): # Set up default values for new nodes if self.parameterNode: self.plusRemoteLogic.setDefaultParameters(self.parameterNode) self.updateGuiFromParameterNode() def updateGuiFromParameterNode(self): self.parameterVolumeList = {'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector} for parameter in self.parameterVolumeList: if self.parameterNode.GetParameter(parameter): self.parameterVolumeList[parameter].blockSignals(True) self.parameterVolumeList[parameter].blockSignals(False) if self.parameterNode.GetParameter('CaptureID'): self.captureIDSelector.blockSignals(True) for i in range(0, self.captureIDSelector.count): if self.parameterNode.GetParameter('CaptureID') == self.captureIDSelector.itemText(i): self.captureIDSelector.setCurrentIndex(int(self.parameterNode.GetParameter('CaptureIdIndex'))) self.captureIDSelector.blockSignals(False) if self.parameterNode.GetParameter('VolumeReconstructor'): self.volumeReconstructorIDSelector.blockSignals(True) for i in range(0, self.volumeReconstructorIDSelector.count): if self.parameterNode.GetParameter('VolumeReconstructor') == self.volumeReconstructorIDSelector.itemText(i): self.volumeReconstructorIDSelector.setCurrentIndex(int(self.parameterNode.GetParameter('VolumeReconstructorIndex'))) self.volumeReconstructorIDSelector.blockSignals(False) self.roiNode = self.parameterNode.GetNthNodeReference('ROI', 0) def updateParameterNodeFromGui(self): #Update parameter node value to save when user change value in the interface if not self.parameterNode: return self.parametersList = {'CaptureID': self.captureIDSelector.currentText, 'CaptureIdIndex': self.captureIDSelector.currentIndex, 'VolumeReconstructor': self.volumeReconstructorIDSelector.currentText, 'VolumeReconstructorIndex': self.volumeReconstructorIDSelector.currentIndex, 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector.currentIndex} for parameter in self.parametersList: self.parameterNode.SetParameter(parameter, str(self.parametersList[parameter])) if self.roiNode: roiNodeID = self.roiNode.GetID() self.parameterNode.SetNthNodeReferenceID('ROI', 0, roiNodeID) # # Connector observation and actions # def onConnectorNodeConnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeConnected") self.connectorNodeConnected = True self.captureIDSelector.setDisabled(False) self.volumeReconstructorIDSelector.setDisabled(False) self.plusRemoteLogic.getCaptureDeviceIds(self.connectorNode.GetID(), self.onGetCaptureDeviceCommandResponseReceived) self.plusRemoteLogic.getVolumeReconstructorDeviceIds(self.connectorNode.GetID(), self.onGetVolumeReconstructorDeviceCommandResponseReceived) self.connectDisconnectButton.setText("Disconnect") def onConnectorNodeDisconnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeDisconnected") self.connectorNodeConnected = False self.startStopRecordingButton.setEnabled(False) self.startStopScoutScanButton.setEnabled(False) self.startStopLiveReconstructionButton.setEnabled(False) self.offlineReconstructButton.setEnabled(False) self.captureIDSelector.setDisabled(True) self.volumeReconstructorIDSelector.setDisabled(True) self.connectDisconnectButton.setText("Connect") def getLiveVolumeRecNode(self): liveVolumeRecNode = slicer.util.getNode(self.LIVE_VOLUME_NODE_NAME) return liveVolumeRecNode def getOfflineVolumeRecNode(self): offlineVolumeRecNode = slicer.util.getNode(self.OFFLINE_VOLUME_NODE_NAME) return offlineVolumeRecNode def getScoutVolumeNode(self): scoutScanVolumeNode = slicer.util.getNode(self.SCOUT_VOLUME_NODE_NAME) return scoutScanVolumeNode def onConnectDisconnectButtonClicked(self): if self.connectorNode.GetState() == slicer.vtkMRMLIGTLConnectorNode.STATE_CONNECTED: self.connectorNode.Stop() else: self.connectorNode.Start() def onStartStopRecordingButtonClicked(self): if self.startStopRecordingButton.isChecked(): self.startStopRecordingButton.setText(" Stop Recording") self.startStopRecordingButton.setIcon(self.stopIcon) self.startStopRecordingButton.setToolTip( "If clicked, stop recording" ) self.onStartRecording(self.generateRecordingOutputFilename()) else: self.startStopRecordingButton.setText(" Start Recording") self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setToolTip( "If clicked, start recording" ) self.onStopRecording(self.onVolumeRecorded) def onStartStopScoutScanButtonClicked(self): if self.startStopScoutScanButton.isChecked(): self.startStopScoutScanButton.setText(" Scout Scan\n Stop Recording and Reconstruct Recorded Volume") self.startStopScoutScanButton.setIcon(self.stopIcon) self.startStopScoutScanButton.setToolTip( "If clicked, stop recording and reconstruct recorded volume" ) self.onStartRecording(self.generateScoutRecordingOutputFilename()) else: self.onStopRecording(self.onScoutVolumeRecorded) def onStartStopLiveReconstructionButtonClicked(self): if self.startStopLiveReconstructionButton.isChecked(): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.startStopLiveReconstructionButton.setText(" Stop Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.stopIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, stop live reconstruction" ) self.onStartRecording(self.getLiveRecordingOutputFilename()) self.onStartReconstruction() else: self.startStopLiveReconstructionButton.setText(" Start Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction" ) self.onStopRecording(self.printCommandResponse) self.onStopReconstruction() def onDisplayRoiButtonClicked(self): if self.displayRoiButton.isChecked(): self.displayRoiButton.setIcon(self.visibleOnIcon) self.displayRoiButton.setToolTip("If clicked, hide ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(1) else: self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(0) def generateRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.RECORDING_FILENAME) def generateScoutRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.SCOUT_RECORDING_FILENAME) def getLiveRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.LIVE_RECORDING_FILENAME) def getLiveReconstructionOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.LIVE_VOLUME_FILENAME) def onStartRecording(self, filename): self.plusRemoteLogic.startRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, filename, self.printCommandResponse) def onStopRecording(self, callback): self.plusRemoteLogic.stopRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, callback) def onStartReconstruction(self): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.plusRemoteLogic.startVolumeReconstuction(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.liveOutputSpacingValue, self.roiOrigin, self.roiExtent, self.printCommandResponse, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) # Set up timer for requesting snapshot self.snapshotTimer.start(self.SNAPSHOT_INTERVAL*1000) def onStopReconstruction(self): self.snapshotTimer.stop() self.plusRemoteLogic.stopVolumeReconstruction(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.onVolumeLiveReconstructed, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) def onReconstVolume(self): self.offlineReconstructButton.setIcon(self.waitIcon) self.offlineReconstructButton.setText(" Offline Reconstruction in progress ...") self.offlineReconstructButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.offlineVolumeToReconstructSelector.currentText, self.outputSpacing, self.onVolumeReconstructed, self.OFFLINE_VOLUME_FILENAME, self.OFFLINE_VOLUME_NODE_NAME) def onScoutScanReconstVolume(self): self.startStopScoutScanButton.setIcon(self.waitIcon) self.startStopScoutScanButton.setText(" Scout Scan\n Reconstruction in progress ...") self.startStopScoutScanButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.lastScoutRecordingOutputFilename, self.outputSpacing, self.onScoutVolumeReconstructed, self.SCOUT_VOLUME_FILENAME, self.SCOUT_VOLUME_NODE_NAME) def onRequestVolumeReconstructionSnapshot(self, stopFlag = ""): self.plusRemoteLogic.getVolumeReconstructionSnapshot(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.LIVE_VOLUME_FILENAME, self.LIVE_VOLUME_NODE_NAME, self.APPLY_HOLE_FILLING_FOR_SNAPSHOT, self.onSnapshotAcquired) def executeCommandDelayed(self, method, delay=100): # Order of OpenIGTLink message receiving and processing is not guaranteed to be the same # therefore we wait a bit to make sure the image message is processed as well QTimer.singleShot(delay, method) def printCommandResponse(self, command, q): statusText = "Command {0} [{1}]: {2}\n".format(command.GetCommandName(), command.GetID(), command.StatusToString(command.GetStatus())) if command.GetResponseMessage(): statusText = statusText + command.GetResponseMessage() elif command.GetResponseText(): statusText = statusText + command.GetResponseText() logging.debug(statusText) def onGetCaptureDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return captureDeviceIdsListString = command.GetResponseMessage() if captureDeviceIdsListString: captureDevicesIdsList = captureDeviceIdsListString.split(",") else: captureDevicesIdsList = [] for i in range(0,len(captureDevicesIdsList)): if self.captureIDSelector.findText(captureDevicesIdsList[i]) == -1: self.captureIDSelector.addItem(captureDevicesIdsList[i]) def onGetVolumeReconstructorDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return volumeReconstructorDeviceIdsListString = command.GetResponseMessage() if volumeReconstructorDeviceIdsListString: volumeReconstructorDeviceIdsList = volumeReconstructorDeviceIdsListString.split(",") else: volumeReconstructorDeviceIdsList = [] self.volumeReconstructorIDSelector.clear() self.volumeReconstructorIDSelector.addItems(volumeReconstructorDeviceIdsList) self.startStopRecordingButton.setEnabled(True) self.offlineReconstructButton.setEnabled(True) self.startStopScoutScanButton.setEnabled(True) if self.roiNode: self.startStopLiveReconstructionButton.setEnabled(True) def onVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) volumeToReconstructFileName = os.path.basename(command.GetResponseMessage()) self.offlineVolumeToReconstructSelector.insertItem(0,volumeToReconstructFileName) self.offlineVolumeToReconstructSelector.setCurrentIndex(0) def onScoutVolumeRecorded(self, command, q): self.printCommandResponse(command,q) self.offlineReconstructButton.setEnabled(True) if command.GetStatus() == command.CommandExpired: logging.fatal("Scout Volume Recording: Timeout while waiting for volume reconstruction result") return if command.GetStatus() == command.CommandSuccess: self.lastScoutRecordingOutputFilename = os.path.basename(command.GetResponseMessage()) self.onScoutScanReconstVolume() def onVolumeReconstructed(self, command, q): self.printCommandResponse(command,q) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setText("Offline Reconstruction") self.offlineReconstructButton.setEnabled(True) self.offlineReconstructButton.setChecked(False) if command.GetStatus() == command.CommandExpired: # volume reconstruction command timed out logging.fatal("Volume Reconstruction: Timeout while waiting for volume reconstruction result") return if command.GetStatus() != command.CommandSuccess: logging.debug("Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onVolumeReconstructedFinalize) def onVolumeReconstructedFinalize(self): applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(self.getOfflineVolumeRecNode()) def onScoutVolumeReconstructed(self, command, q): self.printCommandResponse(command,q) if command.GetStatus() == command.CommandExpired: logging.fatal("Scout Volume Reconstruction: Timeout while waiting for scout volume reconstruction result") return self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setText(" Scout Scan\n Start Recording") self.startStopScoutScanButton.setEnabled(True) if command.GetStatus() != command.CommandSuccess: logging.debug("Scout Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onScoutVolumeReconstructedFinalize) def onScoutVolumeReconstructedFinalize(self): # Create and initialize ROI after scout scan because low resolution scout scan is used to set # a smaller ROI for the live high resolution reconstruction self.roiNode = self.logic.onRoiInitialization(self.SCOUT_VOLUME_NODE_NAME, self.roiNode) self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) scoutScanVolumeNode = self.getScoutVolumeNode() applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(scoutScanVolumeNode) def onSnapshotAcquired(self, command, q): self.printCommandResponse(command,q) if not self.startStopLiveReconstructionButton.isChecked(): # live volume reconstruction is not active return self.executeCommandDelayed(self.onSnapshotAcquiredFinalize) def onSnapshotAcquiredFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode()) self.snapshotTimer.start(self.SNAPSHOT_INTERVAL*1000) def onVolumeLiveReconstructed(self, command, q): self.printCommandResponse(command,q) if command.GetStatus() == command.CommandExpired: logging.fatal("LIVE Volume Reconstruction: Failed to stop volume reconstruction") return if command.GetStatus() != command.CommandSuccess: logging.debug("LIVE Volume Reconstruction " + command.GetResponseMessage()) return self.executeCommandDelayed(self.getLiveVolumeRecNode) def onVolumeLiveReconstructedFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode())