Changeset 2602


Ignore:
Timestamp:
Dec 25, 2016 9:43:21 PM (5 years ago)
Author:
toby
Message:

redo drawing and editing of masks, document; add transfer angles to Integration controls

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIgrid.py

    r2601 r2602  
    9595[ wxID_IMCALIBRATE,wxID_IMRECALIBRATE,wxID_IMINTEGRATE, wxID_IMCLEARCALIB,wxID_IMRECALIBALL, 
    9696    wxID_IMCOPYCONTROLS, wxID_INTEGRATEALL, wxID_IMSAVECONTROLS, wxID_IMLOADCONTROLS, wxID_IMAUTOINTEG,
    97     wxID_IMCOPYSELECTED, wxID_SAVESELECTEDCONTROLS,
    98 ] = [wx.NewId() for item in range(12)]
     97    wxID_IMCOPYSELECTED, wxID_SAVESELECTEDCONTROLS, wxID_IMXFERCONTROLS,
     98] = [wx.NewId() for item in range(13)]
    9999
    100100[ wxID_MASKCOPY, wxID_MASKSAVE, wxID_MASKLOAD, wxID_NEWMASKSPOT,wxID_NEWMASKARC,wxID_NEWMASKRING,
    101     wxID_NEWMASKFRAME, wxID_NEWMASKPOLY,  wxID_MASKLOADNOT,wxID_FINDSPOTS,
    102 ] = [wx.NewId() for item in range(10)]
     101    wxID_NEWMASKFRAME, wxID_NEWMASKPOLY,wxID_MASKLOADNOT,wxID_FINDSPOTS,wxID_MULTISPOTMASK,
     102] = [wx.NewId() for item in range(11)]
    103103
    104104[ wxID_STRSTACOPY, wxID_STRSTAFIT, wxID_STRSTASAVE, wxID_STRSTALOAD,wxID_STRSTSAMPLE,
     
    20982098        self.ImageEdit.Append(help='Save controls from selected images to file',
    20992099            id=wxID_SAVESELECTEDCONTROLS, kind=wx.ITEM_NORMAL,text='Save Multiple Controls')
    2100         self.ImageEdit.Append(help='Load image controls from file', 
     2100        self.ImageEdit.Append(help='Load image controls from file',
    21012101            id=wxID_IMLOADCONTROLS, kind=wx.ITEM_NORMAL,text='Load Controls')
     2102        self.ImageEdit.Append(help='Transfer integration range for other detector distances',
     2103            id=wxID_IMXFERCONTROLS, kind=wx.ITEM_NORMAL,text='Xfer angles')
    21022104        self.ImageEdit.Append(help='Open Auto-integration window to integrate a series of images',
    21032105            id=wxID_IMAUTOINTEG, kind=wx.ITEM_NORMAL,text='Auto Integrate')
     
    21342136        submenu.Append(help='Create a spot mask with mouse input',
    21352137            id=wxID_NEWMASKSPOT, kind=wx.ITEM_NORMAL,text='Spot mask')
     2138        submenu.Append(help='Turn on/off multiple spot mask creation mode',
     2139            id=wxID_MULTISPOTMASK, kind=wx.ITEM_NORMAL,text='Multiple spot masks')
    21362140        self.PostfillDataMenu()
    21372141           
  • trunk/GSASIIimgGUI.py

    r2599 r2602  
    469469        G2plt.PlotExposedImage(G2frame,event=event)
    470470        wx.CallLater(100,UpdateImageControls,G2frame,data,masks)
     471       
     472    def OnTransferAngles(event):
     473        '''Sets the integration range for the selected Images based on the difference in detector distance
     474        '''
     475        Names = G2gd.GetPatternTreeDataNames(G2frame,['IMG ',])
     476        if len(Names) == 1:
     477            G2frame.ErrorDialog('Nothing images to transfer integration angles to','Need more "IMG"s')
     478            return
     479        Source = G2frame.PatternTree.GetItemText(G2frame.Image)
     480        Names.pop(Names.index(Source))
     481# select targets & do copy
     482        dlg = G2G.G2MultiChoiceDialog(G2frame,'Xfer angles','Transfer integration range from '+Source+' to:',Names)
     483        try:
     484            if dlg.ShowModal() == wx.ID_OK:
     485                xferAng = lambda tth,dist1,dist2: asind(dist1 * sind(tth) / dist2)
     486                items = dlg.GetSelections()
     487                G2frame.EnablePlot = False
     488                Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,Source)
     489                data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Image Controls'))
     490                ttmin0,ttmax0 = data['IOtth']
     491                dist0 = data['distance']
     492                print 'distance =',dist0,' integration range: ',data['IOtth']
     493                for item in items:
     494                    name = Names[item]
     495                    Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,name)
     496                    data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Image Controls'))
     497                    dist1 = data['distance']
     498                    data['IOtth'] = [xferAng(ttmin0,dist0,dist1),xferAng(ttmax0,dist0,dist1)]
     499                    print 'distance =',dist1,' integration range: ',data['IOtth']
     500        finally:
     501            dlg.Destroy()
     502            G2frame.PatternTree.SelectItem(G2frame.PickId)       
    471503           
    472504# Sizers
     
    11001132    G2frame.dataFrame.Bind(wx.EVT_MENU, OnClearCalib, id=G2gd.wxID_IMCLEARCALIB)
    11011133    if data.get('calibrant'):
    1102         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=True)
    1103         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMCALIBRATE,enable=True)
    1104         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBALL,enable=True)
     1134        mode = True
    11051135    else:
    1106         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=False)
    1107         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMCALIBRATE,enable=False)
    1108         G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBALL,enable=False)
     1136        mode = False
     1137    G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBRATE,enable=mode)
     1138    G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMCALIBRATE,enable=mode)
     1139    G2frame.dataFrame.ImageEdit.Enable(id=G2gd.wxID_IMRECALIBALL,enable=mode)
    11091140    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrate, id=G2gd.wxID_IMINTEGRATE)
    11101141    G2frame.dataFrame.Bind(wx.EVT_MENU, OnIntegrateAll, id=G2gd.wxID_INTEGRATEALL)
     
    11141145    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSaveMultiControls, id=G2gd.wxID_SAVESELECTEDCONTROLS)
    11151146    G2frame.dataFrame.Bind(wx.EVT_MENU, OnLoadControls, id=G2gd.wxID_IMLOADCONTROLS)
     1147    G2frame.dataFrame.Bind(wx.EVT_MENU, OnTransferAngles, id=G2gd.wxID_IMXFERCONTROLS)
    11161148    def OnDestroy(event):
    11171149        G2frame.autoIntFrame = None
     
    12791311        event.Skip()
    12801312           
     1313    def ToggleSpotMaskMode(event):
     1314        G2plt.ToggleMultiSpotMask(G2frame)
     1315       
    12811316    def OnNewSpotMask(event):
    12821317        'Start a new spot mask'
     
    14731508    G2frame.dataFrame.Bind(wx.EVT_MENU, OnAutoSpotMask, id=G2gd.wxID_FINDSPOTS)
    14741509    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewSpotMask, id=G2gd.wxID_NEWMASKSPOT)
     1510    G2frame.dataFrame.Bind(wx.EVT_MENU, ToggleSpotMaskMode, id=G2gd.wxID_MULTISPOTMASK)
    14751511    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewArcMask, id=G2gd.wxID_NEWMASKARC)
    14761512    G2frame.dataFrame.Bind(wx.EVT_MENU, OnNewRingMask, id=G2gd.wxID_NEWMASKRING)
  • trunk/GSASIIplot.py

    r2601 r2602  
    41014101
    41024102def OnStartMask(G2frame):
    4103     '''Initiate the start of a Frame or Polygon map
     4103    '''Initiate the start of a Frame or Polygon map, etc.
     4104    Called from a menu command (GSASIIimgGUI) or from OnImPlotKeyPress.
     4105    Variable G2frame.MaskKey contains a single letter ('f' or 'p', etc.) that
     4106      determines what type of mask is created.   
    41044107
    41054108    :param wx.Frame G2frame: The main GSAS-II tree "window"
    4106     :param str eventkey: a single letter ('f' or 'p', etc.) that
    4107       determines what type of mask is created.   
    41084109    '''
    41094110    Masks = G2frame.PatternTree.GetItemPyData(
    41104111        G2gd.GetPatternTreeItemId(G2frame,G2frame.Image, 'Masks'))
    41114112    if G2frame.MaskKey == 'f':
    4112         Masks['Frames'] = []
     4113        new,plotNum,Page,Plot,lim = G2frame.G2plotNB.FindPlotTab('2D Powder Image','mpl',newImage=False)
     4114        if Masks['Frames']:
     4115            Masks['Frames'] = []
     4116            PlotImage(G2frame,newImage=True)
     4117            G2frame.MaskKey = 'f'
     4118        Page.figure.suptitle('Defining Frame mask (use right-mouse to end)',color='g',fontweight='bold')
     4119        Page.canvas.draw()
    41134120    elif G2frame.MaskKey == 'p':
    41144121        Masks['Polygons'].append([])
     4122        new,plotNum,Page,Plot,lim = G2frame.G2plotNB.FindPlotTab('2D Powder Image','mpl',newImage=False)
     4123        Page.figure.suptitle('Defining Polygon mask (use right-mouse to end)',color='r',fontweight='bold')
     4124        Page.canvas.draw()
    41154125    elif G2frame.MaskKey == 's':
    41164126        Masks['Points'].append([])
     
    41204130        Masks['Rings'].append([])
    41214131    G2imG.UpdateMasks(G2frame,Masks)
    4122     PlotImage(G2frame,newImage=True)
    41234132   
    41244133def OnStartNewDzero(G2frame):
     
    41344143    return data
    41354144
     4145def ToggleMultiSpotMask(G2frame):
     4146    '''Turns on and off MultiSpot selection mode; displays a subtitle on plot
     4147    the is cleared by the next PlotImage call
     4148    '''
     4149    new,plotNum,Page,Plot,lim = G2frame.G2plotNB.FindPlotTab('2D Powder Image','mpl',newImage=False)
     4150    if G2frame.MaskKey == 'm':
     4151        G2frame.MaskKey = ''
     4152        Page.Choice[-1] = 'm: start multiple spot mask mode'
     4153        wx.CallAfter(PlotImage,G2frame,newImage=True)
     4154    else:
     4155        G2frame.MaskKey = 'm'
     4156        (x0,y0),(x1,y1) = Plot.get_position().get_points()
     4157        Page.figure.suptitle('Multiple spot mode on',color='r',fontweight='bold')
     4158        Page.Choice[-1] = 'm: stop multiple spot mask mode'
     4159        Page.canvas.draw()
     4160
     4161def ComputeArc(angI,angO,wave,azm0=0,azm1=362):
     4162    '''Computes arc/ring arrays in with inner and outer radii from angI,angO
     4163    and beginning and ending azimuths azm0,azm1 (optional).
     4164    Returns the inner and outer ring/arc arrays.
     4165    '''
     4166    Dsp = lambda tth,wave: wave/(2.*npsind(tth/2.))
     4167    xy1 = []
     4168    xy2 = []
     4169    aR = [azm0,azm1,max(3,int(0.5+azm1-azm0))] # number of points should be at least 3
     4170    if azm1-azm0 > 180: aR[2] /= 2  # for more than 180 degrees, steps can be 2 deg.
     4171    Azm = np.linspace(*aR)
     4172    for azm in Azm:
     4173        xy1.append(G2img.GetDetectorXY(Dsp(angI,wave),azm,Data))      #what about hyperbola
     4174        xy2.append(G2img.GetDetectorXY(Dsp(angO,wave),azm,Data))      #what about hyperbola
     4175    return np.array(xy1).T,np.array(xy2).T
     4176
     4177def UpdatePolygon(pick,event,polygon):
     4178    '''Update a polygon (or frame) in response to the location of the mouse.
     4179    Delete the selected point if moved on top of another.
     4180    With right button add a point after the current button.
     4181    '''
     4182    Xpos,Ypos = [event.xdata,event.ydata]
     4183    if event.button == 1:
     4184        # find distance to closest point other than selected point
     4185        dlist = [np.sqrt((x-Xpos)**2 + (y-Ypos)**2) for i,(x,y) in enumerate(polygon)]
     4186        dlist[pick.pointNumber] = max(dlist)
     4187        dmin = min(dlist)
     4188        cp = dlist.index(min(dlist)) # closest point
     4189        if dmin < 1.5 and cp != pick.pointNumber:
     4190            del polygon[pick.pointNumber]
     4191        else:
     4192            polygon[pick.pointNumber] = [Xpos,Ypos]
     4193        polygon[-1] = polygon[0][:]
     4194    elif event.button == 3:
     4195        polygon.insert(pick.pointNumber+1,[Xpos,Ypos])
     4196
    41364197def PlotImage(G2frame,newPlot=False,event=None,newImage=True):
    41374198    '''Plot of 2D detector images as contoured plot. Also plot calibration ellipses,
     
    41464207    import numpy.ma as ma
    41474208    G2frame.cid = None
    4148     Dsp = lambda tth,wave: wave/(2.*npsind(tth/2.))
     4209    #Dsp = lambda tth,wave: wave/(2.*npsind(tth/2.))
    41494210    global Data,Masks,StrSta  # RVD: these are needed for multiple image controls/masks
    41504211    colors=['b','g','r','c','m','k']
     
    42084269    def OnImPlotKeyPress(event):
    42094270        try:
    4210             PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
     4271            treeItem = G2frame.PatternTree.GetItemText(G2frame.PickId)
    42114272        except TypeError:
    42124273            return
    4213         if PickName == 'Masks':
    4214             if event.key in ['l','p','f','s','a','r']:
     4274        if treeItem == 'Masks':
     4275            if event.key == 'm': # implement multiple spot mode
     4276                ToggleMultiSpotMask(G2frame)
     4277                return
     4278            elif event.key == 't':
     4279                try: # called from menu?
     4280                    Xpos,Ypos = event.xdata,event.ydata
     4281                except AttributeError:
     4282                    G2G.G2MessageBox(G2frame,
     4283                         'You must use the "{}" key from the keyboard'.format(event.key),
     4284                         'Keyboard only')
     4285                    return
     4286                if not (event.xdata and event.ydata): return
     4287                spot = [event.xdata,event.ydata,1.]
     4288                Masks['Points'].append(spot)
     4289                artist = Circle(spot[:2],radius=spot[2]/2,fc='none',ec='r',picker=3)
     4290                Page.figure.gca().add_artist(artist)
     4291                artist.itemNumber = len(Masks['Points'])-1
     4292                artist.itemType = 'Spot'
     4293                G2imG.UpdateMasks(G2frame,Masks)
     4294                Page.canvas.draw()
     4295                return
     4296            elif event.key in ['l','p','f','s','a','r']:
    42154297                G2frame.MaskKey = event.key
    42164298                OnStartMask(G2frame)
    4217                 wx.CallAfter(PlotImage,G2frame,newImage=False)
    42184299               
    4219         elif PickName == 'Stress/Strain':
     4300        elif treeItem == 'Stress/Strain':
    42204301            if event.key in ['a',]:
    42214302                G2frame.StrainKey = event.key
     
    42234304                wx.CallAfter(PlotImage,G2frame,newImage=False)
    42244305               
    4225         elif PickName == 'Image Controls':
     4306        elif treeItem == 'Image Controls':
    42264307            if event.key in ['c',]:
    42274308                Xpos = event.xdata
     
    42554336           
    42564337    def OnImPick(event):
     4338        'A object has been picked'
    42574339        def OnDragIntBound(event):
     4340            'Respond to the dragging of one of the integration boundaries'
    42584341            if event.xdata is None or event.ydata is None:
    4259                 # mouse is outside window. Could
     4342                # mouse is outside window. Could abort the movement,
     4343                # for now ignore the movement until it moves back in
    42604344                return
    42614345            tth,azm,D,dsp = G2img.GetTthAzmDsp(event.xdata,event.ydata,Data)
     
    43194403            Page.figure.gca().draw_artist(pick)
    43204404            Page.canvas.blit(Page.figure.gca().bbox)
    4321 
    4322         if G2frame.PatternTree.GetItemText(G2frame.PickId) not in ['Image Controls','Masks']:
    4323             return
     4405        def OnDragMask(event):
     4406            'Respond to the dragging of a mask'
     4407            if event.xdata is None or event.ydata is None:
     4408                # mouse is outside window. Could abort the movement,
     4409                # for now ignore the movement until it moves back in
     4410                return
     4411            Xpos,Ypos = [event.xdata,event.ydata]
     4412            #if Page.toolbar._active: return # zoom/pan selected
     4413            itemPicked = str(G2frame.itemPicked)
     4414            Page.canvas.restore_region(savedplot)
     4415            try:
     4416                pickType = pick.itemType
     4417            except:
     4418                pickType = '?'
     4419            if pickType == "Spot":
     4420                itemNum = G2frame.itemPicked.itemNumber
     4421                if event.button == 1:
     4422                    x = Masks['Points'][itemNum][0]+Xpos-XposBeforeDrag
     4423                    y = Masks['Points'][itemNum][1]+Ypos-YposBeforeDrag
     4424                    pick.center=[x,y]
     4425                elif event.button == 3:
     4426                    r = math.sqrt((Xpos-Masks['Points'][itemNum][0])**2+
     4427                              (Ypos-Masks['Points'][itemNum][1])**2)
     4428                    pick.radius = r
     4429                Page.figure.gca().draw_artist(pick)
     4430            elif pickType.startswith('Ring'):
     4431                wave = Data['wavelength']
     4432                itemNum = G2frame.itemPicked.itemNumber
     4433                if event.button == 1:
     4434                    angO = angI = G2img.GetTth(Xpos,Ypos,Data)
     4435                    if pickType == 'RingInner':
     4436                        angO += Masks['Rings'][itemNum][1]
     4437                    else:
     4438                        angI -= Masks['Rings'][itemNum][1]
     4439                    Masks['Rings'][itemNum][0] = (angO+angI)/2
     4440                elif event.button == 3:
     4441                    ang = G2img.GetTth(Xpos,Ypos,Data)
     4442                    t = 2*abs(ang - Masks['Rings'][itemNum][0])
     4443                    angI = Masks['Rings'][itemNum][0] - t/2.
     4444                    angO = Masks['Rings'][itemNum][0] + t/2.
     4445                    Masks['Rings'][itemNum][1] = t
     4446                (x1,y1),(x2,y2) = ComputeArc(angI,angO,wave)
     4447                pI,pO = G2frame.ringList[pick.itemNumber]
     4448                pI.set_data((x1,y1))
     4449                pO.set_data((x2,y2))
     4450                Page.figure.gca().draw_artist(pI)
     4451                Page.figure.gca().draw_artist(pO)
     4452            elif pickType.startswith('Arc'):
     4453                wave = Data['wavelength']
     4454                itemNum = G2frame.itemPicked.itemNumber
     4455                tth,azm,thick = Masks['Arcs'][itemNum]
     4456                tthN,azmN,D,dsp = G2img.GetTthAzmDsp(Xpos,Ypos,Data)
     4457                if event.button == 1:
     4458                    if pickType == 'ArcInner':
     4459                        angO = angI = tthN
     4460                        angO += thick
     4461                        off = 0
     4462                        Masks['Arcs'][itemNum][0] = (angO + angI)/2
     4463                    elif pickType == 'ArcOuter':
     4464                        angO = angI = tthN
     4465                        angI -= thick
     4466                        off = 0
     4467                        Masks['Arcs'][itemNum][0] = (angO + angI)/2
     4468                    elif pickType == 'ArcLower':
     4469                        angO = tth + thick/2
     4470                        angI = tth - thick/2
     4471                        off = azmN - azm[0]
     4472                    elif pickType == 'ArcUpper':
     4473                        angO = tth + thick/2
     4474                        angI = tth - thick/2
     4475                        off = azmN - azm[1]
     4476                    azm[0] += off
     4477                    azm[1] += off
     4478                elif event.button == 3:
     4479                    if pickType == 'ArcInner' or pickType == 'ArcOuter':
     4480                        t = 2*abs(tthN - tth)
     4481                        angI = tth - t/2.
     4482                        angO = tth + t/2.
     4483                        Masks['Arcs'][itemNum][2] = t
     4484                        off = 0
     4485                    elif pickType == 'ArcLower':
     4486                        angO = tth + thick/2
     4487                        angI = tth - thick/2
     4488                        off = azmN - azm[0]
     4489                    elif pickType == 'ArcUpper':
     4490                        angO = tth + thick/2
     4491                        angI = tth - thick/2
     4492                        off = azmN - azm[1]
     4493                    newRange = azm[1] - azm[0] - 2*off
     4494                    if newRange < 2 or newRange > 358:
     4495                        return # don't let the azimuthal range get too small or large
     4496                    azm[0] += off
     4497                    azm[1] -= off
     4498                (x1,y1),(x2,y2) = ComputeArc(angI,angO,wave,*azm)
     4499                pI,pO,pL,pU = G2frame.arcList[pick.itemNumber]
     4500                pI.set_data((x2,y2))
     4501                pO.set_data((x1,y1))
     4502                pL.set_data(([x1[0],x2[0]],[y1[0],y2[0]]))
     4503                pU.set_data(([x1[-1],x2[-1]],[y1[-1],y2[-1]]))
     4504                Page.figure.gca().draw_artist(pI)
     4505                Page.figure.gca().draw_artist(pO)
     4506                Page.figure.gca().draw_artist(pL)
     4507                Page.figure.gca().draw_artist(pU)
     4508            elif pickType == 'Polygon':
     4509                # respond to drag
     4510                polygon = Masks['Polygons'][pick.itemNumber][:]
     4511                UpdatePolygon(pick,event,polygon)
     4512                xl,yl = np.hsplit(np.array(polygon),2)
     4513                artist = Plot.plot(xl,yl,'r+')[0] # points
     4514                Page.figure.gca().add_artist(artist)
     4515                artist = G2frame.polyList[pick.itemNumber]
     4516                artist.set_data((xl,yl)) # lines
     4517                Page.figure.gca().draw_artist(artist)
     4518            elif pickType == 'Frame':
     4519                polygon = Masks['Frames'][:]
     4520                UpdatePolygon(pick,event,polygon)
     4521                xl,yl = np.hsplit(np.array(polygon),2)
     4522                artist = Plot.plot(xl,yl,'g+')[0] # points
     4523                Page.figure.gca().add_artist(artist)
     4524                artist = G2frame.frameArtist
     4525                artist.set_data((xl,yl)) # lines
     4526                Page.figure.gca().draw_artist(artist)
     4527            else: # non-dragable object
     4528                return
     4529            Page.canvas.blit(Page.figure.gca().bbox)
     4530
    43244531        if G2frame.itemPicked is not None: return
    4325         G2frame.itemPicked = pick = event.artist
    4326         G2frame.mousePicked = event.mouseevent
    43274532        if G2frame.PatternTree.GetItemText(G2frame.PickId) == 'Image Controls':
     4533            G2frame.itemPicked = pick = event.artist
     4534            G2frame.mousePicked = event.mouseevent
    43284535            # prepare to animate move of integration ranges
    43294536            Page = G2frame.G2plotNB.nb.GetPage(plotNum)
     
    43354542            G2frame.cid = Page.canvas.mpl_connect('motion_notify_event', OnDragIntBound)
    43364543            pick.set_linestyle(saveLinestyle) # back to original
    4337        
     4544        elif G2frame.PatternTree.GetItemText(G2frame.PickId) == 'Masks':
     4545            # prepare to animate dragging of mask
     4546            G2frame.itemPicked = pick = event.artist
     4547            G2frame.mousePicked = event.mouseevent
     4548            XposBeforeDrag,YposBeforeDrag = [event.mouseevent.xdata,event.mouseevent.ydata]
     4549            #GSASIIpath.IPyBreak()
     4550            Page = G2frame.G2plotNB.nb.GetPage(plotNum)
     4551            try:
     4552                pickType = pick.itemType
     4553            except: # should not happen anymore
     4554                pickType = '?'
     4555            if pickType == 'Spot':
     4556                pl = [pick,]
     4557            elif pickType.startswith('Ring'):
     4558                pl = G2frame.ringList[pick.itemNumber]
     4559            elif pickType.startswith('Arc'):
     4560                pl = G2frame.arcList[pick.itemNumber]
     4561            elif pickType == 'Polygon':
     4562                pl = [G2frame.polyList[pick.itemNumber]]
     4563            elif pickType == 'Frame':
     4564                pl = [G2frame.frameArtist,]
     4565            else:
     4566                print('picktype {} should not happen!'.format(pickType))
     4567                GSASIIpath.IPyBreak()
     4568            saveLinestyle = [p.get_linestyle() for p in pl]
     4569            for p in pl: p.set_linestyle('dotted') # set line as dotted
     4570            Page.canvas.draw() # refresh without dotted line & save bitmap
     4571            savedplot = Page.canvas.copy_from_bbox(Page.figure.gca().bbox)
     4572            G2frame.cid = Page.canvas.mpl_connect('motion_notify_event', OnDragMask)
     4573            for p,s in zip(pl,saveLinestyle): p.set_linestyle(s) # set back to original
     4574
    43384575    def OnImRelease(event):
     4576        '''Called when the mouse is released inside an image plot window
     4577        '''
    43394578        try:
    4340             PickName = G2frame.PatternTree.GetItemText(G2frame.PickId)
     4579            treeItem = G2frame.PatternTree.GetItemText(G2frame.PickId)
    43414580        except TypeError:
    43424581            return
    4343         if PickName not in ['Image Controls','Masks','Stress/Strain']:
    4344             return
     4582        new,plotNum,Page,Plot,lim = G2frame.G2plotNB.FindPlotTab('2D Powder Image','mpl',newImage=False)
    43454583        if G2frame.cid is not None:         # if there is a drag connection, delete it
    43464584            Page.canvas.mpl_disconnect(G2frame.cid)
    43474585            G2frame.cid = None
     4586        if treeItem not in ['Image Controls','Masks','Stress/Strain']:
     4587            return
    43484588        pixelSize = Data['pixelSize']
    43494589        scalex = 1000./pixelSize[0]
     
    43514591#        pixLimit = Data['pixLimit']    #can be too tight
    43524592        pixLimit = 20       #this makes the search box 40x40 pixels
    4353         if G2frame.itemPicked is None and PickName == 'Image Controls' and len(G2frame.ImageZ):
     4593        if G2frame.itemPicked is None and treeItem == 'Image Controls' and len(G2frame.ImageZ):
     4594            # nothing being dragged, add calibration point (left mouse) or launch calibration (right)
    43544595            Xpos = event.xdata
    43554596            if not (Xpos and G2frame.ifGetRing):                   #got point out of frame
     
    43804621                wx.CallAfter(PlotImage,G2frame,newImage=False)
    43814622            return
    4382         elif G2frame.MaskKey and PickName == 'Masks':
     4623        elif G2frame.MaskKey and treeItem == 'Masks':
     4624            # nothing being dragged, create a new mask
    43834625            Xpos,Ypos = [event.xdata,event.ydata]
    43844626            if not Xpos or not Ypos or Page.toolbar._active:  #got point out of frame or zoom/pan selected
    43854627                return
    4386             if G2frame.MaskKey == 's' and event.button == 1:
     4628            if G2frame.MaskKey == 'm':
     4629                spot = [Xpos,Ypos,1.]
     4630                Masks['Points'].append(spot)
     4631                artist = Circle((Xpos,Ypos),radius=spot[2]/2,fc='none',ec='r',picker=3)
     4632                Page.figure.gca().add_artist(artist)
     4633                artist.itemNumber = len(Masks['Points'])-1
     4634                artist.itemType = 'Spot'
     4635                G2imG.UpdateMasks(G2frame,Masks)
     4636                Page.canvas.draw()
     4637                return
     4638            elif G2frame.MaskKey == 's' and event.button == 1:
    43874639                Masks['Points'][-1] = [Xpos,Ypos,1.]
    43884640                G2frame.MaskKey = ''               
     
    43964648                Masks['Arcs'][-1] = [tth,[azm-5,azm+5],0.1]
    43974649                G2frame.MaskKey = ''               
    4398             elif G2frame.MaskKey =='p':
    4399                 polygon = Masks['Polygons'][-1]
    4400                 if len(polygon) > 2 and event.button == 3:
    4401                     x0,y0 = polygon[0]
    4402                     polygon.append([x0,y0])
     4650            elif G2frame.MaskKey =='p' or G2frame.MaskKey =='f':
     4651                if G2frame.MaskKey =='p':
     4652                    polygon = Masks['Polygons'][-1]
     4653                    color = 'r'
     4654                    lbl = 'Polygon'
     4655                else:
     4656                    polygon = Masks['Frames']
     4657                    color = 'g'
     4658                    lbl = 'Frame'
     4659                if event.button == 3: # close the polygon/frame
     4660                    if len(polygon) <= 2: # too few points
     4661                        if G2frame.MaskKey =='p':
     4662                            del Masks['Polygons']
     4663                        else:
     4664                            Masks['Frames'] = []
     4665                        G2G.G2MessageBox(G2frame.G2plotNB,lbl+' deleted -- not enough points',
     4666                                         'too few points')
     4667                    else:
     4668                        polygon.append(polygon[0][:])
     4669                        # G2frame.G2plotNB.status.SetStatusText('Polygon closed',) # BHT: never gets seen
    44034670                    G2frame.MaskKey = ''
    4404                     G2frame.G2plotNB.status.SetStatusText('Polygon closed',)
     4671                    G2imG.UpdateMasks(G2frame,Masks)
     4672                    wx.CallAfter(PlotImage,G2frame,newImage=True)
     4673                    return
    44054674                else:
    4406                     G2frame.G2plotNB.status.SetStatusText('New polygon point: %.1f,%.1f'%(Xpos,Ypos),1)
     4675                    G2frame.G2plotNB.status.SetStatusText('New '+lbl+' point: %.1f,%.1f'%(Xpos,Ypos),1)
     4676                    if len(polygon):
     4677                        xpr,ypr = polygon[-1]
     4678                        Plot.plot((xpr,Xpos),(ypr,Ypos),color)
     4679                    Plot.plot(Xpos,Ypos,color+'+')
     4680                    Page.canvas.draw()
    44074681                    polygon.append([Xpos,Ypos])
    4408             elif G2frame.MaskKey =='f':
    4409                 frame = Masks['Frames']
    4410                 if len(frame) > 2 and event.button == 3:
    4411                     x0,y0 = frame[0]
    4412                     frame.append([x0,y0])
    4413                     G2frame.MaskKey = ''
    4414                     G2frame.G2plotNB.status.SetStatusText('Frame closed',1)
    4415                 else:
    4416                     G2frame.G2plotNB.status.SetStatusText('New frame point: %.1f,%.1f'%(Xpos,Ypos),1)
    4417                     frame.append([Xpos,Ypos])
     4682                    #G2imG.UpdateMasks(G2frame,Masks)
     4683                    return
    44184684            G2imG.UpdateMasks(G2frame,Masks)
    44194685            wx.CallAfter(PlotImage,G2frame,newImage=False)
    4420         elif PickName == 'Stress/Strain' and G2frame.StrainKey:
     4686        elif treeItem == 'Stress/Strain' and G2frame.StrainKey:
    44214687            Xpos,Ypos = [event.xdata,event.ydata]
    44224688            if not Xpos or not Ypos or Page.toolbar._active:  #got point out of frame or zoom/pan selected
     
    44334699            G2imG.UpdateStressStrain(G2frame,StrSta)
    44344700            wx.CallAfter(PlotImage,G2frame,newPlot=False)           
    4435         else:
     4701        else:   # start here after dragging of integration range lines or a mask
    44364702            Xpos,Ypos = [event.xdata,event.ydata]
    44374703            if not Xpos or not Ypos or Page.toolbar._active:  #got point out of frame or zoom/pan selected
    44384704                return
     4705            tth,azm,dsp = G2img.GetTthAzmDsp(Xpos,Ypos,Data)[:3]
     4706            itemPicked = str(G2frame.itemPicked)
     4707            try:
     4708                pickType = G2frame.itemPicked.itemType
     4709            except:
     4710                pickType = '?'           
    44394711            if G2frame.ifGetRing:                          #delete a calibration ring pick
    44404712                xypos = [Xpos,Ypos]
     
    44434715                    if np.allclose(ring,xypos,.01,0):
    44444716                        rings.remove(ring)
    4445             else:
    4446                 tth,azm,dsp = G2img.GetTthAzmDsp(Xpos,Ypos,Data)[:3]
    4447                 itemPicked = str(G2frame.itemPicked)
    4448                 if 'Line2D' in itemPicked and PickName == 'Image Controls':
    4449                     if 'line1' in itemPicked:
    4450                         Data['IOtth'][0] = max(tth,0.001)
    4451                     elif 'line2' in itemPicked:
    4452                         Data['IOtth'][1] = tth
    4453                     elif 'line3' in itemPicked:
    4454                         Data['LRazimuth'][0] = int(azm)
    4455                     elif 'line4' in itemPicked and not Data['fullIntegrate']:
    4456                         Data['LRazimuth'][1] = int(azm)
    4457                    
    4458                     Data['LRazimuth'][0] %= 360
    4459                     Data['LRazimuth'][1] %= 360
    4460                     if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
    4461                         Data['LRazimuth'][1] += 360                       
    4462                     if Data['fullIntegrate']:
    4463                         Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
    4464                        
    4465                     if  Data['IOtth'][0] > Data['IOtth'][1]:
    4466                         Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
    4467 
    4468                     if Data['binType'] == 'Q':
    4469                         wave = Data['wavelength']
    4470                         IOtth = [4.*math.pi*sind(Data['IOtth'][0]/2.)/wave,4.*math.pi*sind(Data['IOtth'][1]/2.)/wave]
    4471                         G2frame.InnerTth.SetValue(IOtth[0])
    4472                         G2frame.OuterTth.SetValue(IOtth[1])
    4473                     else:
    4474                         G2frame.InnerTth.SetValue(Data['IOtth'][0])
    4475                         G2frame.OuterTth.SetValue(Data['IOtth'][1])
    4476                     G2frame.Lazim.SetValue(Data['LRazimuth'][0])
    4477                     G2frame.Razim.SetValue(Data['LRazimuth'][1])
    4478                 elif 'Circle' in itemPicked and PickName == 'Masks':
    4479                     spots = Masks['Points']
    4480                     newPos = itemPicked.split(')')[0].split('(')[2].split(',')
    4481                     newPos = np.array([float(newPos[0]),float(newPos[1])])
    4482                     for spot in spots:
    4483                         if spot and np.allclose(np.array([spot[:2]]),newPos):
    4484                             spot[:2] = Xpos,Ypos
    4485                     G2imG.UpdateMasks(G2frame,Masks)
    4486                 elif 'Line2D' in itemPicked and PickName == 'Masks':
    4487                     Obj = G2frame.itemPicked.findobj()
    4488                     rings = Masks['Rings']
    4489                     arcs = Masks['Arcs']
    4490                     polygons = Masks['Polygons']
    4491                     frame = Masks['Frames']
    4492                     for ring in G2frame.ringList:
    4493                         if Obj == ring[0]:
    4494                             rN = ring[1]
    4495                             if ring[2] == 'o':
    4496                                 rings[rN][0] = G2img.GetTth(Xpos,Ypos,Data)-rings[rN][1]/2.
    4497                             else:
    4498                                 rings[rN][0] = G2img.GetTth(Xpos,Ypos,Data)+rings[rN][1]/2.
    4499                     for arc in G2frame.arcList:
    4500                         if Obj == arc[0]:
    4501                             aN = arc[1]
    4502                             if arc[2] == 'o':
    4503                                 arcs[aN][0] = G2img.GetTth(Xpos,Ypos,Data)-arcs[aN][2]/2
    4504                             elif arc[2] == 'i':
    4505                                 arcs[aN][0] = G2img.GetTth(Xpos,Ypos,Data)+arcs[aN][2]/2
    4506                             elif arc[2] == 'l':
    4507                                 arcs[aN][1][0] = int(G2img.GetAzm(Xpos,Ypos,Data))
    4508                             else:
    4509                                 arcs[aN][1][1] = int(G2img.GetAzm(Xpos,Ypos,Data))
    4510                     for poly in G2frame.polyList:   #merging points problem here?
    4511                         if Obj == poly[0]:
    4512 #                            ind = G2frame.itemPicked.contains(G2frame.mousePicked)[1]['ind'][0]
    4513                             oldPos = np.array([G2frame.mousePicked.xdata,G2frame.mousePicked.ydata])
    4514                             pN = poly[1]
    4515                             for i,xy in enumerate(polygons[pN]):
    4516                                 if np.allclose(np.array([xy]),oldPos,atol=1.0):
    4517                                     if event.button == 1:
    4518                                         polygons[pN][i] = Xpos,Ypos
    4519                                     elif event.button == 3:
    4520                                         polygons[pN].insert(i,[Xpos,Ypos])
    4521                                         break
    4522                     if frame:
    4523                         oldPos = np.array([G2frame.mousePicked.xdata,G2frame.mousePicked.ydata])
    4524                         for i,xy in enumerate(frame):
    4525                             if np.allclose(np.array([xy]),oldPos,atol=1.0):
    4526                                 if event.button == 1:
    4527                                     frame[i] = Xpos,Ypos
    4528                                 elif event.button == 3:
    4529                                     frame.insert(i,[Xpos,Ypos])
    4530                                     break
    4531                     G2imG.UpdateMasks(G2frame,Masks)
    4532 #                else:                  #keep for future debugging
    4533 #                    print str(G2frame.itemPicked),event.xdata,event.ydata,event.button
     4717            elif 'Line2D' in itemPicked and treeItem == 'Image Controls':
     4718                if 'line1' in itemPicked:
     4719                    Data['IOtth'][0] = max(tth,0.001)
     4720                elif 'line2' in itemPicked:
     4721                    Data['IOtth'][1] = tth
     4722                elif 'line3' in itemPicked:
     4723                    Data['LRazimuth'][0] = int(azm)
     4724                elif 'line4' in itemPicked and not Data['fullIntegrate']:
     4725                    Data['LRazimuth'][1] = int(azm)
     4726
     4727                Data['LRazimuth'][0] %= 360
     4728                Data['LRazimuth'][1] %= 360
     4729                if Data['LRazimuth'][0] > Data['LRazimuth'][1]:
     4730                    Data['LRazimuth'][1] += 360                       
     4731                if Data['fullIntegrate']:
     4732                    Data['LRazimuth'][1] = Data['LRazimuth'][0]+360
     4733
     4734                if  Data['IOtth'][0] > Data['IOtth'][1]:
     4735                    Data['IOtth'][0],Data['IOtth'][1] = Data['IOtth'][1],Data['IOtth'][0]
     4736
     4737                if Data['binType'] == 'Q':
     4738                    wave = Data['wavelength']
     4739                    IOtth = [4.*math.pi*sind(Data['IOtth'][0]/2.)/wave,4.*math.pi*sind(Data['IOtth'][1]/2.)/wave]
     4740                    G2frame.InnerTth.SetValue(IOtth[0])
     4741                    G2frame.OuterTth.SetValue(IOtth[1])
     4742                else:
     4743                    G2frame.InnerTth.SetValue(Data['IOtth'][0])
     4744                    G2frame.OuterTth.SetValue(Data['IOtth'][1])
     4745                G2frame.Lazim.SetValue(Data['LRazimuth'][0])
     4746                G2frame.Razim.SetValue(Data['LRazimuth'][1])
     4747            elif pickType == "Spot" and treeItem == 'Masks':
     4748                # update the selected circle mask with the last drawn values
     4749                spotnum = G2frame.itemPicked.itemNumber
     4750                Masks['Points'][spotnum] = list(G2frame.itemPicked.center) + [
     4751                    2.*G2frame.itemPicked.radius]
     4752                G2imG.UpdateMasks(G2frame,Masks)
     4753            elif pickType.startswith('Ring') and treeItem == 'Masks':
     4754                G2imG.UpdateMasks(G2frame,Masks) # changes saved during animation
     4755            elif pickType.startswith('Arc') and treeItem == 'Masks':
     4756                G2imG.UpdateMasks(G2frame,Masks) # changes saved during animation
     4757            elif pickType == 'Polygon' and treeItem == 'Masks':
     4758                polygon = Masks['Polygons'][G2frame.itemPicked.itemNumber]
     4759                UpdatePolygon(G2frame.itemPicked,event,polygon)
     4760                G2imG.UpdateMasks(G2frame,Masks)
     4761            elif pickType == 'Frame' and treeItem == 'Masks':
     4762                UpdatePolygon(G2frame.itemPicked,event,Masks['Frames'])
     4763                G2imG.UpdateMasks(G2frame,Masks)
     4764            else: # nothing was done, nothing was changed, don't replot
     4765                G2frame.itemPicked = None
     4766                return
    45344767            wx.CallAfter(PlotImage,G2frame,newImage=True)
    45354768            G2frame.itemPicked = None
     
    45404773    xylim = []
    45414774    new,plotNum,Page,Plot,lim = G2frame.G2plotNB.FindPlotTab('2D Powder Image','mpl',newImage=newImage)
     4775    if newImage:
     4776        G2frame.MaskKey = '' # subtitle will be removed, so turn off mode
    45424777    if not new:
    45434778        if not newPlot:
     
    45614796            Page.keyPress = OnImPlotKeyPress
    45624797        elif G2frame.PatternTree.GetItemText(G2frame.PickId) in ['Masks',]:
    4563             Page.Choice = (' key press','l: log(I) on','s: spot mask','a: arc mask','r: ring mask',
    4564                 'p: polygon mask','f: frame mask',)
     4798            Page.Choice = [' key press','l: log(I) on','s: spot mask','a: arc mask','r: ring mask',
     4799                'p: polygon mask','f: frame mask',
     4800                't: add spot mask at mouse position']
     4801            Page.Choice.append('m: start multiple spot mask mode') # this must be the last choice
    45654802            if G2frame.logPlot:
    45664803                Page.Choice[1] = 'l: log(I) off'
     
    46704907                xring,yring = ring['ImxyObs']
    46714908                Plot.plot(xring,yring,colors[N%6]+'.')
    4672         #masks - mask lines numbered after integration limit lines
    4673         spots = Masks['Points']
    4674         rings = Masks['Rings']
    4675         arcs = Masks['Arcs']
    4676         polygons = Masks['Polygons']
    4677         if 'Frames' not in Masks:
    4678             Masks['Frames'] = []
    4679         frame = Masks['Frames']
    4680         for spot in spots:
     4909        # display the Masks
     4910        if 'Frames' not in Masks: Masks['Frames'] = []  # patch
     4911        for i,spot in enumerate(Masks['Points']):   # drawing spot masks
    46814912            if spot:
    46824913                x,y,d = spot
    4683                 Plot.add_artist(Circle((x,y),radius=d/2,fc='none',ec='r',picker=3))
     4914                artist = Circle((x,y),radius=d/2,fc='none',ec='r',picker=3)
     4915                Plot.add_artist(artist)
     4916                artist.itemNumber = i
     4917                artist.itemType = 'Spot'
     4918               
    46844919        G2frame.ringList = []
    4685         for iring,ring in enumerate(rings):
     4920        for iring,ring in enumerate(Masks['Rings']):    # drawing spot masks
    46864921            if ring:
    46874922                tth,thick = ring
    46884923                wave = Data['wavelength']
    4689                 xy1 = []
    4690                 xy2 = []
    4691                 Azm = np.linspace(0,362,181)
    4692                 for azm in Azm:
    4693                     xy1.append(G2img.GetDetectorXY(Dsp(tth+thick/2.,wave),azm,Data))      #what about hyperbola
    4694                     xy2.append(G2img.GetDetectorXY(Dsp(tth-thick/2.,wave),azm,Data))      #what about hyperbola
    4695                 x1,y1 = np.array(xy1).T
    4696                 x2,y2 = np.array(xy2).T
    4697                 G2frame.ringList.append([Plot.plot(x1,y1,'r',picker=3),iring,'o'])           
    4698                 G2frame.ringList.append([Plot.plot(x2,y2,'r',picker=3),iring,'i'])
     4924                (x1,y1),(x2,y2) = ComputeArc(tth-thick/2.,tth+thick/2.,wave)
     4925                artistO, = Plot.plot(x1,y1,'r',picker=3) 
     4926                artistO.itemNumber = iring
     4927                artistO.itemType = 'RingOuter'
     4928                artistI, = Plot.plot(x2,y2,'r',picker=3)
     4929                artistI.itemNumber = iring
     4930                artistI.itemType = 'RingInner'
     4931                G2frame.ringList.append([artistI,artistO])
     4932               
    46994933        G2frame.arcList = []
    4700         for iarc,arc in enumerate(arcs):
     4934        for iarc,arc in enumerate(Masks['Arcs']):      # drawing arc masks
    47014935            if arc:
    47024936                tth,azm,thick = arc           
    47034937                wave = Data['wavelength']
    4704                 xy1 = []
    4705                 xy2 = []
    4706                 aR = azm[0],azm[1],azm[1]-azm[0]
    4707                 if azm[1]-azm[0] > 180:
    4708                     aR[2] /= 2
    4709                 Azm = np.linspace(aR[0],aR[1],aR[2])
    4710                 for azm in Azm:
    4711                     xy1.append(G2img.GetDetectorXY(Dsp(tth+thick/2.,wave),azm,Data))      #what about hyperbola
    4712                     xy2.append(G2img.GetDetectorXY(Dsp(tth-thick/2.,wave),azm,Data))      #what about hyperbola
    4713                 x1,y1 = np.array(xy1).T
    4714                 x2,y2 = np.array(xy2).T
    4715                 G2frame.arcList.append([Plot.plot(x1,y1,'r',picker=3),iarc,'o'])           
    4716                 G2frame.arcList.append([Plot.plot(x2,y2,'r',picker=3),iarc,'i'])
    4717                 G2frame.arcList.append([Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3),iarc,'l'])
    4718                 G2frame.arcList.append([Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3),iarc,'u'])
     4938                (x1,y1),(x2,y2) = ComputeArc(tth-thick/2.,tth+thick/2.,wave,azm[0],azm[1])
     4939                arcList = []
     4940                arcList.append(Plot.plot(x2,y2,'r',picker=3)[0]) # 'inner'
     4941                arcList[-1].itemNumber = iarc
     4942                arcList[-1].itemType = 'ArcInner'
     4943                arcList.append(Plot.plot(x1,y1,'r',picker=3)[0]) # 'outer'           
     4944                arcList[-1].itemNumber = iarc
     4945                arcList[-1].itemType = 'ArcOuter'         
     4946                arcList.append(Plot.plot([x1[0],x2[0]],[y1[0],y2[0]],'r',picker=3)[0]) # 'lower'
     4947                arcList[-1].itemNumber = iarc
     4948                arcList[-1].itemType = 'ArcLower'
     4949                arcList.append(Plot.plot([x1[-1],x2[-1]],[y1[-1],y2[-1]],'r',picker=3)[0]) # 'upper'
     4950                arcList[-1].itemNumber = iarc
     4951                arcList[-1].itemType = 'ArcUpper'
     4952                G2frame.arcList.append(arcList)
     4953               
    47194954        G2frame.polyList = []
    4720         for ipoly,polygon in enumerate(polygons):
    4721             if polygon:
    4722                 x,y = np.hsplit(np.array(polygon),2)
    4723                 G2frame.polyList.append([Plot.plot(x,y,'r+',picker=10),ipoly])
    4724                 Plot.plot(x,y,'r')           
    4725         G2frame.frameList = []
    4726         if frame:
    4727             x,y = np.hsplit(np.array(frame),2)
    4728             G2frame.frameList.append([Plot.plot(x,y,'g+',picker=10),0])
    4729             Plot.plot(x,y,'g')           
     4955        for ipoly,polygon in enumerate(Masks['Polygons']):
     4956            if not polygon: continue # ignore if empty
     4957            if polygon[0] != polygon[-1]:
     4958                print('Closing polygon {}'.format(ipoly))
     4959                polygon.append(polygon[0][:])
     4960            xl,yl = np.hsplit(np.array(polygon),2)
     4961            G2frame.polyList.append(Plot.plot(xl,yl,'r')[0])            # line
     4962            for i,(x,y) in enumerate(zip(xl[:-1],yl[:-1])):
     4963                artist = Plot.plot(x,y,'r+',picker=10)[0] # point (plus sign)
     4964                artist.itemNumber = ipoly
     4965                artist.itemType = 'Polygon'
     4966                artist.pointNumber = i
     4967                   
     4968        G2frame.frameArtist = []
     4969        if Masks['Frames']:
     4970            polygon = Masks['Frames']
     4971            if polygon[0] != polygon[-1]:
     4972                print('Closing frame mask')
     4973                polygon.append(polygon[0][:])
     4974            xl,yl = np.hsplit(np.array(polygon),2)
     4975            G2frame.frameArtist = Plot.plot(xl,yl,'g')[0]
     4976            for i,(x,y) in enumerate(zip(xl[:-1],yl[:-1])):
     4977                artist = Plot.plot(x,y,'g+',picker=10)[0] # point (plus sign)
     4978                artist.itemType = 'Frame'
     4979                artist.pointNumber = i
    47304980        if newImage:
    47314981            Page.figure.colorbar(Page.ImgObj)
  • trunk/help/gsasII.html

    r2545 r2602  
    31693169that can be selected, cut &amp; pasted into a document. <o:p></o:p></span></p>
    31703170
     3171<h3><a name=Tutorials><strong>Macintosh
     3172notes</strong></a><strong>:<o:p></o:p></strong></h3>
     3173
     3174GSAS-II can be run on Windows, Linux and Macintosh/OS X computers, but
     3175due to the different nature of the Mac, the program behaves slightly
     3176differently. On Windows and Linux, there are two menu bars: (A) found
     3177at the top of the GSAS-II data tree and (B) on GSAS-II data editing
     3178window. The latter changes, based on which data item is selected in
     3179the data tree. On the Mac, these menus are combined located on the
     3180location that has been configured for menus (usually at the top of the
     3181screen). The main manu and the data editing menu (if present) are
     3182separated by a vertical bar.
     3183<P>
     3184GSAS-II uses both the left and right buttons on a two-button mouse. If
     3185a mac has a two or three-button mouse attached, these mouse buttons will be
     3186used on the other platforms. If using a Mac touchpad or single-button
     3187mouse, the control-key should be held down to simulate use of the
     3188right mouse button. The left button click is generated otherwise. 
     3189
    31713190<h2><a name=Programmers><strong>Programmers documentation</strong></a><strong>:<o:p></o:p></strong></h2>
    31723191
     
    55055524
    55065525<p class=MsoNormal style='margin-left:.5in'><span style='mso-fareast-font-family:
    5507 "Times New Roman"'>This window... <span class=MsoHyperlink><span
     5526"Times New Roman"'>This window displays calibration values needed to
     5527convert pixel locations to two-theta and azimuth. Also shown are
     5528controls that determine how integration is performed.
     5529<P class=MsoNormal style='margin-left:.5in'>
     5530Menu command for this window are used to perform calibration (fitting
     5531the calibration values from a diffraction pattern image taken with a
     5532calibrant) and for integration. Other menu commands allow the values
     5533on the window to be saved to a file, read from a file or copied to
     5534other images. The "Xfer Angles" menu command scales the current
     5535integration range for other images located at different detector
     5536distances.
     5537
     5538
     5539<span class=MsoHyperlink><span
    55085540style='color:windowtext;text-decoration:none;text-underline:none'><o:p></o:p></span></span></span></p>
    55095541
    5510 <h4 style='margin-left:.5in'>Ma<a name="Image_Masks"></a>sks</h4>
     5542<h4 style='margin-left:.5in'><a name="Image_Masks">Masks</a></h4>
    55115543
    55125544<p class=MsoNormal style='margin-left:.5in'><span style='mso-fareast-font-family:
    5513 "Times New Roman"'>This window... <span class=MsoHyperlink><span
     5545"Times New Roman"'>
     5546Image masks are used designate areas of an image that should not be
     5547included in the integration, typically used due to detector
     5548irregularities, shadows of the beamstop, single-crystal peaks from a
     5549mounting, etc. Masks can be created with a menu command or with
     5550keyboard/mouse shortcuts.
     5551
     5552There are five types of masks:<OL>
     5553<LI style='margin-left:.5in'>Spot masks: occlude a circle with a
     5554  selected center and diameter in image coordinates (mm).
     5555<P style='margin-left:.25in'><B>Create Spot masks</B> with a menu command and then by clicking on
     5556  the location on the image that should be masked. Or, there are also
     5557  three ways to create spot masks with the keyboard:
     5558 <UL>
     5559<LI style='margin-left:.2in'>Press the 's' key and then click on the mask location.   
     5560<LI style='margin-left:.2in'>Press the 'm' key and
     5561   then click successively on multiple locations for spot masks. Press the 'm' key again
     5562   to stop adding spot masks.
     5563<LI style='margin-left:.2in'>Move the mouse to the position for a
     5564   new spot mask and press the 't' key. (Note that
     5565   this can be used while the plot is in Zoom or Pan mode.)
     5566</UL>
     5567<P style='margin-left:.25in'><B>Edit Spot mask location</B> by left-clicking inside
     5568  or on the edge the of the mask and then drag the spot mask to a new
     5569  location.
     5570<P style='margin-left:.25in'><B>Edit Spot mask radius</B> by <a href="#Mac_rightclick">right-clicking*</a> inside
     5571  the mask and then dragging to change the mask size.
     5572
     5573<LI style='margin-left:.5in'>Ring masks: occludes a specific Bragg
     5574  reflection (a ring placed relative to the image center). The
     5575  location and thickness of the ring are specified in degrees
     5576  2-theta.
     5577<P style='margin-left:.25in'><B>Create Ring masks</B> with a menu command and then by clicking on
     5578  the location on the image that should be masked. Or, by pressing the
     5579  'r' key and then clicking at the appropriate radius. Initially the
     5580  mask is given a thickness of 0.1 degrees.
     5581<P style='margin-left:.25in'><B>Edit Ring mask location</B> by
     5582  left-clicking on either the inner or outer circle and drag the
     5583  circle to the new radius.
     5584<P style='margin-left:.25in'><B>Edit Ring mask thickness</B> by
     5585  <a href="#Mac_rightclick">right-clicking*</a> either on the inner or outer circle and drag the
     5586  the circle change spacing between the inner and outer circle.
     5587
     5588<LI style='margin-left:.5in'>Arc masks: occludes a section of a Bragg
     5589  reflection, similar to a ring mask, except that in addition to the
     5590  location and thickness of the ring (in degrees
     5591  2-theta), the starting and ending
     5592  azimuthal angles are also specified in degrees.
     5593
     5594<P style='margin-left:.25in'><B>Create Arc masks</B> with a menu command and then by clicking on
     5595  the location on the image that should be masked. Or, by pressing the
     5596  'a' key and then clicking at the appropriate radius. Initially the
     5597  mask is given a thickness of 0.1 degrees and an azimuthal range of
     5598  10 degrees. 
     5599<P style='margin-left:.25in'><B>Edit Arc mask location</B> by
     5600  left-clicking on either the inner or outer circle and drag the
     5601  circle to the new radius. Alternately, left-click on the upper or
     5602  lower arc limit (the straight lines) and drag them to rotate the
     5603  center of the arc azimuthal range to a new position.
     5604<P style='margin-left:.25in'><B>Edit Arc mask thickness or range</B> by
     5605  <a href="#Mac_rightclick">right-clicking*</a> either on the inner or outer circle and drag the
     5606  the circle change spacing between the inner and outer
     5607  circle. Alternately, <a href="#Mac_rightclick">right-click*</a> on the upper or
     5608  lower arc limit (the straight lines) and drag them to change the
     5609  arc azimuthal range.
     5610
     5611<LI style='margin-left:.5in'>Polygon masks: occludes an arbitary
     5612  region created by line segments joining a series of points
     5613  specified in image coordinates (mm). Pixels inside the polygon mask are not
     5614  used for integration.
     5615<P style='margin-left:.25in'><B>Create Polygon masks</B> with a menu
     5616  command and then by left-clicking successively on the vertices of the
     5617  polygon shape surrounding pixels to be excluded. After the last
     5618  point is defined, <a href="#Mac_rightclick">right-click*</a>
     5619  anywhere to close the mask. Alternately, press the 'p' key and then
     5620  left-click, as before, to define the mask and  <a
     5621  href="#Mac_rightclick">right-click*</a> anywhere to close the mask.
     5622<P style='margin-left:.25in'><B>Edit Polygon mask</B> by
     5623  left-clicking on any point at a vertex in the polygon mask and drag
     5624  that point to a new position. If the vertex is dragged to the same
     5625  position as any other vertex in the mask the dragged point is deleted.
     5626<P style='margin-left:.25in'><B>Add a point to Polygon mask</B> by
     5627  <a href="#Mac_rightclick">right-clicking*</a> on any vertex and dragging. A new
     5628  point is added to the mask immediately after the selected point at
     5629  the position where the mouse is released.
     5630
     5631<LI style='margin-left:.5in'>The Frame mask: occludes an arbitary
     5632  region created by line segments joining a series of points
     5633  specified in image coordinates (mm). Typically a point is placed
     5634  near each corner of the image. Only pixels inside the frame mask are
     5635  used for integration. Only one frame mask can be defined.
     5636<P style='margin-left:.25in'><B>Create a Frame mask</B> with a menu
     5637  command and then by left-clicking successively on the vertices of a
     5638  polygon. After the last point is defined, <a href="#Mac_rightclick">right-click*</a>
     5639  anywhere to close the frame mask. Alternately, press the 'f' key and then
     5640  left-click, as before, to define the mask and  <a
     5641  href="#Mac_rightclick">right-click*</a> anywhere to close the mask.
     5642  Note that if a Frame mask already exists, using the 'f' key or the
     5643  "Create Frame" menu item causes the existing frame mask to be deleted.
     5644<P style='margin-left:.25in'><B>Edit the Frame mask</B> by
     5645  left-clicking on any point at a vertex in the frame mask and drag
     5646  that point to a new position. If the vertex is dragged to the same
     5647  position as any other vertex in the mask the dragged point is deleted.
     5648<P style='margin-left:.25in'><B>Add a point to the Frame mask</B> by
     5649  <a href="#Mac_rightclick">right-clicking*</a> on any vertex and dragging. A new
     5650  point is added to the mask immediately after the selected point at
     5651  the position where the mouse is released.
     5652</OL>
     5653<P style='margin-left:.5in'>The frame mask, if defined, is displayed in green, while
     5654the other types of masks are shown in red. <a name="Mac_rightclick">*</a>Note that on a Mac with a
     5655  one-button mouse, a right-click is generated by pressing the control
     5656  button while clicking the mouse.
     5657<span class=MsoHyperlink><span
    55145658style='color:windowtext;text-decoration:none;text-underline:none'><o:p></o:p></span></span></span></p>
    55155659
     
    74967640style='mso-bookmark:Pawley'><o:p>&nbsp;</o:p></span></p>
    74977641
    7498 <p class=MsoNormal style='margin-left:.5in'><span style='mso-bookmark:Pawley'><!-- hhmts start -->Last
    7499 modified: Mon Oct 31 17:35:19 CDT 2016 <!-- hhmts end --></span></p>
     7642<p class=MsoNormal style='margin-left:.5in'><span style='mso-bookmark:Pawley'><!-- hhmts start -->Last modified: Sun Dec 25 21:30:18 CST 2016 <!-- hhmts end --></span></p>
    75007643
    75017644</div>
Note: See TracChangeset for help on using the changeset viewer.