misc_histo.py 5.71 KB
title = "Histogram"
tip = "density distribution on a map"
onein = 1

import numpy as np
import scipy.stats as ss
from scipy import optimize, signal
try:
   from nodfitting import curve_fit
except:
   from scipy.optimize import curve_fit

from guiqwt import pyplot
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):
            amin = FloatItem('min')
            amax = FloatItem('max')
            same = BoolItem("Set scale", default=False)
            fit  = BoolItem("Gauss fit", default=True)
        name = title.replace(" ", "")
        if args == {}:
           param = FuncParam(_(title), "Histogram noise profile")
        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 hist(self, data, lh, x0, txt):
        try: 
             self.parent.N += 1
        except:
             self.parent.N = 1
             self.parent.fig = pyplot.figure("Intensity distribution")
             self.Nanz = len(self.parent._get_selected_rows())
             self.ix = max(1, int(np.sqrt(self.Nanz+0.25)-0.5 + 0.99))
             self.iy = int(float(self.Nanz)/float(self.ix) + 0.99)
        pyplot.subplot(self.ix, self.iy, self.parent.N)
        if txt != "": pyplot.legend()
        pyplot.hist(data, title=txt, color='blue')
        pyplot.xlabel("Intensity")
        pyplot.ylabel("#bins")
        pyplot.zlabel("distribution")
        if self.parent.N == self.Nanz: pyplot.show(mainloop=False)

    def plot(self, xy, lh, x0, txt, std, filename, p):
        def gauss(X, a, x0, dx, off, slope):
            x = X - dx
            return off + slope*x + a*np.exp(-(x*x)/(2*x0*x0))

        def fit(f, x, y, p0):
            xtol = 1.49012e-08
            Error = True
            while Error:
                  #try:
                  if 1:
                     results = curve_fit(f, x, y, p0=p0, xtol=xtol)
                     popt = results[0]
                     Error = False
                  #except:
                  else:
                     Error = True
                     xtol *= 2.0
                     if xtol > 1.0:
                        return []
            return popt

        x = xy[1][:lh]
        y = xy[0][:lh]
        #for i in range(len(x)):
        #    print x[i], y[i]
        #print
        try: 
             self.parent.N += 1
        except:
             self.parent.N = 1
             self.parent.fig = pyplot.figure("Noise distribution of " + filename)
             self.Nanz = len(self.parent._get_selected_rows())
             self.ix = max(1, int(np.sqrt(self.Nanz+0.25)-0.5 + 0.99))
             self.iy = int(float(self.Nanz)/float(self.ix) + 0.99)
        rms = None
        if p.fit:
           p0 = (max(y), len(x)/4, 0.0, 0.0, 0.0)
           popt = fit(gauss, x, y, p0)
           if popt != []:
              rms = abs(popt[1])
              off = popt[2]
        pyplot.subplot(self.ix, self.iy, self.parent.N)
        if txt != "": pyplot.legend()
        if rms != None:
           pyplot.plot(x, y, "b*", label=txt)
           pyplot.plot(x, gauss(x, *popt), "r-", label=str("RMS=%.2f" % rms))
           pyplot.plot(x, gauss(x, *popt), "", label=str("Off=%.2f" % off))
           self.parent.hist_f = gauss(x, *popt)
           self.parent.hist_f_rms = rms
           self.parent.hist_f_off = off
	else:
           pyplot.plot(x, y, "b-", label=txt)
           self.parent.hist_f = None
        self.parent.hist_x = x
        self.parent.hist_y = y
        pyplot.xlabel("Intensity")
        pyplot.ylabel("#bins")
        pyplot.zlabel("distribution")
        if self.parent.N == self.Nanz: pyplot.show(mainloop=False)

    def function(self, m, p):
        hdata = m.data
        ny, nx = hdata.shape
	mask = ~np.isnan(hdata)
	hdata = hdata[mask]
        med = max(5*np.median(hdata), 5*abs(hdata.min()))
        if p.same:
           bins = 32
           hdata = np.where(hdata == hdata.min(), p.amin, hdata)
           hdata = np.where(hdata == hdata.max(), p.amax, hdata)
           hdata = np.where(hdata < p.amin, np.nan, hdata)
           hdata = np.where(hdata > p.amax, np.nan, hdata)
        else:
           bins = min(int(np.sqrt(nx*ny)), 32)
           hdata = np.where(abs(hdata) < med, hdata, med)
        mask = ~np.isnan(hdata)
        hist, bin_edges = np.histogram(hdata[mask], bins=bins)
        dbin = bin_edges[1] - bin_edges[0]
        #hist /= dbin
        bin_edges += dbin/2.0
        hist = hist[1:]
        bin_edges = bin_edges[1:-1]
        #bin_edges = bin_edges[:-1]
        lh = len(hist)
        for i in range(len(hist)):
            if abs(bin_edges[i]) < med: lh = i
        hmax = 0.0
        imax = 0
        for i in range(lh):
            if hist[i] > imax:
               hmax = bin_edges[i]
               imax = hist[i]
        if "EXTNAME" in m.header: txt = m.header["EXTNAME"].replace("MAP-", "")
        elif "MAPTYPE" in m.header: txt = m.header["MAPTYPE"]
        else: txt = "?"
        if hasattr(self.parent, 'fname'):
           filename = self.parent.fname
        else:
           filename = ""
        self.plot([hist, bin_edges], lh, hmax, txt, np.std(hdata), filename, p)
        #self.hist(hdata, lh, hmax, txt)
        return [], p