Skip to content

Commit

Permalink
Merge pull request #87 from MechMicroMan/develop
Browse files Browse the repository at this point in the history
Add features
  • Loading branch information
mikesmic authored Aug 23, 2021
2 parents 1721b1d + 13b45d7 commit d8769c9
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 40 deletions.
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@
### Fixed


## 0.93.1 (16-04-2020)
## 0.93.3 (23-08-2021)

### Added
- Store EDX data as a dictionary called `EDX` accessible from the EBSD `Map` object
- Add option to change IPF map background colour

### Fixed
- Fix bug with reading cpr EBSD file without EDX data
- Fix issue with plotting Schmid factor maps
- Fix bug with maps `component` not updating after masking


## 0.93.2 (16-04-2021)

### Added
- Reading of Channel project files that contain EDX data
Expand All @@ -19,7 +31,7 @@
- Plotting lines with grain inspector


## 0.93.1 (12-04-2020)
## 0.93.1 (12-04-2021)

### Added
- Started adding type hinting
Expand All @@ -45,7 +57,7 @@
- Fix bug in 'warp' grain finding algorithm


## 0.93.0 (20-02-2020)
## 0.93.0 (20-02-2021)

### Added
- Add EBSD file writing to CTF format.
Expand Down
2 changes: 1 addition & 1 deletion defdap/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.93.2'
__version__ = '0.93.3'
53 changes: 25 additions & 28 deletions defdap/ebsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ class Map(base.Map):
Map of misorientation axis components.
kam : numpy.ndarray
Map of KAM.
averageSchmidFactor : numpy.ndarray
Map of average Schmid factor.
slipSystems : list of list of defdap.crystal.SlipSystem
Slip systems grouped by slip plane.
slipTraceColours list(str)
Expand Down Expand Up @@ -122,7 +120,6 @@ def __init__(self, fileName, dataType=None):
self.misOri = None
self.misOriAxis = None
self.kam = None
self.averageSchmidFactor = None
self.origin = (0, 0)
self.GND = None
self.Nye = None
Expand Down Expand Up @@ -167,6 +164,8 @@ def loadData(self, fileName, dataType=None):
self.bandSlopeArray = dataDict['bandSlope']
self.meanAngularDeviationArray = dataDict['meanAngularDeviation']
self.phaseArray = dataDict['phase']
if int(metadataDict['EDX Windows']['Count']) > 0:
self.EDX = dataDict['EDXDict']

# write final status
yield "Loaded EBSD data (dimensions: {:} x {:} pixels, step " \
Expand Down Expand Up @@ -329,7 +328,7 @@ def plotEulerMap(self, phases=None, **kwargs):

return MapPlot.create(self, map_colours, **plot_params)

def plotIPFMap(self, direction, phases=None, **kwargs):
def plotIPFMap(self, direction, backgroundColour = [0., 0., 0.], phases=None, **kwargs):
"""
Plot a map with points coloured in IPF colouring,
with respect to a given sample direction.
Expand All @@ -338,8 +337,10 @@ def plotIPFMap(self, direction, phases=None, **kwargs):
----------
direction : np.array len 3
Sample directiom.
backgroundColour : np.array len 3
Colour of background (i.e. for phases not plotted).
phases : list of int
Which phases to plot for
Which phases to plot IPF data for.
kwargs
Other arguments passed to :func:`defdap.plotting.MapPlot.create`.
Expand All @@ -359,7 +360,7 @@ def plotIPFMap(self, direction, phases=None, **kwargs):
phase_ids = phases
phases = [self.phases[i] for i in phase_ids]

map_colours = np.zeros(self.shape + (3,))
map_colours = np.tile(np.array(backgroundColour), self.shape + (1,))

for phase, phase_id in zip(phases, phase_ids):
# calculate IPF colours for phase
Expand Down Expand Up @@ -1299,57 +1300,53 @@ def plotAverageGrainSchmidFactorsMap(self, planes=None, directions=None,
"""
# Set default plot parameters then update with any input
plotParams = {
plot_params = {
'vmin': 0,
'vmax': 0.5,
'cmap': 'gray',
'plotColourBar': True,
'clabel': "Schmid factor"
}
plotParams.update(kwargs)
plot_params.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")

grains_sf = []
for grain in self.grainList:
currentSchmidFactor = []
current_sf = []

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])
current_sf.append(
grain.averageSchmidFactors[plane][direction]
)
else:
currentSchmidFactor.append(grain.averageSchmidFactors[plane])
# TODO: what is this doing?
currentSchmidFactor = [max(s) for s in zip(*currentSchmidFactor)]
current_sf += grain.averageSchmidFactors[plane]
else:
currentSchmidFactor = [max(s) for s in zip(*grain.averageSchmidFactors)]
for sf_group in grain.averageSchmidFactors:
current_sf += sf_group

# Fill grain with colour
for coord in grain.coordList:
self.averageSchmidFactor[coord[1], coord[0]] = currentSchmidFactor[0]
grains_sf.append(current_sf)

self.averageSchmidFactor[self.averageSchmidFactor == 0] = 0.5
grains_sf = np.array(grains_sf)
grains_sf_max = np.max(grains_sf, axis=1)

plot = MapPlot.create(self, self.averageSchmidFactor, **plotParams)
plot = self.plotGrainDataMap(grainData=grains_sf_max, bg=0.5,
**plot_params)

return plot


class Grain(base.Grain):
"""
Class to encapsulate a grain in an EBSD map and useful analysis and plotting
methods.
Class to encapsulate a grain in an EBSD map and useful analysis and
plotting methods.
Attributes
----------
Expand Down Expand Up @@ -1517,7 +1514,7 @@ def plotOriSpread(self, direction=np.array([0, 0, 1]), **kwargs):
plotParams.update(kwargs)
return Quat.plotIPF(self.quatList, direction, self.crystalSym,
**plotParams)

def plotUnitCell(self, fig=None, ax=None, plot=None, **kwargs):
"""Plot an unit cell of the average grain orientation.
Expand Down
26 changes: 20 additions & 6 deletions defdap/file_readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ def parsePhase() -> Phase:
*(np.array(acqEulers) * np.pi / 180)
)

# TODO: Load EDX data from .ctf file, if it's accesible
self.loadedMetadata['EDX Windows'] = {'Count': int(0)}

self.checkMetadata()

# Construct data format from table header
Expand Down Expand Up @@ -306,15 +309,17 @@ def parseLine(line: str, groupDict: Dict) -> None:
round(float(phaseMetadata['gamma']), 3) * np.pi / 180
)
))

# Deal with EDX data
edx_fields = {}
if 'EDX Windows' in metadata:
edx_dict = metadata['EDX Windows']
num_edx = int(edx_dict['Count'])
self.loadedMetadata['EDX Windows'] = metadata['EDX Windows']
edx_fields = {}
for i in range(1, num_edx + 1):
key = f"Window{i}"
edx_fields[100+i] = (f'EDX {edx_dict[key]}', 'float32')
for i in range(1, int(self.loadedMetadata['EDX Windows']['Count']) + 1):
name = self.loadedMetadata['EDX Windows'][f"Window{i}"]
edx_fields[100+i] = (f'EDX {name}', 'float32')
else:
self.loadedMetadata['EDX Windows'] = {'Count': int(0)}

self.checkMetadata()

Expand Down Expand Up @@ -378,6 +383,14 @@ def loadOxfordCRC(self, fileName: str, fileDir: str = "") -> None:
eulerAngles = np.reshape(
binData[['ph1', 'phi', 'ph2']], (yDim, xDim)
)

# Load EDX data into a dict
if int(self.loadedMetadata['EDX Windows']['Count']) > 0:
EDXFields = [key for key in binData.dtype.fields.keys() if key.startswith('EDX')]
self.loadedData['EDXDict'] = dict(
[(field[4:], np.reshape(binData[field], (yDim, xDim))) for field in EDXFields]
)

# flatten the structures so that the Euler angles are stored
# into a normal array
eulerAngles = np.array(eulerAngles.tolist()).transpose((2, 0, 1))
Expand Down Expand Up @@ -406,6 +419,7 @@ def load(self, dataDict: Dict[str, Any]) -> None:
self.loadedMetadata['stepSize'] = dataDict['stepSize']
assert type(dataDict['phases']) is list
self.loadedMetadata['phases'] = dataDict['phases']
self.loadedMetadata['EDX Windows'] = {'Count': int(0)}

self.checkMetadata()

Expand Down
8 changes: 6 additions & 2 deletions defdap/hrdic.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ def __init__(self, path, fname, dataType=None):
# max shear component
self.eMaxShear = np.sqrt(((self.e11 - self.e22) / 2.)**2 + self.e12**2)

# Dictionary references to all map types
self.component = {'f11': self.f11, 'f12': self.f12, 'f21': self.f21, 'f22': self.f22,
'e11': self.e11, 'e12': self.e12, 'e22': self.e22,
'eMaxShear': self.eMaxShear,
Expand All @@ -185,7 +184,7 @@ def __init__(self, path, fname, dataType=None):
self.cropDists = np.array(((0, 0), (0, 0)), dtype=int)

self.plotDefault = lambda *args, **kwargs: self.plotMaxShear(plotGBs=True, *args, **kwargs)

@property
def crystalSym(self):
return self.ebsdMap.crystalSym
Expand Down Expand Up @@ -637,6 +636,11 @@ def applyThresholdMask(self):
self.x_map = np.where(self.mask == True, np.nan, self.x_map)
self.y_map = np.where(self.mask == True, np.nan, self.y_map)

self.component = {'f11': self.f11, 'f12': self.f12, 'f21': self.f21, 'f22': self.f22,
'e11': self.e11, 'e12': self.e12, 'e22': self.e22,
'eMaxShear': self.eMaxShear,
'x_map': self.x_map, 'y_map': self.y_map}

@property
def boundaries(self):
"""Returns EBSD map grain boundaries warped to DIC frame.
Expand Down

0 comments on commit d8769c9

Please sign in to comment.