def get_nominal_difc(nxspath, idfpath, outpath=None): ws = msa.LoadEventNexus(nxspath, FilterByTimeStart=0, FilterByTimeStop=1) msa.LoadInstrument(ws, Filename=idfpath, RewriteSpectraMap=False) difc = msa.CalculateDIFC(InputWorkspace=ws) difc = difc.extractY().flatten().copy() msa.DeleteWorkspace('difc') if outpath: np.save(outpath, difc) return difc
def cost(self, x): params0 = self.params0 options = self.options params = opts2fullparams(x, params0, options) self.adjust_model(params) wks_name = self.comp_model.instrument_model.wks_name msa.CalculateDIFC(InputWorkspace=wks_name, OutputWorkspace='difc') difc_new = mtd['difc'].extractY().flatten() difc_new = np.ma.masked_array(difc_new, self.comp_model.instrument_model.mask) difc = self.difc return np.sum((difc_new-difc)**2)
def get_nominal_difc(nxspath, init_IDF, outdir): if not os.path.exists(outdir): os.makedirs(outdir) # ## Compute nominal difc ws = msa.LoadEventNexus(nxspath, FilterByTimeStart=0, FilterByTimeStop=1) # load just one second # msa.LoadInstrument(ws, Filename=init_IDF, RewriteSpectraMap=False) import shutil shutil.copyfile(init_IDF, os.path.join(outdir, 'init_IDF.xml')) # difc = msa.CalculateDIFC(InputWorkspace=ws) difc = difc.extractY().flatten().copy() msa.DeleteWorkspace('difc') np.save(os.path.join(outdir, 'difc-nominal.npy'), difc) return
def _minimisation_func(self, x_0, wks_name, component, firstIndex, lastIndex, difc, mask): """ Basic minimization function used. Returns the chisquared difference between the expected difc and the new difc after the component has been moved or rotated. """ xmap = self._mapOptions(x_0) if self._move: api.MoveInstrumentComponent(wks_name, component, X=xmap[0], Y=xmap[1], Z=xmap[2], RelativePosition=False) if self._rotate: (rotw, rotx, roty, rotz) = self._eulerToAngleAxis(xmap[3], xmap[4], xmap[5], self._eulerConvention) # YZX api.RotateInstrumentComponent(wks_name, component, X=rotx, Y=roty, Z=rotz, Angle=rotw, RelativeRotation=False) api.CalculateDIFC(InputWorkspace=wks_name, OutputWorkspace=wks_name) difc_new = api.mtd[wks_name].extractY().flatten( )[firstIndex:lastIndex + 1] if self._masking: difc_new = np.ma.masked_array(difc_new, mask) return chisquare(f_obs=difc, f_exp=difc_new)[0]
def difc(self): wks_name = self.wks_name msa.CalculateDIFC(InputWorkspace=wks_name, OutputWorkspace='difc') return mtd['difc'].extractY().flatten()
def get_I_d(nxs_files, init_IDF, outdir, packs, dt=1000., d_axis=(2., 11., 0.02), Npixels_per_pack=1024): """nxs_files: paths of calibration nxs files init_IDF: initial IDF path outdir: output directory packs: list of pack names, e.g. C26B/eightpack-bottom dt: time step for loading files. too large will need too much memory d_axis: dmin, dmax, delta_d. e.g. 2., 11., 0.02 Npixels_per_pack: number of pixels per pack Output files: * difc-nominal.npy * detIDs.npy * I_d-xbb.npy * I_d-y-PACKNAME.npy * pack-PACKNAME.yaml NOTE: * Assumed that the difc array from CalculateDIFC is ordered according to the "spectrrum list" in the mantid workspace. See function getDetIDs * Different combinations of nxs_files, init_IDF, d_axis should use different outdirs """ if not os.path.exists(outdir): os.makedirs(outdir) # ## Compute nominal difc using first file in the list nxspath = nxs_files[0] ws = msa.LoadEventNexus(nxspath, FilterByTimeStart=0, FilterByTimeStop=1) # load just one second # msa.LoadInstrument(ws, Filename=init_IDF, RewriteSpectraMap=False) import shutil shutil.copyfile(init_IDF, os.path.join(outdir, 'init_IDF.xml')) # difc = msa.CalculateDIFC(InputWorkspace=ws) difc = difc.extractY().flatten().copy() msa.DeleteWorkspace('difc') np.save(os.path.join(outdir, 'difc-nominal.npy'), difc) # IDs of all pixels detIDs = getDetIDs(ws) np.save(os.path.join(outdir, 'detIDs.npy'), detIDs) # # map pack name to (start_pixelID, stop_pixelID) pack2pixelID_start_stop = dict() for name in packs: pack2pixelID_start_stop[name] = getFirstLastPixelIDs(ws, name) continue # clean up msa.DeleteWorkspace('ws') runtimes = dict() for f in nxs_files: runtimes[f] = getRunTime(f) print "* run times:", runtimes dmin, dmax, delta_d = d_axis Nd = int((dmax - dmin) / delta_d) print "* Number of d bins:", Nd # Npacks = len(packs) y_matrix = np.zeros((Npacks, Npixels_per_pack, Nd)) xbb_saved = None for nxsfile in nxs_files: print "* Working on", nxsfile t_total = runtimes[nxsfile] for tstart in np.arange(0, t_total - dt, dt): print "* tstart", tstart tend = min(t_total - 1, tstart + dt) ws = msa.LoadEventNexus(nxsfile, FilterByTimeStart=tstart, FilterByTimeStop=tend) msa.LoadInstrument(ws, Filename=init_IDF, RewriteSpectraMap=False) I_d = msa.ConvertUnits(InputWorkspace=ws, Target='dSpacing', EMode='Elastic') I_d = msa.Rebin(InputWorkspace=I_d, Params='%s,%s,%s' % (dmin, delta_d, dmax)) # loop over packs for ipack, packname in enumerate(packs): firstpixel, lastpixel = pack2pixelID_start_stop[packname] startindex = detIDs.index(firstpixel) endindex = detIDs.index(lastpixel) print "array indexes of first and last pixel", startindex, endindex y_pack = y_matrix[ipack] # loop over pixels in the pack for i, pixelindex in enumerate(range(startindex, endindex + 1)): I_d_pixel = msa.SumSpectra(InputWorkspace=I_d, StartWorkspaceIndex=pixelindex, EndWorkspaceIndex=pixelindex) xbb = I_d_pixel.readX(0) if xbb_saved is None: xbb_saved = np.array(xbb, copy=True) y = I_d_pixel.readY(0) y_pack[i] += y msa.DeleteWorkspace('I_d_pixel') continue continue msa.DeleteWorkspaces(['ws', 'I_d']) continue continue xbb = np.arange(dmin, dmax + delta_d / 2., delta_d) np.save(os.path.join(outdir, "I_d-xbb.npy"), xbb) # for debugging np.save(os.path.join(outdir, "I_d-y_matrix.npy"), y_matrix) for ipack, packname in enumerate(packs): y_pack = y_matrix[ipack] packname1 = packname.split('/')[0] # "C25T" # save y values of I(d) for the pack np.save(os.path.join(outdir, "I_d-y-%s.npy" % packname1), y_pack) # save pack info first, last = pack2pixelID_start_stop[packname] pixelIDs = dict(first=first, last=last) pack_info = dict(pixelIDs=pixelIDs) dumpYaml(pack_info, os.path.join(outdir, 'pack-%s.yaml' % packname1)) continue return
# coding: utf-8 import os, numpy as np from mantid import simpleapi as msa, mtd workdir = "/SNS/users/lj7/dv/sns-chops/detcalib/SEQ" os.chdir(workdir) # ## Compute nominal difc nxspath = '/SNS/SEQ/IPTS-19573/nexus/SEQ_130249.nxs.h5' ws = msa.LoadEventNexus(nxspath, FilterByTimeStart=0, FilterByTimeStop=1) msa.LoadInstrument(ws, Filename='./SEQUOIA_Definition_guessshortpacks.xml', RewriteSpectraMap=False) difc = msa.CalculateDIFC(InputWorkspace=ws) difc = difc.extractY().flatten().copy() msa.DeleteWorkspace('difc') # get det ID list detIDs = [] for i in range(ws.getNumberHistograms()): sp = ws.getSpectrum(i) dets = list(sp.getDetectorIDs()) assert len(dets) == 1 detIDs.append(dets[0]) continue for i in range(len(detIDs) - 1): assert detIDs[i] < detIDs[i + 1] # # Get pack index
def _minimisation_func(self, x_0, wks_name, component, firstIndex, lastIndex): """ Basic minimization function used. Returns the sum of the absolute values for the fractional peak deviations: .. math:: \\sum_i^{N_d}\\sum_j^{N_p} (1 - m_{i,j}) \\frac{|d_{i,j} - d_j^*|}{d_j^*} where :math:`N_d` is the number of detectors in the bank, :math:`N_p` is the number of reference peaks, and :math:`m_{i,j}` is the mask for peak :math:`j` and detector :math:`i`. The mask evaluates to 1 if the detector is defective or the peak is missing in the detector, otherwise the mask evaluates to zero. There's an implicit one-to-correspondence between array index of ``difc`` and workspace index of ``wks_name``, that is, between row index of the input TOFS table and workspace index of ``wks_name``. @param x_0 :: list of length 3 (new XYZ coordinates of the component) or length 6 (XYZ and rotation coords) @param wks_name :: name of a workspace with an embedded instrument. The instrument will be adjusted according to the new coordinates ``x_0`` for instrument component ``component``. It's pixel spectra will contain the new DIFC @param component :: name of the instrument component to be optimized @param firstIndex :: workspace index of first index of ``difc`` array to be considered when comparing old and new DIFC values. When fitting the source or sample, this is the first spectrum index. @param lastIndex :: workspace index of last index of ``difc`` array to be considered when comparing old and new DIFC values. When fitting the source or sample, this is the last row number of the input TOFS table. @return Chi-square value between old and new DIFC values for the unmasked spectra """ xmap = self._mapOptions( x_0) # pad null rotations when x_0 contains only translations if self._move: api.MoveInstrumentComponent(wks_name, component, X=xmap[0], Y=xmap[1], Z=xmap[2], RelativePosition=False, EnableLogging=False) if self._rotate: (rotw, rotx, roty, rotz) = self._eulerToAngleAxis(xmap[3], xmap[4], xmap[5], self._eulerConvention) # YZX api.RotateInstrumentComponent(wks_name, component, X=rotx, Y=roty, Z=rotz, Angle=rotw, RelativeRotation=False, EnableLogging=False) api.CalculateDIFC(InputWorkspace=wks_name, OutputWorkspace=wks_name, EnableLogging=False) difc = api.mtd[wks_name].extractY().flatten()[firstIndex:lastIndex + 1] peaks_d = self.peaks_tof[ firstIndex:lastIndex + 1] / difc[:, np.newaxis] # peak centers in d-spacing units # calculate the fractional peak center deviations, then sum their absolute values return np.sum(np.abs((peaks_d - self.peaks_ref) / self.peaks_ref))