def readfile(self, filename, prog, z=0): tslfile = file(filename, "r") prog.setMessage("Reading " + filename) count = 1 # line counter lines = tslfile.readlines() nlines = len(lines) data = utils.ReservableList(nlines) angletype = None for line in lines: if line[0] == '#': if line.startswith("Column 1-3", 2): if "radians" in line: angletype = "radians" else: angletype = "degrees" debug.fmsg("Angles are in %s." % angletype) else: # line[0] != '#' substrings = line.split() if len(substrings) < 5: raise ooferror.ErrUserError( "Too few numbers in line %d of %s" % (count, filename)) values = map(float, substrings[:5]) if angletype == "radians": angles = values[:3] elif angletype == "degrees": angles = map(math.radians, values[:3]) else: raise ooferror.ErrDataFileError( "Angle type not specified in TSL data file") orientation = corientation.COrientBunge(*angles) if config.dimension() == 2: point = primitives.Point(values[3], values[4]) elif config.dimension() == 3: point = primitives.Point(values[3], values[4], z) data.append(DataPoint(point, # position angles, ' '.join(substrings[10:]))) # phase name count += 1 # count actual file lines, comments and all prog.setMessage("read %d/%d lines" % (count, nlines)) prog.setFraction(float(count)/nlines) npts = len(data) debug.fmsg("read %d lines, %d data points" % (count, npts)) # We don't yet know if the points are on a rectangular or a # hexagonal lattice, so split the data up into rows. # getrows() is a generator, but we need an actual list so that # we can index into it. rows = list(getrows(data)) if len(rows) < 2: raise ooferror.ErrUserError( "Orientation map data has too few rows.") if rows[0][0].position[0] != rows[1][0].position[0]: # Must be a hexagonal lattice. Throw out every other row. reporter.warn("Converting hexagonal lattice to rectangular by discarding alternate rows.") rows = rows[::2] # discard odd numbered rows return rows, npts
def copyPixelGroup(menuitem, microstructure, group, name): if parallel_enable.enabled(): pixelgroupIPC.ipcpixgrpmenu.Copy(microstructure=microstructure, group=group, name=name) return if group != name: mscontext = ooflib.common.microstructure.microStructures[ microstructure] ms = mscontext.getObject() mscontext.begin_writing() newness = False try: oldgroup = ms.findGroup(group) if oldgroup is not None: (newgroup, newness) = ms.getGroup(name) newgroup.addWithoutCheck(oldgroup) else: raise ooferror.ErrUserError( "There is no pixel group named %s!" % group) finally: mscontext.end_writing() if newness: switchboard.notify("new pixel group", newgroup) switchboard.notify("changed pixel group", newgroup, microstructure)
def loadLog(menuitem, filename, checkpoints): if gtklogger.replaying(): raise ooferror.ErrUserError( "Multiple GUI logs cannot be replayed simultaneously!") debug.fmsg("Loading gui script", filename) menuitem.root().setOption('post_hook', menucheckpoint) dblevel = 0 if debug.debug(): dblevel = 3 #dblevel = 4 global _replaying _replaying = True # When replaying, we have to make sure that progress bars *always* # appear, so we set the delay time to 0. If the delay time is # non-zero, then a script recorded on a slow machine would insert # a checkpoint for opening the activity viewer window, but a # faster machine might never open the window, and would wait # forever for the checkpoint when replaying the script. progressbar_delay.set_delay(None, 0) gtklogger.replay(filename, beginCB=activityViewer.openActivityViewer, finishCB=logFinished, debugLevel=dblevel, threaded=thread_enable.query(), exceptHook=loggererror, checkpoints=checkpoints)
def _copy_group(menuitem, skeleton, group, new_name): skelc = whoville.getClass('Skeleton')[skeleton] groupset = getattr(skelc, menuitem.data) if groupset.isGroup(new_name): raise ooferror.ErrUserError("Group %s already exists." % new_name) if groupset.isGroup(group): groupset.copyGroup(group, new_name)
def renamePixelGroup(menuitem, microstructure, group, new_name): if parallel_enable.enabled(): pixelgroupIPC.ipcpixgrpmenu.Rename(microstructure=microstructure, group=group, new_name=new_name) return # "group" arg is the old group name. mscontext = ooflib.common.microstructure.microStructures[microstructure] ms = mscontext.getObject() mscontext.begin_writing() renamed = False try: grp = ms.findGroup(group) # Don't just say "if grp" here. PixelGroup has a __len__ # function, so empty groups evaluate to "false". if grp is not None: ms.renameGroup(group, new_name) renamed = True if config.dimension() == 2 and runtimeflags.surface_mode: interfacemsplugin = ms.getPlugIn("Interfaces") interfacemsplugin.renameGroup(group, new_name) else: raise ooferror.ErrUserError("There is no pixel group named %s!" % group) finally: mscontext.end_writing() if renamed: switchboard.notify('renamed pixel group', grp, group, new_name)
def _new_group(menuitem, skeleton, name): skelc = whoville.getClass('Skeleton')[skeleton] groupset = getattr(skelc, menuitem.data) if groupset.isGroup(name): raise ooferror.ErrUserError("Group %s already exists." % group) else: groupset.addGroup(name)
def __call__(self, **kwargs): # Check for extra arguments paramnames = [p.name for p in self.params] for argname in kwargs.keys(): if argname not in paramnames: raise ooferror.ErrUserError( "Unexpected argument '%s' in %s constructor" % (argname, self.subclass.__name__)) pdict = {} for p in self.params: try: p.value = kwargs[p.name] except KeyError: pass pdict[p.name] = p.value try: object = self.subclass(**pdict) except TypeError: debug.fmsg("Error creating", self.subclass) debug.fmsg("got arguments=", pdict) debug.fmsg("expected arguments=", self.params) raise if not hasattr(object, 'timestamp'): object.timestamp = timestamp.TimeStamp() return object
def createMSFromImageFile(menuitem, filename, microstructure_name, height, width, depth=0): if (height!=automatic and height<=0) or \ (width!=automatic and width<=0) or \ (config.dimension()==3 and depth!=automatic and depth<=0): raise ooferror.ErrUserError( "Negative microstructure sizes are not allowed.") image = autoReadImage(filename, height, width, depth) ms = ooflib.common.microstructure.Microstructure(microstructure_name, image.sizeInPixels(), image.size()) immidgecontext = imagecontext.imageContexts.add( [ms.name(), image.name()], image, parent=ooflib.common.microstructure.microStructures[ms.name()]) if parallel_enable.enabled(): # For the rear-end guys from ooflib.image.IO import oofimageIPC oofimageIPC.imenu.Create_From_Imagefile_Parallel( msname=microstructure_name, imagename=image.name()) switchboard.notify("redraw")
def meshablePixelGroup(menuitem, microstructure, group, meshable): if parallel_enable.enabled(): pixelgroupIPC.ipcpixgrpmenu.Meshable(microstructure=microstructure, group=group, meshable=meshable) return mscontext = ooflib.common.microstructure.microStructures[microstructure] ms = mscontext.getObject() mscontext.begin_writing() try: grp = ms.findGroup(group) if grp is not None: grp.set_meshable(meshable) # TODO OPT: Does this need to call buildAttributeChangeMap and # updateAttributeVector before recategorize()? ms.recategorize() else: raise ooferror.ErrUserError("There is no pixel group named %s!" % group) finally: mscontext.end_writing() switchboard.notify('redraw') if grp is not None: switchboard.notify("changed pixel group", grp, microstructure)
def constructOrientedSurface(skelcontext, faces, direction): # orientFaces() returns an OrientedSurface object, but its # orientation may not be correct. ofaces = cskeletonface.orientFaces(skelcontext.getObject(), faces, None) if not ofaces: raise ooferror.ErrUserError( "Failed to construct an orientable surface") if ofaces.closed(): if direction.string() not in director.closedSurfaceDirections: raise ooferror.ErrUserError("Direction must be one of " + ` director.closedSurfaceDirections `) vol = ofaces.volume() if (vol > 0 and direction == "Inward" or vol < 0 and direction == "Outward"): ofaces.reverse() else: # not a closed surface if direction.string() not in director.unclosedDirections: raise ooferror.ErrUserError("Direction must be one of " + ` director.unclosedDirections `) normal = ofaces.normal() if ((direction == '-X to +X' and normal[0] < 0) or (direction == '+X to -X' and normal[0] > 0) or (direction == '-Y to +Y' and normal[1] < 0) or (direction == '+Y to -Y' and normal[1] > 0) or (direction == '-Z to +Z' and normal[2] < 0) or (direction == '+Z to -Z' and normal[2] > 0)): ofaces.reverse() return ofaces
def loadscript(menuitem, filename): if filename is not None: debug.fmsg('reading', filename, 'in thread', threadstate.findThreadNumber()) kwargs = {} if subScriptErrorHandler: kwargs['errhandler'] = subScriptErrorHandler interp = PScriptLoader(filename, **kwargs) interp.run() if interp.error: # If the interpreter raised an exception and we're in # batch mode, the shell error status won't be set unless a # new exception is raised here. The old exception has # already been handled by the time we get to this point. # interp.error[0] is the class of the exception. # interp.error[1] is its value. errorname = interp.error[0].__name__ if errorname.lower()[0] in "aeiou": article = "an" else: article = "a" raise ooferror.ErrUserError( "Script '%s' raised %s %s exception" % (filename, article, interp.error[0].__name__) # "Script '%s' raised %s %s exception: %s" % # (filename, article, interp.error[0].__name__, interp.error[1]) ) debug.fmsg('finished reading', filename)
def loadImageIntoMS(image, microstructure): # Used by loadImage() and copyImage() to install an image into a # microstructure. 'image' is an OOFImage object. # 'microstructure' is a Microstructure name. A new Microstructure # is created if necessary. # See if the Microstructure already exists msclass = whoville.getClass('Microstructure') try: # look for existing microstructure ms = msclass[microstructure] # Who object except KeyError: msobj = ooflib.SWIG.common.cmicrostructure.CMicrostructure( microstructure, image.sizeInPixels(), image.size()) ms = msclass.add(microstructure, msobj, parent=None) # Check size of microstructure if ms.getObject().sizeInPixels() != image.sizeInPixels(): debug.fmsg("ms=", ms.getObject().sizeInPixels(), "image=", image.sizeInPixels()) raise ooferror.ErrUserError("Cannot load an image into an existing" " Microstructure of a different size.") # See if the image name is unique in the Microstructure newname = imagecontext.imageContexts.uniqueName([ms.name(), image.name()]) image.rename(newname) # Create ImageContext object immidgecontext = imagecontext.imageContexts.add([ms.name(), newname], image, parent=ms)
def _remove_matl(menuitem, skeleton, group): skelc = whoville.getClass('Skeleton')[skeleton] groupset = getattr(skelc, menuitem.data) if not groupset.isGroup(group): raise ooferror.ErrUserError("Group %s does not exist." % group) groupset.removeMaterial(group) switchboard.notify("redraw")
def renamePixelGroup_parallel(menuitem, microstructure, group, new_name): # "group" arg is the old group name. mscontext = ooflib.common.microstructure.microStructures[microstructure] ms = mscontext.getObject() mscontext.begin_writing() renamed = False try: grp = ms.findGroup(group) # Don't just say "if grp" here. PixelGroup has a __len__ # function, so empty groups evaluate to "false". if grp is not None: ms.renameGroup(group, new_name) renamed = True #Interface branch (only implemented for 2D) if config.dimension() == 2: interfacemsplugin = ms.getPlugIn("Interfaces") interfacemsplugin.renameGroup(group, new_name) else: raise ooferror.ErrUserError("There is no pixel group named %s!" % group) finally: mscontext.end_writing() if renamed: switchboard.notify('renamed pixel group', grp, group, new_name)
def removeBoundary(self, name): # Actual removal from skeletons happens in # SkelContextBoundary.remove(). self.unSyncMeshes() # for mesh in self.getMeshes(): # mesh.removeBoundary(name) ## TODO 3.1: Use virtual methods in the boundary classes instead ## of this ugly if/elif. There should be just one dict for ## the name lookup. if name in self.faceboundaries: self.faceboundaries[name].remove() del self.faceboundaries[name] elif name in self.edgeboundaries: self.edgeboundaries[name].remove() del self.edgeboundaries[name] elif name in self.pointboundaries: self.pointboundaries[name].remove() del self.pointboundaries[name] else: raise ooferror.ErrUserError( "Cannot remove boundary %s, no such boundary." % name) if name == self.selectedBdyName: self.unselectBoundary() # self.bdytimestamp.increment() switchboard.notify("boundary removed", self) switchboard.notify("new boundary configuration", self)
def loadImageIntoMS(image, microstructure): # 'image' is an OOFImage object. # 'microstructure' is a Microstructure name. # See if the Microstructure already exists msclass = whoville.getClass('Microstructure') try: # look for existing microstructure ms = msclass[microstructure] # Who object except KeyError: msobj = ooflib.common.microstructure.Microstructure( microstructure, image.sizeInPixels(), image.size()) ms = msclass.add(microstructure, msobj, parent=None) # Check size of microstructure if ms.getObject().sizeInPixels() != image.sizeInPixels(): raise ooferror.ErrUserError( "Cannot load an image into an existing Microstructure of a different size." ) # See if the image name is unique in the Microstructure newname = imagecontext.imageContexts.uniqueName([ms.name(), image.name()]) image.rename(newname) # Create ImageContext object immidgecontext = imagecontext.imageContexts.add([ms.name(), newname], image, parent=ms)
def __init__(self, param, scope, name=None): # Find the who widget with the skeleton. self.skelwidget = scope.findWidget( lambda x: isinstance(x, whowidget.WhoWidget) and x.whoclass is skeletoncontext.skeletonContexts) # Use it to get the context or proxy. skelname = self.skelwidget.get_value() skelctxt = skeletoncontext.skeletonContexts[skelname] if issubclass(skelctxt.__class__, whoville.WhoProxy): gfxwindow = scope.findData("gfxwindow") if gfxwindow is None: raise ooferror.ErrUserError( "Unable to find a Skeleton or its list of boundaries!") skelctxt = skelctxt.resolve(gfxwindow) bdynames = skelctxt.edgeboundaries.keys() + \ skelctxt.pointboundaries.keys() chooser.MultiListWidget.__init__(self, objlist=bdynames, callback=self.chooserCB) parameterwidgets.ParameterWidget.__init__(self, self.gtk, scope, name, expandable=True) self.set_selection(param.value) self.widgetChanged(1, interactive=0) # Always valid.
def readData(self, tslfile, prog): count = 1 lines = tslfile.readlines() nlines = len(lines) data = utils.ReservableList(nlines) hexgrid = False for line in lines: if line[0] == '#': # line is in the header if line.startswith('# GRID: HexGrid'): hexgrid = True else: # line is not a header line substrings = line.split() if len(substrings) < 5: raise ooferror.ErrUserError( "Not enough columns in line %d of %s" % (count, tslfile.name)) if len(substrings) >= 8: phase = substrings[7] else: phase = 'phase0' values = map(float, substrings[:5]) position = primitives.Point(values[3], values[4]) angles = values[:3] angles[0] = angles[0] - math.radians(self.angle_offset) data.append(DataPoint(position, angles, 'phase' + phase)) count += 1 prog.setMessage("read %d/%d lines" % (count, nlines)) prog.setFraction(float(count) / nlines) debug.fmsg("read %d lines, %d data points" % (count, len(data))) return data, hexgrid
def __init__(self, name=None, firstimage=None, filepattern=None, numfiles=None): # eventually this will be C++ and we will have multiple constructors if (name is not None and firstimage is not None and filepattern is not None and numfiles is not None): self._name = name self._timestamp = timestamp.TimeStamp() format = imghdr.what(firstimage) depth = numfiles readers = {'pbm':vtk.vtkPNMReader, 'pgm':vtk.vtkPNMReader, 'ppm':vtk.vtkPNMReader, 'bmp':vtk.vtkBMPReader, 'jpeg':vtk.vtkJPEGReader, 'tiff':vtk.vtkTIFFReader, 'png':vtk.vtkPNGReader} try: imageReader = readers[format]() except KeyError: raise ooferror.ErrUserError("Unrecognized Image Format") # the width and height are set based on the actual image size imageReader.SetDataExtent(0,0,0,0,0,depth-1) imageReader.SetDataSpacing(1,1,1) imageReader.SetFilePattern(filepattern) self.image = imageReader.GetOutput() self.image.Update() self.makeFourChannel() self.padImage() self.setup()
def _remove_group(menuitem, skeleton, group): skelc = whoville.getClass('Skeleton')[skeleton] groupset = getattr(skelc, menuitem.data) if not groupset.isGroup(group): raise ooferror.ErrUserError("Group %s does not exist." % group) else: groupset.removeGroup(group)
def deleteView(self, menuitem, view): v = namedViews[view] if v.deletable: del namedViews[view] switchboard.notify("view deleted", view) else: raise ooferror.ErrUserError( "Please don't delete the predefined Views.")
def _newInterfaceCB(menuitem,microstructure,name,interface_type): msobj = ooflib.common.microstructure.microStructures[microstructure].getObject() interfacemsplugin=msobj.getPlugIn("Interfaces") errmsg=interface_type.check() if errmsg: raise ooferror.ErrUserError(errmsg) else: interface_type.addToMS(interfacemsplugin,name)
def read(self, filepattern): dirname = os.path.dirname(filepattern) items = os.listdir(dirname) escaped_pattern = string.replace( re.escape(os.path.basename(filepattern)), "\\*", ".*?") files = [] for item in items: match = re.match(escaped_pattern, item) if match != None: span = match.span() if span[0] == 0 and span[1] == len(item): files.append(os.path.join(dirname, item)) prog = progress.getProgress(os.path.basename(filepattern), progress.DEFINITE) try: # Look at the just the first file to get some info z = 0 rows, npts = self.readfile(files[0], prog, z) nx = len(rows[0]) ny = len(rows) nz = len(files) dx = rows[0][1].position[0] - rows[0][0].position[0] dy = rows[1][0].position[1] - rows[0][0].position[1] dz = 1 pxlsize = primitives.Point(dx, dy, dz) size = rows[-1][-1].position + pxlsize od = orientmapdata.OrientMap(primitives.iPoint(nx, ny, nz), size) count = 0 for row in rows: count += 1 for datum in row: self.addDatum(od, datum, pxlsize, ny, count, npts, prog, nz) # now look at the rest of the files for file in files[1:]: z = z + dz rows, nrowpts = self.readfile(file, prog, z) npts = npts + nrowpts count = 0 for row in rows: count += 1 if len(row) != nx: raise ooferror.ErrUserError( "Orientation map data appears to be incomplete" ) for datum in row: self.addDatum(od, datum, pxlsize, ny, count, npts, prog, nz) finally: prog.finish() return od
def makeFourChannel(self): # We make all images, even if they are grayscale, four # channel. Since we need to resample the image when we select # voxels, etc, we always need 3 channels for RGB. In order to # display one material or pixel group at a time, such as with # active area, we need an alpha channel. If all of these # channels are initialized once in the beggining, rendering # selected voxels, active areas, etc, will be more responsive. # The initial image will have 1 to 4 channels. num_components = self.image.GetNumberOfScalarComponents() if num_components > 4: raise ooferror.ErrUserError("Image must have four or less components.") imagecopy = vtk.vtkImageData() imagecopy.DeepCopy(self.image) if num_components != 4: # extract the first component extractor = vtk.vtkImageExtractComponents() extractor.AddInputConnection(imagecopy.GetProducerPort()) extractor.SetComponents(0) # append the first component up to 3 times. appender = vtk.vtkImageAppendComponents() if num_components < 3: # only use the first component if we have less than 3 components for i in xrange(num_components): appender.AddInputConnection(extractor.GetOutputPort()) else: # otherwise use all of the components appender.AddInputConnection(imagecopy.GetProducerPort()) for i in xrange(4-num_components): appender.AddInputConnection(extractor.GetOutputPort()) imagecopy = appender.GetOutput() imagecopy.Update() imagecopy.UpdateInformation() # Set all voxels to have full opacity. This will be slow but # eventually we are converting this class to C++. sighs = imagecopy.GetDimensions() for i in xrange(sighs[0]): for j in xrange(sighs[1]): for k in xrange(sighs[2]): # For some bizarre reason, vtk doesn't like # rendering images when the alpha component is # initialized above 100 or so. So the numbers on # the fourth component will represent the # translucency - 0 indicates an opaque image and # 255 indicates complete transparency. imagecopy.SetScalarComponentFromFloat(i,j,k,3,0.0) imagecopy.Update() imagecopy.UpdateInformation() self.image = imagecopy
def __init__(self, e0, e1, e2, e3): # Make sure it's normalized. norm = math.sqrt(e0 * e0 + e1 * e1 + e2 * e2 + e3 * e3) if norm == 0.0: raise ooferror.ErrUserError("Quaternion cannot be normalized!") self.e0 = e0 / norm self.e1 = e1 / norm self.e2 = e2 / norm self.e3 = e3 / norm self.corient = corientation.COrientQuaternion(self.e0, self.e1, self.e2, self.e3)
def __call__(self, ms, selection): curselection = selection.getObject() orientationmap = orientmapdata.getOrientationMap(ms) if orientationmap is None: raise ooferror.ErrUserError( "The Microstructure has no orientation map.") selection.start() selection.clearAndSelect( pixelselectioncouriero.OrientationSelection( orientationmap, self.orientation.corient, self.lattice_symmetry.schoenflies(), self.misorientation))
def __call__(self, image): # Check that the permutation only swaps axes with the same # image size. axisnumber = {'x': 0, 'y': 1, 'z': 2} pixsize = image.sizeInPixels() for i in range(3): if pixsize[i] != pixsize[axisnumber[self.axes.name[i]]]: raise ooferror.ErrUserError( "Image axes %s and %s do not have the same size." % (self.axes.name[i], "xyz"[i])) image.permuteAxes(self.axes.name)
def getMyMasterElementDict(masterelems): edict = {} masterdict = masterelement.getMasterElementDict() for ename in masterelems: try: master = masterdict[ename] edict[master.ncorners()] = master except KeyError: raise ooferror.ErrUserError("Element type \"%s\" is unknown." % ename) return edict
def _loadOrientationMap(menuitem, filename, reader, microstructure): # format is an Enum object. microstructure is a name. mscontext = ooflib.common.microstructure.microStructures[microstructure] mscontext.reserve() mscontext.begin_writing() try: # Check to see if the microstructure already has an # orientation map. It can't have more than one. if orientmapdata.getOrientationMap(mscontext.getObject()) is not None: raise ooferror.ErrUserError( "A Microstructure can contain only one orientation map.") data = reader.read(filename) # creates OrientMap object if (mscontext.getObject().sizeInPixels() != data.sizeInPixels() or mscontext.getObject().size() != data.size()): raise ooferror.ErrUserError( "Cannot load orientation map into an existing Microstructure of a different size. ms=%sx%s (%dx%d), map=%sx%s (%dx%d)" % ( mscontext.getObject().size()[0], mscontext.getObject().size()[1], mscontext.getObject().sizeInPixels()[0], mscontext.getObject().sizeInPixels()[1], data.size()[0], data.size()[1], data.sizeInPixels()[0], data.sizeInPixels()[1])) # Registering the OrientMapData object under its # microstructure's name allows it to be found by the # OrientationMapProp Property in C++. orientmapdata.registerOrientMap(microstructure, data) data.setMicrostructure(mscontext.getObject()) # Storing it as a Python Microstructure plug-in allows the # data to be found by Python (and keeps a live reference to # it, so we don't have to transfer ownership to C++). All of # this registration doesn't actually duplicate the data. orientmapplugin = mscontext.getObject().getPlugIn("OrientationMap") orientmapplugin.set_data(data, filename) orientmapplugin.timestamp.increment() finally: mscontext.end_writing() mscontext.cancel_reservation() reader.postProcess(mscontext) orientmapdata.orientationmapNotify(mscontext.getObject())
def select(self, immidge, pointlist, selector): ms = immidge.getMicrostructure() orientationmap = orientmapdata.getOrientationMap(ms) if orientationmap is None: raise ooferror.ErrUserError( "The Microstructure has no orientation map.") pt = ms.pixelFromPoint(pointlist[0]) orientation = orientationmap.angle(pt) # a swigged COrientABG selector( pixelselectioncouriero.OrientationSelection( orientationmap, orientation, self.lattice_symmetry.schoenflies(), self.misorientation))