def plotPhaseMap(self, **kwargs): """ Plot a phase map. Parameters ---------- cmap : str, optional Colour scale to plot with. """ # Set default plot parameters then update with any input plotParams = { 'vmin': -1, 'vmax': self.numPhases } plotParams.update(kwargs) plot = MapPlot.create(self, self.phaseArray, **plotParams) # add a legend to the plot phaseIDs = [-1] + list(range(1, self.numPhases + 1)) phaseNames = ["Non-indexed"] + self.phaseNames plot.addLegend(phaseIDs, phaseNames, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) return plot
def plotMaxShear(self, **kwargs): """ Plot a map of maximum shear strain Parameters ---------- plotColourBar : bool, optional Add a colourbar to plot vmin : float, optional Minimum value for colour scale, default is max value of data vmax : float, optional Maximum value for colour scale, default is min value of data cmap plotGBs : bool, optional Add grain boundaries to the plot dilateBoundaries : bool, optional boundaryColour plotScaleBar : bool, optional Add scale bar to plot highlightGrains highlightColours ax updateCurrent : bool, optional """ # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'cLabel': "Effective shear strain" } plotParams.update(kwargs) plot = MapPlot.create(self, self.crop(self.max_shear), **plotParams) return plot
def plotKamMap(self, **kwargs): """ Plot Kernel Average Misorientaion (KAM) for the EBSD map. Parameters ---------- vmin : float, optional Minimum of colour scale vmax : float, optional Maximum of colour scale cmap : str, optional Colour scale to plot with. """ # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'cLabel': "Kernel average misorientation (KAM) ($^\circ$)" } plotParams.update(kwargs) self.calcKam() # Convert to degrees and plot kam = 2 * np.arccos(self.kam) * 180 / np.pi plot = MapPlot.create(self, kam, **plotParams) return plot
def plotPattern(self, **kwargs): """Plot BSE image of Map. For use with setting homog points. Parameters ---------- kwargs All arguments are passed to :func:`defdap.plotting.MapPlot.create`. Returns ------- defdap.plotting.MapPlot """ # Set default plot parameters then update with any input plotParams = {'cmap': 'gray'} try: plotParams['scale'] = self.scale / self.patScale * 1e-6 except (ValueError): pass plotParams.update(kwargs) # Check image path is set if self.patternImPath is None: raise Exception("First set path to pattern image.") bseImage = imread(self.patternImPath) bseImage = self.crop(bseImage, binned=False) plot = MapPlot.create(self, bseImage, **plotParams) return plot
def plotGNDMap(self, **kwargs): # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'cLabel': "Geometrically necessary dislocation (GND) content" } plotParams.update(kwargs) self.calcNye() plot = MapPlot.create(self, np.log10(self.GND), **plotParams) return plot
def plotMisOriMap(self, component=0, **kwargs): """ Plot misorientation map :param component: 0: misorientation, 1, 2, 3: rotation about x, y, z :param plotGBs: Plot grain boundaries :param boundaryColour: Colour of grain boundary :param vmin: Minimum of colour scale (optional) :type vmin: float :param vmax: Maximum of colour scale (optional) :type vmax: float :param cmap: Colour map (optional) :type cmap: str :param cBarLabel: Label for colour bar :return: Figure """ # Check that grains have been detected in the map self.checkGrainsDetected() self.misOri = np.ones([self.yDim, self.xDim]) if component in [1, 2, 3]: for grain in self.grainList: for coord, misOriAxis in zip(grain.coordList, np.array(grain.misOriAxisList)): self.misOri[coord[1], coord[0]] = misOriAxis[component - 1] misOri = self.misOri * 180 / np.pi cLabel = "Rotation around {:} axis ($^\circ$)".format( ['X', 'Y', 'Z'][component-1] ) else: for grain in self.grainList: for coord, misOri in zip(grain.coordList, grain.misOriList): self.misOri[coord[1], coord[0]] = misOri misOri = np.arccos(self.misOri) * 360 / np.pi cLabel = "Grain reference orienation deviation (GROD) ($^\circ$)" # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'cLabel': cLabel } plotParams.update(kwargs) plot = MapPlot.create(self, misOri, **plotParams) return plot
def plotGrainMap(self, **kwargs): """ Plot a map with grains coloured :return: Figure """ # Set default plot parameters then update with any input plotParams = { 'cLabel': "Grain number" } plotParams.update(kwargs) plot = MapPlot.create(self, self.grains, **plotParams) return plot
def plotBoundaryMap(self, **kwargs): """Plot grain boundary map :param dilate: Dilate boundary by one pixel """ # Set default plot parameters then update with any input plotParams = { 'plotGBs': True, 'boundaryColour': 'black' } plotParams.update(kwargs) plot = MapPlot.create(self, None, **plotParams) return plot
def plotEulerMap(self, **kwargs): """ Plot an orientation map in Euler colouring Parameters ---------- ax makeInteractive plotGBs dilateBoundaries boundaryColour plotScaleBar kwargs updateCurrent : bool, optional highlightGrains : iterable(int), optional List of grain ids to highlight highlightColours : str, optional Colour of list of colours to highlight grains. If less colours are given than grains, then the final colour is used for the remaining grains. """ self.checkDataLoaded() # Set default plot parameters then update with any input plotParams = {} plotParams.update(kwargs) eulerMap = np.transpose(self.eulerAngleArray, axes=(1, 2, 0)) # this is the normalisation - different foreach crystal symmetry! if self.crystalSym == 'cubic': norm = np.tile(np.array([2 * np.pi, np.pi / 2, np.pi / 2]), (self.yDim, self.xDim)) norm = np.reshape(norm, (self.yDim, self.xDim, 3)) elif self.crystalSym == 'hexagonal': norm = np.tile(np.array([np.pi, np.pi, np.pi / 3]), (self.yDim, self.xDim)) norm = np.reshape(norm, (self.yDim, self.xDim, 3)) else: Exception("Only hexagonal and cubic symGroup supported") # make non-indexed points green eulerMap = np.where(eulerMap != [0., 0., 0.], eulerMap, [0., 1., 0.]) eulerMap /= norm plot = MapPlot.create(self, eulerMap, **plotParams) return plot
def plotIPFMap(self, direction, **kwargs): # Set default plot parameters then update with any input plotParams = {} plotParams.update(kwargs) # calculate IPF colours IPFcolours = Quat.calcIPFcolours( self.quatArray.flatten(), direction, self.crystalSym ) # reshape back to map shape array IPFcolours = np.reshape(IPFcolours, (self.yDim, self.xDim, 3)) plot = MapPlot.create(self, IPFcolours, **plotParams) return plot
def plotBandContrastMap(self, **kwargs): """ Plot band contrast map """ self.checkDataLoaded() # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'cmap:': 'grey', 'cLabel': "Band contrast" } plotParams.update(kwargs) plot = MapPlot.create(self, self.bandContrastArray, **plotParams) return plot
def plotPhaseBoundaryMap(self, dilate=False, **kwargs): """Plot phase boundary map :param dilate: Dilate boundary by one pixel """ # Set default plot parameters then update with any input plotParams = { 'vmax': 1, 'plotColourBar': True, 'cmap': 'grey' } plotParams.update(kwargs) boundariesImage = -self.phaseBoundaries if dilate: boundariesImage = mph.binary_dilation(boundariesImage) plot = MapPlot.create(self, boundariesImage, **plotParams) return plot
def plotGrainDataMap(self, mapData=None, grainData=None, grainIds=-1, bg=0, **kwargs): # Set default plot parameters then update with any input plotParams = {} plotParams.update(kwargs) if grainData is None: if mapData is None: raise ValueError("Either 'mapData' or 'grainData' must " "be supplied.") else: grainData = self.calcGrainAv(mapData, grainIds=grainIds) # Check that grains have been detected in the map self.checkGrainsDetected() if type(grainIds) is int and grainIds == -1: grainIds = range(len(self)) if len(grainData) != len(grainIds): raise Exception("Must be 1 value for each grain in grainData.") grainMap = np.full([self.yDim, self.xDim], bg, dtype=type(grainData[0])) for grainId, grainValue in zip(grainIds, grainData): grain = self.grainList[grainId] for coord in grain.coordList: grainMap[coord[1], coord[0]] = grainValue plot = MapPlot.create(self, grainMap, **plotParams) return plot
def plotMaxShear(self, **kwargs): """Plot a map of maximum shear strain. Parameters ---------- kwargs All arguments are passed to :func:`defdap.plotting.MapPlot.create`. Returns ------- defdap.plotting.MapPlot Plot containing BSE image of map. """ # Set default plot parameters then update with any input plotParams = { 'plotColourBar': True, 'clabel': "Effective shear strain" } plotParams.update(kwargs) plot = MapPlot.create(self, self.crop(self.eMaxShear), **plotParams) return plot
def plotGrainDataMap(self, mapData=None, grainData=None, grainIds=-1, bg=0, **kwargs): """ Plot a grain map with grains coloured by given data. The data can be provided as a list of values per grain or as a map which a grain average will be applied. Parameters ---------- mapData : numpy.ndarray, optional Array of map data. This must be cropped! You must supply either mapData or grainData. grainData : list or numpy.array, optional Grain values. This an be a single value per grain or RGB values. You must supply either mapData or grainData. grainIds : list(int) or int, optional IDs of grains to plot for. Use -1 for all grains in the map. bg : int or real, optional Value to fill the background with. kwargs : Other parameters are passed to defdap.plotting.MapPlot.create. Returns ------- plot : defdap.plotting.MapPlot Plot object created. """ # Set default plot parameters then update with any input plotParams = {} plotParams.update(kwargs) if grainData is None: if mapData is None: raise ValueError("Either 'mapData' or 'grainData' must " "be supplied.") else: grainData = self.calcGrainAv(mapData, grainIds=grainIds) # Check that grains have been detected in the map self.checkGrainsDetected() if type(grainIds) is int: if grainIds == -1: grainIds = range(len(self)) else: grainIds = [grainIds] grainData = np.array(grainData) if grainData.shape[0] != len(grainIds): raise Exception("The length of supplied grain data does not" "match the number of grains.") if len(grainData.shape) == 1: mapShape = [self.yDim, self.xDim] elif len(grainData.shape) == 2 and grainData.shape[1] == 3: mapShape = [self.yDim, self.xDim, 3] else: raise Exception("The grain data supplied must be either a" "single value or RGB values per grain.") grainMap = np.full(mapShape, bg, dtype=grainData.dtype) for grainId, grainValue in zip(grainIds, grainData): grain = self.grainList[grainId] for coord in grain.coordList: grainMap[coord[1], coord[0]] = grainValue plot = MapPlot.create(self, grainMap, **plotParams) return plot
def plotAverageGrainSchmidFactorsMap(self, planes=None, directions=None, **kwargs): """ Plot maximum Schmid factor map, based on average grain orientation (for all slip systems unless specified) :param planes: Plane ID(s) to consider (optional) :type planes: list :param directions: Direction ID(s) to consider (optional) :type directions: list :param plotGBs: Plots grain boundaries if True :param boundaryColour: Colour of grain boundaries :param dilateBoundaries: Dilates grain boundaries if True :type boundaryColour: string :return: """ # Set default plot parameters then update with any input plotParams = { 'vmin': 0, 'vmax': 0.5, 'cmap': 'gray', 'plotColourBar': True, 'cLabel': "Schmid factor" } plotParams.update(kwargs) # Check that grains have been detected in the map self.checkGrainsDetected() self.averageSchmidFactor = np.zeros([self.yDim, self.xDim]) if self[0].averageSchmidFactors is None: raise Exception("Run 'calcAverageGrainSchmidFactors' first") for grain in self.grainList: currentSchmidFactor = [] if planes is not None: # Error catching if np.max(planes) > len(self.slipSystems) - 1: raise Exception("Check plane IDs exists, IDs range from 0 " "to {0}".format(len(self.slipSystems) - 1)) for plane in planes: if directions is not None: for direction in directions: currentSchmidFactor.append(grain.averageSchmidFactors[plane][direction]) else: currentSchmidFactor.append(grain.averageSchmidFactors[plane]) # TODO: what is this doing? currentSchmidFactor = [max(s) for s in zip(*currentSchmidFactor)] else: currentSchmidFactor = [max(s) for s in zip(*grain.averageSchmidFactors)] # Fill grain with colour for coord in grain.coordList: self.averageSchmidFactor[coord[1], coord[0]] = currentSchmidFactor[0] self.averageSchmidFactor[self.averageSchmidFactor == 0] = 0.5 plot = MapPlot.create(self, self.averageSchmidFactor, **plotParams) return plot