def test_getspacegroup(): # Good cases assert spacegroups.get_spacegroup(1) == \ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] assert spacegroups.get_spacegroup('Pbca') == \ [3, 2, 2, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0] # Error cases assert raises(NicosError, spacegroups.get_spacegroup, 'Pbbb') assert raises(NicosError, spacegroups.get_spacegroup, 300)
def test_canreflect(): # P1 all reflection types are allowed sg = spacegroups.get_spacegroup('P1') assert spacegroups.can_reflect(sg, 0, 0, 0) assert spacegroups.can_reflect(sg, 1, 0, 0) assert spacegroups.can_reflect(sg, 0, 1, 0) assert spacegroups.can_reflect(sg, 0, 0, 1) assert spacegroups.can_reflect(sg, 1, 1, 1)
def generate_hkls(self, offset=None, origin=False, sgroup=True): if offset is None: offset = array([0, 0, 0]) else: offset = array(offset) o1 = array(self.cell._orient1) o2 = array(self.cell._orient2) hkls = [] sg = None if sgroup: sg = get_spacegroup(self.tasinfo['spacegroup']) for i in range(-10, 11): for j in range(-10, 11): base = i * o1 + j * o2 if i == j == 0: if not origin: continue elif sg and not can_reflect(sg, *base): continue hkls.append(base + offset) return self.check_hkls(hkls)
def powderfit(powder, scans=None, peaks=None, ki=None, dmono=3.355, spacegroup=1): """Fit powder peaks of a powder sample to calibrate instrument wavelength. First argument is either a string that names a known material (currently only ``'YIG'`` is available) or a cubic lattice parameter. Then you need to give either scan numbers (*scans*) or peak positions (*peaks*) and a neutron wavevector (*ki*). Examples: >>> powderfit('YIG', scans=[1382, 1383, 1384, ...]) >>> powderfit(12.377932, peaks=[45.396, 61.344, 66.096, ...], ki=1.4) As a further argument, *dmono* is the lattice constant of the monochromator (only used to calculate monochromator 2-theta offsets), it defaults to PG (3.355 A). """ maxhkl = 10 # max H/K/L to consider when looking for d-values maxdd = 0.2 # max distance in d-value when looking for peak indices ksteps = 50 # steps with different ki dki = 0.002 # relative ki stepsize if powder == 'YIG': a = 12.377932 spacegroup = 230 session.log.info('YIG: using cubic lattice constant of %.6f A', a) session.log.info('') else: if not isinstance(powder, float): raise UsageError('first argument must be either "YIG" or a ' 'lattice constant') a = powder sg = get_spacegroup(spacegroup) # calculate (possible) d-values # loop through some hkl-sets, also consider higher harmonics... dhkls = {} for h in range(maxhkl): for k in range(maxhkl): for l in range(maxhkl): if h + k + l > 0: # assume all reflections are possible if not can_reflect(sg, h, k, l): continue G = sqrt(h * h + k * k + l * l) dhkls[a / G] = '(%d %d %d)' % (h, k, l) dhkls[a / (2 * G)] = '(%d %d %d)/2' % (h, k, l) dhkls[a / (3 * G)] = '(%d %d %d)/3' % (h, k, l) dhkls[a / (4 * G)] = '(%d %d %d)/4' % (h, k, l) dhkls[a / (5 * G)] = '(%d %d %d)/5' % (h, k, l) # generate list from dict dvals = sorted(dhkls) # fit and helper functions def dk2tt(d, k): return 2.0 * degrees(arcsin(pi / (d * k))) def model(x, k, stt0): return stt0 + dk2tt(x, k) data = {} if not peaks: if not scans: raise UsageError('please give either scans or peaks argument') for dataset in session.experiment.data.getLastScans(): num = dataset.counter if num not in scans: continue res = _extract_powder_data(num, dataset) session.log.debug('powder_data from %d: %s', num, res) if res: ki, peaks = res data.setdefault(ki, []).extend( [None, p, dp, '#%d ' % num] for (p, dp) in peaks) if not data: session.log.warning('no data found, check the scan numbers!') return else: if scans: raise UsageError('please give either scans or peaks argument') if not ki: raise UsageError('please give ki argument together with peaks') data[float(ki)] = [[None, p, 0.1, ''] for p in peaks] beststt0s = [] bestmtt0s = [] bestrms = 1.0 bestlines = [] orig_data = data for j in [0] + [i * s for i in range(1, ksteps) for s in (-1, 1)]: out = [] p = out.append data = deepcopy(orig_data) # now iterate through data (for all ki and for all peaks) and try to # assign a d-value assuming the ki not to be completely off! for ki1 in sorted(data): new_ki = ki1 + j * dki * ki1 # iterate over ki specific list, start at last element for el in reversed(data[ki1]): tdval = pi / new_ki / sin(abs(radians( el[1] / 2.))) # dvalue from scan distances = [(abs(d - tdval), i) for (i, d) in enumerate(dvals)] mindist = min(distances) if mindist[0] > maxdd: p('%speak at %7.3f -> no hkl found' % (el[3], el[1])) data[ki1].remove(el) else: el[0] = dvals[mindist[1]] if el[1] < 0: el[0] *= -1 p('%speak at %7.3f could be %s at d = %-7.4f' % (el[3], el[1], dhkls[abs(el[0])], el[0])) p('') restxt = [] restxt.append('___final_results___') restxt.append('ki_exp #peaks | ki_fit dki_fit mtt_0 lambda | ' 'stt_0 dstt_0 | chisqr') stt0s = [] mtt0s = [] rms = 0 for ki1 in sorted(data): new_ki = ki1 + j * dki * ki1 peaks = data[ki1] failed = True if len(peaks) > 2: fit = Fit('ki', model, ['ki', 'stt0'], [new_ki, 0]) res = fit.run([el[0] for el in peaks], [el[1] for el in peaks], [el[2] for el in peaks]) failed = res._failed if failed: restxt.append('%4.3f %-6d | No fit!' % (ki1, len(peaks))) rms += 1e6 continue mtt0 = dk2tt(dmono, res.ki) - dk2tt(dmono, ki1) restxt.append('%5.3f %-6d | %-7.4f %-7.4f %-7.4f %-7.4f | ' '%-7.4f %-7.4f | %.2f' % (ki1, len(peaks), res.ki, res.dki, mtt0, 2 * pi / res.ki, res.stt0, res.dstt0, res.chi2)) stt0s.append(res.stt0) mtt0s.append(mtt0) peaks_fit = [model(el[0], res.ki, res.stt0) for el in peaks] p('___fitted_peaks_for_ki=%.3f___' % ki1) p('peak dval measured fitpos delta') for i, el in enumerate(peaks): p('%-10s %7.3f %7.3f %7.3f %7.3f%s' % (dhkls[abs(el[0])], el[0], el[1], peaks_fit[i], peaks_fit[i] - el[1], '' if abs(peaks_fit[i] - el[1]) < 0.10 else " **")) p('') rms += sum( (pobs - pfit)**2 for (pobs, pfit) in zip([el[1] for el in peaks], peaks_fit)) / len(peaks) out.extend(restxt) session.log.debug('') session.log.debug('-' * 80) session.log.debug('result from run with j=%d (RMS = %g):', j, rms) for line in out: session.log.debug(line) if rms < bestrms: beststt0s = stt0s bestmtt0s = mtt0s bestrms = rms bestlines = out session.log.debug('') session.log.debug('*** new best result: RMS = %g', rms) if not beststt0s: session.log.warning('No successful fit results!') if ki is not None: session.log.warning('Is the initial guess for ki too far off?') return for line in bestlines: session.log.info(line) meanstt0 = sum(beststt0s) / len(beststt0s) meanmtt0 = sum(bestmtt0s) / len(bestmtt0s) session.log.info('Check errors (dki, dstt0)! RMS = %.3g', bestrms) session.log.info('') session.log.info('Adjust using:') # TODO: fix suggestions using adjust() session.log.info('mtt.offset += %.4f', meanmtt0) session.log.info('mth.offset += %.4f', meanmtt0 / 2) session.log.info('stt.offset += %.4f', meanstt0) return CommandLineFitResult((meanmtt0, meanstt0))
def doWriteSpacegroup(self, val): try: get_spacegroup(val) except NicosError as err: self.log.warning('%s; new value will be ignored', err)
def __init__(self, spgr): self.spgr = get_spacegroup(spgr)