base_EKHrestore1.py 5.35 KB
title = "EKH-Restore"
tip = "restore multi-horn maps scanned in Azimuth"
onein = False

import copy as cp
import numpy as np
#from scipy.ndimage import gaussian_filter1d
from scipy.interpolate import interp1d

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 _

from nodmath import nan_interpol

def factorial(n):
    return reduce(lambda x,y:x*y,[1]+range(1,n+1))

def median(x):
    xl = list(x)
    xl.sort()
    return xl[len(xl)/2]

def nint(x):
    if x > 0: return int(x+0.5)
    else: return int(x-0.5)

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):
            order = IntItem('Order', default=7, max=13, min=1)
            #adjust = BoolItem('Adjust', default=False)
        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 autocal(self, data1, data2, ix):
        d1 = list(np.ravel(data1[:,ix:]))
        d2 = list(np.ravel(data2[:,:-ix]))
        d1.sort()
        d2.sort()
        nl = max(10, len(d1)/10)
        a1, a0 = np.polyfit(d2[-nl:], d1[-nl:], 1)
        return data1, a0 + a1*data2
        
    def polymat(self, order, dx, xx):
        mat = []
        for x in xx:    
            y = []
            #for n in range(order-1,-1,-1):
            for n in range(order-1,1,-1):
                y.append(float(x+dx)**n - float(x)**n)
            #y.append(float(x-dx))
            y.append(float(dx))
            y.append(1.0)
            mat.append(y)
        return np.array(mat)
    
    def xconv(self, diff, cols, cfunc, rnorm):
        out = []
        ldif = len(diff)
        lfun = len(cfunc)
        for i in range(cols):
            asum = 0.0
            for j in range(lfun):
                k = i - ldif + j + 2
                if k >= 0 and k < cols:
                   asum += diff[k] * cfunc[j]
            out.append(asum/rnorm)
        return np.array(out)

    def conf4(self, ndim, ptsep):
        ndim2 = 2*ndim - 1
        nsincs = int((float(ndim) / ptsep) + 0.5)
        nsinc2 = nsincs * 2 + 1
        cfunc = []
        sumt = 0.0
        for i in range(ndim2):
            dx = i - ndim + 1
            asum = 0.0
            b1 = - (nsincs * ptsep)
            for j in range(nsinc2):
                sn = b1
                b1 += ptsep
                asum -= np.sinc(dx - sn)
            cfunc.append(asum)
            sumt += asum
        sumt = (-sumt * ndim) / float(ndim2)
        for k in range(ndim2):
            cfunc[k] = cfunc[k]/sumt
        cfunc[ndim-1] += 1.0
        return cfunc

    def conf22(self, ndim, ptsep):
        ptsep2 = ptsep*0.5
        ndim2 = 2*ndim - 1
        nsincs = int((float(ndim) / ptsep) + 0.5)
        nsinc2 = nsincs * 2
        cfunc = []
        for i in range(ndim2):
            dx = i - ndim + 1 #+ ptsep2
            asum = 0.0
            b1 = (ptsep/2.0) - (nsincs * ptsep)
            alpha = 1.0
            for j in range(nsinc2):
                sn = b1
                b1 += ptsep
                asum -= np.sinc(dx - sn) * np.sign(sn)
            cfunc.append(asum)
        #return cfunc
        for i in range(ndim):
            k = ndim2-1 - i
            x = cfunc[k]
            cfunc[k] = -cfunc[i]
            cfunc[i] = -x
        return cfunc

    def ipol(self, y, x, dx):
        ix = int(dx)
        d = dx-ix
        if d == 0.0:
           return y[x-ix]
        val0 = y[x-ix] 
        val1 = y[x-ix-1] 
        return val0*(1-d) + val1*d
        
    def function(self, ms, p):
        nmaps = len(ms)
        combinations = factorial(nmaps)/(2*factorial(nmaps-2))
        data = []
        coord = []
        for n in range(nmaps):
            for m in range(n+1, nmaps):
                m1 = ms[n]
                m2 = ms[m]
                mask1, m1.data = nan_interpol(m1.data)
                mask2, m2.data = nan_interpol(m2.data)
                dx = (m1.header['PATLONG'] - m2.header['PATLONG']) / m1.header['CDELT1']
                if dx < 0:
                   m1 = ms[m]
                   m2 = ms[n]
                   dx = (m1.header['PATLONG'] - m2.header['PATLONG']) / m1.header['CDELT1']
                if abs(dx) > 30.0: dx = abs(dx)/3600.0
                ix = nint(dx)
                data1, data2 = self.autocal(m1.data, m2.data, ix)
                rows, cols = data1.shape
                kamm = self.conf22(cols, dx)
                basl = self.conf4(cols, dx)
                for row in range(rows):
                    diff = data2[row] - data1[row] 
                    diff = self.xconv(diff, cols, basl, 1.0)
                    data1[row] = self.xconv(diff, cols, kamm, 2.0)
        m1.data = data1
        #m1.header['CRPIX1'] -= dx/2 + 2
        m1.header['CRPIX1'] -= 2
        m1.header['PATLONG'] = 0.0
        self.parent.SidOut = True
        return m1, p