misc_Contour.py 5.49 KB
title = "Contour Plot"
tip = "creates a contour plot as overlay"
onein = True

import numpy as np

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

from matplotlib.pyplot import contour
from guiqwt.styles import CurveParam
from guiqwt.curve import PolygonMapItem

Colors = {'White': 0xffffffff, 'Black': 0xff000000, 'Green': 0xff7fff00, 'Yellow': 0xffffff00,
          'Blue': 0xff00bfff, 'Red': 0xffff0000}
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")
            Num = IntItem('NumOfContours', default=10, max=30, min=2)
            Start = FloatItem('StartContour', default=0.0)
            Step = FloatItem('StepContour', default=100.0, min=0.0)
            #Per = FloatItem('Outliers', default=2.5, min=0.0, max=100.0)
            #b = BoolItem("bool", default=True)
            Scale = ChoiceItem("Scale", (("linear", "linear"), ("logarithm", "logarithm")),
                                        default="linear")
            Color = ChoiceItem("Color", (("White", "White"), ("Black", "Black"), 
                                        ("Yellow", "Yellow"), ("Green", "Green"),
                                        ("Red", "Red"), ("Blue", "Blue")), default="White")
        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 eliminate_outliers(self, Data, percent=2., bins=256):
        """Eliminate data histogram outliers"""
        data = Data.ravel()
        mask = ~np.isnan(data)
        hist, bin_edges = np.histogram(data[mask], bins)
        vmin, vmax = hist_range_threshold(hist, bin_edges, percent)
        return vmin, vmax

    def del_plot(self):
        items = self.parent.plot.get_items()
        for item in items:
            itm = str(item).split()[0].split(".")[-1]
            if itm == "PolygonMapItem":
               self.parent.plot.del_items([item])

    def make_contour(self, m, levels, color='white'):
        #ow, oh, width, height = self.parent.plot.canvas().rect().getRect()
        #self.del_plot()
        rows, cols = m.data.shape
        x1, y1 = self.parent.get_plot_coordinates(0.0, 0.0)
        x2, y2 = self.parent.get_plot_coordinates(cols, rows)
        if hasattr(self.parent, 'vu'): 
           f = self.parent.vu
        else: 
           f = 1.0
        dx = float(x2 - x1) / float(cols)
        dy = float(y2 - y1) / float(rows)
        xx = np.arange(f*x1, f*x2, f*dx)[:cols]
        yy = np.arange(f*y1, f*y2, f*dy)[:rows]
        X, Y = np.meshgrid(xx, yy)
        Z = m.data
        CS = contour(X, Y, Z, levels)
        has_not_allsegs = False
        if not hasattr(CS, 'allsegs'):
           has_not_allsegs = True
           CS.allsegs = []
           for path in CS.collections:
               CS.allsegs.append(path.get_paths())
        pos = []
        off = []
        col = []
        num = 0
        n = 0
        for path, cval in zip(CS.allsegs, CS.cvalues):
            for p in path:
                if has_not_allsegs: p = p.vertices
                if p[0][0] != p[-1][0] or p[0][1] != p[-1][1]:
                   q = list(p)
                   q.reverse()
                   p = np.concatenate([p, q])
                pos.append(p) 
                off.append([n, num])
                num += len(p)
                #col.append([0xffffffff, 0x00000000])
                col.append([Colors[color], 0x00000000])
                n += 1
        if pos == []: 
           self.Error("sorry, no contours available!")
           return
        pos = np.concatenate(pos)
        off = np.array(off)
        curveparam = CurveParam(title="PolygonMap", icon="curve.png")
        curveparam.label = "Contour"
        crv = PolygonMapItem(curveparam)
        crv.set_data(pos, off, col)
        crv.setTitle(curveparam.label)
        crv.Name = "Contours"
        crv.Levels = levels
        crv.Color = color
        crv.Linewidth = 0.5
        crv.Data = m.data
        self.parent.plot.add_item(crv)
        self.parent.plot.replot()

    def function(self, m, p):
        #xmin, xmax = self.eliminate_outliers(m.data, percent=p.Per)
        #p.Step = abs(xmax - xmin)/float(p.Num)
        #levels = np.arange(xmin+p.Step/3, xmax, p.Step)
        self.parent.del_polygon("Contour")
        xmin = p.Start
        xmax = p.Start + p.Num*p.Step
        if p.Scale == "linear":
           levels = np.arange(xmin, xmax, p.Step)
        elif p.Scale == "logarithm":
           levels = [xmin]
           step = (xmax-xmin)**(1.0/(p.Num))
           f = np.nanmax(m.data)/xmax
	   xx = xmin
           for n in range(1,p.Num):
               #levels.append(xmin + n*p.Step + f*step**n) 
               xx *= 10.0**p.Step 
               levels.append(xx) 
        #print levels
        self.make_contour(m, levels, p.Color)
        return [], p