Skip to content

Commit 850ad81

Browse files
author
Joel Bernier
committed
modifications to findorientations + bug fixes
1 parent ba0cb5d commit 850ad81

File tree

5 files changed

+45
-100
lines changed

5 files changed

+45
-100
lines changed

hexrd/config/findorientations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class ClusteringConfig(Config):
7070
def algorithm(self):
7171
key = 'find_orientations:clustering:algorithm'
7272
choices = ['dbscan', 'ort-dbscan', 'sph-dbscan', 'fclusterdata']
73-
temp = self._cfg.get(key, 'ort-dbscan').lower()
73+
temp = self._cfg.get(key, 'dbscan').lower()
7474
if temp in choices:
7575
return temp
7676
raise RuntimeError(

hexrd/findorientations.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,10 @@ def quat_distance(x, y):
173173
qfib_r = qfib[:, np.array(compl) > min_compl]
174174

175175
num_ors = qfib_r.shape[1]
176-
176+
177177
if num_ors > 25000:
178178
if algorithm == 'sph-dbscan' or algorithm == 'fclusterdata':
179-
logger.info("defaulting to orthographic DBSCAN")
179+
logger.info("falling back to euclidean DBSCAN")
180180
algorithm = 'ort-dbscan'
181181
#raise RuntimeError, \
182182
# "Requested clustering of %d orientations, which would be too slow!" %qfib_r.shape[1]
@@ -191,18 +191,19 @@ def quat_distance(x, y):
191191
logger.warning(
192192
"sklearn >= 0.14 required for dbscan; using fclusterdata"
193193
)
194-
194+
195195
if algorithm == 'dbscan' or algorithm == 'ort-dbscan' or algorithm == 'sph-dbscan':
196196
# munge min_samples according to options
197197
if min_samples is None or cfg.find_orientations.use_quaternion_grid is not None:
198198
min_samples = 1
199-
199+
200200
if algorithm == 'sph-dbscan':
201+
logger.info("using spherical DBSCAN")
201202
# compute distance matrix
202203
pdist = pairwise_distances(
203204
qfib_r.T, metric=quat_distance, n_jobs=1
204205
)
205-
206+
206207
# run dbscan
207208
core_samples, labels = dbscan(
208209
pdist,
@@ -212,11 +213,13 @@ def quat_distance(x, y):
212213
)
213214
else:
214215
if algorithm == 'ort-dbscan':
216+
logger.info("using euclidean orthographic DBSCAN")
215217
pts = qfib_r[1:, :].T
216-
eps = 0.9*np.radians(cl_radius)
218+
eps = 0.25*np.radians(cl_radius)
217219
else:
220+
logger.info("using euclidean DBSCAN")
218221
pts = qfib_r.T
219-
eps = np.radians(cl_radius)
222+
eps = 0.5*np.radians(cl_radius)
220223

221224
# run dbscan
222225
core_samples, labels = dbscan(
@@ -226,19 +229,20 @@ def quat_distance(x, y):
226229
metric='minkowski', p=2,
227230
)
228231

229-
# extract cluster labels
232+
# extract cluster labels
230233
cl = np.array(labels, dtype=int) # convert to array
231234
noise_points = cl == -1 # index for marking noise
232235
cl += 1 # move index to 1-based instead of 0
233236
cl[noise_points] = -1 # re-mark noise as -1
234-
logger.info("dbscan found %d noise points", sum(noise_points))
237+
logger.info("dbscan found %d noise points", sum(noise_points))
235238
elif algorithm == 'fclusterdata':
239+
logger.info("using spherical fclusetrdata")
236240
cl = cluster.hierarchy.fclusterdata(
237241
qfib_r.T,
238242
np.radians(cl_radius),
239243
criterion='distance',
240244
metric=quat_distance
241-
)
245+
)
242246
else:
243247
raise RuntimeError(
244248
"Clustering algorithm %s not recognized" % algorithm
@@ -249,26 +253,18 @@ def quat_distance(x, y):
249253
nblobs = len(np.unique(cl)) - 1
250254
else:
251255
nblobs = len(np.unique(cl))
252-
256+
253257
#import pdb; pdb.set_trace()
254-
258+
255259
""" PERFORM AVERAGING TO GET CLUSTER CENTROIDS """
256260
qbar = np.zeros((4, nblobs))
257-
if algorithm == 'sph-dbscan' or algorithm == 'fclusterdata':
258-
# here clusters can be split across fr
259-
for i in range(nblobs):
260-
npts = sum(cl == i + 1)
261-
qbar[:, i] = rot.quatAverageCluster(
262-
qfib_r[:, cl == i + 1].reshape(4, npts), qsym
263-
).flatten()
264-
pass
265-
else:
266-
# here clusters are ompact by construction
267-
for i in range(nblobs):
268-
qbar[:, i] = np.average(np.atleast_2d(qfib_r[:, cl == i + 1]), axis=1)
269-
pass
270-
qbar = sym.toFundamentalRegion(mutil.unitVector(qbar), crysSym=qsym)
271-
261+
for i in range(nblobs):
262+
npts = sum(cl == i + 1)
263+
qbar[:, i] = rot.quatAverageCluster(
264+
qfib_r[:, cl == i + 1].reshape(4, npts), qsym
265+
).flatten()
266+
pass
267+
pass
272268
logger.info("clustering took %f seconds", time.clock() - start)
273269
logger.info(
274270
"Found %d orientation clusters with >=%.1f%% completeness"
@@ -377,6 +373,8 @@ def find_orientations(cfg, hkls=None, clean=False, profile=False):
377373
else:
378374
distortion = None
379375

376+
min_compl = cfg.find_orientations.clustering.completeness
377+
380378
# start logger
381379
logger.info("beginning analysis '%s'", cfg.analysis_name)
382380

@@ -477,8 +475,9 @@ def find_orientations(cfg, hkls=None, clean=False, profile=False):
477475
refl_per_grain[i] = len(sim_results[0])
478476
num_seed_refls[i] = np.sum([sum(sim_results[0] == hkl_id) for hkl_id in hkl_ids])
479477
pass
478+
#min_samples = 2
480479
min_samples = max(
481-
np.floor(cfg.find_orientations.clustering.completeness*np.average(num_seed_refls)),
480+
int(np.floor(0.5*min_compl*min(num_seed_refls))),
482481
2
483482
)
484483
mean_rpg = int(np.round(np.average(refl_per_grain)))

hexrd/xrd/crystallography.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -863,15 +863,15 @@ def getMergedRanges(self, cullDupl=False):
863863

864864
# if you end exlcusions in a doublet (or multiple close rings)
865865
# then this will 'fail'. May need to revisit...
866-
nonoverlapNexts = np.hstack((tThRanges[:-1,1] < tThRanges[1:,0], True))
866+
nonoverlapNexts = num.hstack((tThRanges[:-1,1] < tThRanges[1:,0], True))
867867
iHKLLists = []
868868
mergedRanges = []
869869
hklsCur = []
870870
tThLoIdx = 0
871-
tThLoCur = tThHiCur = 0.
871+
tThHiCur = 0.
872872
for iHKL, nonoverlapNext in enumerate(nonoverlapNexts):
873873
print tThLoIdx
874-
ThHi = tThRanges[iHKL, -1]
874+
tThHi = tThRanges[iHKL, -1]
875875
if not nonoverlapNext:
876876
if cullDupl and abs(tThs[iHKL] - tThs[iHKL+1]) < sqrt_epsf:
877877
continue

hexrd/xrd/rotations.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -352,18 +352,10 @@ def quatAverageCluster(q_in, qsym):
352352
q_bar = quatProduct(q_in[:, 0].reshape(4, 1),
353353
quatOfExpMap(0.5*ma*unitVector(mq[1:].reshape(3, 1))))
354354
else:
355-
# use first quat as initial guess
356-
phi = 2. * arccos(q_in[0, 0])
357-
if phi <= finfo(float).eps:
358-
x0 = zeros(3)
359-
else:
360-
n = unitVector(q_in[1:, 0].reshape(3, 1))
361-
x0 = phi*n.flatten()
362-
363355
# first drag to origin using first quat (arb!)
364356
q0 = q_in[:, 0].reshape(4, 1)
365357
qrot = dot(
366-
quatProductMatrix( invertQuat( q0 ), mult='right' ),
358+
quatProductMatrix( invertQuat( q0 ), mult='left' ),
367359
q_in)
368360

369361
# second, re-cast to FR
@@ -374,7 +366,7 @@ def quatAverageCluster(q_in, qsym):
374366

375367
# unrotate!
376368
q_bar = dot(
377-
quatProductMatrix( q0, mult='right' ),
369+
quatProductMatrix( q0, mult='left' ),
378370
q_bar)
379371

380372
# re-map

hexrd/xrd/xrdutil.py

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,53 +3170,6 @@ def validateAngleRanges(angList, startAngs, stopAngs, ccw=True):
31703170
reflInRange = reflInRange | num.logical_and(zStart >= 0, zStop <= 0)
31713171
return reflInRange
31723172

3173-
def tVec_d_from_old_parfile(old_par, detOrigin):
3174-
beamXYD = old_par[:3, 0]
3175-
rMat_d = xf.makeDetectorRotMat(old_par[3:6, 0])
3176-
bVec_ref = num.c_[0., 0., -1.].T
3177-
args=(rMat_d, beamXYD, detOrigin, bVec_ref)
3178-
tvd_xy = opt.leastsq(objFun_tVec_d, -beamXYD[:2], args=args)[0]
3179-
return num.hstack([tvd_xy, -beamXYD[2]]).reshape(3, 1)
3180-
3181-
def objFun_tVec_d(tvd_xy, rMat_d, beamXYD, detOrigin, bHat_l):
3182-
"""
3183-
"""
3184-
xformed_xy = beamXYD[:2] - detOrigin
3185-
tVec_d = num.hstack([tvd_xy, -beamXYD[2]]).T
3186-
n_d = rMat_d[:, 2]
3187-
3188-
bVec_l = (num.dot(n_d, tVec_d) / num.dot(n_d, bHat_l)) * bHat_l
3189-
bVec_d = num.hstack([xformed_xy, 0.]).T
3190-
3191-
return num.dot(rMat_d, bVec_d).flatten() + tVec_d.flatten() - bVec_l.flatten()
3192-
3193-
def beamXYD_from_tVec_d(rMat_d, tVec_d, bVec_ref, detOrigin):
3194-
# calculate beam position
3195-
Zd_l = num.dot(rMat_d, num.c_[0, 0, 1].T)
3196-
bScl = num.dot(Zd_l.T, tVec_d) / num.dot(Zd_l.T, bVec_ref)
3197-
beamPos_l = bScl*bVec_ref
3198-
return num.dot(rMat_d.T, beamPos_l - tVec_d) + num.hstack([detOrigin, -tVec_d[2]]).reshape(3, 1)
3199-
3200-
def write_old_parfile(filename, results):
3201-
if isinstance(filename, file):
3202-
fid = filename
3203-
elif isinstance(filename, str) or isinstance(filename, unicode):
3204-
fid = open(filename, 'w')
3205-
pass
3206-
rMat_d = xf.makeDetectorRotMat(results['tiltAngles'])
3207-
tVec_d = results['tVec_d'] - results['tVec_s']
3208-
beamXYD = beamXYD_from_tVec_d(rMat_d, tVec_d, bVec_ref, detOrigin)
3209-
det_plist = num.zeros(12)
3210-
det_plist[:3] = beamXYD.flatten()
3211-
det_plist[3:6] = results['tiltAngles']
3212-
det_plist[6:] = results['dParams']
3213-
print >> fid, "# DETECTOR PARAMETERS (from new geometry model fit)"
3214-
print >> fid, "# \n# <class 'hexrd.xrd.detector.DetectorGeomGE'>\n#"
3215-
for i in range(len(det_plist)):
3216-
print >> fid, "%1.8e\t%d" % (det_plist[i], 0)
3217-
fid.close()
3218-
return
3219-
32203173
def simulateOmeEtaMaps(omeEdges, etaEdges, planeData, expMaps,
32213174
chi=0.,
32223175
etaTol=None, omeTol=None,
@@ -3429,7 +3382,7 @@ def simulateGVecs(pd, detector_params, grain_params,
34293382
pixel_pitch=(0.2, 0.2),
34303383
distortion=(dFunc_ref, dParams_ref)):
34313384
"""
3432-
returns valid_hkl, valid_ang, valid_xy, ang_ps
3385+
returns valid_ids, valid_hkl, valid_ang, valid_xy, ang_ps
34333386
34343387
panel_dims are [(xmin, ymin), (xmax, ymax)] in mm
34353388
@@ -3506,17 +3459,19 @@ def simulateGVecs(pd, detector_params, grain_params,
35063459
det_xy[:, 1] >= panel_dims[0][1],
35073460
det_xy[:, 1] <= panel_dims[1][1]
35083461
)
3509-
on_panel = num.logical_and(on_panel_x, on_panel_y)
3462+
on_panel = num.logical_and(on_panel_x, on_panel_y)
35103463
#
3511-
valid_ang = allAngs[on_panel, :]
3464+
op_idx = num.where(on_panel)[0]
3465+
#
3466+
valid_ang = allAngs[op_idx, :]
35123467
valid_ang[:, 2] = xf.mapAngle(valid_ang[:, 2], ome_period)
3513-
valid_ids = allHKLs[on_panel, 0]
3514-
valid_hkl = allHKLs[on_panel, 1:]
3515-
valid_xy = det_xy[on_panel, :]
3516-
ang_ps = angularPixelSize(valid_xy, pixel_pitch,
3517-
rMat_d, rMat_s,
3518-
tVec_d, tVec_s, tVec_c,
3519-
distortion=distortion)
3468+
valid_ids = allHKLs[op_idx, 0]
3469+
valid_hkl = allHKLs[op_idx, 1:]
3470+
valid_xy = det_xy[op_idx, :]
3471+
ang_ps = angularPixelSize(valid_xy, pixel_pitch,
3472+
rMat_d, rMat_s,
3473+
tVec_d, tVec_s, tVec_c,
3474+
distortion=distortion)
35203475

35213476
return valid_ids, valid_hkl, valid_ang, valid_xy, ang_ps
35223477

@@ -3575,7 +3530,6 @@ def simulateLauePattern(hkls, bMat,
35753530
LOOP OVER GRAINS
35763531
"""
35773532

3578-
35793533
for iG, gp in enumerate(grain_params):
35803534
rmat_c = xfcapi.makeRotMatOfExpMap(gp[:3])
35813535
tvec_c = gp[3:6].reshape(3, 1)

0 commit comments

Comments
 (0)