Commit af1789aa authored by Daniel Brown's avatar Daniel Brown
Browse files

adding latest, not sure what i've changed in all of these files...

parent f396735c
......@@ -8,7 +8,7 @@ import exceptions
import pykat.gui.resources
import pykat
import inspect
import pykat.gui.graphics
from pykat.gui.graphics import *
from pykat.node_network import *
from PyQt4.QtGui import *
......@@ -40,9 +40,10 @@ class Component(object) :
n = self._kat.nodes.createNode(name)
if n == None:
raise exceptions.RuntimeError("getNode did not return a node for '{0}'".format(name))
raise exceptions.RuntimeError("createNode did not return a node for '{0}'".format(name))
else:
n.connect(self)
n.connect(self)
self.__nodes.append(n)
return n
......@@ -143,12 +144,11 @@ class mirror(Component):
def getQGraphicsItem(self):
if self._svgItem == None:
self._svgItem = ComponentQGraphicsItem(":/resources/mirror_flat.svg",self
self._svgItem = pykat.gui.graphics.ComponentQGraphicsItem(":/resources/mirror_flat.svg",self
,[(-4,15,self.node1),(14,15,self.node2)])
return self._svgItem
class space(Component):
def __init__(self,kat , name, node1, node2, L=0, n=1):
Component.__init__(self,name,kat)
......@@ -177,11 +177,25 @@ class space(Component):
def getQGraphicsItem(self):
if self._QItem == None:
self._QItem = SpaceQGraphicsItem(self)
self._QItem = pykat.gui.graphics.SpaceQGraphicsItem(self)
return self._QItem
def changeNode(self, node_old, node_new):
'''
Called when a space's node has been connected
to another components node
'''
node_new.connect(self)
node_old.disconnect(self)
if self.node1 == node_old:
self.node1 = node_new
if self.node2 == node_old:
self.node2 = node_new
class laser(Component):
def __init__(self,kat,name,node,P=1,f_offset=0,phase=0):
Component.__init__(self,name,kat)
......@@ -215,7 +229,7 @@ class laser(Component):
def getQGraphicsItem(self):
if self._svgItem == None:
self._svgItem = ComponentQGraphicsItem(":/resources/laser.svg",
self._svgItem = pykat.gui.graphics.ComponentQGraphicsItem(":/resources/laser.svg",
self,[(65,25,self.node)])
return self._svgItem
......
......@@ -11,8 +11,6 @@ from pykat.utils import *
from pykat.gui.graphics import *
from pykat.node_network import *
from PyQt4.QtGui import *
from PyQt4.Qt import *
class Detector(object) :
def __init__(self, name,node,kat):
......
......@@ -10,7 +10,6 @@ import subprocess
import tempfile
import numpy as np
import datetime
#from colorama import Fore
import pickle
from pykat.node_network import NodeNetwork
......@@ -85,7 +84,7 @@ class kat(object):
def noxaxis(self): return self.__noxaxis
@noxaxis.setter
def noxaxis(self,value): self.__noxaxis = bool(value)
def run(self, printout=1, printerr=1, save_output=False, save_kat=False,kat_name=None) :
"""
Runs the current simulation setup that has been built thus far.
......@@ -287,6 +286,44 @@ class kat(object):
def getComponents(self):
return self.__components.values()
def hasComponent(self, name):
return (name in self.__components)
def getNewComponentName(self,prefix):
'''
Returns a name for a component which hasn't already been added.
Returns [prefix] + number, where number is greater than 1. e.g.
if m1 exists getNewName('m') will return 'm2'
'''
n = 1
name = "{0}{1}".format(prefix, n)
while name in self.__components:
n += 1
name = "{0}{1}".format(prefix,n)
return name
def getNewNodeNames(self,prefix,N=1):
'''
Returns a list of names for N number of nodes which haven't already been added.
Returns [prefix] + number, where number is greater than 1. e.g.
if m1 exists getNewName('m') will return 'm2'
'''
rtn = []
n = 1
for M in range(1,N+1):
name = "{0}{1}".format(prefix, n)
while name in self.nodes.getNodes() or (name in rtn):
n += 1
name = "{0}{1}".format(prefix,n)
rtn.append(name)
return rtn
def __add_detector(self, det):
......
......@@ -8,21 +8,37 @@ Created on Fri Feb 01 09:13:03 2013
from PyQt4.QtGui import *
from PyQt4.Qt import *
import pykat.components
import exceptions
nsize = 8
class NodeQGraphicItem(QGraphicsRectItem):
def __init__(self, node, x,y, *args, **kwargs):
QGraphicsRectItem.__init__(self, *args, **kwargs)
self.__node = node
self.setPos(x,y)
item = QGraphicsTextItem(node.name, self)
rect = item.boundingRect()
item.setPos(-0.5*rect.width(), 0)
self.setAcceptHoverEvents(True)
self.marked = False
@property
def node(self): return self.__node
def refresh(self):
if not self.marked:
if self.__node.isConnected():
self.setBrush(QBrush(Qt.red))
else:
self.setBrush(QBrush(Qt.green))
else:
self.setBrush(QBrush(Qt.yellow))
class SpaceQGraphicsItem(QGraphicsLineItem):
def __init__(self, spaceComponent):
QGraphicsLineItem.__init__(self)
......@@ -36,18 +52,21 @@ class SpaceQGraphicsItem(QGraphicsLineItem):
self.refresh()
@property
def space(self): return self.__space
def refresh(self):
nodes = self.__space.getNodes()
if self.__n1 == None:
self.__n1 = NodeQGraphicItem(nodes[0],0,0,-nsize/2,-nsize/2,nsize,nsize,self)
self.__n1.setPen(QPen(Qt.black))
conn = nodes[0].amIConnected(self.__space)
if conn[0]:
if conn[1] != None:
self.__n1.setVisible(False)
if self.__n1 is not None:
# i.e. we have a node graphic item but now it is connected to something
self.__n1.scene().removeItem(self.__n2)
self.__n1 = None
# now check if a connected component was returned too
if conn[1] != None:
# so this node should be attached to something
......@@ -57,20 +76,26 @@ class SpaceQGraphicsItem(QGraphicsLineItem):
x1 = itm.x() + itm.nodedx[conn[2]][0]
y1 = itm.y() + itm.nodedx[conn[2]][1]
else:
if self.__n1 == None:
self.__n1 = NodeQGraphicItem(nodes[0],0,0,-nsize/2,-nsize/2,nsize,nsize,self)
self.__n1.setPen(QPen(Qt.black,1))
self.__n1.setVisible(True)
self.__n1.setBrush(QBrush(Qt.red))
x1 = 0
y1 = 0
if self.__n2 == None:
self.__n2 = NodeQGraphicItem(nodes[1],0,0,-nsize/2,-nsize/2,nsize,nsize,self)
self.__n2.setPen(QPen(Qt.black))
self.__n1.setBrush(QBrush(Qt.green))
p = self.__n1.pos()
x1 = self.x()+p.x()
y1 = self.y()+p.y()
conn = nodes[1].amIConnected(self.__space)
if conn[0]:
if conn[1] != None:
self.__n2.setVisible(False)
if self.__n2 is not None:
# i.e. we have a node graphic item but now it is connected to something
self.__n2.scene().removeItem(self.__n2)
self.__n2 = None
# now check if a connected component was returned too
if conn[1] != None:
# so this node should be attached to something
......@@ -80,32 +105,40 @@ class SpaceQGraphicsItem(QGraphicsLineItem):
x2 = itm.x() + itm.nodedx[conn[2]][0]
y2 = itm.y() + itm.nodedx[conn[2]][1]
else:
if self.__n2 == None:
self.__n2 = NodeQGraphicItem(nodes[1],0,0,-nsize/2,-nsize/2,nsize,nsize,self)
self.__n2.setPen(QPen(Qt.black,1))
self.__n2.setVisible(True)
self.__n2.setBrush(QBrush(Qt.red))
self.__n2.setBrush(QBrush(Qt.green))
p = self.__n2.pos()
x2 = -p.x()
y2 = -p.y()
x2 = self.x()+p.x()
y2 = self.y()+p.y()
# convert x1,y1,x2 and y2 into the local coordinates of the
# space object
p = QPointF((x1-x2)*0.5,(y1-y2)*0.5)
self.setPos(x1 - p.x(), y1 - p.y())
# if the nodes are visible then reposition them in the
# component reference frame
if self.__n1.isVisible():
if self.__n1 is not None and self.__n1.isVisible():
self.__n1.setPos(QPointF(p.x(),p.y()))
self.__n1.refresh()
if self.__n2.isVisible():
if self.__n2 is not None and self.__n2.isVisible():
self.__n2.setPos(QPointF(p.x()+x2-x1, p.y()+y2-y1))
self.__n2.refresh()
self.setLine(p.x(), p.y(), p.x()+x2-x1, p.y()+y2-y1)
self.setPen(QPen(Qt.red, 3))
class ComponentQGraphicsItem(QGraphicsSvgItem):
def __init__(self, svgfile, component, nodes):
QGraphicsSvgItem.__init__(self,svgfile)
self.__nodeGraphics = []
self.__component = component
# this signals the itemChange() method when this item is moved
# used for refreshing the spaces between components
......@@ -116,11 +149,25 @@ class ComponentQGraphicsItem(QGraphicsSvgItem):
rect = item.boundingRect()
item.setPos(-0.5*rect.width(),40-0.5*rect.height())
self.setAcceptsHoverEvents(True)
for n in nodes:
self.nodedx.append([n[0],n[1]])
node = NodeQGraphicItem(n[2],n[0],n[1],-nsize/2,-nsize/2,nsize,nsize,self)
node.setBrush(QBrush(Qt.red))
node = n[2].getQGraphicsItem(n[0],n[1],nsize,self)
node.setPen(QPen(Qt.black))
node.refresh()
self.__nodeGraphics.append(node)
self.refresh()
self.installEventFilter(self)
self.setHandlesChildEvents(True)
@property
def component(self): return self.__component
def refresh(self):
for n in self.__nodeGraphics:
n.refresh()
def itemChange(self, change, value):
# if the item move then update any spaces
......
......@@ -13,13 +13,15 @@ from PyQt4.Qt import *
from PyQt4.QtGui import QCursor, QGraphicsItem
from pykat.gui.graphics import *
import qt_gui
import functools
def openGUI(kat):
app = QtGui.QApplication([""])
pykatgui = pyKatGUI(kat)
pykatgui.main()
app.exec_()
class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow):
def __init__(self, kat,parent=None):
super(pyKatGUI, self).__init__(parent)
......@@ -28,6 +30,9 @@ class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow):
self.graphicsView = pyKatGraphicsView(self.centralwidget)
self.graphicsView.setObjectName("graphicsView")
self.graphicsView.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
self.graphicsView.viewport().setMouseTracking(True)
self.setMouseTracking(True)
self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1)
# create a new scene
......@@ -43,7 +48,7 @@ class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow):
self.actionExport_to_SVG.triggered.connect(lambda: self.exportToSVG())
self.actionClose.triggered.connect(lambda: self.close)
self._kat = kat
self.kat = kat
def main(self):
self.show()
......@@ -55,23 +60,32 @@ class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow):
def addComponentsToScene(self):
for c in self._kat.getComponents():
itm = c.getQGraphicsItem()
if itm != None:
itm.setPos(0,0)
# uncomment this line to stop background bitmap caching of
# svg rendering. Important to make sure when rendering to
# svg file that it is in a vector format. Gradients however
# don't work...
itm.setCacheMode(QGraphicsItem.NoCache)
self.__scene.addItem(itm)
for c in self.kat.getComponents():
self.addComponentToScene(c)
def addComponentToScene(self,c,x=0,y=0):
itm = c.getQGraphicsItem()
if itm != None:
itm.setPos(x,y)
# uncomment this line to stop background bitmap caching of
# svg rendering. Important to make sure when rendering to
# svg file that it is in a vector format. Gradients however
# don't work...
itm.refresh()
itm.setCacheMode(QGraphicsItem.NoCache)
self.__scene.addItem(itm)
def exportToSVG(self):
self.statusbar.showMessage("Saving to 'output.svg'...")
svg = QSvgGenerator()
svg.setFileName("./output.svg")
filename = QtGui.QFileDialog.getSaveFileNameAndFilter(self,'Save SVG File',filter=".svg")
if filename == None:
return None
svg.setFileName(filename)
svg.setSize(QSize(self.__scene.width(), self.__scene.height()))
svg.setViewBox(QRect(0,0,self.__scene.width(), self.__scene.height()))
svg.setTitle("pyKat output of example.kat")
......@@ -81,6 +95,13 @@ class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow):
pntr.end()
self.statusbar.showMessage("Complete: Saved to 'output.svg'")
def addMirror(self, x,y):
name = self.kat.getNewComponentName('m')
n = self.kat.getNewNodeNames('n',2)
m = pykat.components.mirror(self.kat,name,n[0],n[1])
self.addComponentToScene(m,x,y)
class pyKatGraphicsScene(QGraphicsScene):
def drawBackground(self, painter, rect):
......@@ -115,21 +136,31 @@ class pyKatGraphicsView(QGraphicsView):
self.__selected_item = None
self.__prev_pt = None
self.setMouseTracking(True)
self.__itemHover = None
self.__marked = None
def contextMenuEvent(self, ev):
pt = self.mapToScene(ev.pos())
gui = self.parentWidget().parent() # get the main gui window
menu = QMenu(self)
addmenu = menu.addMenu("Add...")
addmenu.addAction("Mirror")
action = addmenu.addAction("Mirror")
action.triggered.connect(functools.partial(gui.addMirror,pt.x(),pt.y()))
addmenu.addAction("Laser")
addmenu.addAction("Beamsplitter")
addmenu.addAction("Photodiode")
item = self.itemAt(pt.x(),pt.y())
item = self.scene().itemAt(pt.x(),pt.y())
if item != None :
if isinstance(item, Component):
print pt.x(),pt.y(),item
if item is not None :
if isinstance(item, ComponentQGraphicsItem):
menu.addSeparator()
menu.addAction("Edit")
menu.addAction("Delete")
......@@ -157,22 +188,52 @@ class pyKatGraphicsView(QGraphicsView):
self.__selected_item = item
self.__prev_pt = pt
elif isinstance(item, NodeQGraphicItem):
if item == None:
self.__selected_item = None
self.__prev_pt = None
else:
if isinstance(item.parentItem(),SpaceQGraphicsItem):
self.__selected_item = item
self.__prev_pt = pt
if isinstance(item.parentItem(),SpaceQGraphicsItem):
self.__selected_item = item
self.__prev_pt = pt
elif isinstance(item.parentItem(),ComponentQGraphicsItem):
self.__selected_item = item.parentItem()
self.__prev_pt = pt
if self.__selected_item is not None:
self.setCursor(QCursor(Qt.ClosedHandCursor))
def mouseReleaseEvent(self, ev):
# if we have dragged a node and marked another to connect it too
if self.__selected_item is not None and isinstance(self.__selected_item, NodeQGraphicItem) and self.__marked is not None:
# node attached to space which needs to be removed
node_s = self.__selected_item.node
# get the selected node which must be attached to a space, which is the nodes parent
# and then get the space component from it
qspace = self.__selected_item.parentItem()
space = qspace.space
# marked node, then get the parent object and component
node_c = self.__marked.node
qcomp = self.__marked.parentItem()
# connect space of node dragged to the component node
space.changeNode(node_s,node_c)
node_s.remove()
# then refresh the graphical items
qspace.refresh()
qcomp.refresh()
if self.__marked is not None:
self.__marked.marked = False
self.__marked.refresh()
self.__marked = None
self.__selected_item = None
self.setCursor(QCursor(Qt.ArrowCursor))
pass
def mouseMoveEvent(self, ev):
if self.__selected_item != None:
self.setCursor(QCursor(Qt.ClosedHandCursor))
item = self.__selected_item
#pt_ = self.__prev_pt
......@@ -183,9 +244,60 @@ class pyKatGraphicsView(QGraphicsView):
# then snap to some integer value
snap = 10.0
item.setPos(int(round(pt.x()/snap)*snap),int(round(pt.y()/snap)*snap))
# if we are moving a node, it must be attached to a space
# component otherwise we shouldn't be here
if isinstance(item, NodeQGraphicItem) and isinstance(item.parentItem(), SpaceQGraphicsItem):
space = item.parentItem()
item.setPos(pt.x()-space.x(),pt.y()-space.y())
space.refresh()
# now check to see if any other connectable nodes are within reach
# and if so hightlight them
select_size = 20
rect = QRectF(pt.x()-select_size/2,pt.y()-select_size/2,select_size,select_size)
itms = item.scene().items(rect)
# remove the node we are dragging
if item in itms:
itms.remove(item)
if self.__marked is not None:
self.__marked.marked = False
self.__marked.refresh()
self.__marked = None
if len(itms) > 0:
for i in itms:
if isinstance(i,NodeQGraphicItem) and i != item:
i.marked = True
i.refresh()
self.__marked = i
break
else:
item.setPos(int(round(pt.x()/snap)*snap),int(round(pt.y()/snap)*snap))
self.__prev_pt = pt
return
else:
item = self.itemAt(ev.pos())
if isinstance(item, (NodeQGraphicItem, ComponentQGraphicsItem)) or item is None:
#if item is not None or self.__itemHover is not None:
if isinstance(item, ComponentQGraphicsItem):
self.__itemHover = item
elif isinstance(item,NodeQGraphicItem) and (not item.node.isConnected()):
self.__itemHover = item
else:
self.__itemHover = None
if self.__itemHover is not None:
self.setCursor(QCursor(Qt.OpenHandCursor))
else:
self.setCursor(QCursor(Qt.ArrowCursor))
\ No newline at end of file
......@@ -5,6 +5,7 @@ Created on Sun Jan 27 10:02:41 2013
@author: Daniel
"""
import exceptions
import pykat.gui.graphics
from pykat.components import Component
from pykat.detectors import Detector
......@@ -18,17 +19,36 @@ class NodeNetwork(object):
return DumpNode()
if node_name in self._nodes:
n = self._nodes[node_name]
return n
# then this node already exists
return self._nodes[node_name]
else:
n = Node(node_name)
n = Node(node_name,self)
self._nodes[node_name] = n
return n
def removeNode(self, node):
if not isinstance(node,Node):
raise exceptions.ValueError("node argument is not of type Node")
if node not in self._nodes:
raise exceptions.RuntimeError("Trying to remove node {0} when it has not been added".format(node.name))
C = node.getComponents()
if C[0][0] is not None or C[0][1] is not None:
raise exceptions.RuntimeError("Cannot remove a node which is attached to components still")
if len(C[1]) > 0:
raise exceptions.RuntimeError("Cannot remove a node which is attached to detectors still")