From 1e805c57ae65f0b8691663fad109cbba8d59bb92 Mon Sep 17 00:00:00 2001 From: Marco Selig <mselig@ncg-02.MPA-Garching.MPG.DE> Date: Thu, 11 Sep 2014 16:10:46 +0200 Subject: [PATCH] intermediate update; healpy update hotfix. --- __init__.py | 1 + nifty_core.py | 14 +-- nifty_power_conversion.py | 253 ++++++++++++++++++++++++++++++++++++++ nifty_tools.py | 18 +-- 4 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 nifty_power_conversion.py diff --git a/__init__.py b/__init__.py index 5dd278c84..564ff2ece 100644 --- a/__init__.py +++ b/__init__.py @@ -26,6 +26,7 @@ from nifty_power import * from nifty_tools import * from nifty_explicit import * +from nifty_power_conversion import * ##----------------------------------------------------------------------------- diff --git a/nifty_core.py b/nifty_core.py index 72ab4ea6b..338f35c54 100644 --- a/nifty_core.py +++ b/nifty_core.py @@ -514,7 +514,7 @@ class _about(object): ## nifty support class for global settings """ ## version - self._version = "0.8.1" + self._version = "0.8.4" ## switches and notifications self._errors = notification(default=True,ccode=notification._code) @@ -5137,7 +5137,7 @@ class hp_space(space): if(self.discrete): x = self.calc_weight(x,power=-0.5) ## transform - Tx = hp.map2alm(x.astype(np.float64),lmax=codomain.para[0],mmax=codomain.para[1],iter=kwargs.get("iter",self.niter),pol=True,use_weights=False,regression=True,datapath=None) + Tx = hp.map2alm(x.astype(np.float64),lmax=codomain.para[0],mmax=codomain.para[1],iter=kwargs.get("iter",self.niter),pol=True,use_weights=False,datapath=None) else: raise ValueError(about._errors.cstring("ERROR: unsupported transformation.")) @@ -5181,7 +5181,7 @@ class hp_space(space): elif(sigma<0): raise ValueError(about._errors.cstring("ERROR: invalid sigma.")) ## smooth - return hp.smoothing(x,fwhm=0.0,sigma=sigma,invert=False,pol=True,iter=kwargs.get("iter",self.niter),lmax=3*self.para[0]-1,mmax=3*self.para[0]-1,use_weights=False,regression=True,datapath=None) + return hp.smoothing(x,fwhm=0.0,sigma=sigma,invert=False,pol=True,iter=kwargs.get("iter",self.niter),lmax=3*self.para[0]-1,mmax=3*self.para[0]-1,use_weights=False,datapath=None) ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -5211,7 +5211,7 @@ class hp_space(space): if(self.discrete): x = self.calc_weight(x,power=-0.5) ## power spectrum - return hp.anafast(x,map2=None,nspec=None,lmax=3*self.para[0]-1,mmax=3*self.para[0]-1,iter=kwargs.get("iter",self.niter),alm=False,pol=True,use_weights=False,regression=True,datapath=None) + return hp.anafast(x,map2=None,nspec=None,lmax=3*self.para[0]-1,mmax=3*self.para[0]-1,iter=kwargs.get("iter",self.niter),alm=False,pol=True,use_weights=False,datapath=None) ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -8755,7 +8755,7 @@ class diagonal_operator(operator): if(np.any(self.val==0)): if(pseudo): x_ = field(self.domain,val=None,target=x.target) - x_.val = x.val*np.where(self.val==0,0,1/self.val) ## bypasses self.domain.enforce_values + x_.val = np.ma.filled(x.val/np.ma.masked_where(self.val==0,self.val,copy=False),fill_value=0) ## bypasses self.domain.enforce_values return x_ else: raise AttributeError(about._errors.cstring("ERROR: singular operator.")) @@ -8768,7 +8768,7 @@ class diagonal_operator(operator): if(np.any(self.val==0)): if(pseudo): x_ = field(self.domain,val=None,target=x.target) - x_.val = x.val*np.where(self.val==0,0,1/np.conjugate(self.val)) ## bypasses self.domain.enforce_values + x_.val = np.ma.filled(x.val/np.ma.masked_where(self.val==0,np.conjugate(self.val),copy=False),fill_value=0) ## bypasses self.domain.enforce_values return x_ else: raise AttributeError(about._errors.cstring("ERROR: singular operator.")) @@ -8781,7 +8781,7 @@ class diagonal_operator(operator): if(np.any(self.val==0)): if(pseudo): x_ = field(self.domain,val=None,target=x.target) - x_.val = x.val*np.where(self.val==0,0,np.conjugate(1/self.val)) ## bypasses self.domain.enforce_values + x_.val = np.ma.filled(x.val/np.conjugate(np.ma.masked_where(self.val==0,self.val,copy=False)),fill_value=0) ## bypasses self.domain.enforce_values return x_ else: raise AttributeError(about._errors.cstring("ERROR: singular operator.")) diff --git a/nifty_power_conversion.py b/nifty_power_conversion.py new file mode 100644 index 000000000..999e18f32 --- /dev/null +++ b/nifty_power_conversion.py @@ -0,0 +1,253 @@ +from nifty import * + +def power_backward_conversion_rg(k_space,p,mean=None,bare=True): + """ + This function is designed to convert a theoretical/statistical power + spectrum of a log-normal field to the theoretical power spectrum of + the underlying Gaussian field. + The function only works for power spectra defined for rg_spaces + + Parameters + ---------- + k_space : nifty.rg_space, + a regular grid space with the attribute `Fourier = True` + p : np.array, + the power spectrum of the log-normal field. + Needs to have the same number of entries as + `k_space.get_power_indices()[0]` + mean : float, *optional* + specifies the mean of the log-normal field. If `mean` is not + specified the function will use the monopole of the power spectrum. + If it is specified the function will NOT use the monopole of the + spectrum (default: None). + WARNING: a mean that is too low can violate positive definiteness + of the log-normal field. In this case the function produces an + error. + bare : bool, *optional* + whether `p` is the bare power spectrum or not (default: True). + + Returns + ------- + mean : float, + the recovered mean of the underlying Gaussian distribution. + p1 : np.array, + the power spectrum of the underlying Gaussian field, where the + monopole has been set to zero. Eventual monopole power has been + shifted to the mean. + + References + ---------- + .. [#] M. Greiner and T.A. Ensslin, "Log-transforming the matter power spectrum"; + `arXiv:1312.1354 <http://arxiv.org/abs/1312.1354>`_ + """ + pindex = k_space.get_power_indices()[2] + V = k_space.vol.prod()**(-1) + + mono_ind = np.where(pindex==0) + + spec = power_operator(k_space,spec=p,bare=bare).get_power(bare=False) + + if(mean is None): + mean = 0. + else: + spec[0] = 0. + + pf = field(k_space,val=spec[pindex]).transform()+mean**2 + + if(np.any(pf.val<0.)): + raise ValueError(about._errors.cstring("ERROR: spectrum or mean incompatible with positive definiteness.\n Try increasing the mean.")) + return None + + p1 = sqrt(log(pf).power()) + + p1[0] = (log(pf)).transform()[mono_ind][0] + + p2 = 0.5*V*log(k_space.calc_weight(spec[pindex],1).sum()+mean**2) + + logmean = 1/V * (p1[0]-p2) + + p1[0] = 0. + + if(np.any(p1<0.)): + raise ValueError(about._errors.cstring("ERROR: spectrum or mean incompatible with positive definiteness.\n Try increasing the mean.")) + return None + + if(bare==True): + return logmean.real,power_operator(k_space,spec=p1,bare=False).get_power(bare=True).real + else: + return logmean.real,p1.real + +def power_forward_conversion_rg(k_space,p,mean=0,bare=True): + """ + This function is designed to convert a theoretical/statistical power + spectrum of a Gaussian field to the theoretical power spectrum of + the exponentiated field. + The function only works for power spectra defined for rg_spaces + + Parameters + ---------- + k_space : nifty.rg_space, + a regular grid space with the attribute `Fourier = True` + p : np.array, + the power spectrum of the Gaussian field. + Needs to have the same number of entries as + `k_space.get_power_indices()[0]` + mean : float, *optional* + specifies the mean of the Gaussian field (default: 0). + bare : bool, *optional* + whether `p` is the bare power spectrum or not (default: True). + + Returns + ------- + p1 : np.array, + the power spectrum of the exponentiated Gaussian field. + + References + ---------- + .. [#] M. Greiner and T.A. Ensslin, "Log-transforming the matter power spectrum"; + `arXiv:1312.1354 <http://arxiv.org/abs/1312.1354>`_ + """ + + pindex = k_space.get_power_indices()[2] + + spec = power_operator(k_space,spec=p,bare=bare).get_power(bare=False) + + S_x = field(k_space,val=spec[pindex]).transform() + + S_0 = k_space.calc_weight(spec[pindex],1).sum() + + pf = exp(S_x+S_0+2*mean) + + p1 = sqrt(pf.power()) + + if(bare==True): + return power_operator(k_space,spec=p1,bare=False).get_power(bare=True).real + else: + return p1.real + + + +def power_backward_conversion_lm(k_space,p,mean=None): + """ + This function is designed to convert a theoretical/statistical power + spectrum of a log-normal field to the theoretical power spectrum of + the underlying Gaussian field. + The function only works for power spectra defined for lm_spaces + + Parameters + ---------- + k_space : nifty.rg_space, + a regular grid space with the attribute `Fourier = True` + p : np.array, + the power spectrum of the log-normal field. + Needs to have the same number of entries as + `k_space.get_power_indices()[0]` + mean : float, *optional* + specifies the mean of the log-normal field. If `mean` is not + specified the function will use the monopole of the power spectrum. + If it is specified the function will NOT use the monopole of the + spectrum. (default: None) + WARNING: a mean that is too low can violate positive definiteness + of the log-normal field. In this case the function produces an + error. + + Returns + ------- + mean : float, + the recovered mean of the underlying Gaussian distribution. + p1 : np.array, + the power spectrum of the underlying Gaussian field, where the + monopole has been set to zero. Eventual monopole power has been + shifted to the mean. + + References + ---------- + .. [#] M. Greiner and T.A. Ensslin, "Log-transforming the matter power spectrum"; + `arXiv:1312.1354 <http://arxiv.org/abs/1312.1354>`_ + """ + + p = np.copy(p) + if(mean is not None): + p[0] = 4*pi*mean**2 + + klen = k_space.get_power_indices()[0] + C_0_Omega = field(k_space,val=0) + C_0_Omega.val[:len(klen)] = p*sqrt(2*klen+1)/sqrt(4*pi) + C_0_Omega = C_0_Omega.transform() + + if(np.any(C_0_Omega.val<0.)): + raise ValueError(about._errors.cstring("ERROR: spectrum or mean incompatible with positive definiteness.\n Try increasing the mean.")) + return None + + lC = log(C_0_Omega) + + Z = lC.transform() + + spec = Z.val[:len(klen)] + + mean = (spec[0]-0.5*sqrt(4*pi)*log((p*(2*klen+1)/(4*pi)).sum()))/sqrt(4*pi) + + spec[0] = 0. + + spec = spec*sqrt(4*pi)/sqrt(2*klen+1) + + spec = np.real(spec) + + if(np.any(spec<0.)): + spec = spec*(spec>0.) + about.warnings.cprint("WARNING: negative modes set to zero.") + + return mean.real,spec + + +def power_forward_conversion_lm(k_space,p,mean=0): + """ + This function is designed to convert a theoretical/statistical power + spectrum of a Gaussian field to the theoretical power spectrum of + the exponentiated field. + The function only works for power spectra defined for lm_spaces + + Parameters + ---------- + k_space : nifty.rg_space, + a regular grid space with the attribute `Fourier = True` + p : np.array, + the power spectrum of the Gaussian field. + Needs to have the same number of entries as + `k_space.get_power_indices()[0]` + m : float, *optional* + specifies the mean of the Gaussian field (default: 0). + + Returns + ------- + p1 : np.array, + the power spectrum of the exponentiated Gaussian field. + + References + ---------- + .. [#] M. Greiner and T.A. Ensslin, "Log-transforming the matter power spectrum"; + `arXiv:1312.1354 <http://arxiv.org/abs/1312.1354>`_ + """ + m = mean + klen = k_space.get_power_indices()[0] + C_0_Omega = field(k_space,val=0) + C_0_Omega.val[:len(klen)] = p*sqrt(2*klen+1)/sqrt(4*pi) + C_0_Omega = C_0_Omega.transform() + + C_0_0 = (p*(2*klen+1)/(4*pi)).sum() + + exC = exp(C_0_Omega+C_0_0+2*m) + + Z = exC.transform() + + spec = Z.val[:len(klen)] + + spec = spec*sqrt(4*pi)/sqrt(2*klen+1) + + spec = np.real(spec) + + if(np.any(spec<0.)): + spec = spec*(spec>0.) + about.warnings.cprint("WARNING: negative modes set to zero.") + + return spec \ No newline at end of file diff --git a/nifty_tools.py b/nifty_tools.py index db13db114..a91d83881 100644 --- a/nifty_tools.py +++ b/nifty_tools.py @@ -155,8 +155,8 @@ class invertible_operator(operator): x : field Valid input field. force : bool - Indicates wheter to return a field instead of ``None`` is - forced incase the conjugate gradient fails. + Indicates wheter to return a field instead of ``None`` in case + the conjugate gradient fails. Returns ------- @@ -213,8 +213,8 @@ class invertible_operator(operator): x : field Valid input field. force : bool - Indicates wheter to return a field instead of ``None`` is - forced incase the conjugate gradient fails. + Indicates wheter to return a field instead of ``None`` in case + the conjugate gradient fails. Returns ------- @@ -430,10 +430,10 @@ class propagator_operator(operator): ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def _inverse_multiply_1(self,x,**kwargs): ## > applies A1 + A2 in self.codomain - return self._A1(x)+self._A2(x.transform(self.domain)).transform(self.codomain) + return self._A1(x,pseudo=True)+self._A2(x.transform(self.domain)).transform(self.codomain) def _inverse_multiply_2(self,x,**kwargs): ## > applies A1 + A2 in self.domain - return self._A1(x.transform(self.codomain)).transform(self.domain)+self._A2(x) + return self._A1(x.transform(self.codomain),pseudo=True).transform(self.domain)+self._A2(x) ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -475,8 +475,8 @@ class propagator_operator(operator): Scalars are interpreted as constant arrays, and an array will be interpreted as a field on the domain of the operator. force : bool - Indicates wheter to return a field instead of ``None`` is - forced incase the conjugate gradient fails. + Indicates wheter to return a field instead of ``None`` in case + the conjugate gradient fails. Returns ------- @@ -836,6 +836,8 @@ class conjugate_gradient(object): s = self.W(r) gamma_ = gamma gamma = r.dot(s) + if(np.signbit(np.real(gamma))): + about.warnings.cprint("WARNING: positive definiteness of W violated.") beta = max(0,gamma/gamma_) ## positive definite d = s+beta*d ## conjugated gradient -- GitLab