pol_polvec.py 10.3 KB
title = "PolVec"
tip = "plots the polarization vectors"
onein = 2

import numpy as np
import copy as cp
try: from matplotlib.nxutils import points_inside_poly
except: from nod3tools import points_inside_poly

from guiqwt import pyplot
from guiqwt.curve import PolygonMapItem
from guiqwt.styles import CurveParam
from guidata.qt.QtGui import QMessageBox, QColor, QPen, QBrush, QPolygonF
from guidata.dataset.datatypes import DataSet
from guidata.dataset.dataitems import (IntItem, StringItem, ChoiceItem, FloatItem, BoolItem)
from guiqwt.config import _

from guidata.qt.QtCore import (Qt, QPoint, QPointF, QLineF, SIGNAL, QRectF, QLine)

from nodmath import topixeln

Colors = {'White': 0xffffffff, 'Black': 0xff000000, 'Green': 0xff7fff00, 'Yellow': 0xffffff00,
          'Blue': 0xff00bfff, 'Red': 0xffff0000}
Colors1 = {'White': 'w', 'Black': 'k', 'Green': 'g', 'Yellow': 'y',
          'Blue': 'b', 'Red': 'r'}

try:
    from gshhs import simplify_poly
except ImportError:
    from guiqwt.curve import _simplify_poly as simplify_poly


RAD = np.pi/180.0

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):
            box = IntItem('Box-size:', default=5, max=100, min=1)
            off = FloatItem('Angle-offset:', default=90.0)
            rms = FloatItem('Threshold:', default=0.0)
            scale = FloatItem('Scale(arcmin/Intensity):', default=100.0)
            mode = ChoiceItem("Mode:", (("Default", "Default"),
                                       ("Average", "Average"), ("Median", "Median"),
                                       ("Maximum", "Maximum")), default = "Default")
            color = ChoiceItem("Color", (("White", "White"), ("Black", "Black"),
                                        ("Yellow", "Yellow"), ("Green", "Green"),
                                        ("Red", "Red"), ("Blue", "Blue")), default="White")
            linewidth = IntItem('LineWidth:', default=1, min=1, max=10)
        name = title.replace(" ", "")
        if args == {}:
           param = FuncParam(_(title), "Your choise:")
        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 checkit(self, x0, y0, vcos, vsin):
        if points_inside_poly([(x0-vcos, y0-vsin)], self.border):
           x1 = x0-vcos
           y1 = y0-vsin
        else:
           x1 = x0
           y1 = y0
        if points_inside_poly([(x0+vcos, y0+vsin)], self.border):
           x2 = x0+vcos
           y2 = y0+vsin
        else:
           x2 = x0
           y2 = y0
        return (x1,y1), (x2,y2)

    def draw(self, painter, xMap, yMap, canvasRect):
        p1x = xMap.p1()
        s1x = xMap.s1()
        ax = (xMap.p2() - p1x)/(xMap.s2()-s1x)
        p1y = yMap.p1()
        s1y = yMap.s1()
        ay = (yMap.p2() - p1y)/(yMap.s2()-s1y)
        bx, by = p1x-s1x*ax, p1y-s1y*ay
        _c = self._c
        _n = self._n
        fgcol = QColor()
        bgcol = QColor()
        polygons = simplify_poly(self._pts, _n, (ax, bx, ay, by),
                                 canvasRect.getCoords() )
        for poly, num in polygons:
            points = []
            for i in xrange(poly.shape[0]):
                points.append(QPointF(poly[i,0],poly[i,1]))
            pg = QPolygonF(points)
            fgcol.setRgba(int(_c[num,0]))
            bgcol.setRgba(int(_c[num,1]))
            pen = QPen(fgcol)
            pen.setWidth(self.lw) 
            #painter.setPen(QPen(fgcol))
            painter.setPen(pen)
            #painter.setBrush(QBrush(bgcol))
            painter.drawPolygon(pg)

    def getCoord(self, positions, mat):
        newpos = []
        for pos in positions: 
            newp = []
            for p in pos:
                l, b = p
                x = np.cos(RAD*b)*np.cos(RAD*l)
                y = np.cos(RAD*b)*np.sin(RAD*l)
                z = np.sin(RAD*b)
                xyz = np.dot(np.array(mat), np.array([x,y,z]))
                l1 = np.arctan2(xyz[1], xyz[0])
                b1 = np.arctan2(xyz[2], np.sqrt(xyz[1]**2 + xyz[0]**2))
                newp.append((l1/RAD, b1/RAD))
            newpos.append(newp)
        return newpos

    def rotmat_x(self, a):
        xrot = [[1.0, 0.0, 0.0], \
                [0.0, np.cos(a*RAD), -np.sin(a*RAD)], \
                [0.0, np.sin(a*RAD),  np.cos(a*RAD)]]
        return xrot

    def plotit(self, boxval, boxang, coords, box, aoff, scale, lw=1, col='White'):
        box2 = box/2
        pmin = np.nanmin(boxval)
        pmax = np.nanmax(boxval)
        #amp = self.dy*scale / 60.0
        amp = scale / 60
        r = np.pi/180.0
        pos = []
        off = []
        color = []
        self.lw = lw
        v = amp*np.array(boxval)
        a = np.array(boxang) + aoff + 90.0  # starts at north
        vsin = self.dy*v*np.sin(r*a) 
        vcos = self.dx*v*np.cos(r*a)
        for n in range(len(coords)):
            x0, y0 = coords[n]
            pos.append(self.checkit(x0, y0, vcos[n], vsin[n]))
            off.append([n, 2*n])
            color.append([Colors[col], 0x00000000])
        if pos == []: return
        # save data for matlabplot
        positions = cp.copy(pos)
        # add corners for plot scaling
        n = len(coords)
        pos.append((self.border[0], self.border[0]))
        pos.append((self.border[2], self.border[2]))
        off.append([n, 2*n])
        off.append([n+1, 2*(n+1)])
        color.append([0x00000000, 0x00000000])
        color.append([0x00000000, 0x00000000])
        #
        pos = self.f*np.concatenate(pos)
        off = np.array(off)
        self._c = np.array(color, copy=False)
        self._n = off
        self._pts = pos
        self.parent.del_polygon("PolVec")
        curveparam = CurveParam(_(title), icon="polyline.png")
        curveparam.label = "PolVec"
        crv = PolygonMapItem(curveparam=curveparam)
        crv.draw = self.draw
        crv.set_data(pos, off, color)
        crv.setTitle(curveparam.label)
        crv.update_params()
        crv.Name = "Lines"
        #crv.Positions = topixeln(self.ph, positions)      NOW DONE IN PLOT
        ## check for map rotation: cannot plot with kapteyn without rotation
        #if 'CROTA2' in self.ph:
        #   rotang = self.ph['CROTA2'] 
        #else:
        #   rotang = 0.0
        #if rotang != 0.0:
        #   mat = self.rotmat_x(rotang)
        #   positions = crv.Positions = self.getCoord(positions, mat)
        crv.Positions = positions
        crv.Pixel = False
        crv.Color = Colors1[col]
        crv.Linewidth = lw/2.0
        self.parent.plot.add_item(crv)
        self.parent.plot.replot()

    def function(self, ms, p):
        data = None
        i = -1
        for m in ms:
            i += 1
            if m.header["MAPTYPE"] == "PA":
               PA = m.data
               self.pa = m.header
               unselect = i
            elif m.header["MAPTYPE"] == "PI":
               PI = m.data 
               self.ph = m.header
               select = i
            else:
               self.Error("sorry, not a PA or PI map")
               return [], p
        boxval = []
        boxang = []
        coords = []
        if hasattr(self.parent, 'vu'):
           self.f = self.parent.vu
        else:
           self.f = 1.0
        rows, cols = PI.shape
        x1, y1 = self.parent.get_plot_coordinates(0, 0)
        x2, y2 = self.parent.get_plot_coordinates(cols, rows)
        self.border = np.array([[x1,y1], [x1,y2], [x2,y2], [x2, y1], [x1, y1]])
        self.dx = (x2-x1)/cols
        self.dy = (y2-y1)/rows
        self.progress = self.parent.imagewidget.Progress
        self.progress.showMessage(_("stop program with ^C"), 5000)
        for row in range(0, int(rows-0.5*p.box), p.box):
            for col in range(0, int(cols-0.5*p.box), p.box):
                self.progress.showMessage(_("stop program with ^C"), 5000)
                if self.parent.STOP:
                   self.progress.showMessage(_("stopped by ^C"), 5000)
                   self.parent.STOP = False 
                   return [], p
                rc, cc = row+p.box/2, col+p.box/2
                if p.mode == "Default":
                   if PI[rc, cc] > p.rms:
                      boxval.append(PI[rc, cc])
                      boxang.append(PA[rc, cc])
                      #l, b = self.parent.get_plot_coordinates(col+0.5*p.box, row+0.5*p.box)
                      l, b = self.parent.get_plot_coordinates(cc, rc)
                      coords.append((l, b))
                elif p.mode == "Average":
                   if np.nanmean(PI[row:row+p.box, col:col+p.box]) > p.rms:
                      boxval.append(np.nanmean(PI[row:row+p.box, col:col+p.box]))
                      boxang.append(np.nanmean(PA[row:row+p.box, col:col+p.box]))
                      #l, b = self.parent.get_plot_coordinates(col+0.5*p.box, row+0.5*p.box)
                      l, b = self.parent.get_plot_coordinates(cc, rc)
                      coords.append((l, b))
                elif p.mode == "Median":
                   if np.median(PI[row:row+p.box, col:col+p.box]) > p.rms:
                      boxval.append(np.median(PI[row:row+p.box, col:col+p.box]))
                      boxang.append(np.median(PA[row:row+p.box, col:col+p.box]))
                      #l, b = self.parent.get_plot_coordinates(col+0.5*p.box, row+0.5*p.box)
                      l, b = self.parent.get_plot_coordinates(cc, rc)
                      coords.append((l, b))
                elif p.mode == "Maximum":
                   if np.nanmax(PI[row:row+p.box, col:col+p.box]) > p.rms:
                      boxval.append(np.nanmax(PI[row:row+p.box, col:col+p.box]))
                      boxang.append(np.nanmax(PA[row:row+p.box, col:col+p.box]))
                      #l, b = self.parent.get_plot_coordinates(col+0.5*p.box, row+0.5*p.box)
                      l, b = self.parent.get_plot_coordinates(cc, rc)
                      coords.append((l, b))
        if boxval == []:
           self.Error("sorry, no values available with your choise")
           return [], p
        self.plotit(boxval, boxang, coords, p.box, p.off, p.scale, p.linewidth, p.color)
        return [], p