Changeset 5636


Ignore:
Timestamp:
Jul 27, 2023 6:21:18 PM (4 months ago)
Author:
toby
Message:

add autobackground feature; scale fixed bkg points by mag factors

Files:
61 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIctrlGUI.py

    r5635 r5636  
    50835083            except IndexError: # has this been tested?
    50845084                #print row,col,value
     5085                if self.GetNumberRows() == 0: return
    50855086                # add a new row
    50865087                if row > self.GetNumberRows():
     
    73487349     '''This shows how to get an initial estimate of background parameters from a suite of fixed points
    73497350     before beginning Rietveld refinement.'''],
     7351     
     7352    ['AutoBkg', 'AutoBkg.html',  'Using the "Auto Background" feature',
     7353     '''This shows how to use the "Auto Background" feature in GSAS-II to get an estimate of background parameters for a
     7354     series of histograms with quite significant background levels. This estimate can be used to define a set of fixed points
     7355     or to define a "Fixed background histogram."'''],
    73507356     
    73517357    ['LeBail', 'LeBailSucrose.htm', 'Le Bail Intensity Extraction in GSAS-II - Sucrose',
  • trunk/GSASIIplot.py

    r5629 r5636  
    40674067        G2frame.MagLines = magMarkers
    40684068    if PickId and G2frame.GPXtree.GetItemText(PickId) == 'Background':
     4069        mag2th = [0]+[x for x,m in data[0].get('Magnification',[])][1:]
     4070        magmult = [m for x,m in data[0].get('Magnification',[])]
    40694071        # plot fixed background points
    40704072        backDict = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,G2frame.PatternId, 'Background'))[1]
     
    40744076            Parms = None
    40754077        for x,y in backDict.get('FixedPoints',[]):
     4078            if magmult:
     4079                mult = magmult[np.searchsorted(mag2th, x, side = 'right')-1]
     4080            else:
     4081                mult = 1.
    40764082            # "normal" intensity modes only!
    40774083            if G2frame.SubBack or G2frame.Weight or G2frame.Contour or not G2frame.SinglePlot:
     
    40914097                else:
    40924098                    break
    4093             Plot.plot(x,y,'rD',clip_on=Clip_on,picker=True,pickradius=10.)
     4099            Plot.plot(x,y*mult,'rD',clip_on=Clip_on,picker=True,pickradius=10.)
    40944100
    40954101    # plot the partials. TODO: get partials to show up in publication plot
  • trunk/GSASIIpwd.py

    r5625 r5636  
    21182118                backVary += ['BF mult',]
    21192119    return bakType,backDict,backVary
     2120
     2121def autoBkgCalc(bkgdict,ydata):
     2122    '''Compute the autobackground using the selected pybaselines function
     2123   
     2124    :param dict bkgdict: background parameters
     2125    :param np.array ydata: array of Y values
     2126    :returns: points for background intensity at each Y position
     2127    '''
     2128    import pybaselines.whittaker
     2129    lamb = int(10**bkgdict['autoPrms']['logLam'])
     2130    if bkgdict['autoPrms']['opt'] == 0:
     2131        func = pybaselines.whittaker.arpls
     2132    else:
     2133        func = pybaselines.whittaker.arpls
     2134    return func(ydata, lam=lamb, max_iter=10)[0]
    21202135   
    21212136def DoCalibInst(IndexPeaks,Inst):
  • trunk/GSASIIpwdGUI.py

    r5626 r5636  
    18251825
    18261826        fileSizer = wx.BoxSizer(wx.VERTICAL)
     1827        fileSizer.Add((-1,5))
     1828        backSizer = wx.BoxSizer(wx.HORIZONTAL)
     1829        btn = wx.Button(G2frame.dataWindow, wx.ID_ANY,'Fit to fixed bkg')
     1830        backSizer.Add(btn,0,wx.RIGHT,3)
     1831        btn.Enable(len(data[1].get('FixedPoints',[])) > 5)
     1832        btn.Bind(wx.EVT_BUTTON,OnBkgFit)
     1833       
     1834        btn = wx.Button(G2frame.dataWindow, wx.ID_ANY,'Compute auto background')
     1835        backSizer.Add(btn,0,wx.RIGHT,3)
     1836        btn.Bind(wx.EVT_BUTTON,onAutoBack)
     1837
     1838        btn = wx.Button(G2frame.dataWindow, wx.ID_ANY,'Copy auto background')
     1839        backSizer.Add(btn,0,wx.RIGHT,3)
     1840        data[1]['autoPrms'] = data[1].get('autoPrms',{})
     1841        btn.Enable(bool(data[1]['autoPrms'].get('Mode')))
     1842        btn.Bind(wx.EVT_BUTTON,copyAutoBack)
     1843        fileSizer.Add(backSizer)
     1844        fileSizer.Add((-1,5))
     1845       
    18271846        fileSizer.Add(wx.StaticText(G2frame.dataWindow,-1,' Fixed background histogram (for point-by-point subtraction):'),0)
    18281847        if 'background PWDR' not in data[1]:
     
    18461865        fileSizer.Add(backSizer)
    18471866        return fileSizer
    1848    
     1867
     1868    def onAutoBack(event):
     1869        '''Open a window for auto background computation
     1870        '''
     1871        bkgdict = data[1]
     1872        xydata = G2frame.GPXtree.GetItemPyData(G2frame.PatternId)[1]
     1873        autoBackground(G2frame)
     1874        if bkgdict['autoPrms']['Mode'] == 'fixed':
     1875            xydata[4] = G2pwd.autoBkgCalc(bkgdict,xydata[1])
     1876            addAutoBack(G2frame,data,xydata)
     1877            wx.CallAfter(UpdateBackground,G2frame,data)
     1878            G2plt.PlotPatterns(G2frame,plotType='PWDR')
     1879        elif bkgdict['autoPrms']['Mode'] == 'fit':
     1880            xydata[4] = G2pwd.autoBkgCalc(bkgdict,xydata[1])
     1881            npts = len(xydata[0])
     1882            bkgdict['FixedPoints'] = [i for i in zip(
     1883                xydata[0].data[::npts//100],
     1884                xydata[4].data[::npts//100])]
     1885            OnBkgFit(event)
     1886        else:
     1887            wx.CallAfter(UpdateBackground,G2frame,data)
     1888            G2plt.PlotPatterns(G2frame,plotType='PWDR')
     1889
     1890    def copyAutoBack(event):
     1891        '''reproduce the auto background computation on selected
     1892        other histograms
     1893        '''
     1894        savePatternId = G2frame.PatternId
     1895        hst = G2frame.GPXtree.GetItemText(G2frame.PatternId)
     1896        autoBkgDict = data[1].get('autoPrms')
     1897        if not autoBkgDict.get('Mode'):
     1898            G2frame.ErrorDialog('No auto bkg setting','This is unexpected, no auto bkg parms for histogram '+hst,G2frame)
     1899            return
     1900        elif autoBkgDict['Mode'] == 'fit':
     1901            txt = 'set fixed points from auto bkg calc'
     1902        else:
     1903            txt = 'use auto bkg calc to define Fixed Bkg histogram'
     1904        histList = [i for i in GetHistsLikeSelected(G2frame)
     1905                        if 'Autobkg for' not in i]
     1906        if not histList:
     1907            G2frame.ErrorDialog('No match','No histograms match '+hst,G2frame)
     1908            return
     1909        dlg = G2G.G2MultiChoiceDialog(G2frame,
     1910                        f'Select histogram(s) to {txt} based on {hst}',
     1911                        'Compute auto bkg for...', histList)
     1912        try:
     1913            copyList = []
     1914            if dlg.ShowModal() == wx.ID_OK:
     1915                for i in dlg.GetSelections():
     1916                    copyList.append(histList[i])
     1917        finally:
     1918            dlg.Destroy()
     1919        for item in copyList:
     1920            Id = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,item)
     1921            G2frame.PatternId = Id
     1922            xydata = G2frame.GPXtree.GetItemPyData(Id)[1]
     1923            G2frame.GPXtree.SetItemPyData
     1924            bkgId = G2gd.GetGPXtreeItemId(G2frame,Id,'Background')
     1925            G2frame.GPXtree.SetItemPyData(bkgId,copy.deepcopy(data))
     1926            itemData = G2frame.GPXtree.GetItemPyData(bkgId)
     1927            if autoBkgDict['Mode'] == 'fixed':
     1928                xydata[4] = G2pwd.autoBkgCalc(itemData[1],xydata[1])
     1929                addAutoBack(G2frame,itemData,xydata)
     1930            elif autoBkgDict['Mode'] == 'fit':
     1931                xydata[4] = G2pwd.autoBkgCalc(itemData[1],xydata[1])
     1932                npts = len(xydata[0])
     1933                itemData[1]['FixedPoints'] = [i for i in zip(
     1934                xydata[0].data[::npts//100],
     1935                xydata[4].data[::npts//100])]
     1936                OnBkgFit(event)
     1937        G2frame.PatternId = savePatternId
     1938        wx.CallAfter(UpdateBackground,G2frame,data)
     1939
    18491940    def CalcBack(PatternId=G2frame.PatternId):
    18501941        limits = G2frame.GPXtree.GetItemPyData(G2gd.GetGPXtreeItemId(G2frame,PatternId, 'Limits'))[1]
     
    19021993    G2frame.dataWindow.SetSizer(mainSizer)
    19031994    G2frame.dataWindow.SetDataSize()
    1904        
     1995
     1996def addAutoBack(G2frame,data,xydata):
     1997    '''Create a new histogram for the computed auto background and place
     1998    as the fixed background histogram
     1999    '''   
     2000    bkgHistName = 'PWDR Autobkg for '+G2frame.GPXtree.GetItemText(G2frame.PatternId)[5:]
     2001    # if histogram exists we should probably reuse it, but for now, just create a new one
     2002    bkgHistName = G2obj.MakeUniqueLabel(bkgHistName,G2frame.GetHistogramNames('PWDR'))
     2003
     2004    Ymin = min(xydata[4])
     2005    Ymax = max(xydata[4])
     2006    d = copy.deepcopy(G2frame.GPXtree.GetItemPyData(G2frame.PatternId))
     2007    d[0] = {'wtFactor': 1.0, 'Dummy': False,
     2008                  'ranId': ran.randint(0, sys.maxsize),
     2009                  'Offset': [0.0, 0.0], 'delOffset': 0.02*Ymax,
     2010                  'refOffset': -0.1*Ymax, 'refDelt': 0.1*Ymax,
     2011                  'Yminmax': [Ymin, Ymax]}
     2012    d[1][1] = xydata[4]
     2013    d[1][2] = np.ones_like(xydata[4])
     2014    d[1][3] = np.zeros_like(xydata[4])
     2015    d[1][4] = np.zeros_like(xydata[4])
     2016    d[1][5] = np.zeros_like(xydata[4])
     2017    NewId = G2frame.GPXtree.AppendItem(parent=G2frame.root,text=bkgHistName)
     2018    G2frame.GPXtree.SetItemPyData(NewId,d)
     2019                 
     2020    item, cookie = G2frame.GPXtree.GetFirstChild(G2frame.PatternId)
     2021    while item:
     2022        nam = G2frame.GPXtree.GetItemText(item)
     2023        if nam == 'Comments':
     2024            d = [' # background generated with Autobkg']
     2025        elif nam == 'Background':
     2026            d = [['chebyschev-1',True,3,1.0,0.0,0.0],
     2027                     {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[],
     2028                          'background PWDR':['',1.0,False],'FixedPoints':[]}]
     2029        elif nam == 'Peak List':
     2030            d = {'sigDict':{},'peaks':[]}
     2031        elif nam == 'Index Peak List':
     2032            d = [[], []]
     2033        elif nam == 'Unit Cells List':
     2034            d = []
     2035        elif nam == 'Reflection Lists':
     2036            d = {}               
     2037        else:
     2038            d = copy.deepcopy(G2frame.GPXtree.GetItemPyData(item))
     2039        G2frame.GPXtree.SetItemPyData(
     2040                    G2frame.GPXtree.AppendItem(parent=NewId,text=nam),d)
     2041        item, cookie = G2frame.GPXtree.GetNextChild(G2frame.PatternId, cookie)
     2042
     2043
     2044    bId = G2gd.GetGPXtreeItemId(G2frame,G2frame.PatternId,'Background')
     2045    data = G2frame.GPXtree.GetItemPyData(bId)
     2046    # set fixed bkg & turn off computed background
     2047    data[1]['background PWDR'] = [bkgHistName, 1.0, False]
     2048    data[0][1] = False
     2049    data[0][3:] = data[0][2]*[0.]
     2050    for p in data[1]['peaksList']:
     2051        p[2] = 0.
     2052        p[1::2] = 4*[False]
     2053    for p in data[1]['debyeTerms']:
     2054        p[0] = 0
     2055        p[1::2] = 3*[False]
     2056    G2frame.GetUsedHistogramsAndPhasesfromTree() # reindex
     2057
     2058# Autobackground Dialog
     2059class autoBackground(wx.Dialog):
     2060    '''Create a file selection widget for setting background with
     2061    pybaselines, as requested by James Feng.
     2062
     2063    :param wx.Frame G2frame: reference to the main GSAS-II frame.
     2064
     2065    '''
     2066    def __init__(self,G2frame,*args,**kwargs):
     2067        self.G2frame = G2frame
     2068        bId = G2gd.GetGPXtreeItemId(G2frame,G2frame.PatternId,'Background')
     2069        data = G2frame.GPXtree.GetItemPyData(bId)
     2070        self.bkgdict = data[1]
     2071        self.xydata = G2frame.GPXtree.GetItemPyData(G2frame.PatternId)[1]
     2072        npts = len(self.xydata[0])
     2073        # add auto bkg to background prms dict
     2074        self.bkgdict['autoPrms'] = self.bkgdict.get('autoPrms',{})
     2075        self.bkgdict['autoPrms']['opt'] = self.bkgdict['autoPrms'].get('opt',0)
     2076        logLam =  min(10,float(int(10*np.log10(npts)**1.5)-9.5)/10.)
     2077        self.bkgdict['autoPrms']['logLam'] = self.bkgdict['autoPrms'].get('logLam',logLam)
     2078        self.bkgdict['autoPrms']['Mode'] = None
     2079        maxLam = min(15.,1.*int(3*self.bkgdict['autoPrms']['logLam']+0.9))
     2080        # save starting point info
     2081        self.startingBackground = copy.deepcopy(self.xydata[4])
     2082        # start process
     2083        wx.Dialog.__init__(self, parent=G2frame,
     2084                                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
     2085        self.CenterOnParent()
     2086       
     2087        mainSizer = wx.BoxSizer(wx.VERTICAL)
     2088        mainSizer.Add(wx.StaticText(self,label=' Compute autobackground'),0)
     2089        choices = ['arpls','iarpls']
     2090        subSiz = wx.BoxSizer(wx.HORIZONTAL)
     2091        subSiz.Add(wx.StaticText(self,label='Computation option'))
     2092        for w in G2G.G2RadioButtons(self,self.bkgdict['autoPrms'],'opt',choices,
     2093                                    OnChange=self._calcBkg):
     2094            subSiz.Add(w,0,wx.ALIGN_CENTER_VERTICAL,0)
     2095        mainSizer.Add(subSiz)
     2096        siz = G2G.G2SliderWidget(self,self.bkgdict['autoPrms'],
     2097                                'logLam','log(Lambda)',
     2098                                1.,maxLam,100,self._calcBkg)
     2099        mainSizer.Add(siz)
     2100       
     2101        subSiz = wx.BoxSizer(wx.HORIZONTAL)
     2102        subSiz.Add((-1,-1),1,wx.EXPAND,1)
     2103        btn = wx.Button(self, wx.ID_CLOSE, label='Set Fixed\nPoints && Fit')
     2104        btn.Bind(wx.EVT_BUTTON,lambda event: self.EndModal(wx.ID_CLOSE))
     2105        subSiz.Add(btn)
     2106        subSiz.Add((5,-1))
     2107        btn = wx.Button(self, wx.ID_OK, label='Define Fixed\nBkg histogram')
     2108        btn.Bind(wx.EVT_BUTTON,lambda event: self.EndModal(wx.ID_OK))
     2109        subSiz.Add(btn)
     2110        btn = wx.Button(self, wx.ID_CANCEL)
     2111        subSiz.Add((5,-1))
     2112        subSiz.Add(btn,0,wx.CENTER)
     2113        subSiz.Add((-1,-1),1,wx.EXPAND,1)
     2114        mainSizer.Add((-1,5))
     2115        mainSizer.Add(subSiz,0,wx.EXPAND)
     2116        mainSizer.Add((-1,5))
     2117        self.SetSizer(mainSizer)
     2118        mainSizer.Fit(self)
     2119        self._calcBkg()
     2120        res = self.ShowModal()
     2121        if res == wx.ID_CLOSE:
     2122            self.bkgdict['autoPrms']['Mode'] = 'fit'
     2123        elif res == wx.ID_OK:
     2124            self.bkgdict['autoPrms']['Mode'] = 'fixed'
     2125        else:
     2126            # restore the background to the starting values
     2127            self.xydata[4] = self.startingBackground
     2128            self.bkgdict['autoPrms']['Mode'] = None
     2129       
     2130    def _calcBkg(self,event=None):
     2131        '''respond to a change in the background parameters by recomputing
     2132        the auto background
     2133        '''
     2134        self.xydata[4] = G2pwd.autoBkgCalc(self.bkgdict,self.xydata[1].data)
     2135        import GSASIIplot as G2plt
     2136        G2plt.PlotPatterns(self.G2frame,plotType='PWDR')
     2137   
    19052138################################################################################
    19062139#####  Limits
    1907 ################################################################################           
    1908        
     2140################################################################################       
    19092141def UpdateLimitsGrid(G2frame, data,datatype):
    19102142    '''respond to selection of PWDR Limits data tree item.
  • trunk/docs/source/packages.rst

    r5611 r5636  
    1 GSAS-II Requirements and Options
    2 ==========================================
     1GSAS-II Requirements, Optional and Included Packages
     2======================================================
    33
    44Supported Platforms
     
    2828  Windows-11, but expect the Windows-10 distribution to run fine there.
    2929
    30 * **MacOS**: GSAS-II can run natively on Intel or ARM ("M1" or "Apple
     30* **MacOS**: GSAS-II can run natively on Intel or ARM ("M1",  "M2" or "Apple
    3131  Silicon") processors. With the native code, Mac ARM machines offer
    3232  the highest performance seen on any platform.
     
    3434  For Intel processor Macs, we provide an installer. This can also be
    3535  used on ARM-equipped Macs but native M1 code runs way
    36   faster. Native ARM code installation is a bit more complex; but
     36  faster. Installation of the native ARM code is a bit more complex; but
    3737  detailed instructions are provided
    38   (https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/MacM1Notes)
    39   that require use of either the miniforge package or the homebrew
     38  (https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/MacM1Notes).
     39  This requires use of either the miniforge package or the homebrew
    4040  package installer.
    4141  Macs older than Catalina (10.15) will likely require older
    4242  distributions of Python. 
    4343
    44 * **Linux** (Intel-compatible): Note that GSAS-II does not get a lot of testing
     44* **Linux**: Note that GSAS-II does not get a lot of testing
    4545  in Linux by us, but is used fairly widely on this platform
    46   nonetheless.  One can use the
    47   installer that we provide, but compatibility with older and very new
    48   versions of Linux may require compatibility
    49   library installation, not always easy to do. It may be
     46  nonetheless.  We provide an installer that includes Python and
     47  needed packages for Intel-compatible Linuxes, but compatibility with
     48  older and very new versions of Linux can sometimes be tricky as
     49  compatibility libraries may be needed -- not always easy to do. It may be
    5050  better to use your Linux distribution's versions of Python and
    5151  packages (typically done with a software tool such as apt or yum.)
    52   You may possibly need to use pip as well. Adapt from the detailed
    53   example for how to do for the 32-bit Raspberry Pi OS:
    54   https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/InstallPiLinux. 
    55 
     52  You may possibly need to use pip as well. For an example on how that
     53  is done see the 32-bit Raspberry Pi OS instructions:
     54  https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/InstallPiLinux.
     55
     56  Will GSAS-II run on Linux with other types of CPUs? That will mostly
     57  depend on support for Python and wxPython on that CPU. If those run,
     58  you can likely build the GSAS-II binaries with gcc &
     59  gfortran. Expect to modify the SConstruct file.
     60 
    5661* **Raspberry Pi** (ARM) Linux: GSAS-II has been installed on both 32-bit
    5762  and the 64-bit version of the Raspberry Pi OS (formerly
     
    399404
    400405
    401 Referenced Externally-Developed Software
     406Supported Externally-Developed Software
    402407----------------------------------------------------
    403408
     
    432437    integrated into the GSAS-II GUI.
    433438
     439  **pybaselines**
     440   Determines a background for a powder pattern in the "autobackground"
     441   option. See https://pybaselines.readthedocs.io for more
     442   information.
     443   
    434444The following web services can also be accessed from computers that
    435445have internet access. All software needed for this access is included
     
    477487    For small-box fitting of PDFs; see
    478488    https://github.com/diffpy/diffpy.pdffit2#pdffit2. This code is no
    479     longer supported by the authors, but is still quite useful. It can
    480     only be run with older Python versions. It is supplied within
    481     GSAS-II for Windows with Python 3.7-3.9 and for MacOS only with Python 3.7.
    482     When running GSAS-II with later versions of Python, as is strongly
    483     encouraged, it is best to install a separate older Python
     489    longer being updated by the authors, but is still quite useful.
     490    It is supplied within GSAS-II for Python 3.7.
     491    It is likely best to install a separate Python
    484492    interpreter specifically for PDFfit2. When GSAS-II is run from a
    485493    Python installation that includes the conda package manager (the
    486494    usual installation practice), the GUI will offer an option to
    487     install PDFfit2 via a separate Python 3.7 environment when the
     495    install PDFfit2 via a separate environment when the
    488496    PDFfit2 option is selected on the Phase/RMC tab.
  • trunk/help/Tutorials.html

    r5446 r5636  
    3838<blockquote><I>This shows how to get an initial estimate of background parameters from a suite of fixed points
    3939     before beginning Rietveld refinement.</I></blockquote>
     40<LI><A href="https://subversion.xray.aps.anl.gov/pyGSAS/Tutorials/AutoBkg/AutoBkg.html">Using the "Auto Background" feature</A>
     41 [no example data or video].
     42<blockquote><I>This shows how to use the "Auto Background" feature in GSAS-II to get an estimate of background parameters for a
     43     series of histograms with quite significant background levels. This estimate can be used to define a set of fixed points
     44     or to define a "Fixed background histogram."</I></blockquote>
    4045<LI><A href="https://subversion.xray.aps.anl.gov/pyGSAS/Tutorials/LeBail/LeBailSucrose.htm">Le Bail Intensity Extraction in GSAS-II - Sucrose</A>
    4146 [link: <A href="https://subversion.xray.aps.anl.gov/pyGSAS/Tutorials/LeBail/data">Exercise files</A>].
Note: See TracChangeset for help on using the changeset viewer.