Changeset 5468


Ignore:
Timestamp:
Jan 9, 2023 11:00:59 AM (11 months ago)
Author:
toby
Message:

replace AutoSpotMask? with faster version from Wenqian et al

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIimage.py

    r5256 r5468  
    2424import scipy.interpolate as scint
    2525import scipy.special as sc
     26from scipy.stats import median_absolute_deviation as MAD
    2627import copy
    2728import GSASIIpath
     
    17081709        else:
    17091710            return None
    1710    
     1711
     1712# Original version
    17111713def AutoSpotMask(Image,Masks,Controls,numChans,dlg=None):
    1712    
     1714    '''Find "bad" regions on an image and remove them with a spot mask.
     1715    This works by masking pixels that are well outside the range of the
     1716    radial average.
     1717    Original version from RBVD, takes 1-5 min per image. No longer in use.
     1718    '''
     1719    #if GSASIIpath.GetConfigValue('debug'): print('original AutoSpotMask starting')
    17131720    frame = Masks['Frames']
    17141721    tam = ma.make_mask_none(Image.shape)
     
    17371744    return mask
    17381745
     1746def AutoSpotMask(Image, Masks, Controls, numChans, dlg=None):
     1747    '''Find "bad" regions on an image and remove them with a spot mask.
     1748    This works by masking pixels that are well outside the range of the
     1749    median at that radial distance.
     1750    This is ~4x faster than the original version from RBVD.
     1751    Developed by Howard Yanxon, Wenqian Xu and James Weng.
     1752
     1753    Called from OnFindSpotMask (single image) and OnAutoFindSpotMask
     1754    (multiple images) in :func:`GSASIIimgGUI.UpdateMasks`
     1755
     1756    :param np.array Image: 2D data structure describing a diffaction image
     1757    :param dict Masks: contents of Masks data tree
     1758    :param dict Controls: diffraction & calibration parameters for image from
     1759      IMG data tree entry
     1760    :param int numChans: number of channels in eventual 2theta pattern
     1761      after integration
     1762    :param wx.Dialog dlg: a widget that can be used to show the status of
     1763      the spot mask scan and can optionally be used to cancel the scan. If
     1764      dlg=None then this is ignored (for non-GUI use).
     1765    :returns: a mask array with the same shape as Image or None if the
     1766      the scan is cancelled from the dlg Dialog.
     1767    '''
     1768    #if GSASIIpath.GetConfigValue('debug'): print('faster all-Python AutoSpotMask')
     1769    frame = Masks['Frames']
     1770    tam = ma.make_mask_none(Image.shape)
     1771    if frame:
     1772        tam = ma.mask_or(tam,MakeFrameMask(Controls,frame))
     1773    LUtth = np.array(Controls['IOtth'])
     1774    dtth = (LUtth[1]-LUtth[0])/numChans
     1775    esdMul = Masks['SpotMask']['esdMul']   
     1776    print(' Spots greater or less than %.1f of median abs deviation are masked'%esdMul)
     1777    band = np.array(Image)
     1778    TA = Make2ThetaAzimuthMap(Controls, (0, Image.shape[0]), (0, Image.shape[1]))[0]
     1779    TThs = np.linspace(LUtth[0], LUtth[1], numChans, False)
     1780    mask = (TA >= LUtth[1]) | (TA < LUtth[0]) | tam
     1781 
     1782    for it in range(len(TThs)):
     1783        masker = (TA >= TThs[it]) & (TA < TThs[it]+dtth) & ~tam
     1784        bin = band[masker]
     1785        if np.all(np.isnan(bin)):
     1786            continue
     1787        if bin.size < 1:
     1788            continue
     1789        median = np.nanmedian(bin) 
     1790        mad = MAD(bin, nan_policy='omit')       
     1791        anom = np.abs(band-median)/mad <= esdMul
     1792        mask |= (anom & masker)
     1793        if not dlg is None:
     1794            GoOn = dlg.Update(it,newmsg='Processed 2-theta rings = %d'%(it))
     1795            if not GoOn[0]:
     1796                return None
     1797                #break
     1798    return ~mask
     1799
    17391800def DoPolaCalib(ImageZ,imageData,arcTth):
    17401801    ''' Determine image polarization by successive integrations with & without preset arc mask.
  • trunk/GSASIIimgGUI.py

    r5446 r5468  
    17981798           
    17991799    def OnFindSpotMask(event):
    1800         'Do auto search for spot masks'
     1800        '''Do auto search for spot masks
     1801        Called from (Masks) Operations->"Spot mask search"
     1802        '''
     1803        dlg = wx.MessageDialog(G2frame.dataWindow,
     1804                'NB: This can be slow (0.5 to 2 min)',
     1805                'Spot mask search', wx.OK|wx.CANCEL)
    18011806        try:
    1802             if wx.MessageDialog(G2frame.dataWindow,'NB: This is slow (5-10min)',
    1803                 'Spot mask search', wx.OK|wx.CANCEL).ShowModal() == wx.ID_OK:
     1807            if dlg.ShowModal() == wx.ID_OK:
    18041808                Controls = G2frame.GPXtree.GetItemPyData(
    18051809                    G2gd.GetGPXtreeItemId(G2frame,G2frame.Image,'Image Controls'))
     
    18241828        except:
    18251829            print('Invalid limits - spot mask search not done')
     1830        finally:
     1831            dlg.Destroy()
    18261832           
    18271833    def OnAutoFindSpotMask(event):
Note: See TracChangeset for help on using the changeset viewer.