Changeset 1889


Ignore:
Timestamp:
Jun 15, 2015 3:00:17 PM (7 years ago)
Author:
toby
Message:

Add fixed background points; animate dragging points and lines; add fixed bkg fit routine (bkg peaks buggy\!)

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIgrid.py

    r1878 r1889  
    780780        self.BackEdit.Append(id=wxID_PEAKSMOVE, kind=wx.ITEM_NORMAL,text='Move peaks',
    781781            help='Move background peaks to Peak List')
    782            
     782        self.BackFixed = wx.Menu(title='') # fixed background point menu
     783        self.BackMenu.Append(menu=self.BackFixed, title='Fixed Points')
     784        self.wxID_BackPts = {}
     785        self.wxID_BackPts['Add'] = wx.NewId() # N.B. not using wxID_ global as for other menu items
     786        self.BackFixed.Append(id=self.wxID_BackPts['Add'], kind=wx.ITEM_RADIO,text='Add',
     787            help='Add fixed background points with mouse clicks')
     788        self.wxID_BackPts['Move'] = wx.NewId()
     789        item = self.BackFixed.Append(id=self.wxID_BackPts['Move'], kind=wx.ITEM_RADIO,text='Move',
     790            help='Move selected fixed background points with mouse drags')
     791        item.Check(True)
     792        self.wxID_BackPts['Del'] = wx.NewId()
     793        self.BackFixed.Append(id=self.wxID_BackPts['Del'], kind=wx.ITEM_RADIO,text='Delete',
     794            help='Delete fixed background points with mouse clicks')
     795        self.wxID_BackPts['Fit'] = wx.NewId()
     796        self.BackFixed.Append(id=self.wxID_BackPts['Fit'], kind=wx.ITEM_NORMAL,text='Fit background',
     797            help='Fit background function to fixed background points')
    783798        self.PostfillDataMenu()
    784799           
  • trunk/GSASIIplot.py

    r1882 r1889  
    6666   
    6767class G2PlotMpl(wx.Panel):   
    68     'needs a doc string'
     68    'Creates a Matplotlib 2-D plot in the GSAS-II graphics window'
    6969    def __init__(self,parent,id=-1,dpi=None,**kwargs):
    7070        wx.Panel.__init__(self,parent,id=id,**kwargs)
     
    8282       
    8383class G2PlotOgl(wx.Panel):
    84     'needs a doc string'
     84    'Creates an OpenGL plot in the GSAS-II graphics window'
    8585    def __init__(self,parent,id=-1,dpi=None,**kwargs):
    8686        self.figure = wx.Panel.__init__(self,parent,id=id,**kwargs)
     
    103103       
    104104class G2Plot3D(wx.Panel):
    105     'needs a doc string'
     105    'Creates a 3D Matplotlib plot in the GSAS-II graphics window'
    106106    def __init__(self,parent,id=-1,dpi=None,**kwargs):
    107107        wx.Panel.__init__(self,parent,id=id,**kwargs)
     
    118118                             
    119119class G2PlotNoteBook(wx.Panel):
    120     'create a tabbed window for plotting'
     120    'create a tabbed window for GSAS-II graphics'
    121121    def __init__(self,parent,id=-1):
    122122        wx.Panel.__init__(self,parent,id=id)
     
    11671167                                                   
    11681168    def OnPick(event):
     1169        '''Respond to an item being picked. This usually means that the item
     1170        will be dragged with the mouse.
     1171        '''
     1172        def OnDragMarker(event):
     1173            '''Respond to dragging of a plot Marker
     1174            '''
     1175            Page.canvas.restore_region(savedplot)
     1176            G2frame.itemPicked.set_data([event.xdata], [event.ydata])
     1177            Page.figure.gca().draw_artist(G2frame.itemPicked)
     1178            Page.canvas.blit(Page.figure.gca().bbox)
     1179        def OnDragLine(event):
     1180            '''Respond to dragging of a plot line
     1181            '''
     1182            Page.canvas.restore_region(savedplot)
     1183            coords = G2frame.itemPicked.get_data()
     1184            coords[0][0] = coords[0][1] = event.xdata
     1185            coords = G2frame.itemPicked.set_data(coords)
     1186            Page.figure.gca().draw_artist(G2frame.itemPicked)
     1187            Page.canvas.blit(Page.figure.gca().bbox)
     1188
    11691189        if G2frame.itemPicked is not None: return
    11701190        PatternId = G2frame.PatternId
     
    11801200        ind = event.ind
    11811201        xy = list(zip(np.take(xpos,ind),np.take(ypos,ind))[0])
     1202        # convert from plot units
     1203        if G2frame.plotStyle['qPlot']:                              #qplot - convert back to 2-theta
     1204            xy[0] = G2lat.Dsp2pos(Parms,2*np.pi/xy[0])
     1205        elif G2frame.plotStyle['dPlot']:                            #dplot - convert back to 2-theta
     1206            xy[0] = G2lat.Dsp2pos(Parms,xy[0])
     1207        if G2frame.plotStyle['sqrtPlot']:
     1208            xy[1] = xy[1]**2
    11821209        if G2frame.PatternTree.GetItemText(PickId) == 'Peak List':
    11831210            if ind.all() != [0] and ObsLine[0].get_label() in str(pick):                                    #picked a data point
    11841211                data = G2frame.PatternTree.GetItemPyData(G2frame.PickId)
    1185                 if G2frame.plotStyle['qPlot']:                              #qplot - convert back to 2-theta
    1186                     xy[0] = G2lat.Dsp2pos(Parms,2*np.pi/xy[0])
    1187                 elif G2frame.plotStyle['dPlot']:                            #dplot - convert back to 2-theta
    1188                     xy[0] = G2lat.Dsp2pos(Parms,xy[0])
    11891212                XY = G2mth.setPeakparms(Parms,Parms2,xy[0],xy[1])
    11901213                data['peaks'].append(XY)
     
    12171240                wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
    12181241            else:                                                   #picked a limit line
     1242                # prepare to animate move of line
    12191243                G2frame.itemPicked = pick
     1244                pick.set_linestyle(':') # set line as dotted
     1245                Page = G2frame.G2plotNB.nb.GetPage(plotNum)
     1246                Plot = Page.figure.gca()
     1247                Page.canvas.draw() # refresh without dotted line & save bitmap
     1248                savedplot = Page.canvas.copy_from_bbox(Page.figure.gca().bbox)
     1249                G2frame.cid = Page.canvas.mpl_connect('motion_notify_event', OnDragLine)
     1250                pick.set_linestyle('--') # back to dashed
     1251               
    12201252        elif G2frame.PatternTree.GetItemText(PickId) == 'Models':
    12211253            if ind.all() != [0]:                                    #picked a data point
     
    12301262            else:                                                   #picked a limit line
    12311263                G2frame.itemPicked = pick
    1232         elif G2frame.PatternTree.GetItemText(PickId) == 'Reflection Lists' or \
    1233             'PWDR' in G2frame.PatternTree.GetItemText(PickId):
     1264        elif (G2frame.PatternTree.GetItemText(PickId) == 'Reflection Lists' or
     1265                'PWDR' in G2frame.PatternTree.GetItemText(PickId)
     1266                ):
    12341267            G2frame.itemPicked = pick
    12351268            pick = str(pick)
    1236        
    1237     def OnRelease(event):
     1269        elif G2frame.PatternTree.GetItemText(PickId) == 'Background':
     1270            # selected a fixed background point. Can move it or delete it.
     1271            for mode,id in G2frame.dataFrame.wxID_BackPts.iteritems(): # what menu is selected?
     1272                if G2frame.dataFrame.BackMenu.FindItemById(id).IsChecked():
     1273                    break
     1274            # mode will be 'Add' or 'Move' or 'Del'
     1275            if pick.get_marker() == 'D':
     1276                # find the closest point
     1277                backDict = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Background'))[1]
     1278                d2 = [(x-xy[0])**2+(y-xy[1])**2 for x,y in backDict['FixedPoints']]
     1279                G2frame.fixPtMarker = d2.index(min(d2))
     1280                if mode == 'Move':
     1281                    # animate move of FixedBkg marker
     1282                    G2frame.itemPicked = pick
     1283                    pick.set_marker('|') # change the point appearance
     1284                    Page = G2frame.G2plotNB.nb.GetPage(plotNum)
     1285                    Plot = Page.figure.gca()
     1286                    Page.canvas.draw() # refresh with changed point & save bitmap
     1287                    savedplot = Page.canvas.copy_from_bbox(Page.figure.gca().bbox)
     1288                    G2frame.cid = Page.canvas.mpl_connect('motion_notify_event', OnDragMarker)
     1289                    pick.set_marker('D') # put it back
     1290                elif mode == 'Del':
     1291                    del backDict['FixedPoints'][G2frame.fixPtMarker]
     1292                    wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
     1293                return
     1294    def OnRelease(event): # mouse release from item pick or background pt add/move/del
     1295        plotNum = G2frame.G2plotNB.plotList.index('Powder Patterns')
     1296        Page = G2frame.G2plotNB.nb.GetPage(plotNum)
     1297        if G2frame.cid is not None:         # if there is a drag connection, delete it
     1298            Page.canvas.mpl_disconnect(G2frame.cid)
     1299            G2frame.cid = None
     1300        PickId = G2frame.PickId                             # points to item in tree
     1301        if G2frame.PatternTree.GetItemText(PickId) == 'Background' and event.xdata:
     1302            # Background page, deal with fixed background points
     1303            if G2frame.SubBack or G2frame.Weight or G2frame.Contour or not G2frame.SinglePlot:
     1304                return
     1305            backDict = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Background'))[1]
     1306            if 'FixedPoints' not in backDict: backDict['FixedPoints'] = []
     1307            try:
     1308                Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
     1309            except TypeError:
     1310                return
     1311            # unit conversions
     1312            xy = [event.xdata,event.ydata]
     1313            if G2frame.plotStyle['qPlot']:                              #qplot - convert back to 2-theta
     1314                xy[0] = G2lat.Dsp2pos(Parms,2*np.pi/xy[0])
     1315            elif G2frame.plotStyle['dPlot']:                            #dplot - convert back to 2-theta
     1316                xy[0] = G2lat.Dsp2pos(Parms,xy[0])
     1317            if G2frame.plotStyle['sqrtPlot']:
     1318                xy[1] = xy[1]**2
     1319            for mode,id in G2frame.dataFrame.wxID_BackPts.iteritems(): # what menu item is selected?
     1320                if G2frame.dataFrame.BackMenu.FindItemById(id).IsChecked():
     1321                    break
     1322            if mode == 'Add':
     1323                backDict['FixedPoints'].append(xy)
     1324                Plot = Page.figure.gca()
     1325                Plot.plot(event.xdata,event.ydata,'rD',clip_on=False,picker=3.)
     1326                Page.canvas.draw()
     1327                return
     1328            elif G2frame.itemPicked is not None: # end of drag in move
     1329                backDict['FixedPoints'][G2frame.fixPtMarker] = xy
     1330                G2frame.itemPicked = None
     1331                wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
     1332                return
     1333       
    12381334        if G2frame.itemPicked is None: return
    1239         PickId = G2frame.PickId
    12401335        if str(DifLine[0]) == str(G2frame.itemPicked):
    12411336            data = G2frame.PatternTree.GetItemPyData(PickId)
     
    12441339            G2frame.itemPicked = None
    12451340            G2frame.PatternTree.SetItemPyData(PickId,data)
    1246             PlotPatterns(G2frame,plotType=plottype)
     1341            wx.CallAfter(PlotPatterns,G2frame,plotType=plottype)
    12471342            return
    12481343        Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
     
    13191414        G2frame.itemPicked = None   
    13201415
     1416    # beginning PlotPatterns execution
    13211417    try:
    13221418        plotNum = G2frame.G2plotNB.plotList.index('Powder Patterns')
     
    13871483                        'd: offset down','l: offset left','r: offset right','u: offset up','o: reset offset',
    13881484                        'q: toggle S(q) plot','m: toggle multidata plot','w: toggle (Io-Ic)/sig plot','+: no selection')
    1389 
     1485    G2frame.cid = None
    13901486    Page.keyPress = OnPlotKeyPress   
    13911487    PickId = G2frame.PickId
     
    17441840    else:
    17451841        G2frame.Lines = Lines
     1842    if G2frame.PatternTree.GetItemText(PickId) == 'Background':
     1843        # plot fixed background points
     1844        backDict = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Background'))[1]
     1845        try:
     1846            Parms,Parms2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Instrument Parameters'))
     1847        except TypeError:
     1848            Parms = None
     1849        for x,y in backDict.get('FixedPoints',[]):
     1850            # "normal" intensity modes only!
     1851            if G2frame.SubBack or G2frame.Weight or G2frame.Contour or not G2frame.SinglePlot:
     1852                break
     1853            if y < 0 and (G2frame.plotStyle['sqrtPlot'] or G2frame.logPlot):
     1854                y = Page.figure.gca().get_ylim()[0] # put out of range point at bottom of plot
     1855            elif G2frame.plotStyle['sqrtPlot']:
     1856                y = math.sqrt(y)
     1857            if G2frame.plotStyle['qPlot']:     #Q - convert from 2-theta
     1858                if Parms:
     1859                    x = 2*np.pi/G2lat.Pos2dsp(Parms,x)
     1860                else:
     1861                    break
     1862            elif G2frame.plotStyle['dPlot']:   #d - convert from 2-theta
     1863                if Parms:
     1864                    x = G2lat.Dsp2pos(Parms,x)
     1865                else:
     1866                    break
     1867            Plot.plot(x,y,'rD',clip_on=False,picker=3.)
    17461868    if not newPlot:
    17471869        Page.toolbar.push_current()
  • trunk/GSASIIpwd.py

    r1878 r1889  
    13201320           
    13211321def DoPeakFit(FitPgm,Peaks,Background,Limits,Inst,Inst2,data,prevVaryList=[],oneCycle=False,controls=None,dlg=None):
    1322     'needs a doc string'
    1323        
     1322    '''Called to perform a peak fit, refining the selected items in the peak
     1323    table as well as selected items in the background.
     1324
     1325    :param str FitPgm: type of fit to perform. At present "LSQ" is the only
     1326      option that works
     1327    :param list Peaks: a list of peaks. Each peak entry is a list with 8 values:
     1328      four values followed by a refine flag where the values are: position, intensity,
     1329      sigma (Gaussian width) and gamma (Lorentzian width). From the Histogram/"Peak List"
     1330      tree entry, dict item "peaks"
     1331    :param list Background: describes the background. List with two items.
     1332      Item 0 specifies a background model and coefficients. Item 1 is a dict.
     1333      From the Histogram/Background tree entry.
     1334    :param list Limits: min and max x-value to use
     1335    :param dict Inst: Instrument parameters
     1336    :param dict Inst2: more Instrument parameters
     1337    :param numpy.array data: a 5xn array. data[0] is the x-values,
     1338      data[1] is the y-values, data[2] are weight values, data[3], [4] and [5] are
     1339      calc, background and difference intensities, respectively.
     1340    :param list prevVaryList: Used in sequential refinements to override the
     1341      variable list. Defaults as an empty list.
     1342    :param bool oneCycle: True if only one cycle of fitting should be performed
     1343    :param dict controls: a dict specifying two values, Ftol = controls['min dM/M']
     1344      and derivType = controls['deriv type']. If None default values are used.
     1345    :param wx.Dialog dlg: A dialog box that is updated with progress from the fit.
     1346      Defaults to None, which means no updates are done.
     1347    '''
    13241348    def GetBackgroundParms(parmList,Background):
    13251349        iBak = 0
     
    15871611                ncyc = int(result[2]['nfev']/2)
    15881612            finally:
    1589                 dlg.Destroy()
     1613                if dlg: dlg.Destroy()
    15901614            runtime = time.time()-begin   
    15911615            chisq = np.sum(result[2]['fvec']**2)
     
    15941618            Rvals['GOF'] = chisq/(xFin-xBeg-len(varyList))       #reduced chi^2
    15951619            print 'Number of function calls:',result[2]['nfev'],' Number of observations: ',xFin-xBeg,' Number of parameters: ',len(varyList)
    1596             print 'fitpeak time = %8.3fs, %8.3fs/cycle'%(runtime,runtime/ncyc)
     1620            if ncyc:
     1621                print 'fitpeak time = %8.3fs, %8.3fs/cycle'%(runtime,runtime/ncyc)
    15971622            print 'Rwp = %7.2f%%, chi**2 = %12.6g, reduced chi**2 = %6.2f'%(Rvals['Rwp'],chisq,Rvals['GOF'])
     1623            sig = [0]*len(varyList)
     1624            if len(varyList) == 0: break  # if nothing was refined
    15981625            try:
    15991626                sig = np.sqrt(np.diag(result[1])*Rvals['GOF'])
     
    16101637                        del(varyList[ipvt-1])
    16111638                        break
     1639                else: # nothing removed
     1640                    break
    16121641        elif FitPgm == 'BFGS':
    16131642            print 'Other program here'
     
    16191648    yd[xBeg:xFin] = y[xBeg:xFin]-yc[xBeg:xFin]
    16201649    GetBackgroundParms(parmDict,Background)
    1621     BackgroundPrint(Background,sigDict)
     1650    if bakVary: BackgroundPrint(Background,sigDict)
    16221651    GetInstParms(parmDict,Inst,varyList,Peaks)
    1623     InstPrint(Inst,sigDict)
     1652    if insVary: InstPrint(Inst,sigDict)
    16241653    GetPeaksParms(Inst,parmDict,Peaks,varyList)   
    1625     PeaksPrint(dataType,parmDict,sigDict,varyList)
     1654    if peakVary: PeaksPrint(dataType,parmDict,sigDict,varyList)
    16261655    return sigDict,result,sig,Rvals,varyList,parmDict,fullvaryList,badVary
    16271656
  • trunk/GSASIIpwdGUI.py

    r1881 r1889  
    789789            G2frame.PatternTree.SetItemPyData(
    790790                G2gd.GetPatternTreeItemId(G2frame,Id,'Background'),copy.copy(data))
    791                
     791
     792    def OnBkgFit(event):
     793        def SetInstParms(Inst):
     794            dataType = Inst['Type'][0]
     795            insVary = []
     796            insNames = []
     797            insVals = []
     798            for parm in Inst:
     799                insNames.append(parm)
     800                insVals.append(Inst[parm][1])
     801                if parm in ['U','V','W','X','Y','SH/L','I(L2)/I(L1)','alpha',
     802                    'beta-0','beta-1','beta-q','sig-0','sig-1','sig-2','sig-q',] and Inst[parm][2]:
     803                        insVary.append(parm)
     804            instDict = dict(zip(insNames,insVals))
     805            instDict['X'] = max(instDict['X'],0.01)
     806            instDict['Y'] = max(instDict['Y'],0.01)
     807            if 'SH/L' in instDict:
     808                instDict['SH/L'] = max(instDict['SH/L'],0.002)
     809            return dataType,instDict,insVary
     810   
     811        PatternId = G2frame.PatternId       
     812        controls = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Controls'))
     813        background = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Background'))
     814        limits = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Limits'))[1]
     815        inst,inst2 = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId, 'Instrument Parameters'))
     816       
     817        X = [x for x,y in background[1]['FixedPoints'] if limits[0] <= x <= limits[1]]
     818        Y = [y for x,y in background[1]['FixedPoints'] if limits[0] <= x <= limits[1]]
     819        W = [1]*len(X)
     820        Z = [0]*len(X)
     821
     822        # load instrument and background params
     823        dataType,insDict,insVary = SetInstParms(inst)
     824        bakType,bakDict,bakVary = G2pwd.SetBackgroundParms(background)
     825        # how many background parameters are refined?
     826        if len(bakVary)*1.5 > len(X):
     827            msg = ("You are attempting to vary "+str(len(bakVary))+
     828                   " background terms with only "+str(len(X))+" background points"+
     829                    "\nAdd more points or reduce the number of terms")
     830            print msg
     831            G2frame.ErrorDialog('Too few points',msg)
     832            return
     833       
     834        wx.BeginBusyCursor()
     835        try:
     836            G2pwd.DoPeakFit('LSQ',[],background,limits,inst,inst2,
     837                            np.array((X,Y,W,Z,Z,Z)),bakVary,False,controls)
     838        finally:
     839            wx.EndBusyCursor()
     840        # compute the background values and plot them
     841        pwddata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
     842        x = pwddata[0]
     843        xBeg = np.searchsorted(x,limits[0])
     844        xFin = np.searchsorted(x,limits[1])
     845        parmDict = {}
     846        bakType,bakDict,bakVary = G2pwd.SetBackgroundParms(background)
     847        parmDict.update(bakDict)
     848        parmDict.update(insDict)
     849        pwddata[3] *= 0
     850        pwddata[5] *= 0
     851        pwddata[4][xBeg:xFin] = G2pwd.getBackground(
     852            '',parmDict,bakType,dataType,x[xBeg:xFin])[0]
     853        G2plt.PlotPatterns(G2frame,plotType='PWDR')
     854        # show the updated background values
     855        wx.CallLater(100,UpdateBackground,G2frame,data)
     856   
    792857    def OnPeaksMove(event):
    793858        if not data[1]['nPeaks']:
     
    9921057    G2frame.Bind(wx.EVT_MENU,OnBackFlagCopy,id=G2gd.wxID_BACKFLAGCOPY)
    9931058    G2frame.Bind(wx.EVT_MENU,OnPeaksMove,id=G2gd.wxID_PEAKSMOVE)
     1059    G2frame.Bind(wx.EVT_MENU,OnBkgFit,id=G2frame.dataFrame.wxID_BackPts['Fit'])
    9941060    BackId = G2gd.GetPatternTreeItemId(G2frame,G2frame.PatternId, 'Background')
    9951061    Choices = ['chebyschev','cosine','Q^2 power series','Q^-2 powder series','lin interpolate','inv interpolate','log interpolate']
Note: See TracChangeset for help on using the changeset viewer.