filter_denoise.py 3.02 KB
title = "Denoise"
tip = "smoothes maps"
onein = True

import numpy as np
import scipy.stats as stats

from guidata.qt.QtGui import QMessageBox
from guidata.dataset.datatypes import DataSet
from guidata.dataset.dataitems import (IntItem, StringItem, ChoiceItem, FloatItem, BoolItem)
from guiqwt.config import _

class NOD3_App:

    def __init__(self, parent):
        self.parent = parent
        self.parent.activateWindow()

    def Error(self, msg):
        QMessageBox.critical(self.parent.parent(), title,
                              _(u"Error:")+"\n%s" % str(msg))

    def compute_app(self, **args):
        class FuncParam(DataSet):
            s = StringItem('s', default="string")
            i = IntItem('i', default=0, max=100, min=0)
            a = FloatItem('a', default=1.)
            b = BoolItem("bool", default=True)
            choice = ChoiceItem("Unit", ("Degree", "Arcmin", "Arcsec"), default=2)
        name = title.replace(" ", "")
        if args == {}:
           param = FuncParam(_(title), "description")
        else:
           param = self.parent.ScriptParameter(name, args)

        # if no parameter needed set param to None. activate next line
        param = None
        self.parent.compute_11(name, lambda m, p: self.function(m, p), param, onein) 

    def denoise(self, data, n1=1, n2=2):
        mask = np.isnan(data)
        data[mask] = np.interp(np.flatnonzero(mask), np.flatnonzero(~mask), data[~mask])
        rows, cols = data.shape
        Data1 = np.zeros(data.shape, dtype=float)
        Data2 = np.zeros(data.shape, dtype=float)
        f = 1.0/float(n1+n2)
        wsum = 0.0
        for row in range(rows):
            if row >= rows-n1: row1 = 2*rows-row-n1-2
            else: row1 = row+n1
            wsum += (data[row1] - data[abs(row-n2)])*f
            Data1[row] = wsum        
        for col in range(cols):
            Data1[:,col] += (np.median(data[:,col]) - np.median(Data1[:,col]))
        wsum = 0.0
        for col in range(cols):
            if col >= cols-n1: col1 = 2*cols-col-n1-2
            else: col1 = col+n1
            wsum += (data[:,col1] - data[:,abs(col-n2)])*f
            Data2[:,col] = wsum
        for row in range(rows):
            Data2[row] += (np.median(data[row]) - np.median(Data2[row]))
        # basket weaving
        aver = (Data2 + Data1)/2.0
        diff = (Data2 - Data1)/2.0
        clip = 2.5*np.std(diff)
        pfit_col = np.zeros((rows, cols))
        pfit_row = np.zeros((rows, cols))
        x = np.arange(cols)
        y = np.arange(rows)
        for row in range(rows):
            mk = np.abs(diff[row]) < clip 
            poly = np.poly1d(np.polyfit(x[mk], diff[row][mk], 1))
            pfit_row[row] = poly(x)
        for col in range(cols):
            mk = np.abs(diff[:,col]) < clip 
            poly = np.poly1d(np.polyfit(y[mk], diff[:,col][mk], 1))
            pfit_col[:,col] = poly(y)
        Data = aver + pfit_col - pfit_row
        Data[mask] = np.nan
        return Data

    def function(self, m, p):
        m.data = self.denoise(m.data)
        return m, p