Commit 28fe4cf9 by Martin Reinecke

### Merge branch 'docu_fixes' into 'NIFTy_5'

```High-level docu

See merge request ift/nifty-dev!153```
parents addd0938 17041b3f
 ... @@ -15,28 +15,33 @@ ... @@ -15,28 +15,33 @@ # # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. import nifty5 as ift ##################################################################### # Bernoulli reconstruction # Reconstruct an event probability field with values between 0 and 1 # from the observed events # 1D (set mode=0), 2D (mode=1), or on the sphere (mode=2) ##################################################################### import numpy as np import numpy as np import nifty5 as ift if __name__ == '__main__': if __name__ == '__main__': # FIXME ABOUT THIS CODE np.random.seed(41) np.random.seed(41) # Set up the position space of the signal # Set up the position space of the signal # mode = 2 # # One dimensional regular grid with uniform exposure if mode == 0: # position_space = ift.RGSpace(1024) # One-dimensional regular grid # exposure = np.ones(position_space.shape) position_space = ift.RGSpace(1024) elif mode == 1: # Two-dimensional regular grid with inhomogeneous exposure # Two-dimensional regular grid position_space = ift.RGSpace([512, 512]) position_space = ift.RGSpace([512, 512]) else: # Sphere with uniform exposure # Sphere # position_space = ift.HPSpace(128) position_space = ift.HPSpace(128) # exposure = ift.Field.full(position_space, 1.) # Define harmonic space and transform # Defining harmonic space and transform harmonic_space = position_space.get_default_codomain() harmonic_space = position_space.get_default_codomain() HT = ift.HarmonicTransformOperator(harmonic_space, position_space) HT = ift.HarmonicTransformOperator(harmonic_space, position_space) ... @@ -44,15 +49,13 @@ if __name__ == '__main__': ... @@ -44,15 +49,13 @@ if __name__ == '__main__': # Define power spectrum and amplitudes # Define power spectrum and amplitudes def sqrtpspec(k): def sqrtpspec(k): return 1. / (20. + k**2) return 1./(20. + k**2) A = ift.create_power_operator(harmonic_space, sqrtpspec) A = ift.create_power_operator(harmonic_space, sqrtpspec) # Set up a sky model # Set up a sky model and instrumental response sky = ift.positive_tanh(HT(A)) sky = ift.positive_tanh(HT(A)) GR = ift.GeometryRemover(position_space) GR = ift.GeometryRemover(position_space) # Set up instrumental response R = GR R = GR # Generate mock data # Generate mock data ... @@ -65,8 +68,8 @@ if __name__ == '__main__': ... @@ -65,8 +68,8 @@ if __name__ == '__main__': # Compute likelihood and Hamiltonian # Compute likelihood and Hamiltonian position = ift.from_random('normal', harmonic_space) position = ift.from_random('normal', harmonic_space) likelihood = ift.BernoulliEnergy(data)(p) likelihood = ift.BernoulliEnergy(data)(p) ic_newton = ift.DeltaEnergyController(name='Newton', iteration_limit=100, ic_newton = ift.DeltaEnergyController( tol_rel_deltaE=1e-8) name='Newton', iteration_limit=100, tol_rel_deltaE=1e-8) minimizer = ift.NewtonCG(ic_newton) minimizer = ift.NewtonCG(ic_newton) ic_sampling = ift.GradientNormController(iteration_limit=100) ic_sampling = ift.GradientNormController(iteration_limit=100) ... @@ -82,5 +85,4 @@ if __name__ == '__main__': ... @@ -82,5 +85,4 @@ if __name__ == '__main__': plot.add(reconstruction, title='reconstruction') plot.add(reconstruction, title='reconstruction') plot.add(GR.adjoint_times(data), title='data') plot.add(GR.adjoint_times(data), title='data') plot.add(sky(mock_position), title='truth') plot.add(sky(mock_position), title='truth') plot.output(nx=3, xsize=16, ysize=5, title="results", plot.output(nx=3, xsize=16, ysize=9, title="results", name="bernoulli.png") name="bernoulli.png")
 ... @@ -15,26 +15,36 @@ ... @@ -15,26 +15,36 @@ # # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. import nifty5 as ift ############################################################################### # Compute a Wiener filter solution with NIFTy # Shows how measurement gaps are filled in # 1D (set mode=0), 2D (mode=1), or on the sphere (mode=2) ############################################################################### import numpy as np import numpy as np import nifty5 as ift def make_chess_mask(position_space): def make_checkerboard_mask(position_space): # Checkerboard mask for 2D mode mask = np.ones(position_space.shape) mask = np.ones(position_space.shape) for i in range(4): for i in range(4): for j in range(4): for j in range(4): if (i+j) % 2 == 0: if (i + j) % 2 == 0: mask[i*128//4:(i+1)*128//4, j*128//4:(j+1)*128//4] = 0 mask[i*128//4:(i + 1)*128//4, j*128//4:(j + 1)*128//4] = 0 return mask return mask def make_random_mask(): def make_random_mask(): # Random mask for spherical mode mask = ift.from_random('pm1', position_space) mask = ift.from_random('pm1', position_space) mask = (mask+1)/2 mask = (mask + 1)/2 return mask.to_global_data() return mask.to_global_data() def mask_to_nan(mask, field): def mask_to_nan(mask, field): # Set masked pixels to nan for plotting masked_data = field.local_data.copy() masked_data = field.local_data.copy() masked_data[mask.local_data == 0] = np.nan masked_data[mask.local_data == 0] = np.nan return ift.from_local_data(field.domain, masked_data) return ift.from_local_data(field.domain, masked_data) ... @@ -42,49 +52,68 @@ def mask_to_nan(mask, field): ... @@ -42,49 +52,68 @@ def mask_to_nan(mask, field): if __name__ == '__main__': if __name__ == '__main__': np.random.seed(42) np.random.seed(42) # FIXME description of the tutorial # Choose problem geometry and masking # Choose space on which the signal field is defined mode = 1 mode = 1 if mode == 0: if mode == 0: # One dimensional regular grid # One-dimensional regular grid position_space = ift.RGSpace([1024]) position_space = ift.RGSpace([1024]) mask = np.ones(position_space.shape) mask = np.ones(position_space.shape) elif mode == 1: elif mode == 1: # Two dimensional regular grid with chess mask # Two-dimensional regular grid with checkerboard mask position_space = ift.RGSpace([128, 128]) position_space = ift.RGSpace([128, 128]) mask = make_chess_mask(position_space) mask = make_checkerboard_mask(position_space) else: else: # Sphere with half of its locations randomly masked # Sphere with half of its pixels randomly masked position_space = ift.HPSpace(128) position_space = ift.HPSpace(128) mask = make_random_mask() mask = make_random_mask() # Specify harmonic space corresponding to signal harmonic_space = position_space.get_default_codomain() harmonic_space = position_space.get_default_codomain() # Harmonic transform from harmonic space to position space HT = ift.HarmonicTransformOperator(harmonic_space, target=position_space) HT = ift.HarmonicTransformOperator(harmonic_space, target=position_space) # Set correlation structure with a power spectrum and build # Set prior correlation covariance with a power spectrum leading to # prior correlation covariance # homogeneous and isotropic statistics def power_spectrum(k): def power_spectrum(k): return 100. / (20.+k**3) return 100./(20. + k**3) # 1D spectral space on which the power spectrum is defined power_space = ift.PowerSpace(harmonic_space) power_space = ift.PowerSpace(harmonic_space) # Mapping to (higher dimensional) harmonic space PD = ift.PowerDistributor(harmonic_space, power_space) PD = ift.PowerDistributor(harmonic_space, power_space) # Apply the mapping prior_correlation_structure = PD(ift.PS_field(power_space, power_spectrum)) prior_correlation_structure = PD(ift.PS_field(power_space, power_spectrum)) # Insert the result into the diagonal of an harmonic space operator S = ift.DiagonalOperator(prior_correlation_structure) S = ift.DiagonalOperator(prior_correlation_structure) # S is the prior field covariance # Build instrument response consisting of a discretization, mask # Build instrument response consisting of a discretization, mask # and harmonic transformaion # and harmonic transformaion # Data is defined on a geometry-free space, thus the geometry is removed GR = ift.GeometryRemover(position_space) GR = ift.GeometryRemover(position_space) # Masking operator to model that parts of the field have not been observed mask = ift.Field.from_global_data(position_space, mask) mask = ift.Field.from_global_data(position_space, mask) Mask = ift.DiagonalOperator(mask) Mask = ift.DiagonalOperator(mask) # Operators can be composed either with paranthesis # The response operator consists of # - an harmonic transform (to get to image space) # - the application of the mask # - the removal of geometric information # Operators can be composed either with parenthesis R = GR(Mask(HT)) R = GR(Mask(HT)) # or with @ # or with @ R = GR @ Mask @ HT R = GR @ Mask @ HT data_space = GR.target data_space = GR.target # Set the noise covariance # Set the noise covariance N noise = 5. noise = 5. N = ift.ScalingOperator(noise, data_space) N = ift.ScalingOperator(noise, data_space) ... @@ -93,17 +122,17 @@ if __name__ == '__main__': ... @@ -93,17 +122,17 @@ if __name__ == '__main__': MOCK_NOISE = N.draw_sample() MOCK_NOISE = N.draw_sample() data = R(MOCK_SIGNAL) + MOCK_NOISE data = R(MOCK_SIGNAL) + MOCK_NOISE # Build propagator D and information source j # Build inverse propagator D and information source j j = R.adjoint_times(N.inverse_times(data)) D_inv = R.adjoint @ N.inverse @ R + S.inverse D_inv = R.adjoint @ N.inverse @ R + S.inverse # Make it invertible j = R.adjoint_times(N.inverse_times(data)) # Make D_inv invertible (via Conjugate Gradient) IC = ift.GradientNormController(iteration_limit=500, tol_abs_gradnorm=1e-3) IC = ift.GradientNormController(iteration_limit=500, tol_abs_gradnorm=1e-3) D = ift.InversionEnabler(D_inv, IC, approximation=S.inverse).inverse D = ift.InversionEnabler(D_inv, IC, approximation=S.inverse).inverse # WIENER FILTER # Calculate WIENER FILTER solution m = D(j) m = D(j) # PLOTTING # Plotting rg = isinstance(position_space, ift.RGSpace) rg = isinstance(position_space, ift.RGSpace) plot = ift.Plot() plot = ift.Plot() if rg and len(position_space.shape) == 1: if rg and len(position_space.shape) == 1: ... @@ -118,5 +147,5 @@ if __name__ == '__main__': ... @@ -118,5 +147,5 @@ if __name__ == '__main__': plot.add(HT(MOCK_SIGNAL), title='Mock Signal') plot.add(HT(MOCK_SIGNAL), title='Mock Signal') plot.add(mask_to_nan(mask, (GR(Mask)).adjoint(data)), title='Data') plot.add(mask_to_nan(mask, (GR(Mask)).adjoint(data)), title='Data') plot.add(HT(m), title='Reconstruction') plot.add(HT(m), title='Reconstruction') plot.add(mask_to_nan(mask, HT(m-MOCK_SIGNAL)), title='Residuals') plot.add(mask_to_nan(mask, HT(m - MOCK_SIGNAL)), title='Residuals') plot.output(nx=2, ny=2, xsize=10, ysize=10, title="getting_started_1") plot.output(nx=2, ny=2, xsize=10, ysize=10, title="getting_started_1")
 ... @@ -15,11 +15,19 @@ ... @@ -15,11 +15,19 @@ # # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. import nifty5 as ift ############################################################################### # Log-normal field reconstruction from Poissonian data with inhomogenous # exposure (in case for 2D mode) # 1D (set mode=0), 2D (mode=1), or on the sphere (mode=2) ############################################################################### import numpy as np import numpy as np import nifty5 as ift def get_2D_exposure(): def exposure_2d(): # Structured exposure for 2D mode x_shape, y_shape = position_space.shape x_shape, y_shape = position_space.shape exposure = np.ones(position_space.shape) exposure = np.ones(position_space.shape) ... @@ -30,72 +38,73 @@ def get_2D_exposure(): ... @@ -30,72 +38,73 @@ def get_2D_exposure(): exposure[:, x_shape*4//5:x_shape] *= .1 exposure[:, x_shape*4//5:x_shape] *= .1 exposure[:, x_shape//2:x_shape*3//2] *= 3. exposure[:, x_shape//2:x_shape*3//2] *= 3. exposure = ift.Field.from_global_data(position_space, exposure) return ift.Field.from_global_data(position_space, exposure) return exposure if __name__ == '__main__': if __name__ == '__main__': # FIXME description of the tutorial # FIXME All random seeds to 42 np.random.seed(41) np.random.seed(41) # Set up the position space of the signal # Choose space on which the signal field is defined # mode = 2 # # One dimensional regular grid with uniform exposure if mode == 0: # position_space = ift.RGSpace(1024) # One-dimensional regular grid with uniform exposure # exposure = ift.Field.full(position_space, 1.) position_space = ift.RGSpace(1024) exposure = ift.Field.full(position_space, 1.) # Two-dimensional regular grid with inhomogeneous exposure elif mode == 1: position_space = ift.RGSpace([512, 512]) # Two-dimensional regular grid with inhomogeneous exposure exposure = get_2D_exposure() position_space = ift.RGSpace([512, 512]) exposure = exposure_2d() # Sphere with uniform exposure else: # position_space = ift.HPSpace(128) # Sphere with uniform exposure # exposure = ift.Field.full(position_space, 1.) position_space = ift.HPSpace(128) exposure = ift.Field.full(position_space, 1.) # Defining harmonic space and transform # Define harmonic space and harmonic transform harmonic_space = position_space.get_default_codomain() harmonic_space = position_space.get_default_codomain() HT = ift.HarmonicTransformOperator(harmonic_space, position_space) HT = ift.HarmonicTransformOperator(harmonic_space, position_space) # Domain on which the field's degrees of freedom are defined domain = ift.DomainTuple.make(harmonic_space) domain = ift.DomainTuple.make(harmonic_space) position = ift.from_random('normal', domain) # Define power spectrum and amplitudes # Define amplitude (square root of power spectrum) def sqrtpspec(k): def sqrtpspec(k): return 1. / (20. + k**2) return 1./(20. + k**2) p_space = ift.PowerSpace(harmonic_space) p_space = ift.PowerSpace(harmonic_space) pd = ift.PowerDistributor(harmonic_space, p_space) pd = ift.PowerDistributor(harmonic_space, p_space) a = ift.PS_field(p_space, sqrtpspec) a = ift.PS_field(p_space, sqrtpspec) A = pd(a) A = pd(a) # Set up a sky model # Define sky model sky = ift.exp(HT(ift.makeOp(A))) sky = ift.exp(HT(ift.makeOp(A))) M = ift.DiagonalOperator(exposure) M = ift.DiagonalOperator(exposure) GR = ift.GeometryRemover(position_space) GR = ift.GeometryRemover(position_space) # Set up instrumental response # Define instrumental response R = GR(M) R = GR(M) # Generate mock data # Generate mock data and define likelihood operator d_space = R.target[0] d_space = R.target[0] lamb = R(sky) lamb = R(sky) mock_position = ift.from_random('normal', domain) mock_position = ift.from_random('normal', domain) data = lamb(mock_position) data = lamb(mock_position) data = np.random.poisson(data.to_global_data().astype(np.float64)) data = np.random.poisson(data.to_global_data().astype(np.float64)) data = ift.Field.from_global_data(d_space, data) data = ift.Field.from_global_data(d_space, data) # Compute likelihood and Hamiltonian ic_newton = ift.DeltaEnergyController(name='Newton', iteration_limit=100, tol_rel_deltaE=1e-8) likelihood = ift.PoissonianEnergy(data)(lamb) likelihood = ift.PoissonianEnergy(data)(lamb) # Settings for minimization ic_newton = ift.DeltaEnergyController( name='Newton', iteration_limit=100, tol_rel_deltaE=1e-8) minimizer = ift.NewtonCG(ic_newton) minimizer = ift.NewtonCG(ic_newton) # Minimize the Hamiltonian # Compute MAP solution by minimizing the information Hamiltonian H = ift.Hamiltonian(likelihood) H = ift.Hamiltonian(likelihood) H = ift.EnergyAdapter(position, H, want_metric=True) initial_position = ift.from_random('normal', domain) H = ift.EnergyAdapter(initial_position, H, want_metric=True) H, convergence = minimizer(H) H, convergence = minimizer(H) # Plot results # Plotting signal = sky(mock_position) signal = sky(mock_position) reconst = sky(H.position) reconst = sky(H.position) plot = ift.Plot() plot = ift.Plot() ... @@ -103,4 +112,4 @@ if __name__ == '__main__': ... @@ -103,4 +112,4 @@ if __name__ == '__main__': plot.add(GR.adjoint(data), title='Data') plot.add(GR.adjoint(data), title='Data') plot.add(reconst, title='Reconstruction') plot.add(reconst, title='Reconstruction') plot.add(reconst - signal, title='Residuals') plot.add(reconst - signal, title='Residuals') plot.output(name='getting_started_2.png', xsize=16, ysize=16) plot.output(name='getting_started_2.pdf', xsize=16, ysize=16)
 ... @@ -15,99 +15,133 @@ ... @@ -15,99 +15,133 @@ # # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. import nifty5 as ift ############################################################ # Non-linear tomography # The data is integrated lines of sight # Random lines (set mode=0), radial lines (mode=1) ############################################################# import numpy as np import numpy as np import nifty5 as ift def random_los(n_los): starts = list(np.random.uniform(0, 1, (n_los, 2)).T) ends = list(0.5 + 0*np.random.uniform(0, 1, (n_los, 2)).T) return starts, ends def get_random_LOS(n_los): def radial_los(n_los): starts = list(np.random.uniform(0, 1, (n_los, 2)).T) starts = list(np.random.uniform(0, 1, (n_los, 2)).T) ends = list(np.random.uniform(0, 1, (n_los, 2)).T) ends = list(np.random.uniform(0, 1, (n_los, 2)).T) return starts, ends return starts, ends if __name__ == '__main__': if __name__ == '__main__': # FIXME description of the tutorial np.random.seed(420) np.random.seed(42) np.seterr(all='raise') position_space = ift.RGSpace([128, 128]) # Setting up an amplitude model # Choose between random line-of-sight response (mode=1) and radial lines A = ift.AmplitudeModel(position_space, 64, 3, 0.4, -4., 1, 1., 1.) # of sight (mode=2) mode = 1 # Building the model for a correlated signal position_space = ift.RGSpace([128, 128]) # Set up an amplitude model for the field # The parameters mean: # 64 spectral bins # # Spectral smoothness (affects Gaussian process part) # 3 = relatively high variance of spectral curbvature # 0.4 = quefrency mode below which cepstrum flattens # # Power-law part of spectrum: # -5 = preferred power-law slope # 0.5 = low variance of power-law slope # 0.4 = y-intercept mean # 0.3 = relatively high y-intercept variance A = ift.AmplitudeModel(position_space, 64, 3, 0.4, -5., 0.5, 0.4, 0.3) # Build the model for a correlated signal harmonic_space = position_space.get_default_codomain() harmonic_space = position_space.get_default_codomain() ht = ift.HarmonicTransformOperator(harmonic_space, position_space) ht = ift.HarmonicTransformOperator(harmonic_space, position_space) power_space = A.target[0] power_space = A.target[0] power_distributor = ift.PowerDistributor(harmonic_space, power_space) power_distributor = ift.PowerDistributor(harmonic_space, power_space) vol = harmonic_space.scalar_dvol vol = ift.ScalingOperator(harmonic_space.scalar_dvol**(-0.5), vol = ift.ScalingOperator(vol**(-0.5), harmonic_space) harmonic_space) correlated_field = ht( correlated_field = ht( vol(power_distributor(A))*ift.ducktape(harmonic_space, None, 'xi')) vol(power_distributor(A))*ift.ducktape(harmonic_space, None, 'xi')) # alternatively to the block above one can do: # Alternatively, one can use: #correlated_field = ift.CorrelatedField(position_space, A) # correlated_field = ift.CorrelatedField(position_space, A) # apply some nonlinearity # Apply a nonlinearity signal = ift.positive_tanh(correlated_field) signal = ift.positive_tanh(correlated_field) # Building the Line of Sight response # Build the line-of-sight response and define signal response LOS_starts, LOS_ends = get_random_LOS(100) LOS_starts, LOS_ends = random_los(100) if mode == 1 else radial_los(100) R = ift.LOSResponse(position_space, starts=LOS_starts, ends=LOS_ends) R = ift.LOSResponse(position_space, starts=LOS_starts, ends=LOS_ends) # build signal response model and model likelihood signal_response = R(signal) signal_response = R(signal) # specify noise # Specify noise data_space = R.target data_space = R.target noise = .001 noise = .001 N = ift.ScalingOperator(noise, data_space) N = ift.ScalingOperator(noise, data_space) # generate mock data # Generate mock signal and data MOCK_POSITION = ift.from_random('normal', signal_response.domain)