Commit b47f67fd authored by M Selig's avatar M Selig

Merge pull request #11 from mselig/develop

verison update.
parents ca8d66e9 a5f253a1
......@@ -13,6 +13,7 @@
build
demos/*
!demos/__init__.py
!demos/demo_faraday.py
!demos/demo_faraday_map.npy
!demos/demo_excaliwir.py
......
......@@ -99,7 +99,7 @@ Requirements
Download
........
The latest release is tagged **v0.8.0** and is available as a source package
The latest release is tagged **v0.9.0** and is available as a source package
at `<https://github.com/mselig/nifty/tags>`_. The current version can be
obtained by cloning the repository::
......
......@@ -26,7 +26,7 @@ from nifty_power import *
from nifty_tools import *
from nifty_explicit import *
from nifty_power_conversion import *
#from nifty_power_conversion import *
##-----------------------------------------------------------------------------
......
## NIFTY (Numerical Information Field Theory) has been developed at the
## Max-Planck-Institute for Astrophysics.
##
## Copyright (C) 2014 Max-Planck-Society
##
## Author: Marco Selig
## Project homepage: <http://www.mpa-garching.mpg.de/ift/nifty/>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
pass
......@@ -237,4 +237,43 @@ class ncmap(object):
return cm("Plus Minus", segmentdata, N=int(ncolors), gamma=1.0)
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@staticmethod
def planck(ncolors=256):
"""
Returns a color map similar to the one used for the "Planck CMB Map".
Parameters
----------
ncolors : int, *optional*
Number of color segments (default: 256).
Returns
-------
cmap : matplotlib.colors.LinearSegmentedColormap instance
Linear segmented color map.
"""
segmentdata = {"red": [(0.0, 0.00, 0.00), (0.1, 0.00, 0.00),
(0.2, 0.00, 0.00), (0.3, 0.00, 0.00),
(0.4, 0.00, 0.00), (0.5, 1.00, 1.00),
(0.6, 1.00, 1.00), (0.7, 1.00, 1.00),
(0.8, 0.83, 0.83), (0.9, 0.67, 0.67),
(1.0, 0.50, 0.50)],
"green": [(0.0, 0.00, 0.00), (0.1, 0.00, 0.00),
(0.2, 0.00, 0.00), (0.3, 0.30, 0.30),
(0.4, 0.70, 0.70), (0.5, 1.00, 1.00),
(0.6, 0.70, 0.70), (0.7, 0.30, 0.30),
(0.8, 0.00, 0.00), (0.9, 0.00, 0.00),
(1.0, 0.00, 0.00)],
"blue": [(0.0, 0.50, 0.50), (0.1, 0.67, 0.67),
(0.2, 0.83, 0.83), (0.3, 1.00, 1.00),
(0.4, 1.00, 1.00), (0.5, 1.00, 1.00),
(0.6, 0.00, 0.00), (0.7, 0.00, 0.00),
(0.8, 0.00, 0.00), (0.9, 0.00, 0.00),
(1.0, 0.00, 0.00)]}
return cm("Planck-like", segmentdata, N=int(ncolors), gamma=1.0)
##-----------------------------------------------------------------------------
......@@ -514,7 +514,7 @@ class _about(object): ## nifty support class for global settings
"""
## version
self._version = "0.8.4"
self._version = "0.9.0"
## switches and notifications
self._errors = notification(default=True,ccode=notification._code)
......@@ -2485,7 +2485,7 @@ class rg_space(space):
config = {"binbounds":kwargs.get("binbounds",None),"log":kwargs.get("log",None),"nbin":kwargs.get("nbin",None)}
## power indices
about.infos.cflush("INFO: setting power indices ...")
pindex,kindex,rho = gp.get_power_indices(self.para[:(np.size(self.para)-1)//2],self.vol,self.para[-((np.size(self.para)-1)//2):].astype(np.bool),fourier=True)
pindex,kindex,rho = gp.get_power_indices2(self.para[:(np.size(self.para)-1)//2],self.vol,self.para[-((np.size(self.para)-1)//2):].astype(np.bool),fourier=True)
## bin if ...
if(config.get("log") is not None)or(config.get("nbin") is not None)or(config.get("binbounds") is not None):
pindex,kindex,rho = gp.bin_power_indices(pindex,kindex,rho,**config)
......@@ -3195,6 +3195,9 @@ class rg_space(space):
about.infos.cprint("INFO: absolute values and phases are plotted.")
if(title):
title += " "
if(bool(kwargs.get("save",False))):
save_ = os.path.splitext(os.path.basename(str(kwargs.get("save"))))
kwargs.update(save=save_[0]+"_absolute"+save_[1])
self.get_plot(np.absolute(x),title=title+"(absolute)",vmin=vmin,vmax=vmax,power=False,unit=unit,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
# self.get_plot(np.real(x),title=title+"(real part)",vmin=vmin,vmax=vmax,power=False,unit=unit,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
# self.get_plot(np.imag(x),title=title+"(imaginary part)",vmin=vmin,vmax=vmax,power=False,unit=unit,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
......@@ -3202,6 +3205,8 @@ class rg_space(space):
unit = "rad"
if(cmap is None):
cmap = pl.cm.hsv_r
if(bool(kwargs.get("save",False))):
kwargs.update(save=save_[0]+"_phase"+save_[1])
self.get_plot(np.angle(x,deg=False),title=title+"(phase)",vmin=-3.1416,vmax=3.1416,power=False,unit=unit,norm=None,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs) ## values in [-pi,pi]
return None ## leave method
else:
......@@ -4011,11 +4016,16 @@ class lm_space(space):
if(np.iscomplexobj(x)):
if(title):
title += " "
if(bool(kwargs.get("save",False))):
save_ = os.path.splitext(os.path.basename(str(kwargs.get("save"))))
kwargs.update(save=save_[0]+"_absolute"+save_[1])
self.get_plot(np.absolute(x),title=title+"(absolute)",vmin=vmin,vmax=vmax,power=False,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
# self.get_plot(np.real(x),title=title+"(real part)",vmin=vmin,vmax=vmax,power=False,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
# self.get_plot(np.imag(x),title=title+"(imaginary part)",vmin=vmin,vmax=vmax,power=False,norm=norm,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs)
if(cmap is None):
cmap = pl.cm.hsv_r
if(bool(kwargs.get("save",False))):
kwargs.update(save=save_[0]+"_phase"+save_[1])
self.get_plot(np.angle(x,deg=False),title=title+"(phase)",vmin=-3.1416,vmax=3.1416,power=False,norm=None,cmap=cmap,cbar=cbar,other=None,legend=False,**kwargs) ## values in [-pi,pi]
return None ## leave method
else:
......@@ -5413,7 +5423,7 @@ class nested_space(space):
self.datatype = self.nest[-1].datatype
self.discrete = np.prod([nn.discrete for nn in self.nest],axis=0,dtype=np.bool,out=None)
self.vol = None ## not needed
self.vol = np.prod([nn.get_meta_volume(total=True) for nn in self.nest],axis=0,dtype=None,out=None) ## total volume
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......@@ -5738,7 +5748,7 @@ class nested_space(space):
"""
if(total):
## product
return np.prod([nn.get_meta_volume(total=True) for nn in self.nest],axis=0,dtype=None,out=None)
return self.vol ## == np.prod([nn.get_meta_volume(total=True) for nn in self.nest],axis=0,dtype=None,out=None)
else:
mol = self.nest[0].get_meta_volume(total=False)
## tensor product
......@@ -8280,26 +8290,52 @@ class operator(object):
def det(self):
"""
Computes the determinant of the operator
Computes the determinant of the operator.
Returns
-------
det : float
The determinant
"""
raise NotImplementedError(about._errors.cstring("ERROR: no generic instance method 'det'."))
def inverse_det(self):
"""
Computes the determinant of the inverse operator
Computes the determinant of the inverse operator.
Returns
-------
det : float
The determinant
"""
raise NotImplementedError(about._errors.cstring("ERROR: no generic instance method 'inverse_det'."))
def log_det(self):
"""
Computes the logarithm of the determinant of the operator (if applicable).
Returns
-------
logdet : float
The logarithm of the determinant
"""
raise NotImplementedError(about._errors.cstring("ERROR: no generic instance method 'log_det'."))
def tr_log(self):
"""
Computes the trace of the logarithm of the operator (if applicable).
Returns
-------
logdet : float
The trace of the logarithm
"""
return self.log_det()
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def hat(self,bare=False,domain=None,target=None,**kwargs):
......@@ -9119,6 +9155,23 @@ class diagonal_operator(operator):
else:
raise ValueError(about._errors.cstring("ERROR: singular operator."))
def log_det(self):
"""
Computes the logarithm of the determinant of the operator.
Returns
-------
logdet : float
The logarithm of the determinant
"""
if(self.uni): ## identity
return 0
elif(self.domain.dim(split=False)<self.domain.dof()): ## hidden degrees of freedom
return self.domain.calc_dot(np.ones(self.domain.dim(split=True),dtype=self.domain.datatype,order='C'),np.log(self.val))
else:
return np.sum(np.log(self.val),axis=None,dtype=None,out=None)
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def get_random_field(self,domain=None,target=None,**kwargs):
......@@ -10202,6 +10255,7 @@ class vecvec_operator(operator):
def inverse_diag(self):
"""
Inverse is ill-defined for this operator.
"""
raise AttributeError(about._errors.cstring("ERROR: singular operator."))
......@@ -10209,18 +10263,27 @@ class vecvec_operator(operator):
def det(self):
"""
Computes the determinant of the operator
Computes the determinant of the operator.
Returns
-------
det : 0
The determinant
"""
return 0
def inverse_det(self):
"""
Inverse is ill-defined for this operator.
"""
raise AttributeError(about._errors.cstring("ERROR: singular operator."))
def log_det(self):
"""
Logarithm of the determinant is ill-defined for this singular operator.
"""
raise AttributeError(about._errors.cstring("ERROR: singular operator."))
......
......@@ -1077,7 +1077,11 @@ class explicit_operator(operator):
if(np.any(self._hidden)):
about.warnings.cprint("WARNING: inappropriate determinant calculation.")
return np.linalg.det(self.weight(rowpower=0.5,colpower=0.5,overwrite=False))
det = np.linalg.det(self.weight(rowpower=0.5,colpower=0.5,overwrite=False))
if(np.isreal(det)):
return np.asscalar(np.real(det))
else:
return det
def inverse_det(self):
"""
......@@ -1104,6 +1108,44 @@ class explicit_operator(operator):
else:
raise ValueError(about._errors.cstring("ERROR: singular matrix."))
def log_det(self):
"""
Computes the logarithm of the determinant of the operator
(if applicable).
Returns
-------
logdet : float
The logarithm of the determinant
See Also
--------
numpy.linalg.slogdet
Raises
------
ValueError
If `domain` and `target` are unequal or it is non-positive
definite matrix.
"""
if(self.domain!=self.target):
raise ValueError(about._errors.cstring("ERROR: determinant ill-defined."))
if(np.any(self._hidden)):
about.warnings.cprint("WARNING: inappropriate determinant calculation.")
sign,logdet = np.linalg.slogdet(self.weight(rowpower=0.5,colpower=0.5,overwrite=False))
if(abs(sign)<0.1): ## abs(sign) << 1
raise ValueError(about._errors.cstring("ERROR: singular matrix."))
if(sign==-1):
raise ValueError(about._errors.cstring("ERROR: non-positive definite matrix."))
else:
logdet += np.log(sign)
if(np.isreal(logdet)):
return np.asscalar(np.real(logdet))
else:
return logdet
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def __len__(self):
......@@ -2324,7 +2366,11 @@ def explicify(op,newdomain=None,newtarget=None,ncpu=2,nper=1,loop=False,**quargs
raise TypeError(about._errors.cstring("ERROR: invalid input."))
elif(newdomain is not None)and(newtarget is None)and(op.domain==op.target):
newtarget = newdomain
return explicit_probing(op=op,function=op.times,domain=newdomain,codomain=newtarget,target=op.domain,ncpu=ncpu,nper=nper,**quargs)(loop=loop)
if(newdomain is None)or(newdomain==op.domain):
target_ = None
else:
target_ = op.domain
return explicit_probing(op=op,function=op.times,domain=newdomain,codomain=newtarget,target=target_,ncpu=ncpu,nper=nper,**quargs)(loop=loop)
##-----------------------------------------------------------------------------
......@@ -575,7 +575,7 @@ def infer_power(m,domain=None,Sk=None,D=None,pindex=None,pundex=None,kindex=None
##-----------------------------------------------------------------------------
def interpolate_power(spec,mode="linear",domain=None,kindex=None,newkindex=None,**kwargs):
def interpolate_power(spec,mode="linear",domain=None,kindex=None,newkindex=None,loglog=False,**kwargs):
"""
Interpolates a given power spectrum at new k(-indices).
......@@ -604,6 +604,9 @@ def interpolate_power(spec,mode="linear",domain=None,kindex=None,newkindex=None,
Scales corresponding to each band in the new power spectrum;
can be retrieved from `domain` if `kindex` is given
(default: None).
loglog : bool, *optional*
Flag specifying whether the interpolation is done on log-log-scale
(ignoring the monopole) or not (default: False)
Returns
-------
......@@ -719,6 +722,12 @@ def interpolate_power(spec,mode="linear",domain=None,kindex=None,newkindex=None,
spec = np.r_[spec,np.exp(2*np.log(spec[-1])-np.log(spec[-nmirror:-1][::-1]))]
kindex = np.r_[kindex,(2*kindex[-1]-kindex[-nmirror:-1][::-1])]
## interpolation
if(loglog):
## map to log-log-scale ignoring monopole
logspec = np.log(spec[1:])
logspec = ip(np.log(kindex[1:]),logspec,kind=mode,axis=0,copy=True,bounds_error=True,fill_value=np.NAN)(np.log(newkindex[1:]))
newspec = np.concatenate([[spec[0]],np.exp(logspec)])
else:
newspec = ip(kindex,spec,kind=mode,axis=0,copy=True,bounds_error=True,fill_value=np.NAN)(newkindex)
## check new power spectrum
if(not np.all(np.isfinite(newspec))):
......
## NIFTY (Numerical Information Field Theory) has been developed at the
## Max-Planck-Institute for Astrophysics.
##
## Copyright (C) 2014 Max-Planck-Society
##
## Author: Maksim Greiner
## Project homepage: <http://www.mpa-garching.mpg.de/ift/nifty/>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
from nifty import *
def power_backward_conversion_rg(k_space,p,mean=None,bare=True):
......
......@@ -774,10 +774,7 @@ class conjugate_gradient(object):
delta = delta_*np.absolute(gamma)**0.5
self.note.cflush("\niteration : %08u alpha = %3.1E beta = %3.1E delta = %3.1E"%(ii,np.real(alpha),np.real(beta),np.real(delta)))
if(ii==limii):
self.note.cprint("\n... quit.")
break
elif(gamma==0):
if(gamma==0):
convergence = clevel+1
self.note.cprint(" convergence level : INF\n... done.")
break
......@@ -789,6 +786,9 @@ class conjugate_gradient(object):
break
else:
convergence = max(0,convergence-1)
if(ii==limii):
self.note.cprint("\n... quit.")
break
if(self.spam is not None):
self.spam(self.x,ii)
......@@ -843,10 +843,7 @@ class conjugate_gradient(object):
delta = delta_*np.absolute(gamma)**0.5
self.note.cflush("\niteration : %08u alpha = %3.1E beta = %3.1E delta = %3.1E"%(ii,np.real(alpha),np.real(beta),np.real(delta)))
if(ii==limii):
self.note.cprint("\n... quit.")
break
elif(gamma==0):
if(gamma==0):
convergence = clevel+1
self.note.cprint(" convergence level : INF\n... done.")
break
......@@ -858,6 +855,9 @@ class conjugate_gradient(object):
break
else:
convergence = max(0,convergence-1)
if(ii==limii):
self.note.cprint("\n... quit.")
break
if(self.spam is not None):
self.spam(self.x,ii)
......@@ -1066,10 +1066,7 @@ class steepest_descent(object):
alpha *= a
norm = g.norm() ## gradient norm
if(ii==limii):
self.note.cprint("\n... quit.")
break
elif(delta==0):
if(delta==0):
convergence = clevel+2
self.note.cprint(" convergence level : %u\n... done."%convergence)
break
......@@ -1082,6 +1079,9 @@ class steepest_descent(object):
break
else:
convergence = max(0,convergence-1)
if(ii==limii):
self.note.cprint("\n... quit.")
break
if(self.spam is not None):
self.spam(self.x,ii)
......
......@@ -385,6 +385,66 @@ def get_power_indices(axes,dgrid,zerocentered,fourier=True):
return ind,klength,rho
def get_power_indices2(axes,dgrid,zerocentered,fourier=True):
"""
Returns the index of the Fourier grid points in a numpy
array, ordered following the zerocentered flag.
Parameters
----------
axes : ndarray
An array with the length of each axis.
dgrid : ndarray
An array with the pixel length of each axis.
zerocentered : bool
Whether the output array should be zerocentered, i.e. starting with
negative Fourier modes going over the zero mode to positive modes,
or not zerocentered, where zero, positive and negative modes are
simpy ordered consecutively.
irred : bool : *optional*
If True, the function returns an array of all k-vector lengths and
their degeneracy factors. If False, just the power index array is
returned.
fourier : bool : *optional*
Whether the output should be in Fourier space or not
(default=False).
Returns
-------
index, klength, rho : ndarrays
Returns the power index array, an array of all k-vector lengths and
their degeneracy factors.
"""
## kdict, klength
if(np.any(zerocentered==False)):
kdict = np.fft.fftshift(nkdict_fast2(axes,dgrid,fourier),axes=shiftaxes(zerocentered,st_to_zero_mode=True))
else:
kdict = nkdict_fast2(axes,dgrid,fourier)
klength,rho,ind = nkdict_to_indices(kdict)
return ind,klength,rho
def nkdict_to_indices(kdict):
kindex,pindex = np.unique(kdict,return_inverse=True)
pindex = pindex.reshape(kdict.shape)
rho = pindex.flatten()
rho.sort()
rho = np.unique(rho,return_index=True,return_inverse=False)[1]
rho = np.append(rho[1:]-rho[:-1],[np.prod(pindex.shape)-rho[-1]])
return kindex,rho,pindex
def bin_power_indices(pindex,kindex,rho,log=False,nbin=None,binbounds=None):
"""
Returns the (re)binned power indices associated with the Fourier grid.
......@@ -622,6 +682,31 @@ def nkdict_fast(axes,dgrid,fourier=True):
return np.sqrt(np.sum((temp_vecs),axis=-1))
def nkdict_fast2(axes,dgrid,fourier=True):
"""
Calculates an n-dimensional array with its entries being the lengths of
the k-vectors from the zero point of the grid.
"""
if(fourier):
dk = dgrid
else:
dk = np.array([1/dgrid[i]/axes[i] for i in range(len(axes))])
inds = []
for a in axes:
inds += [slice(0,a)]
cords = np.ogrid[inds]
dists = ((cords[0]-axes[0]//2)*dk[0])**2
for ii in range(1,len(axes)):
dists = dists + ((cords[ii]-axes[ii]//2)*dk[ii])**2
dists = np.sqrt(dists)
return dists
def nklength(kdict):
return np.sort(list(set(kdict.flatten())))
......
......@@ -23,17 +23,12 @@ from distutils.core import setup
import os
setup(name="nifty",
version="0.8.0",
version="0.9.0",
description="Numerical Information Field Theory",
author="Marco Selig",
author_email="mselig@mpa-garching.mpg.de",
url="http://www.mpa-garching.mpg.de/ift/nifty/",
packages=["nifty"],
packages=["nifty", "nifty.demos"],
package_dir={"nifty": ""},
package_data={"nifty": ["demos/demo_excaliwir.py",
"demos/demo_faraday.py",
"demos/demo_faraday_map.npy",
"demos/demo_wf1.py",
"demos/demo_wf2.py",
"demos/demo_wf3.py"]},
data_files=[(os.path.expanduser('~') + "/.nifty", ["nifty_config"])])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment