Open edwinsupple opened 3 years ago
Hi Edwin,
So, the vector matching workflow (as you've found) is not in a good way. This is for a couple of reasons, primarily due to upstream issues about dealing with ragged arrays and downstream issues to do with orix. I expect the 0.12
version will run okay, but, the following are probably better routes forward.
1) Use the template matching workflow instead if you can. This is better developed within pyxem, and has a recently been improved to give much faster results.
2) I will have a look at exactly what's going on with the issue described over the next couple of days, it may end up being just a small hiccup from the changes introduced to make the code work more nicely with orix. In which case you may well be able to just plug away with it as is. The most cursory of looks suggests that:
def crystal_from_vector_matching(z_matches):
"""Takes vector matching results for a single navigation position and
returns the best matching phase and orientation with correlation and
reliability to define a crystallographic map.
Parameters
----------
z_matches : numpy.array
Template matching results in an array of shape (m,5) sorted by
total_error (ascending) within each phase, with entries
[phase, R, match_rate, ehkls, total_error]
Returns
-------
results_array : numpy.array
Crystallographic mapping results in an array of shape (3) with entries
[phase, np.array((z, x, z)), dict(metrics)]
"""
is the function that controls the output of:
crystal_map = refined_results.get_crystallographic_map()
if that's the case then:
.isig[0]
will give you the phase and isig[1]
will give you the euler angles. Clearly inelegant, but might help...
3) If you think there is a good reason you want to do vector matching, I have short/medium term plans to rebuild some/all of this workflow, and would be happy to start a dialogue to effect.
I have used the template matching function. Vector matching was appealing because it seems like it might handle arbitrary crystal orientations better than pattern matching.
I also saw you updated the notebook, thanks for doing that. .plot_best_matching_results_on_signal()
, though, seems to show that it's mis-identifying the zinc blende DPs as wurtzite DPs. Would it do a better job matching with different parameters entered earlier?
The information about .isig
was very helpful, I was able to view the data from crystal_map
with a little more work. I'll see how this compares to the pattern matching workflow. Here's what I did to get some data from vector matching, starting from immediately after you use dp.find_peaks()
:
vectors = DiffractionVectors.from_peaks(peaks, dp.center_of_mass().data, 0.2)
#if you don't use .data it doesn't work properly.
vectors = vectors.inav[1,:10,:5,:]
#previously vectors didn't have the fourth 2 index long dimension.
#I think with :10 I am just selecting 10 peaks to index with but I'm not sure about that.
vectors.calculate_cartesian_coordinates(accelerating_voltage=accelarating_voltage,
camera_length=camera_length)
indexation_generator = VectorIndexationGenerator(vectors, vec_lib)
then the rest follows as before. I end up with crystal_map = <VectorMatchingResults, title: , dimensions: (10, 5, 45|3)>
To plot the orientations I did:
def orientation_map(crystal_map):
"""
Produce an x1 by x2 by 3 np array from a Pyxem VectorMatchingResults object.
Returns:
np array with first two dimensions of the source image, and third dimension
holding x, y, and z Euler angles.
"""
orientations = crystal_map.isig[1].data
orientations = orientations.squeeze()
new_shape = orientations.shape + (3,)
orientations_data = np.zeros(new_shape)
for i in range(new_shape[0]):
for j in range(new_shape[1]):
orientations_data[i,j,0] = orientations[i,j][0]
orientations_data[i,j,1] = orientations[i,j][1]
orientations_data[i,j,2] = orientations[i,j][2]
return orientations_data
orientations = orientation_map(crystal_map)
fig, ax3 = plt.subplots(1,3)
ax3[0].imshow(orientations[:,:,0])
ax3[1].imshow(orientations[:,:,1])
ax3[2].imshow(orientations[:,:,2])
Attaching an image from the sample data. Seems to be picking up something but not exactly great results.
I have used the template matching function. Vector matching was appealing because it seems like it might handle arbitrary crystal orientations better than pattern matching.
I also saw you updated the notebook, thanks for doing that.
.plot_best_matching_results_on_signal()
, though, seems to show that it's mis-identifying the zinc blende DPs as wurtzite DPs. Would it do a better job matching with different parameters entered earlier?
I think so, yes, the max_excitation_error
value is very large for example (which is why you see too many peaks). In checking this I also found a bug in to_crystal_map
, which means that the phase map is wrong in this stage (https://github.com/pyxem/pyxem/issues/730). We have a enough things for a patch release, so I'll fix this early next week, hopefully solving this problem for a 0.13.1
version which I can push out the door fairly quickly.
The information about
.isig
was very helpful, I was able to view the data fromcrystal_map
with a little more work. I'll see how this compares to the pattern matching workflow. Here's what I did to get some data from vector matching, starting from immediately after you usedp.find_peaks()
:vectors = DiffractionVectors.from_peaks(peaks, dp.center_of_mass().data, 0.2) #if you don't use .data it doesn't work properly.
That .data
is probably for lazy/non-lazy method reasons.
vectors = vectors.inav[1,:10,:5,:] #previously vectors didn't have the fourth 2 index long dimension. #I think with :10 I am just selecting 10 peaks to index with but I'm not sure about that.
Might be picking real space pixels, I would check the shapes.
vectors.calculate_cartesian_coordinates(accelerating_voltage=accelarating_voltage, camera_length=camera_length) indexation_generator = VectorIndexationGenerator(vectors, vec_lib)
then the rest follows as before. I end up with
crystal_map = <VectorMatchingResults, title: , dimensions: (10, 5, 45|3)>
So at a guess I would say this object is:
10 potential matches
5 x dimension
45 y dimension
3 signal bits: phase, array of eulers and dict
And I would start by checking the phase map is reasonable, as plotting euler angles can be very confusing. If that works we can think about tidying up the orientation conversion code, which at a glance looks like it's probably correct.
I am trying to work through section 4.3 in example notebook 2 in version 0.13 and am having some trouble. In particular, it appears like
get_crystallographic_map()
is just making another vector object instead of a crystal_map type object. And so then crystal_map doesn't have associatedget_phase_map()
,get_orientation_map()
functions and I am having trouble figuring out how to access the data within crystal_map. Could you please give some guidance on how to use these features?Thanks,
Edwin