平滑而不用零填充缺失值

时间:2018-04-24 19:05:59

标签: python healpy

我想要平滑一张不能覆盖整个天空的地图。此地图不是高斯分布,也不是零,所以healpy的默认行为(其中0填充缺失值)会导致偏向此掩码边缘的较低值:

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

我想通过将屏蔽值的权重设置为零来保留锐边,而不是将值设置为零。这看起来很困难,因为healpy在谐波空间中执行平滑。

更具体地说,我想模仿scipy.gaussian_filter()中的mode关键字。 healpy.smoothing()隐含地将mode=constantcval=0一起使用,但我需要mode=reflect之类的内容。

有没有合理的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

处理此问题的最简单方法是删除地图的平均值,使用hp.smoothing执行平滑处理,然后再添加偏移量。 这解决了这个问题,因为现在地图是零均值,因此零填充不会产生边界效果。

def masked_smoothing(m, fwhm_deg=5.0): #make sure m is a masked healpy array m = hp.ma(m) offset = m.mean() smoothed=hp.smoothing(m - offset, fwhm=np.radians(fwhm_deg))
return smoothed + offset

我能想到的另一个选择是在平滑之前以“反射”模式填充地图的迭代算法,可能在cythonnumba中实现,主要问题是复杂程度如何你的边界。如果它像纬度切割一样容易,那么所有这一切都很容易,因为一般情况非常复杂,并且可能需要处理很多极端情况:

识别“边界图层”

  • 获取所有缺少的像素
  • 找到邻居并找到哪个邻居并将其标记为“第一个边界”
  • 重复此算法,找到具有“第一个边框”像素邻居的像素,并将其标记为“第二个边框”
  • 重复,直到您拥有所需的所有图层

填写反映值

  • 在边界图层上循环
  • 循环每个图层像素
  • 找到有效的邻居,计算它们的重心,现在假设边界像素中心和重心之间的直线穿过掩模边界并且掩模边界是中途
  • 现在通过在遮罩内部方向加倍来扩展此线,在该位置获取地图的插值并将其指定给当前缺失的像素
  • 通过播放该行的长度为其他图层重复此操作。

答案 1 :(得分:1)

此问题与以下问答有关(免责声明:来自我):

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

可以按照以下方式转移到您的案例:

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')