Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ DefDAP.egg-info/

# coverage
.coverage

# vscode
.vscode
7 changes: 1 addition & 6 deletions defdap/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,12 +914,7 @@ def grain_data(self, map_data):
Array containing this grains values from the given map data.

"""
grain_data = np.zeros(len(self), dtype=map_data.dtype)

for i, coord in enumerate(self.data.point):
grain_data[i] = map_data[coord[1], coord[0]]

return grain_data
return map_data[..., self.data.point[:, 1], self.data.point[:, 0]]

def grain_map_data(self, map_data=None, grain_data=None, bg=np.nan):
"""Extract a single grain map from the given map data.
Expand Down
114 changes: 109 additions & 5 deletions defdap/file_readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,9 @@ def get_loader(data_type: str) -> 'Type[DICDataLoader]':
try:
loader = {
'davis': DavisLoader,
'openpiv': OpenPivLoader,
'openpiv': OpenPivTextLoader, #Backwards compatability
'openpivtext': OpenPivTextLoader,
'openpivbinary': OpenPivBinaryLoader
}[data_type]
except KeyError:
raise ValueError(f"No loader for DIC data of type {data_type}.")
Expand Down Expand Up @@ -741,7 +743,7 @@ def load_davis_image_data(file_name: pathlib.Path) -> np.ndarray:
return np.array(data)


class OpenPivLoader(DICDataLoader):
class OpenPivTextLoader(DICDataLoader):
def load(self, file_name: pathlib.Path) -> None:
""" Load from Open PIV .txt file.

Expand Down Expand Up @@ -777,19 +779,121 @@ def load(self, file_name: pathlib.Path) -> None:

# shape of map (from header)
shape = data[:, [col['y'], col['x']]].max(axis=0) + binning / 2
assert np.allclose(shape % binning, 0.)
shape = tuple((shape / binning).astype(int).tolist())
self.loaded_metadata['shape'] = shape

self.checkMetadata()

data = data.reshape(shape + (-1,))[::-1].transpose((2, 0, 1))

# if y descending, flip
if np.all(np.diff(data[:, col['y']].reshape(shape)[:,0])) > 0:
data = data.reshape(shape + (-1,))[::-1].transpose((2, 0, 1))

self.loaded_data.coordinate = data[[col['x'], col['y']]]
self.loaded_data.displacement = data[[col['u'], col['v']]]

self.check_data()

class OpenPivBinaryLoader(DICDataLoader):
def load(self, file_name: pathlib.Path) -> None:
""" Load from Open PIV .npz file.

Parameters
----------
file_name
Path to file

"""
if not file_name.is_file():
raise FileNotFoundError(f"Cannot open file {file_name}")

data = np.load(file_name)

# Software name and version
self.loaded_metadata['format'] = data['format']
self.loaded_metadata['version'] = data['version']

# Load binning and shape
self.loaded_metadata['binning'] = data['binning']
self.loaded_metadata['shape'] = tuple(data['shape'])

self.checkMetadata()

# if y descending, flip
if np.all(np.diff(data['y'][:,0])) > 0:
self.loaded_data.coordinate = np.array([data['x'][::-1], data['y'][::-1]])
self.loaded_data.displacement = np.array([data['u'][::-1], data['v'][::-1]])
else:
self.loaded_data.coordinate = np.array([data['x'], data['y']])
self.loaded_data.displacement = np.array([data['u'], data['v']])

self.check_data()


class PyValeLoader(DICDataLoader):
def load(self, file_name: pathlib.Path) -> None:
""" Load from PyVale csv file.

Parameters
----------
file_name
Path to file

"""
if not file_name.is_file():
raise FileNotFoundError(f"Cannot open file {file_name}")

with open(str(file_name), 'r') as f:
header = f.readline()[1:].split()
data = np.loadtxt(f, delimiter=',')
col = {
'x': 0,
'y': 1,
'u': 2,
'v': 3,
'displacement_mag': 4,
'converged': 5,
'cost': 6,
'ftol': 7,
'xtol': 8,
'num_iterations': 9,
}

# Software name and version
self.loaded_metadata['format'] = 'PyVale'
self.loaded_metadata['version'] = 'n/a'

# Sub-window width in pixels
binning_x = int(np.min(np.abs(np.diff(data[:, col['x']]))))
binning_y = int(np.max(np.abs(np.diff(data[:, col['y']]))))
assert binning_x == binning_y
binning = binning_x
self.loaded_metadata['binning'] = binning

# shape of map (from header)
shape = (
data[:, [col['y'], col['x']]].max(axis=0)
- data[:, [col['y'], col['x']]].min(axis=0)
)
assert np.allclose(shape % binning, 0.)
shape = tuple((shape / binning + 1).astype(int).tolist())
self.loaded_metadata['shape'] = shape

self.checkMetadata()

index_array = ((
data[:, [col['y'], col['x']]]
- data[:, [col['y'], col['x']]].min(axis=0)
) // binning).astype(int)
disp_dense = np.zeros(shape + (2,))
disp_dense[index_array[:, 0], index_array[:, 1]] = data[:, [col['u'], col['v']]]
print(disp_dense.shape)
disp_dense = disp_dense.transpose((2, 0, 1))

self.loaded_data.coordinate = data[[col['x'], col['y']]]
self.loaded_data.displacement = disp_dense

# self.check_data()


def read_until_string(
file: TextIO,
Expand Down
6 changes: 3 additions & 3 deletions defdap/hrdic.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def load_data(self, file_name, data_type=None):

# write final status
yield (f"Loaded {self.format} {self.version} data "
f"(dimensions: {self.xdim} x {self.xdim} pixels, "
f"(dimensions: {self.xdim} x {self.ydim} pixels, "
f"sub-window size: {self.binning} x {self.binning} pixels)")

def load_corr_val_data(self, file_name, data_type=None):
Expand Down Expand Up @@ -488,10 +488,10 @@ def generate_threshold_mask(self, mask, dilation=0, preview=True):
num_removed_crop = np.sum(self.crop(self.mask))
num_total_crop = self.x_dim * self.y_dim

print('Filtering will remove {0} \ {1} ({2:.3f} %) datapoints in map'
print('Filtering will remove {0} / {1} ({2:.3f} %) datapoints in map'
.format(num_removed, num_total, (num_removed / num_total) * 100))
print(
'Filtering will remove {0} \ {1} ({2:.3f} %) datapoints in cropped map'
'Filtering will remove {0} / {1} ({2:.3f} %) datapoints in cropped map'
.format(num_removed_crop, num_total_crop,
(num_removed_crop / num_total_crop * 100)))

Expand Down
4 changes: 2 additions & 2 deletions defdap/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ def save_file(self,

"""

with open(self.selected_dic_map.path + str(self.filename), 'w') as file:
with open(self.selected_dic_map.file_name.parent / str(self.filename), 'w') as file:
file.write('# This is a file generated by defdap which contains ')
file.write('definitions of slip lines drawn in grains by grainInspector\n')
file.write('# [(x0, y0, x1, y1), angle, groupID]\n')
Expand Down Expand Up @@ -631,7 +631,7 @@ def load_file(self,

"""

with open(self.selected_dic_map.path + str(self.filename), 'r') as file:
with open(self.selected_dic_map.file_name.parent / str(self.filename), 'r') as file:
lines = file.readlines()

# Parse file and make list of
Expand Down
15 changes: 15 additions & 0 deletions docs/source/papers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,24 @@ Papers

Here is a list of papers which have used the DefDAP Python library.

2025
------

* `B.Yang, X.Xu, D.Lunt, F.Zhang, M.D.Atkinson, Y.Li, J.LLorca, X.Zhou. Grain size dependence of microscopic strain distribution in a high entropy alloy at the onset of plastic deformation. Acta Materialia. Volume 285, Feb 2025, 120682. <https://doi.org/10.1016/j.actamat.2024.120682>`_

* `D.Hu, A.D.Smith, D.Lunt, R.Thomas, M.D.Atkinson, X.Liu, Ö.Koç, J.M.Donoghue, Z.Zhang, J.Quinta da Fonseca, M.Preuss, Tracking the onset of plasticity in a Ni-base superalloy using in-situ High-Resolution Digital Image Correlation. Materialia. Volume 220, Feb 2025, 114654. <https://doi.org/10.1016/j.matchar.2024.114654>`_

2024
------

* `S.Cao, R.Thomas, A.D.Smith, P.Zhang, L.Meng, H.Liu, J.Guo, J.Donoghue, D.Lunt. The effect of a keyhole defect on strain localisation in an additive manufactured titanium alloy. Journal of Materials Research and Technology. Volume 33, Nov–Dec 2024. Pages 9664-9673. <https://doi.org/10.1016/j.jmrt.2024.11.237>`_

* `B.Poole, A.Marsh, D.Lunt, C.Hardie, M.Gorley, C.Hamelin, A.Harte. Nanoscale speckle patterning for combined high-resolution strain and orientation mapping of environmentally sensitive materials. Strain. Volume 60. Issue 6. Dec 2024. <https://doi.org/10.1111/str.12477>`_

* `R.Nia, C.J.Boehlert, Y.Zenga, B.Chen, S.Huang, J.Zheng, H.Zhou, Q.Wang, D.Yin. Automated analysis framework of strain partitioning and deformation mechanisms via multimodal fusion and computer vision. International Journal of Plasticity. Volume 182. 2024. 104119. <https://doi.org/10.1016/j.ijplas.2024.104119>`_

* `E. Nieto-Valeiras, A. Orozco-Caballero, M. Sarebanzadeh, J. Sun, J. LLorca. Analysis of slip transfer across grain boundaries in Ti via diffraction contrast tomography and high-resolution digital image correlation: When the geometrical criteria are not sufficient. Volume 175, April 2024, 103941. <https://doi.org/10.1016/j.ijplas.2024.103941>`_

* `I.Alakiozidis, C.Hunt, R.Thomas, D.Lunt, A.D.Smith, M.Maric, Z.Shah, A.Ambard, P.Frankel. Quantifying cracking and strain localisation in a cold spray chromium coating on a zirconium alloy substrate under tensile loading at room temperature. Journal of Nuclear Materials. Apr 2024. 154899. <https://doi.org/10.1016/j.jnucmat.2024.154899>`_

* `B.Poole, A.Marsh, D.Lunt, M.Gorley, C.Hamelin, C. Hardie, A.Harte. High-resolution strain mapping in a thermionic LaB6 scanning electron microscope. Strain. Feb 2024. <https://doi.org/10.1111/str.12472>`_
Expand Down
2 changes: 1 addition & 1 deletion tests/test_ebsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def test_calc(mock_map, min_grain_size):
f'{EXPECTED_RESULTS_DIR}/ebsd_grains_5deg_{min_grain_size}.npz'
)['grains']

assert np.alltrue(result == expected)
assert np.all(result == expected)

@staticmethod
def test_add_derivative(mock_map):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_hrdic.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def test_calc_warp(mock_map, algorithm, min_grain_size):
f'{EXPECTED_RESULTS_DIR}/hrdic_grains_{algorithm}{min_grain_size}.npz'
)['grains']

assert np.alltrue(result == expected)
assert np.all(result == expected)

@staticmethod
def test_add_derivative(mock_map):
Expand Down