@@ -69,125 +69,98 @@ def get_cell_params(spg, hkls, two_thetas, wave_length=1.54184):
6969 thetas = np .radians (two_thetas / 2 )
7070 d_spacings = wave_length / (2 * np .sin (thetas ))
7171
72- cell_values = []
72+ cells = []
7373 if spg >= 195 : # cubic, only need a
7474 h_sq_sum = np .sum (hkls ** 2 , axis = 1 )
75- a_values = d_spacings * np .sqrt (h_sq_sum )
76- cell_values = [[a ] for a in a_values if 0 < a < 50 ]
75+ cells = d_spacings * np .sqrt (h_sq_sum )
76+ cells = cells [cells < 50.0 ]
77+ cells = np .reshape (cells , [len (cells ), 1 ])
7778
7879 elif 143 <= spg <= 194 : # hexagonal, need a and c
7980 # need two hkls to determine a and c
8081 len_solutions = len (hkls ) // 2
81- for i in range (len_solutions ):
82- (h1 , k1 , l1 ), (h2 , k2 , l2 ) = hkls [2 * i ], hkls [2 * i + 1 ]
83- theta1 = np .radians (two_thetas [2 * i ] / 2 )
84- theta2 = np .radians (two_thetas [2 * i + 1 ] / 2 )
85- d1 = wave_length / (2 * np .sin (theta1 ))
86- d2 = wave_length / (2 * np .sin (theta2 ))
87- A = np .array ([[4 / 3 * (h1 ** 2 + h1 * k1 + k1 ** 2 ), l1 ** 2 ],
88- [4 / 3 * (h2 ** 2 + h2 * k2 + k2 ** 2 ), l2 ** 2 ]])
89- b = np .array ([1 / d1 ** 2 , 1 / d2 ** 2 ])
90- try :
91- x = np .linalg .solve (A , b )
92- if x [0 ] <= 0 or x [1 ] <= 0 :
93- continue
94- a = np .sqrt (1 / x [0 ])
95- c = np .sqrt (1 / x [1 ])
96- if a > 50 : continue
97- cell_values .append ((a , c ))
98- except np .linalg .LinAlgError :
99- continue
82+ ds = (2 * np .sin (thetas ) / wave_length )** 2
83+ A = np .zeros ([len (hkls ), 2 ])
84+ A [:, 0 ] = 4 / 3 * (hkls [:, 0 ] ** 2 + hkls [:, 0 ] * hkls [:, 1 ] + hkls [:, 1 ] ** 2 )
85+ A [:, 1 ] = hkls [:, 2 ] ** 2
86+ B = np .reshape (ds , [len_solutions , 2 ])
87+ A = np .reshape (A , [len_solutions , 2 , 2 ])#; print(A.shape, B.shape)
88+ xs = np .linalg .solve (A , B )#; print(xs); import sys; sys.exit()
89+ xs = xs [xs [:, 0 ] > 0 ]
90+ xs = xs [xs [:, 1 ] > 0 ]
91+ cells = np .sqrt (1 / xs )
92+ cells = cells [cells [:, 0 ] < 50.0 ]
10093
10194 elif 75 <= spg <= 142 : # tetragonal, need a and c
10295 # need two hkls to determine a and c
10396 len_solutions = len (hkls ) // 2
104- for i in range (len_solutions ):
105- (h1 , k1 , l1 ), (h2 , k2 , l2 ) = hkls [2 * i ], hkls [2 * i + 1 ]
106- theta1 = np .radians (two_thetas [2 * i ] / 2 )
107- theta2 = np .radians (two_thetas [2 * i + 1 ] / 2 )
108- d1 = wave_length / (2 * np .sin (theta1 ))
109- d2 = wave_length / (2 * np .sin (theta2 ))
110- A = np .array ([[h1 ** 2 + k1 ** 2 , l1 ** 2 ],
111- [h2 ** 2 + k2 ** 2 , l2 ** 2 ]])
112- b = np .array ([1 / d1 ** 2 , 1 / d2 ** 2 ])
113- try :
114- x = np .linalg .solve (A , b )
115- if x [0 ] <= 0 or x [1 ] <= 0 :
116- continue
117- a = np .sqrt (1 / x [0 ])
118- c = np .sqrt (1 / x [1 ])
119- if a > 50 : continue
120- cell_values .append ((a , c ))
121- except np .linalg .LinAlgError :
122- continue
97+ ds = (2 * np .sin (thetas ) / wave_length )** 2
98+ A = np .zeros ([len (hkls ), 2 ])
99+ A [:, 0 ] = hkls [:, 0 ] ** 2 + hkls [:, 1 ] ** 2
100+ A [:, 1 ] = hkls [:, 2 ] ** 2
101+ B = np .reshape (ds , [len_solutions , 2 ])
102+ A = np .reshape (A , [len_solutions , 2 , 2 ])#; print(A.shape, B.shape)
103+ xs = np .linalg .solve (A , B )#; print(xs); import sys; sys.exit()
104+ xs = xs [xs [:, 0 ] > 0 ]
105+ xs = xs [xs [:, 1 ] > 0 ]
106+ cells = np .sqrt (1 / xs )
107+ cells = cells [cells [:, 0 ] < 50.0 ]
108+
123109 elif 16 <= spg <= 74 : # orthorhombic, need a, b, c
124110 # need three hkls to determine a, b, c
125111 len_solutions = len (hkls ) // 3
126- for i in range (len_solutions ):
127- (h1 , k1 , l1 ), (h2 , k2 , l2 ), (h3 , k3 , l3 ) = hkls [3 * i ], hkls [3 * i + 1 ], hkls [3 * i + 2 ]
128- theta1 = np .radians (two_thetas [3 * i ] / 2 )
129- theta2 = np .radians (two_thetas [3 * i + 1 ] / 2 )
130- theta3 = np .radians (two_thetas [3 * i + 2 ] / 2 )
131- d1 = wave_length / (2 * np .sin (theta1 ))
132- d2 = wave_length / (2 * np .sin (theta2 ))
133- d3 = wave_length / (2 * np .sin (theta3 ))
134- A = np .array ([[h1 ** 2 , k1 ** 2 , l1 ** 2 ],
135- [h2 ** 2 , k2 ** 2 , l2 ** 2 ],
136- [h3 ** 2 , k3 ** 2 , l3 ** 2 ]])
137- b = np .array ([1 / d1 ** 2 , 1 / d2 ** 2 , 1 / d3 ** 2 ])
138- try :
139- x = np .linalg .solve (A , b )
140- if x [0 ] <= 0 or x [1 ] <= 0 or x [2 ] <= 0 :
141- continue
142- a = np .sqrt (1 / x [0 ])
143- b = np .sqrt (1 / x [1 ])
144- c = np .sqrt (1 / x [2 ])
145- if a > 50 or b > 50 or c > 50 : continue
146- cell_values .append ((a , b , c ))
147- except np .linalg .LinAlgError :
148- continue
112+ ds = (2 * np .sin (thetas ) / wave_length )** 2
113+ A = np .zeros ([len (hkls ), 3 ])
114+ A [:, 0 ] = hkls [:, 0 ] ** 2
115+ A [:, 1 ] = hkls [:, 1 ] ** 2
116+ A [:, 2 ] = hkls [:, 2 ] ** 2
117+ B = np .reshape (ds , [len_solutions , 3 ])
118+ A = np .reshape (A , [len_solutions , 3 , 3 ])#; print(A.shape, B.shape)
119+ xs = np .linalg .solve (A , B )#; print(xs); import sys; sys.exit()
120+ xs = xs [xs [:, 0 ] > 0 ]
121+ xs = xs [xs [:, 1 ] > 0 ]
122+ xs = xs [xs [:, 2 ] > 0 ]
123+ cells = np .sqrt (1 / xs )
124+ cells = cells [np .all (cells [:, :3 ] < 50.0 , axis = 1 )]
149125
150126 elif 3 <= spg <= 15 : # monoclinic, need a, b, c, beta
151127 # need four hkls to determine a, b, c, beta
152- N = 4
153- len_solutions = len (hkls ) // N
154- for i in range (len_solutions ):
155- hkls_sub = hkls [N * i :N * i + N ]
156- thetas_sub = np .radians (two_thetas [N * i :N * i + N ]/ 2 )
157- d_sub = (2 * np .sin (thetas_sub ) / wave_length )** 2
158- h1 , k1 , l1 = hkls_sub [0 ]
159- h2 , k2 , l2 = hkls_sub [1 ]
160- h3 , k3 , l3 = hkls_sub [2 ]
161- h4 , k4 , l4 = hkls_sub [3 ]
162- d1 , d2 , d3 , d4 = d_sub [0 ], d_sub [1 ], d_sub [2 ], d_sub [3 ]
163- A = np .array ([[h1 ** 2 , k1 ** 2 , l1 ** 2 , h1 * l1 ],
164- [h2 ** 2 , k2 ** 2 , l2 ** 2 , h2 * l2 ],
165- [h3 ** 2 , k3 ** 2 , l3 ** 2 , h3 * l3 ],
166- [h4 ** 2 , k4 ** 2 , l4 ** 2 , h4 * l4 ]])
167- b = np .array ([d1 , d2 , d3 , d4 ])
168- #print(A, b)
169- try :
170- x = np .linalg .solve (A , b )#; print(A, x)
171- a1 , a2 , a3 , a4 = x
172- if a1 <= 0 or a2 <= 0 or a3 <= 0 : continue
173- b = np .sqrt (1 / a2 )#; print('b value', b); import sys; sys.exit()
174- cos_beta = - a4 / (2 * np .sqrt (a1 ) * np .sqrt (a3 ))
175- if cos_beta < - 1 or cos_beta > 1 : continue
176- betar = np .arccos (cos_beta )
177- sin_beta = np .sin (betar )
178- if sin_beta <= np .sin (np .pi / 6 ): continue
179- a = np .sqrt (1 / a1 ) / sin_beta
180- c = np .sqrt (1 / a3 ) / sin_beta
181- if a > 50 or b > 50 or c > 50 : continue
182- cell_values .append ((a , b , c , np .degrees (betar )))
183- #print(h1, k1, l1, cell_values[-1])
184- except np .linalg .LinAlgError :
185- continue
128+ len_solutions = len (hkls ) // 4
129+ thetas = np .radians (two_thetas / 2 )
130+ ds = (2 * np .sin (thetas ) / wave_length )** 2
131+ # hkls (4*N, 3) A=> N, 4, 4
132+ A = np .zeros ([len (hkls ), 4 ])
133+ A [:, 0 ] = hkls [:, 0 ] ** 2
134+ A [:, 1 ] = hkls [:, 1 ] ** 2
135+ A [:, 2 ] = hkls [:, 2 ] ** 2
136+ A [:, 3 ] = hkls [:, 0 ] * hkls [:, 2 ]
137+ B = np .reshape (ds , [len_solutions , 4 ])
138+ A = np .reshape (A , [len_solutions , 4 , 4 ])#; print(A.shape, B.shape)
139+ xs = np .linalg .solve (A , B )#; print(xs); import sys; sys.exit()
140+ xs = xs [xs [:, 0 ] > 0 ]
141+ xs = xs [xs [:, 1 ] > 0 ]
142+ xs = xs [xs [:, 2 ] > 0 ]
143+ cos_betas = - xs [:, 3 ] / (2 * np .sqrt (xs [:, 0 ] * xs [:, 2 ]))
144+ masks = np .abs (cos_betas ) <= 1 / np .sqrt (2 )
145+ xs = xs [masks ]
146+ cos_betas = cos_betas [masks ]
147+ sin_betas = np .sqrt (1 - cos_betas ** 2 )
148+ cells = np .zeros ([len (xs ), 4 ])
149+ cells [:, 1 ] = np .sqrt (1 / xs [:, 1 ])
150+ cells [:, 3 ] = np .degrees (np .arccos (cos_betas ))
151+ cells [:, 0 ] = np .sqrt (1 / xs [:, 0 ]) / sin_betas
152+ cells [:, 2 ] = np .sqrt (1 / xs [:, 2 ]) / sin_betas
153+
154+ # force angle to be less than 90
155+ mask = cells [:, 3 ] > 90.0
156+ cells [mask , 3 ] = 180.0 - cells [mask , 3 ]
157+ cells = cells [np .all (cells [:, :3 ] < 50.0 , axis = 1 )]
158+ #print(cells)
186159 else :
187160 msg = "Only cubic, tetragonal, hexagonal, and orthorhombic systems are supported."
188161 raise NotImplementedError (msg )
189162
190- return cell_values
163+ return cells
191164
192165def get_d_hkl_from_cell (spg , cells , h , k , l ):
193166 """
@@ -382,6 +355,10 @@ def get_cell_from_multi_hkls(spg, hkls, two_thetas, long_thetas=None, wave_lengt
382355
383356 cells = np .array (cells )
384357 if len (cells ) == 0 : return []
358+ # keep cells up to 4 decimal places
359+ if spg < 16 :
360+ cells [:, - 1 ] = np .round (cells [:, - 1 ], decimals = 2 )
361+ cells [:, :3 ] = np .round (cells [:, :3 ], decimals = 4 )
385362 cells = np .unique (cells , axis = 0 )#; print(cells) # remove duplicates
386363
387364 # get the maximum h from assuming the cell[-1] is (h00)
@@ -434,6 +411,7 @@ def get_cell_from_multi_hkls(spg, hkls, two_thetas, long_thetas=None, wave_lengt
434411 avg_error = np .mean ([match [- 1 ] for match in matched_peaks ])
435412 consistency_score = 1.0 / (1.0 + avg_error ) # lower error = higher score
436413 score = coverage * consistency_score
414+ #print("Cell:", cell, "Matched:", n_matched, "Score:", score)
437415
438416 if score > min_score :
439417 solutions .append ({
@@ -450,10 +428,12 @@ def get_cell_from_multi_hkls(spg, hkls, two_thetas, long_thetas=None, wave_lengt
450428 from pyxtal import pyxtal
451429 from itertools import combinations
452430 np .set_printoptions (precision = 4 , suppress = True )
453-
431+
454432 xtal = pyxtal ()
455- #xtal.from_seed('pyxtal/database/cifs/JVASP-62168.cif')
456- xtal .from_seed ('pyxtal/database/cifs/JVASP-98225.cif' )
433+ xtal .from_seed ('pyxtal/database/cifs/JVASP-62168.cif' )
434+ #xtal.from_seed('pyxtal/database/cifs/JVASP-98225.cif')
435+ #xtal.from_seed('pyxtal/database/cifs/JVASP-50935.cif')
436+ #xtal.from_seed('pyxtal/database/cifs/JVASP-28565.cif')
457437 xrd = xtal .get_XRD (thetas = [0 , 120 ], SCALED_INTENSITY_TOL = 0.5 )
458438 cell_ref = np .sort (np .array (xtal .lattice .encode ()))
459439 long_thetas = xrd .pxrd [:15 , 0 ]
@@ -465,17 +445,23 @@ def get_cell_from_multi_hkls(spg, hkls, two_thetas, long_thetas=None, wave_lengt
465445 if spg >= 16 :
466446 guesses = xtal .group .generate_hkl_guesses (2 , 3 , 5 , max_square = 29 , total_square = 40 , verbose = True )
467447 else :
468- guesses = xtal .group .generate_hkl_guesses (2 , 2 , 2 , max_square = 20 , total_square = 30 , verbose = True )
448+ guesses = xtal .group .generate_hkl_guesses (3 , 3 , 6 , max_square = 38 , total_square = 48 , verbose = True )
469449 guesses = np .array (guesses )
470450 print ("Total guesses:" , len (guesses ))
471451 sum_squares = np .sum (guesses ** 2 , axis = (1 ,2 ))
472452 sorted_indices = np .argsort (sum_squares )
473453 guesses = guesses [sorted_indices ]
474454 #guesses = np.array([[[2, 0, 0], [1, 1, 0], [0, 1, 1], [0, 0, 2]]])
475455 #guesses = np.array([[[2, 0, 0], [1, 1, 0], [0, 0, 2], [2, 0, -2]]])
456+ #guesses = np.array([[[0, 2, 0], [0, 0, 1], [1, 0, 0], [1, 0, -1]]])
476457
477458 # Check the quality of each (hkl, 2theta) solutions
459+ cell2 = np .sort (np .array (xtal .lattice .encode ()))
460+ if spg <= 15 and cell2 [3 ] > 90 : cell2 [3 ] = 180 - cell2 [3 ]
461+ cells_all = np .reshape (cell2 , (1 , len (cell2 )))
462+
478463 for guess in guesses [:]:
464+ #print('New guess', guess.flatten())
479465 found = False
480466 n_peaks = len (guess )
481467
@@ -490,75 +476,19 @@ def get_cell_from_multi_hkls(spg, hkls, two_thetas, long_thetas=None, wave_lengt
490476
491477 solutions = get_cell_from_multi_hkls (spg , hkls_t , thetas , long_thetas , use_seed = False )
492478 for sol in solutions :
493- d2 = np .sum (guess ** 2 )
494- print ("Guess:" , guess .flatten (), d2 , "->" , sol ['cell' ], thetas [:len (guess )], "Score:" , sol ['score' ])
495479 cell1 = np .sort (np .array (sol ['cell' ]))
496- diff = np .sum ((cell1 - cell_ref )** 2 )
497- if diff < 0.1 :
480+ if spg <= 15 and cell1 [3 ] > 90 : cell1 [3 ] = 180 - cell1 [3 ]
481+
482+ # Check if it is a new solution
483+ diffs = np .sum ((cells_all - cell1 )** 2 , axis = 1 )
484+ if len (cells_all [diffs < 0.1 ]) == 0 :
485+ print ("Guess:" , guess .flatten (), np .sum (guess ** 2 ), "->" , cell1 , sol ['score' ])
486+ cells_all = np .vstack ((cells_all , cell1 ))
487+
488+ if diffs [0 ] < 0.1 : #result['score'] > 0.9999:
489+ print ("Guess:" , guess .flatten (), np .sum (guess ** 2 ), "->" , cell1 , sol ['score' ])
498490 print ("High score, exiting early." )
499491 found = True
500492 break
501493 if found :
502494 break
503-
504-
505- #guesses = [
506- # [(1, 1, 1), (2, 2, 0), (3, 1, 1)],
507- # [(0, 0, 2), (1, 0, 0)],#, (1, 0, 1)],
508- # [(0, 0, 2), (1, 0, 1), (1, 1, 0)],
509- # [(1, 0, 0), (1, 0, 1), (1, 1, 0)],
510- # [(2, 0, 0), (1, 0, 1), (2, 1, 0)],
511- # [(1, 0, 0), (1, 1, 1), (1, 0, 2)],
512- # [(1, 0, 1), (1, 1, 1), (3, 1, 1)],
513- # [(2, 2, 0), (3, 1, 1), (2, 2, 2)],
514- # [(1, 1, 1), (2, 0, 0), (2, 2, 0)],
515- # [(1, 1), (2, 0, 0), (2, 2, 0)], # test bad case
516- # [(0, 0, 1), (2, 0, -1), (2, 0, 1), (4, 0, 0), (1, 1, 0)],
517- # ]
518- #for prototype in ["diamond", "graphite", "a-cristobalite", "olivine", "beta-Ga2O3"]:
519- # xtal.from_prototype(prototype)
520- # xrd = xtal.get_XRD(thetas=[0, 120], SCALED_INTENSITY_TOL=0.5)
521- # spg = xtal.group.number
522- # print("\nTesting prototype:", prototype, xtal.lattice, xtal.group.symbol, xtal.group.number)
523- # print(xrd.by_hkl(N_max=10))
524- # if True:
525- # if xtal.group.number >= 195:
526- # guesses = xtal.group.generate_hkl_guesses(3, max_square=16)
527- # elif xtal.group.number >= 75:
528- # guesses = xtal.group.generate_hkl_guesses(2, 2, 6, max_square=36)
529- # elif xtal.group.number >= 16:
530- # guesses = xtal.group.generate_hkl_guesses(3, 3, 3, max_square=20)
531- # else:
532- # guesses = xtal.group.generate_hkl_guesses(4, 2, 2, max_square=17, verbose=True)
533-
534- # guesses = np.array(guesses)
535- # print("Total guesses:", len(guesses))
536- # sum_squares = np.sum(guesses**2, axis=(1,2))
537- # sorted_indices = np.argsort(sum_squares)
538- # guesses = guesses[sorted_indices]
539-
540- # for guess in guesses:
541- # hkls = [tuple(hkl) for hkl in guess if len(hkl) == 3]
542- # if len(hkls)>3 and (hkls[0] == (1, 1, -1) and hkls[1] == (0, 0, -1) and hkls[2] == (2, 0, -1)):
543- # print("Trying guess:", hkls)
544- # run = True
545- # else:
546- # run = False
547- # n_peaks = len(guess)
548- # # select n peaks from first n+1 peaks, skipping a peak
549- # exit = False
550- # if n_peaks < len(xrd.pxrd):
551- # available_peaks = xrd.pxrd[:n_peaks+1, 0]
552- # # Try each combination of n peaks from the first n+1 peaks
553- # for peak_combo in combinations(range(n_peaks+1), n_peaks):
554- # theta = available_peaks[list(peak_combo)]
555- # result = get_cell_from_multi_hkls(spg, hkls, theta, xrd.pxrd[:15, 0])
556- # if result is not None and result['score'] > 0.95:
557- # print("Guess:", hkls, "->", result['cell'], "Score:", result['score'],
558- # "Matched peaks:", result['n_matched'], "/", result['n_total'])
559- # if result['score'] > 0.992:
560- # print("High score, exiting early.")
561- # exit = True
562- # break
563- # if exit:
564- # break
0 commit comments