From 97640621157e967ab3254f30d9e6e16d25b7c6e4 Mon Sep 17 00:00:00 2001 From: rfetick <r.fetick@gmail.com> Date: Fri, 8 May 2020 18:37:29 +0200 Subject: [PATCH] Add small functions getgaussnoise and rmserror --- maoppy/psfmodel.py | 38 +++++++++++++++++++------------------- maoppy/utils.py | 11 +++++++++++ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/maoppy/psfmodel.py b/maoppy/psfmodel.py index a6f6141..4cd98df 100644 --- a/maoppy/psfmodel.py +++ b/maoppy/psfmodel.py @@ -12,9 +12,18 @@ from astropy.io import fits import time from numpy.fft import fft2, fftshift, ifft2 from maoppy.config import _EPSILON -from maoppy.utils import binning +from maoppy.utils import binning, getgaussnoise #%% FITTING FUNCTION +def rmserror(model,image,weights=1.0,background=True, positive_bck=False): + """Compute the RMS error between a PSF model and an image""" + amp,bck = lsq_flux_bck(model, image, weights=weights, background=background, positive_bck=positive_bck) + diff = amp*model+bck - image + noise_std = getgaussnoise(image) + err = np.sqrt(np.sum(diff**2.0 - noise_std**2.0)) + err = err/np.sum(image) + return err + def lsq_flux_bck(model, data, weights, background=True, positive_bck=False): """Compute the analytical least-square solution for flux and background LS = SUM_pixels { weights*(flux*model + bck - data)² } @@ -104,20 +113,16 @@ def psffit(psf,Model,x0,weights=None,dxdy=(0.,0.),flux_bck=(True,True), Value of cost function at optimum """ Model_inst = Model(np.shape(psf),**kwargs) - if weights is None: - weights = np.ones_like(psf) - elif len(psf)!=len(weights): - raise ValueError("Keyword `weights` must have same number of elements as `psf`") + if weights is None: weights = np.ones_like(psf) + elif len(psf)!=len(weights): raise ValueError("Keyword `weights` must have same number of elements as `psf`") sqW = np.sqrt(weights) class CostClass(object): def __init__(self): self.iter = 0 def __call__(self,y): - if (self.iter%3) == 0: - print("-",end="") + if (self.iter%3)==0: print("-",end="") self.iter += 1 - x, dxdy = mini2input(y) m = Model_inst(x,dx=dxdy[0],dy=dxdy[1]) amp, bck = lsq_flux_bck(m, psf, weights, background=flux_bck[1], positive_bck=positive_bck) @@ -126,17 +131,14 @@ def psffit(psf,Model,x0,weights=None,dxdy=(0.,0.),flux_bck=(True,True), cost = CostClass() if fixed is not None: - if len(fixed)!=len(x0): - raise ValueError("When defined, `fixed` must be same size as `x0`") + if len(fixed)!=len(x0): raise ValueError("When defined, `fixed` must be same size as `x0`") FREE = [not fixed[i] for i in range(len(fixed))] INDFREE = np.where(FREE)[0] def input2mini(x,dxdy): # Transform user parameters to minimizer parameters - if fixed is None: - xfree = x - else: - xfree = np.take(x,INDFREE) + if fixed is None: xfree = x + else: xfree = np.take(x,INDFREE) return np.concatenate((xfree,dxdy)) def mini2input(y): @@ -151,12 +153,10 @@ def psffit(psf,Model,x0,weights=None,dxdy=(0.,0.),flux_bck=(True,True), def get_bound(inst): b_low = inst.bounds[0] - if fixed is not None: - b_low = np.take(b_low,INDFREE) + if fixed is not None: b_low = np.take(b_low,INDFREE) b_low = np.concatenate((b_low,[-np.inf,-np.inf])) b_up = inst.bounds[1] - if fixed is not None: - b_up = np.take(b_up,INDFREE) + if fixed is not None: b_up = np.take(b_up,INDFREE) b_up = np.concatenate((b_up,[np.inf,np.inf])) return (b_low,b_up) @@ -173,7 +173,7 @@ def psffit(psf,Model,x0,weights=None,dxdy=(0.,0.),flux_bck=(True,True), result.psf = m return result -#%% BESIC FUNCTIONS +#%% BASIC FUNCTIONS def reduced_coord(XY,ax,ay,theta,cx,cy): c = np.cos(theta) s = np.sin(theta) diff --git a/maoppy/utils.py b/maoppy/utils.py index df80f0c..42d569a 100644 --- a/maoppy/utils.py +++ b/maoppy/utils.py @@ -8,12 +8,23 @@ Created on Mon May 27 17:27:44 2019 import numpy as np from scipy.special import jv +from numpy.fft import fft2, fftshift #%% CONSTANTS # Radian to arcsec RAD2ARCSEC = 180./np.pi * 3600. #%% IMAGE PROCESSING FUNCTIONS +def getgaussnoise(image): + """Compute the std deviation of a gaussian noise in an image""" + sx, sy = np.shape(image) + ft_im2 = fftshift(np.abs(fft2(image))**2) + sn = np.sum(ft_im2[0,0:sy-1])+np.sum(ft_im2[0:sx-1,sy-1])+np.sum(ft_im2[sx-1,sy-1:0:-1])+np.sum(ft_im2[sx-1:0:-1,0]) + sn = sn/(2*sx+2*sy-4) + sigma = np.sqrt(sn/(sx*sy)) + return sigma + + def circarr(Npix, center=(None, None)): """Compute array of radii to the center of array -- GitLab