Search code examples
pythonhealpy

Smoothing without filling missing values with zeros


I'd like to smooth a map that doesn't cover the full sky. This map is not Gaussian nor has it mean zero, so the default behavior of healpy in which it fills missing values with 0 leads to a bias towards lower values at the edges of this mask:

import healpy as hp

nside = 128
npix = hp.nside2npix(nside)

arr = np.ones(npix)
mask = np.zeros(npix, dtype=bool)

mask[:mask.size//2] = True

arr[~mask] = hp.UNSEEN
arr_sm = hp.smoothing(arr, fwhm=np.radians(5.))

hp.mollview(arr, title='Input array')
hp.mollview(arr_sm, title='Smoothed array')

enter image description here enter image description here

I would like to preserve the sharp edge by setting the weight of the masked values to zero, instead of setting the values to zero. This appears to be difficult because healpy performs the smoothing in harmonic space.

To be more specific, I'd like to mimic the mode keyword in scipy.gaussian_filter(). healpy.smoothing() implicitly uses mode=constant with cval=0, but I'd require something like mode=reflect.

Is there any reasonable way to overcome this issue?


Solution

  • This problem is related to the following question and answer (disclaimer: from me):

    https://stackoverflow.com/a/36307291/5350621

    It can be transferred to your case as follows:

    import numpy as np
    import healpy as hp
    
    nside = 128
    npix = hp.nside2npix(nside)
    
    # using random numbers here to see the actual smoothing
    arr = np.random.rand(npix) 
    mask = np.zeros(npix, dtype=bool)
    mask[:mask.size//2] = True
    
    def masked_smoothing(U, rad=5.0):     
        V=U.copy()
        V[U!=U]=0
        VV=hp.smoothing(V, fwhm=np.radians(rad))    
        W=0*U.copy()+1
        W[U!=U]=0
        WW=hp.smoothing(W, fwhm=np.radians(rad))    
        return VV/WW
    
    # setting array to np.nan to exclude the pixels in the smoothing
    arr[~mask] = np.nan
    arr_sm = masked_smoothing(arr)
    arr_sm[~mask] = hp.UNSEEN
    
    hp.mollview(arr, title='Input array')
    hp.mollview(arr_sm, title='Smoothed array')