def move_thread(self, skeleton, x, y, shift, ctrl): debug.subthreadTest() self.mouselock.acquire() try: if self.movingnode is not None: self.moving = 1 homogeneity = 0.0 shapeenergy = 0.0 point = self.getPoint(x,y) # It's generally forbidden to call node.moveTo instead of # skeleton.moveNodeTo, but since we're going to move the # node back (see up(), below), it's ok. if point is not None: self.movingnode.moveTo(point) if self.movingnode.illegal(): homogtext = "---" shapetext = "---" labeltext = "Illegal node position!" else: for element in self.nbrelements: # Evaluating homogeneity and shape energy is # safe, because the Skeleton's read lock was # acquired when the mouse went down. homogeneity += element.homogeneity(skeleton.MS) shapeenergy += element.energyShape() homogtext = "%-11.4g" % (homogeneity-self.homogeneity0) shapetext = "%-11.4g" % (shapeenergy-self.shapeenergy0) labeltext = "" mainthread.runBlock(self.move_info, (point, homogtext, shapetext, labeltext)) gtklogger.checkpoint("Move Node toolbox move event") finally: self.mouselock.release()
def updateAAInfo(self): # must be called on subthread debug.subthreadTest() ms = self.getCurrentMS() if ms is not None: activearea = ms.getObject().activearea activearea.begin_reading() try: aasize = activearea.size() mssize = ms.getObject().sizeInPixels() if config.dimension()==2: mpxls = mssize[0] * mssize[1] pixstring="pixels" elif config.dimension()==3: mpxls = mssize[0] * mssize[1] * mssize[2] pixstring="voxels" apxls = mpxls - aasize if ms.getObject().activearea.getOverride(): msg = "OVERRIDE: all %d %s are active" % (mpxls, pixstring) else: msg = "%d of %d %s are active" % (apxls, mpxls, pixstring) finally: activearea.end_reading() else: msg = "No Microstructure selected" mainthread.runBlock(self.aainfo.set_text, (msg,)) gtklogger.checkpoint("active area status updated")
def rebuild_grouplist(self): debug.subthreadTest() mscontext = self.currentMScontext() msg = None if mscontext is not None: mscontext.begin_reading() ms = mscontext.getObject() try: if ms.nGroups() > 0: grpnames = ms.groupNames() dispnames = grpnames[:] for i in range(len(grpnames)): grpname = grpnames[i] grp = ms.findGroup(grpname) dispnames[i] += " (%d %s%s" % (len(grp), pixstring, "s"*(len(grp)!=1)) if grp.is_meshable(): dispnames[i] += ", meshable)" else: dispnames[i] += ")" else: msg = 'No %s groups defined!'%pixstring finally: mscontext.end_reading() else: # ms is None msg = 'No Microstructure defined!' if msg: mainthread.runBlock(self.set_group_message, (msg,)) else: mainthread.runBlock(self.set_group_list, (grpnames, dispnames)) self.setMeshableButton()
def __init__(self, name, gfxmgr, clone=0): debug.subthreadTest() self.gfxlock = lock.Lock() mainthread.runBlock(self.preinitialize, (name, gfxmgr, clone)) self.newCanvas() ghostgfxwindow.GhostGfxWindow.__init__(self, name, gfxmgr, clone=clone) mainthread.runBlock(self.postinitialize, (name, gfxmgr, clone))
def setInfo_subthread(self): debug.subthreadTest() source = self.getSelectionSource() if source is not None: source.begin_reading() try: selection = source.getSelectionContext( **self.toolbox.extrakwargs) ## Selection can be None because an Image must be created ## before a Microstructure, but the selection source for ## an Image is its Microstructure. if selection is not None: selection.begin_reading() try: sizetextdata = ` selection.size() ` finally: selection.end_reading() else: sizetextdata = '0' finally: source.end_reading() else: sizetextdata = self.toolbox.emptyMessage() mainthread.runBlock(self._write_text, (sizetextdata, ))
def __init__(self, name, gfxmgr, clone=0): debug.subthreadTest() # self.name is also assigned by GhostGfxWindow, but it's # helpful for debugging for it to be assigned as soon as # possible in all execution paths. self.name = name self.gfxlock = lock.Lock() self.acquireGfxLock() # This whole initialization sequence is complicated. The # reason is that the order of operations is important -- the # ghostgfxwindow makes function calls which need to be # redefined in the GUI before they occur -- and there is a # requirement that the main thread never be locked. # Furthermore, the ghostgfxwindow has to create the menu # before the SubWindow init gets called. It could probably be # rationalized, but it's not urgent. # preinitialize and postinitialize are defined in gfxwindow.py # for 2D and gfxwindow3d.py for 3D. mainthread.runBlock(self.preinitialize, (name, gfxmgr, clone)) # GhostGfxWindow.__init__ creates the canvas, among other things. ghostgfxwindow.GhostGfxWindow.__init__(self, name, gfxmgr, clone=clone) mainthread.runBlock(self.postinitialize, (name, gfxmgr, clone)) self.releaseGfxLock() self.switchboardCallbacks.append( switchboard.requestCallback("shutdown", self.shutdownCB))
def updateSomething(self, container): debug.subthreadTest() segment = container.object skeleton = container.skeleton container.context.begin_reading() try: sindex = `segment.getIndex()` self.updateNodeList(self.nodes, list(segment.get_nodes())) self.syncPeeker(self.nodes, "Node") self.updateElementList(self.elem, segment.getElements()) self.syncPeeker(self.elem, "Element") length = `segment.length()` homogval = segment.homogeneity(skeleton.MS) if 0.9999 < homogval < 1.0: homog = "1 - (%e)" % (1.0-homogval) else: homog = `homogval` self.updateGroup(segment) bdynames = ','.join( segment.boundaryNames(container.context.getObject())) # mat = segment.material(container.context) # if mat: # matname = mat.name() # else: # matname = "<No material>" finally: container.context.end_reading() mainthread.runBlock(self.updateSomething_thread, (sindex, length, homog, bdynames, #matname ))
def setInfo_subthread(self): debug.subthreadTest() source = self.getSource() if source is not None: source.begin_reading() try: selection = source.getSelectionContext( **self.toolbox.extrakwargs) ## Selection can be None because an Image must be created ## before a Microstructure, but the selection source for ## an Image is its Microstructure. if selection is not None: selection.begin_reading() try: sizetextdata = `selection.size()` finally: selection.end_reading() else: sizetextdata = '0' finally: source.end_reading() else: sizetextdata = self.toolbox.emptyMessage() mainthread.runBlock(self._write_text, (sizetextdata,)) gtklogger.checkpoint("selection info updated")
def kbmove_subthread(self, skelctxt, point): debug.subthreadTest() # In order to prohibit illegal node moves, we have to actually # move the node, check it, and move the node back. If it's # ok, then we call the menu item, which makes the permanent # move. skelctxt.begin_writing() skeleton = skelctxt.getObject() try: # Compute initial energy of neighboring elements neighbors = self.node().getElements() homogeneity0 = 0.0 shapeenergy0 = 0.0 for element in neighbors: if element.illegal(): continue homogeneity0 += \ element.homogeneity(skeleton.getMicrostructure()) shapeenergy0 += element.energyShape() # Energy after node move self.node().moveTo(point.asTuple()) illegal = False homogeneity = 0.0 shapeenergy = 0.0 for element in neighbors: if not illegal: if element.illegal(): illegal = True else: homogeneity += \ element.homogeneity(skeleton.getMicrostructure()) shapeenergy += element.energyShape() self.node().moveBack() finally: skelctxt.end_writing() if illegal: if self.allow_illegal.get_active(): mainthread.runBlock(self.move_info, (point, "---", "---", "")) self.toolbox.menu.MoveNode(node=self.node().uiIdentifier(), destination=point) else: # Illegal move not allowed. Reset the x and y text so # that the user can try again. mainthread.runBlock( self.move_info, (self.node().position(), "---", "---", "")) else: mainthread.runBlock(self.move_info, (point, "%-11.4g" % (homogeneity - homogeneity0), "%-11.4g" % (shapeenergy - shapeenergy0), "")) self.toolbox.menu.MoveNode(node=self.node().uiIdentifier(), destination=point)
def update(self, indx): debug.subthreadTest() skelctxt = self.getContext() if not skelctxt: return skeleton = skelctxt.getObject() if indx is not None and 0 <= indx < skeleton.nelements(): skelctxt.begin_reading() try: microstructure = skeleton.getMicrostructure() # If the user typed the index, instead of clicking on # an element, it could be invalid. if indx < 0 or indx >= skeleton.nelements(): return element = skeleton.getElement(indx) assert element is not None if config.dimension() == 3: self.updateFaceList(self.faces, skeleton.getElementFaces(element)) self.updateSegmentList(self.segs, skeleton.getElementSegments(element)) self.updateNodeList(self.nodes, element.getNodes(), element) eid = ` indx ` etype = skeleton.getElementType(element.getIndex()) if config.dimension() == 3: earea = "%g" % element.volume() elif config.dimension() == 2: earea = "%g" % element.area() if not element.illegal(): domCat = element.dominantPixel(skeleton) hom = "%f" % element.homogeneity(skeleton) eshape = "%f" % element.energyShape() mat = element.material(skeleton) egrps = ", ".join(element.groupNames()) if mat: matname = mat.name() else: matname = "<No material>" else: # illegal element domCat = "Not Computed" egrps = "???" hom = "???" eshape = "???" matname = "???" mainthread.runBlock(self.update_thread, (etype, eid, earea, ` domCat `, egrps, hom, eshape, matname)) return finally: skelctxt.end_reading() # end if indx is not None # Nothing to display -- no element or no indx. mainthread.runBlock(self.update_thread, ("", "", "", "", "", "", "", "")) mainthread.runBlock(self.clearObjLists)
def updateSomething(self, container): debug.subthreadTest() node = container.object skeleton = container.skeleton container.context.begin_reading() try: nindex = `node.getIndex()` if config.dimension() == 2: npos = "(%s, %s)" % (node.position().x, node.position().y) elif config.dimension() == 3: npos = "(%s, %s, %s)" % (node.position().x, node.position().y, node.position().z) if config.dimension() == 2: if node.movable_x() and node.movable_y(): nmob = "free" elif node.movable_x() and not node.movable_y(): nmob = "x only" elif not node.movable_x() and node.movable_y(): nmob = "y only" elif node.pinned(): nmob = "pinned" else: nmob = "fixed" elif config.dimension() == 3: if node.movable_x() and node.movable_y() and node.movable_z(): nmob = "free" elif node.movable_x() and node.movable_y() and not node.movable_z(): nmob = "x and y only" elif node.movable_x() and not node.movable_y() and node.movable_z(): nmob = "x and z only" elif not node.movable_x() and node.movable_y() and node.movable_z(): nmob = "y and z only" elif node.movable_x() and not node.movable_y() and not node.movable_z(): nmob = "x only" elif not node.movable_x() and node.movable_y() and not node.movable_z(): nmob = "y only" elif not node.movable_x() and not node.movable_y() and node.movable_z(): nmob = "z only" elif node.pinned(): nmob = "pinned" else: nmob = "fixed" self.updateElementList(self.elem, node.neighborElements()) self.syncPeeker(self.elem, "Element") self.updateGroup(node) bdys = [] for key, bdy in skeleton.pointboundaries.items(): if node in bdy.nodes: bdys.append(key) bdynames = string.join(bdys, ", ") finally: container.context.end_reading() mainthread.runBlock(self.updateSomething_thread, (nindex, npos, nmob, bdynames))
def kbmove_subthread(self, skelctxt, point): debug.subthreadTest() # In order to prohibit illegal node moves, we have to actually # move the node, check it, and move the node back. If it's # ok, then we call the menu item, which makes the permanent # move. skelctxt.begin_writing() skeleton = skelctxt.getObject() try: # Compute initial energy of neighboring elements neighbors = self.node().neighborElements() homogeneity0 = 0.0 shapeenergy0 = 0.0 for element in neighbors: if element.illegal(): continue homogeneity0 += element.homogeneity(skeleton.MS) shapeenergy0 += element.energyShape() # Energy after node move self.node().moveTo(point) illegal = False homogeneity = 0.0 shapeenergy = 0.0 for element in neighbors: if not illegal: if element.illegal(): illegal = True else: homogeneity += element.homogeneity(skeleton.MS) shapeenergy += element.energyShape() self.node().moveBack() finally: skelctxt.end_writing() if illegal: if self.allow_illegal.get_active(): mainthread.runBlock(self.move_info, (point, "---", "---", "")) self.toolbox.menu.MoveNode(origin=self.node().position(), destination=point) else: # Illegal move not allowed. Reset the x and y text so # that the user can try again. mainthread.runBlock( self.move_info, (self.node().position(), "---", "---", "")) else: mainthread.runBlock(self.move_info, (point, "%-11.4g" % (homogeneity - homogeneity0), "%-11.4g" % (shapeenergy - shapeenergy0), "")) self.toolbox.menu.MoveNode(origin=self.node().position(), destination=point)
def update(self, indx): debug.subthreadTest() skelctxt = self.getContext() skeleton = skelctxt.getObject() if indx is not None and 0 <= indx < skeleton.nnodes(): skelctxt.begin_reading() try: node = skeleton.getNode(indx) assert node is not None self.updateElementList(self.elem, node.getElements()) self.updateSegmentList(self.segs, skeleton.getNodeSegments(node)) if config.dimension() == 3: self.updateFaceList(self.faces, skeleton.getNodeFaces(node)) nuid = ` indx ` npos = genericinfoGUI.posString(node.position()) movabilities = [ node.movable_x(), node.movable_y(), node.movable_z() ] nmobile = sum(movabilities) if nmobile == config.dimension(): mobstr = "free" elif nmobile == 0: if node.pinned(): mobstr = "pinned" else: mobstr = "fixed" else: # nmobile = 1 or 2 # mobstr is something like "x only" or "x and y only" m = [ "xyz"[i] for i in range(config.dimension()) if movabilities[i] ] mobstr = " and ".join(m) + " only" bdynames = [ nm for (nm, bdy) in skelctxt.pointboundaries.items() if bdy.current_boundary().hasNode(node) ] grpnames = node.groupNames() mainthread.runBlock(self.update_thread, (nuid, npos, mobstr, ", ".join(grpnames), ", ".join(bdynames))) return finally: skelctxt.end_reading() # end if indx is not None # Nothing to display mainthread.runBlock(self.update_thread, ("", "", "", "", "")) mainthread.runBlock(self.clearObjLists)
def update(self, skelname, locked): debug.subthreadTest() # Most pages are updated when their info changes even if # they're not currently visible. Because the Skeleton Page # displays the homogeneity which may be slow to compute, it's # not updated unless it's currently visible. if not self.is_current(): # not displayed in the GUI self.postponed_update = True return self.postponed_update = False skelpath = labeltree.makePath(skelname) if skelpath: skelctxt = skeletoncontext.skeletonContexts[skelpath] skel = skelctxt.getObject() ## Updating the state info is done in two stages, because ## the homogeneity index can take a while to compute. In ## the first stage, the quick stuff is computed, and the ## homogeneity index is displayed as '????'. if not locked: skelctxt.begin_reading() try: ms_name = skel.MS.name() nNodes = len(skel.nodes) nElements = len(skel.elements) illegalcount = skel.getIllegalCount() shapecounts = skel.countShapes() lr_periodicity = skel.left_right_periodicity tb_periodicity = skel.top_bottom_periodicity if config.dimension() == 3: fb_periodicity = skel.front_back_periodicity else: fb_periodicity = False finally: if not locked: skelctxt.end_reading() mainthread.runBlock(self.writeInfoBuffer, (nNodes, nElements, illegalcount, shapecounts, None, lr_periodicity, tb_periodicity, fb_periodicity)) # Homogeneity Index stuff. if not locked: skelctxt.begin_writing() try: homogIndex = skel.getHomogeneityIndex() finally: if not locked: skelctxt.end_writing() mainthread.runBlock(self.writeInfoBuffer, (nNodes, nElements, illegalcount, shapecounts, homogIndex, lr_periodicity, tb_periodicity, fb_periodicity)) else: mainthread.runBlock(self.deleteInfoBuffer) self.sensitize()
def newCanvas(self): # Recreate the canvas object. # It's important to acquire and release the lock in the # subthread, before calling mainthread.runBlock, to avoid # deadlocks. debug.subthreadTest() self.acquireGfxLock() try: mainthread.runBlock(self.newCanvas_thread) finally: self.releaseGfxLock()
def selectionSize(self): debug.subthreadTest() skelcontext = mainthread.runBlock(self.getCurrentSkeleton) if skelcontext is not None: skelcontext.begin_reading() try: if not skelcontext.defunct(): return self.activemode.getSelectionContext(skelcontext).size() finally: skelcontext.end_reading() return 0
def updateSomething(self, container): debug.subthreadTest() element = container.object skeleton = container.skeleton container.context.begin_reading() try: etype = ` element.type() ` [1:-1] # strip quotes eindex = ` element.getIndex() ` if config.dimension() == 2: self.updateNodeListAngle(self.nodes, element) elif config.dimension() == 3: self.updateNodeList(self.nodes, element.nodes) # Clear the selection in the list of nodes if there's # nothing in the peeker. self.syncPeeker(self.nodes, "Node") esegs = element.getSegments(skeleton) self.updateSegmentList(self.segs, esegs) # Clear the selection in the list of segments if there's # nothing in the peeker. self.syncPeeker(self.segs, "Segment") if config.dimension() == 2: earea = "%s" % element.area() elif config.dimension() == 3: earea = "%s" % element.volume() if not element.illegal(): domCat = element.dominantPixel(skeleton.MS) repPix = skeleton.MS.getRepresentativePixel(domCat) pixGrp = pixelgroup.pixelGroupNames(skeleton.MS, repPix) pixgrps = string.join(pixGrp, ", ") ehom = "%f" % element.homogeneity(skeleton.MS) eshape = "%f" % element.energyShape() mat = element.material(container.context) if mat: matname = mat.name() else: matname = "<No material>" else: # illegal element pixgrps = "???" ehom = "???" eshape = "???" matname = "???" self.updateGroup(element) finally: container.context.end_reading() mainthread.runBlock( self.updateSomething_thread, (etype, eindex, earea, pixgrps, ehom, eshape, matname))
def updateSomething(self, container): debug.subthreadTest() element = container.object skeleton = container.skeleton container.context.begin_reading() try: etype = `element.type()`[1:-1] # strip quotes eindex = `element.getIndex()` if config.dimension() == 2: self.updateNodeListAngle(self.nodes, element) elif config.dimension() == 3: self.updateNodeList(self.nodes, element.nodes) # Clear the selection in the list of nodes if there's # nothing in the peeker. self.syncPeeker(self.nodes, "Node") esegs = element.getSegments(skeleton) self.updateSegmentList(self.segs, esegs) # Clear the selection in the list of segments if there's # nothing in the peeker. self.syncPeeker(self.segs, "Segment") if config.dimension() == 2: earea = "%s" % element.area() elif config.dimension() == 3: earea = "%s" % element.volume() if not element.illegal(): domCat = element.dominantPixel(skeleton.MS) repPix = skeleton.MS.getRepresentativePixel(domCat) pixGrp = pixelgroup.pixelGroupNames(skeleton.MS, repPix) pixgrps = string.join(pixGrp, ", ") ehom = "%f" % element.homogeneity(skeleton.MS) eshape = "%f" % element.energyShape() mat = element.material(container.context) if mat: matname = mat.name() else: matname = "<No material>" else: # illegal element pixgrps = "???" ehom = "???" eshape = "???" matname = "???" self.updateGroup(element) finally: container.context.end_reading() mainthread.runBlock(self.updateSomething_thread, (etype, eindex, earea, pixgrps, ehom, eshape, matname))
def group_added(self, skelcontext, gset, name): debug.subthreadTest() gset = mainthread.runBlock(self.check_skel_and_gset, (skelcontext, gset)) if gset: skelcontext.begin_reading() try: names = gset.allGroups() finally: skelcontext.end_reading() self.update_grouplist(names, map(gset.displayString, names)) mainthread.runBlock(self.grouplist.set_selection, (name, )) self.sensitize_subthread()
def setMeshableButton(self): debug.subthreadTest() mscontext = self.currentMScontext() if mscontext: mscontext.begin_reading() try: grp = self.currentGroup() meshable = grp is not None and grp.is_meshable() finally: mscontext.end_reading() else: meshable = False mainthread.runBlock(self.setMeshableButton_thread, (meshable,))
def groupset_changed(self, skelcontext, gset): debug.subthreadTest() gset = mainthread.runBlock(self.check_skel_and_gset, (skelcontext,gset)) if gset: skelcontext.begin_reading() try: names = gset.allGroups() finally: skelcontext.end_reading() self.update_grouplist(names, map(gset.displayString, names)) # Must sensitize -- if the current group has become empty, the # "clear" button's sensitivity will have changed. self.sensitize_subthread() switchboard.notify("redraw skeletongroups", skelcontext)
def down_subthread(self, x, y, shift, ctrl): debug.subthreadTest() self.mouselock.acquire() try: self.downed = 1 point = primitives.Point(x,y) mainthread.runBlock(self.move_info, (point, "0", "0", '')) skel = mainthread.runBlock(self.getSkeleton) skelctxt = mainthread.runBlock(self.getSkeletonContext) reserved = skel is not None and skelctxt.query_reservation() if skel is not None and not reserved and point is not None: self.movingnode = skel.nearestNode(point) self.nodeChanged() #Store this point for use by the up callback's call to MoveNode self.downpt=point if self.movingnode.pinned(): self.nodeChanged() # TODO: Is this required? Redundant? self.movingnode = None else: # Mouse-down events are only accepted in Mouse mode, # so the end_reading() call corresponding to this # begin_reading() is in the "Mouse" section of the # up() callback. skelctxt.begin_reading() self.nbrnodes = skel.getNeighborNodes(self.movingnode) # self.movingnode.aperiodicNeighborNodes(skel) self.nbrelements = self.movingnode.getElements() self.startpt = tuple(self.movingnode.position()) # Get initial values of homogeneity and shape energy self.homogeneity0 = 0.0 self.shapeenergy0 = 0.0 for element in self.nbrelements: if not element.illegal(): self.homogeneity0 += element.homogeneity( skel.getMicrostructure()) self.shapeenergy0 += element.energyShape() # Create rubberband points = [] for n in self.nbrnodes: pos = n.position() points.append(primitives.Point(pos[0],pos[1],pos[2])) # points = [n.position() for n in self.nbrnodes] rb = mainthread.runBlock(rubberband.SpiderRubberBand, (points,)) mainthread.runBlock( self.gfxwindow().setRubberband, (rb,) ) gtklogger.checkpoint("Move Node toolbox down event") finally: self.mouselock.release()
def group_resized(self, skelcontext, gset): debug.subthreadTest() gset = mainthread.runBlock(self.check_skel_and_gset, (skelcontext,gset)) if gset: skelcontext.begin_reading() try: names = gset.allGroups() finally: skelcontext.end_reading() self.update_grouplist(names, map(gset.displayString, names)) # Must sensitize -- if the resize was to or away from size 0, # the clear button needs updating. # mainthread.runBlock(self.sensitize) self.sensitize_subthread()
def updateData(self): debug.subthreadTest() self.updateLock.acquire() try: if self.datawidget: mainthread.runBlock(self.datawidget.destroy) self.datawidget = None op = mainthread.runBlock(self.outputwidget.get_value) if (self.currentMesh is not None and self.position is not None and op is not None): #self.currentMesh.begin_reading() self.currentMesh.restoreCachedData(self.time) val = None try: # precompute *must* be called on a subthread self.currentMesh.precompute_all_subproblems() ## TODO: If op is a ConcatenateOutput and just one ## of its inputs is incomputable, it would be nice ## to still display the other one. That doesn't ## happen with the current structure because ## op.incomputable is True if just one input is ## incomputable. if (op is not None and not op.incomputable(self.currentMesh)): element = self.currentMesh.enclosingElement( self.position) # op.evaluate eventually calls mesh precompute # for the "Energy" or "Strain" selections in # the Data Viewer, so we can't put these in # updateDataMain below (running it with # mainthread.runBlock), otherwise we get a # lock error. if element is not None: masterpos = element.to_master(self.position) val = op.evaluate(self.currentMesh.getObject(), [element], [[masterpos]])[0] finally: self.currentMesh.releaseCachedData() #self.currentMesh.end_reading() mainthread.runBlock(self.updateDataMain, (val, )) gtklogger.checkpoint(self._name + " data updated") finally: self.updateLock.release()
def sensitize_subthread(self, skelcontext, current_selection): debug.subthreadTest() # Locks are only allowed on the subthread, but GUI updates # must be on the main thread. (c,u,i,r)=(0,0,0,0) if skelcontext is not None and current_selection is not None: current_selection.begin_reading() if not skelcontext.defunct(): try: c = current_selection.clearable() u = current_selection.undoable() i = current_selection.invertable() r = current_selection.redoable() finally: current_selection.end_reading() mainthread.runBlock(self._set_buttons, (c,u,i,r))
def quit(self): # Waiting for threads is a bad idea if this function is # called on the main thread, since it will block the main # thread. debug.subthreadTest() if len(self.listofminithreads) > 0: # This is done differently than it is for Worker threads. # Worker threads are stopped by setting the stop flag in # their Progress objects. It is assumed that all Workers # working on long tasks are using Progress objects. # MiniThreads are probably not using them, so this calls # stopAll which ultimately calls pthread_cancel. # Unfortunately, pthread_cancel doesn't seem to work # reliably on all systems. self.stopAll() self.waitForAllThreads()
def drawAtTime(self, time): debug.subthreadTest() if time is not None: self.setDisplayTime(time) mainthread.runBlock(self.timeslider.set_value, (self.displayTime, )) # Ensure that animatable layers will be redrawn by backdating # them, and then calling "draw". All time-dependent layers # are animatable, and they get their time from the GfxWindow's # displayTime. for layer in self.layers: layer.timeChanged() self.draw() mainthread.runBlock(self.sensitizeTimeButtons)
def update_thread(self, where): debug.subthreadTest() microstructure = self.toolbox.findMicrostructure() if microstructure and where is not None: mscntxt = ooflib.common.microstructure.getMSContextFromMS( microstructure) msname = microstructure.name() mscntxt.begin_reading() try: names = pixelgroup.pixelGroupNames(microstructure, where) finally: mscntxt.end_reading() grpnames = '\n'.join(names) else: msname = '(No microstructure)' grpnames = '' mainthread.runBlock(self.reallyupdate, (msname, grpnames))
def sensitize(self): debug.subthreadTest() context = self.currentSkeletonContext() if context is not None: skelselected = True context.begin_reading() try: undoable = context.undoable() redoable = context.redoable() not_illegal = self.legalityCheck() finally: context.end_reading() else: skelselected = False undoable = redoable = False not_illegal = False mainthread.runBlock(self.sensitize_thread, (skelselected, undoable, redoable, not_illegal))
def group_added(self, skelcontext, gset, name): debug.subthreadTest() gset = mainthread.runBlock(self.check_skel_and_gset, (skelcontext,gset)) if gset: skelcontext.begin_reading() try: names = gset.allGroups() finally: skelcontext.end_reading() self.update_grouplist(names, map(gset.displayString, names)) mainthread.runBlock(self.grouplist.set_selection, (name,) ) self.sensitize_subthread() # TODO: Remove this line. May # require re-recording gui # tests. self.sensitize_subthread() switchboard.notify("redraw skeletongroups", skelcontext)
def down_subthread(self, x, y, shift, ctrl): debug.subthreadTest() self.mouselock.acquire() try: self.downed = 1 point = self.getPoint(x,y) mainthread.runBlock(self.move_info, (point, "0", "0", '')) skel = mainthread.runBlock(self.getSkeleton) skelctxt = mainthread.runBlock(self.getSkeletonContext) reserved = skel is not None and skelctxt.query_reservation() if skel is not None and not reserved and point is not None: self.movingnode = skel.nearestNode(point) self.nodeChanged() #Store this point for use by the up callback's call to MoveNode self.downpt=point if self.movingnode.pinned(): self.nodeChanged() self.movingnode = None else: # Mouse-down events are only accepted in Mouse mode, # so the end_reading() call corresponding to this # begin_reading() is in the "Mouse" section of the # up() callback. skelctxt.begin_reading() self.nbrnodes = self.movingnode.aperiodicNeighborNodes(skel) self.nbrelements = self.movingnode.neighborElements() self.startpt = self.movingnode.position() # Get initial values of homogeneity and shape energy self.homogeneity0 = 0.0 self.shapeenergy0 = 0.0 for element in self.nbrelements: if not element.illegal(): self.homogeneity0 += element.homogeneity(skel.MS) self.shapeenergy0 += element.energyShape() # Create rubberband points = [n.position() for n in self.nbrnodes] rb = mainthread.runBlock(rubberband.SpiderRubberBand, (points,)) mainthread.runBlock( self.gfxwindow().setRubberband, (rb,) ) gtklogger.checkpoint("Move Node toolbox down event") finally: self.mouselock.release()
def up_subthread(self, x, y, shift, ctrl): debug.subthreadTest() self.mouselock.acquire() try: point = self.getPoint(x,y) if self.mode == "Mouse": skelcontext = mainthread.runBlock(self.getSkeletonContext) if skelcontext is not None: skelcontext.end_reading() if self.moving: self.moving = 0 # Dunmovin, CA is east of the Sierra Nevada mainthread.runBlock(self.showPosition, (point,)) # Accept/reject conditon: # Allow_illegal is ON : unconditionally accept everything # Allow_illegal is OFF : any node associated with # illegal nodes before or after will not be moved. aige = mainthread.runBlock(self.allow_illegal.get_active) if self.movingnode.illegal() and not aige: # Restore the state of the skeleton, and show # the original position in the toolbox. self.movingnode.moveTo(self.startpt) mainthread.runBlock(self.showPosition, (self.startpt,)) mainthread.runBlock(self.statusText.set_text, (self.illegalityText(),)) else: # Restore the state of the skeleton so that the non-GUI # movenode command can do the real work. self.movingnode.moveTo(self.startpt) try: self.toolbox.menu.MoveNode( origin=self.downpt, destination=point) finally: rbb = mainthread.runBlock(rubberband.NoRubberBand) mainthread.runBlock(self.gfxwindow().setRubberband, (rbb,) ) self.nbrnodes = [] elif self.mode == "Keyboard": self.toolbox.menu.SelectNode(position=point) gtklogger.checkpoint("Move Node toolbox up event") finally: self.mouselock.release()
def solver_precompute(self, solving=False): # Called before time-stepping. This routine precomputes # things that can't possibly be time-dependent. Called by # Mesh.solver_precompute(), which is called by the Solve # menuitem callback before calling evolve(). debug.subthreadTest() if self._precomputing: return if self.solveFlag and self.solver_mode is not None: subprob = self.getObject() subprob.precomputeLock.acquire() self._precomputing = True try: if subprob.precomputeRequired: # Check that materials are well defined, etc. # Being badly defined isn't an error unless we're # actually trying to solve a problem now. If # we're just precomputing to find out if the Solve # button should be sensitized, or something like # that, it's ok to simply bail out without raising # an exception. unsolvable = self.checkSolvability() if unsolvable: if solving: raise ooferror2.ErrUserError(unsolvable) else: return self.precomputeMaterials(lock=False) # Find mapping for symmetrization. # find_equation_mapping calls # CSubProblem::set_equation_mapping, which is a # fairly expensive operation, since it loops over # all nodal equations. from ooflib.engine import conjugate # avoid import loop conjugate.listofconjugatepairs.find_equation_mapping(self) conjugate.check_symmetry(self.path()) subprob.precomputeRequired = False finally: self._precomputing = False subprob.precomputeLock.release()
def renamepixgrp(self, group, oldname, newname): # switchboard 'rename pixel group' debug.subthreadTest() self.grouplock.acquire() try: mscontext = self.currentMScontext() if mscontext: mscontext.begin_reading() try: ms = mscontext.getObject() ok = group.name() in ms.groupNames() finally: mscontext.end_reading() if ok: # Ensure that the new pixel group is selected. self.rebuild_grouplist() mainthread.runBlock(self.grplist.set_selection, (newname,)) self.sensitize() finally: self.grouplock.release()
def updateData(self): debug.subthreadTest() self.updateLock.acquire() try: if self.datawidget: mainthread.runBlock(self.datawidget.destroy) self.datawidget = None op = mainthread.runBlock(self.outputwidget.get_value) if (self.currentMesh is not None and self.position is not None and op is not None): #self.currentMesh.begin_reading() self.currentMesh.restoreCachedData(self.time) val = None try: # precompute *must* be called on a subthread self.currentMesh.precompute_all_subproblems() if (op is not None and not op.incomputable(self.currentMesh)): element = self.currentMesh.enclosingElement( self.position) # op.evaluate eventually calls mesh precompute # for the "Energy" or "Strain" selections in # the Data Viewer, so we can't put these in # updateDataMain below (running it with # mainthread.runBlock), otherwise we get a # lock error. if element is not None: masterpos = element.to_master(self.position) val = op.evaluate(self.currentMesh.getObject(), [element], [[masterpos]])[0] finally: self.currentMesh.releaseCachedData() #self.currentMesh.end_reading() mainthread.runBlock(self.updateDataMain, (val,)) gtklogger.checkpoint(self._name+" data updated") finally: self.updateLock.release()
def sensitize_subthread(self): debug.subthreadTest() source = self.getSource() try: # The source may not have been completely built yet... selection = source.getSelectionContext(**self.toolbox.extrakwargs) except AttributeError: selection = None if source is None or selection is None: (u,r,c,i) = (0,0,0,0) else: selection.begin_reading() try: u = selection.undoable() r = selection.redoable() c = selection.clearable() i = 1 finally: selection.end_reading() mainthread.runBlock(self._set_button_sensitivities, (u,r,c,i)) gtklogger.checkpoint(self.gfxwindow().name + " " + self._name + " sensitized")
def displayMSInfo(self, *args): # *args is given because this is used as a switchboard # callback for ('rename who', 'Image') as well as being called # directly. This indicates either slovenliness or efficiency # on the part of the programmer. debug.subthreadTest() mscontext = self.currentMScontext() text = "" if mscontext is not None: mscontext.begin_reading() try: # ms might be None if the context was destroyed while # we were waiting for the read lock. ms = mscontext.getObject() if ms is not None: size = ms.sizeInPixels() if config.dimension() == 2: text += 'Pixel size: %dx%d\n' % (size.x, size.y) size = ms.size() text += 'Physical size: %sx%s\n' % (size.x, size.y) elif config.dimension() == 3: text += 'Voxel size: %dx%dx%d\n' % ( size.x, size.y, size.z) size = ms.size() text += 'Physical size: %sx%sx%s\n' % ( size.x, size.y, size.z) imagenames = ms.imageNames() if imagenames: text += 'Images:\n' for name in imagenames: text += ' ' + name + '\n' for infoplugin in self.infoplugins: plugintext = infoplugin(mscontext) if plugintext: text += plugintext + '\n' finally: mscontext.end_reading() mainthread.runBlock(self.infoarea.get_buffer().set_text, (text,))
def sensitize(self): debug.subthreadTest() ms_available = False grp_selected = False nonemptygrp = False pixelsselected = False ngrps = 0 msctxt = self.currentMScontext() if msctxt: msctxt.begin_reading() try: ms = msctxt.getObject() if ms is not None: ms_available = True grp = self.currentGroup() grp_selected = (grp is not None) and ms_available nonemptygrp = grp_selected and len(grp) > 0 pixelsselected = ms.pixelselection.size() > 0 ngrps = ms.nGroups() finally: msctxt.end_reading() mainthread.runBlock(self.sensitize_thread, (ms_available, grp_selected, pixelsselected, nonemptygrp, ngrps))
def displayImageInfo(self): debug.subthreadTest() imagecontext = self.getCurrentImage() text = "" if imagecontext: imagecontext.begin_reading() try: if config.dimension() == 2: image = imagecontext.getObject() size = image.sizeInPixels() text += 'Pixel size: %dx%d\n' % (size.x, size.y) size = image.size() text += 'Physical size: %sx%s\n' % (size.x, size.y) if image.comment(): text += '\nComments:\n%s\n' % image.comment() elif config.dimension() == 3: image = imagecontext.getObject() size = image.sizeInPixels() text += 'Voxel size: %dx%dx%d\n' % (size.x, size.y, size.z) size = image.size() text += 'Physical size: %sx%sx%s\n' % (size.x, size.y, size.z) finally: imagecontext.end_reading() mainthread.runBlock(self.displayImageInfo_thread, (text,))
def sensitize_subthread(self): debug.subthreadTest() ssize = self.parent.selectionSize() # requires subthread mainthread.runBlock(self.sensitize_mainagain, (ssize,))
def findTimeDependent(self): debug.subthreadTest() self._timeDependent = (self.solveFlag and self.solver_mode is not None and self.time_stepper.derivOrder() != 0)