#pylint: disable=no-init,invalid-name from mantid.api import PythonAlgorithm, AlgorithmFactory, ITableWorkspaceProperty, WorkspaceFactory from mantid.kernel import Direction import warnings _OUTPUTLEVEL = "NOOUTPUT" class SelectPowderDiffPeaks(PythonAlgorithm): """ Algorithm to select the powder diffraction peaks for Le Bail Fit """ mPeaks = None def category(self): """ """ return "Diffraction;Utility" def name(self): """ """ return "SelectPowderDiffPeaks" def summary(self): return "Select the powder diffraction peaks for Le Bail Fit" def PyInit(self): """ Declare properties """ self.declareProperty(ITableWorkspaceProperty("BraggPeakParameterWorkspace", "", Direction.Input),\ "Name of Table Workspace containing peak parameters.") self.declareProperty(ITableWorkspaceProperty("ZscoreWorkspace", "", Direction.Input),\ "Name of Table Workspace containing z-score for the peak parametrs.") self.declareProperty(ITableWorkspaceProperty("OutputBraggPeakParameterWorkspace", "", Direction.Output),\ "Name of Table Workspace containing the filtered peaks' parameters.") self.declareProperty("MinimumPeakHeight", 0.0, "Minimum peak height allowed for the peaks to fit. ") self.declareProperty("ZscoreFilter", "", "Filter on the Zscore of the peak parameters.") return def PyExec(self): """ Main Execution Body """ warnings.warn("A message", ModuleDeprecationWarning) # 1. Get Input properties inppeakws = self.getProperty("BraggPeakParameterWorkspace").value inpzscows = self.getProperty("ZscoreWorkspace").value minpeakheight = float(self.getPropertyValue("MinimumPeakHeight")) zscorefilterstr = self.getPropertyValue("ZscoreFilter") print "Input: PeakParameterWorkspace = %s; ZscoreWorkspace = %s" % (inppeakws.name, inpzscows.name) print " Minimum peak height = %f" % (minpeakheight) print " Zscore filter: %s" % (zscorefilterstr) # 3. Parse Zscore table and peak parameters self.mPeaks = {} zscoredict = self.parseBraggPeakParameterTable(inpzscows) self.mPeaks = self.parseBraggPeakParameterTable(inppeakws) # 4. Filter by peak height self.filterByPeakHeight(minpeakheight) # 5. Filter by zscore zscorefilterdict = self.parseZscoreFilter(zscorefilterstr) self.filterByZscore(zscoredict, zscorefilterdict) # 6. Generate the output paramWS = WorkspaceFactory.createTable() self.genBraggPeakParameterWorkspace(paramWS) self.setProperty("OutputBraggPeakParameterWorkspace", paramWS) return def genBraggPeakParameterWorkspace(self, tablews): """ Create TableWorkspace containing peak parameters """ # 1. Create an empty workspace and set the column tablews.addColumn("int", "H") tablews.addColumn("int", "K") tablews.addColumn("int", "L") tablews.addColumn("double", "d_h") tablews.addColumn("double", "TOF_h") tablews.addColumn("double", "Height") tablews.addColumn("double", "Alpha") tablews.addColumn("double", "Beta") tablews.addColumn("double", "Sigma") # 2. Sort the dictionary by d-spacing dspdict = {} hkls = self.mPeaks.keys() for hkl in hkls: dsp = self.mPeaks[hkl]["d_h"] dspdict[dsp] = hkl dhs = dspdict.keys() dhs = sorted(dhs) # 3. Add peaks for dsp in dhs: hkl = dspdict[dsp] h = hkl[0] k = hkl[1] l = hkl[2] tof_h = self.mPeaks[hkl]["TOF_h"] height = self.mPeaks[hkl]["Height"] alpha = self.mPeaks[hkl]["Alpha"] beta = self.mPeaks[hkl]["Beta"] sigma = self.mPeaks[hkl]["Sigma"] tablews.addRow([h, k, l, dsp, tof_h, height, alpha, beta, sigma]) # ENDFOR return tablews def parseBraggPeakParameterTable(self, tablews): """ Parse Zscore parameter table workspace Return: zscoredict """ numrows = tablews.rowCount() numcols = tablews.columnCount() colnames = tablews.getColumnNames() peakparameterdict = {} for irow in xrange(numrows): ppdict = {} for icol in xrange(numcols): colname = colnames[icol] value = tablews.cell(irow, icol) ppdict[colname] = value # ENDFOR Column h = ppdict["H"] k = ppdict["K"] l = ppdict["L"] peakparameterdict[(h, k, l)] = ppdict # ENDFOR return peakparameterdict def filterByPeakHeight(self, minpeakheight): """ Filter by peak height """ for hkl in self.mPeaks.keys(): height = self.mPeaks[hkl]["Height"] wbuf = "Peak %d %d %d: Height = %f " % (hkl[0], hkl[1], hkl[2], height) if height < minpeakheight: self.mPeaks.pop(hkl) wbuf += "Removed due to height < %f" % (minpeakheight) else: # wbuf += "Kept due to height > %f" % (minpeakheight) pass print wbuf # ENDFOR return def filterByZscore(self, zscoredict, zscorefilter): """ Filter by zscore """ # 1. Loop over peaks for hkl in self.mPeaks.keys(): zscores = zscoredict[hkl] deletethispeak = False errmsgout = False # 2. Loop over zscore filters for parname in zscorefilter.keys(): # Maximum allowed Z score maxzscore = zscorefilter[parname] # Convert to regular parameter name to parameter name in Zcore workspace zparname = "Z_"+parname if zscores.has_key(zparname): # Zscore table has this parameter's zscore zscore = zscores[zparname] if zscore > maxzscore: deletethispeak = True break # ENDIF else: # Zscore table has no such parameter print "Warning! Zscore table has no parameter %s (from %s)" % (zparname, parname) errmsgout = True # ENDIF # ENDFOR Fitler # 3. Delete if if deletethispeak is True: self.mPeaks.pop(hkl) if errmsgout is True: msg = "Parameters (keys):\t\t" for key in zscores.keys(): msg += "%s,\t\t" % (key) print msg # ENDFOR Each Peak return def parseZscoreFilter(self, zscorefilterstr): """ Parse Zscore filter string Return: zscore filter dictionary Parameter Name: Maximum Allowed """ zscorefilter = {} terms = zscorefilterstr.split(',') if len(terms) % 2 == 1: raise NotImplementedError("Zscore filter is not defined correct. It must have string and float in pair.") for i in xrange(len(terms)/2): parname = terms[2*i].strip() maxzscore = float(terms[2*i+1]) zscorefilter[parname] = maxzscore return zscorefilter # Register algorithm with Mantid AlgorithmFactory.subscribe(SelectPowderDiffPeaks)