download as script · edit page

A junction is a boundary vertex where the number of meeting grain boundary segments is not two. On a square measurement grid, four pixels meet at every interior vertex. A checkerboard arrangement of two labels can therefore create a junction with four boundary segments - a quadruple point.

The ambiguity is diagonal connectivity. Connecting one pair of like pixels separates the other pair, while connecting the other pair reverses that decision. The resulting grain count can depend on which diagonal is chosen because a grain is a spatially connected region.

Exact four-way contacts in a two-dimensional physical network are usually unstable and split into three-segment junctions. The grid contact on this page is instead a digital-topology ambiguity introduced by sampling. In three dimensions, a physical quadruple point has a different meaning.

The removeQuadruplePoints option to calcGrains resolves this ambiguity during reconstruction. This page assumes the reconstruction concepts introduced in Grain Reconstruction.

import numpy as np
from mtex import *
# display matrix rows downwards and columns to the right
plottingConvention.default('y↓→x')

Construct a diagonal contact

This artificial map contains one crystal phase and two orientations. The pixels selected by ring form a ring whose ends touch diagonally at its lower corner.

cs = crystalFrame('1', mineral='test')

ring = np.array([
  [0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 0, 0, 0, 0, 0]]) == 1

# one orientation on the ring and the identity on the background
rot = rotation.byEuler(np.where(ring, 130 * degree, 0.0), np.where(ring, 120 * degree, 0.0), np.where(ring, 110 * degree, 0.0))

ebsd = EBSDsquare(rot, np.ones(ring.shape, dtype=int), ['notIndexed', cs])

# compute orientation colours explicitly to keep the output focused
colorKey = ipfColorKey(ebsd)
ebsdColors = colorKey.orientation2color(ebsd.orientations)
plot(ebsd, ebsdColors, micronbar='off')

The two colours meet in a checkerboard pattern at the lower contact. The picture alone cannot say which diagonal should be connected.

Reconstruct without resolving the junction

Ordinary reconstruction closes the oriented ring at the diagonal contact. It then treats the identity-oriented interior and exterior as separate grains, so the map contains three grains rather than two.

grainsWithQuadruple = calcGrains(ebsd, angle=10 * degree)

print(f'ordinary reconstruction: {len(grainsWithQuadruple)} grains')

grainColors = colorKey.orientation2color(grainsWithQuadruple.meanOrientation)
plot(grainsWithQuadruple, grainColors, micronbar='off')
hold(True)
plot(grainsWithQuadruple.boundary, lineWidth=2)
hold(False)
ordinary reconstruction: 3 grains

The interior patch has its own outline. At the diagonal contact, four thick boundary segments end at the same vertex.

Resolve the junction during reconstruction

The removeQuadruplePoints option selects the other diagonal. It keeps the like-oriented interior and exterior connected; the ring pixels were already connected to each other elsewhere. The expected two grains remain.

grains = calcGrains(ebsd, angle=10 * degree, removeQuadruplePoints=True)

print(f'resolved reconstruction: {len(grains)} grains')
print(f'total boundary length: {np.sum(grainsWithQuadruple.boundary.segLength):g} before, '
      f'{np.sum(grains.boundary.segLength):g} after')
print(f'strict triple points: {len(grains.triplePoints)}')

grainColors = colorKey.orientation2color(grains.meanOrientation)
plot(grains, grainColors, micronbar='off')
hold(True)
plot(grains.boundary, lineWidth=2)
hold(False)
resolved reconstruction: 2 grains
total boundary length: 52 before, 52 after
strict triple points: 0

The interior outline has joined the exterior network, while the boundary segments and their total length are unchanged. Only their connectivity at the critical vertex differs.

The option replaces the four-segment vertex with two coincident three-segment junctions. In this two-grain example they are not strict triple points, because a triple point must separate three distinct real grains. See Triple Points for that distinction.

Separate the coincident junctions for display

The two replacement junctions initially have identical coordinates. smoothBoundary normally fixes every junction. Its moveTriplePoints option releases every interior junction, despite the narrower name, and lets the two points move apart.

A taubinFilter suppresses the pixel staircase while limiting the systematic area loss of Laplacian smoothing.

grains = smoothBoundary(grains, taubinFilter(), moveTriplePoints=True)

grainColors = colorKey.orientation2color(grains.meanOrientation)
plot(grains, grainColors, lineWidth=2, micronbar='off')

The coincident contact has opened into a narrow neck. Smoothing has moved the geometry for display; it did not perform the topological correction.

Curvature at the opened contact

Signed curvature makes the opened pinch visible as neighbouring bends in opposite directions.

gB = grains[1].boundary

plot(gB, gB.curvature(10), lineWidth=6, micronbar='off')
mtexColorMap('blue2red')
setColorRange(0.5 * np.array([-1, 1]))
mtexColorbar(title='signed curvature in 1/grid unit')

The blue and red extrema beside the pinch have opposite signs. The sign depends on the stored walk direction, so use Boundary Curvature before interpreting it as convex or concave relative to a particular grain.

References

Next

Continue with Boundary Intersections for geometric crossings between boundaries and other curves. For the two operations used here, see Grain Boundary Smoothing and Boundary Curvature.

Technical Details

EBSDsquare(rotations, phaseId, CSList) builds a map on a square grid from an array of rotations, MATLAB’s constructor of the same name; the rows of the array are the rows of pixels. An array of identities is written as rotation.byEuler of three arrays, where MATLAB has rotation.id(size).

MATLAB numbers the ring grain 1 and the surrounding grain 2, the port the other way round, so the curvature is drawn for grains[1] where MATLAB writes grains(1). The smaller id is the first side of a segment in both, so MATLAB walks the ring with the ring on its left and the port with the surrounding grain on its left, and the signs, the colours of the figure, are reversed. The inverse pole figure key of the triclinic frame colours the two orientations grey and purple where MATLAB colours them red and mint.

Citing this page. This page is part of the documentation of MTEX, a free and open source MATLAB toolbox for analyzing and modeling crystallographic textures. It was written by The MTEX Developers and is published at https://mtex-toolbox.github.io/QuadruplePoints_py.html. If you use MTEX, or reuse text or figures from this page, in your research, please cite

F. Bachmann, R. Hielscher, H. Schaeben: Texture Analysis with MTEX - Free and Open Source Software Toolbox, Solid State Phenomena 160 (2010), 63-68. 10.4028/www.scientific.net/SSP.160.63

BibTeX
@article{bachmann2010mtex,
  author  = {F. Bachmann and R. Hielscher and H. Schaeben},
  title   = {Texture Analysis with MTEX - Free and Open Source Software Toolbox},
  journal = {Solid State Phenomena},
  volume  = {160},
  pages   = {63-68},
  year    = {2010},
  doi     = {10.4028/www.scientific.net/SSP.160.63},
  url     = {https://doi.org/10.4028/www.scientific.net/SSP.160.63}
}

Other papers describing specific MTEX methods are listed under Publications — please cite the one that best fits your application. The MTEX source code is licensed under the GNU General Public License v2.0; the text and figures of this documentation are licensed under CC BY 4.0, which permits reuse — including by automated systems — provided The MTEX Developers and this page are credited.