casacore
Loading...
Searching...
No Matches
Convolver.h
Go to the documentation of this file.
1//# Convolver.h: this defines Convolver a class for doing convolution
2//# Copyright (C) 1996,1999,2001,2002,2003
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: casa-feedback@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25
26#ifndef SCIMATH_CONVOLVER_H
27#define SCIMATH_CONVOLVER_H
28
29#include <casacore/casa/aips.h>
30#include <casacore/casa/Arrays/Array.h>
31#include <casacore/casa/BasicSL/Complex.h>
32#include <casacore/scimath/Mathematics/FFTServer.h>
33#include <casacore/casa/Arrays/IPosition.h>
34#include <casacore/scimath/Mathematics/NumericTraits.h>
35
36namespace casacore { //# NAMESPACE CASACORE - BEGIN
37
38// Forward Declarations
39template <class FType> class Convolver;
40
41// Typedefs
44
45// <summary>
46// A class for doing multi-dimensional convolution
47// </summary>
48
49// <use visibility=export>
50
51// <reviewed reviewer="Brian Glendenning " date="1996/05/27"
52// tests="tConvolution">
53// </reviewed>
54
55// <prerequisite>
56// <li> The mathematical concept of convolution
57// </prerequisite>
58//
59// <etymology>
60// The convolver class performs convolution!
61// </etymology>
62//
63// <synopsis>
64// This class will perform linear or circular convolution on arrays.
65//
66// The dimension of the convolution done is determined by the dimension of
67// the point spread function (psf), so for example, if the psf is a Vector,
68// one dimensional convolution will be done. The dimension of the model
69// that is to be convolved must be at least the same as the point
70// spread function, but it can be larger. If it is then the convolution will
71// be repeated for each row or plane of the model.
72// <note role=tip>
73// This class strips all degenerate axes when determining the dimensionality
74// of the psf or model. So a psf with shapes of [1,1,16] or [16,1,1] is
75// treated the same as a Vector of length 16, and will result in one
76// dimensional convolutions along the first non-degenerate axis of the
77// supplied model.
78// </note>
79
80// Repeated convolution can only be done along the fastest moving axes of
81// the supplied image. For example, if a one dimensional psf is used (so
82// that one dimensional convolution is being done), and a cube of data is
83// supplied then the convolution will be repeated for each row in the
84// cube. It is not currently possible to have this class do repeated one
85// dimensional convolution along all the columns or along the z
86// axis. To do this you need to use an iterator external to the class to
87// successively feed in the appropriate slices of your Array.
88
89// The difference between linear and circular convolution can best be
90// explained with a one dimensional example.
91// Suppose the psf and data to be convolved are:
92// <srcblock>
93// psf = [0 .5 1 .1]; data = [1 0 0 0 0 0]
94// </srcblock>
95// then their linear and circular convolutions are:
96// <srcblock>
97// circular convolution = [1 .1 0 0 0 .5]
98// linear convolution = [1 .1 0 0 0 0] (fullSize == False)
99// linear convolution = [0 .5 1 .1 0 0 0 0 0] (fullSize == True)
100// </srcblock>
101// The circular convolution "wraps around" whereas the linear one does not.
102// Usage of the fullSize option is explained below. As can be seen from the
103// above example this class does not normalise the convolved result by any
104// factor that depends on the psf, so if the "beam area" is not unity the
105// flux scales will vary.
106
107// The "centre" of the convolution is at the point (NX/2, NY/2) (assuming a
108// 2 dimensional psf) where the first point in the psf is at (0,0) and the
109// last is at (NX-1, NY-1). This means that a psf that is all zero except
110// for 1 at the "centre" pixel will when convolved with any model leave the
111// model unchanged.
112
113// The convolution is done in the Fourier domain and the transform of the
114// psf (the transfer function) is cached by this class. If the cached
115// transfer function is the wrong size for a given model it will be
116// automatically be recomputed to the right size (this will involve two
117// FFT's)
118
119// Each convolution requires two Fourier transforms which dominate the
120// computational load. Hence the computational expense is
121// <em> n Log(n) </em> for 1 dimensional and
122// <em> n^2 Log(n) </em> for 2 dimensional convolutions.
123
124// The size of the convolved result is always the same as the input model
125// unless linear convolution is done with the fullSize option set to True.
126// In this case the result will be larger than the model and include the
127// full linear convolution (resultSize = psfSize+modelSize-1), rather than
128// the central portion.
129
130// If the convolver is constructed with an expected model size (as in the
131// example below) then the cached transfer function will be computed to a
132// size appropriate for linear convolution of models of that size. If no
133// model size is given then the cached transfer function will be computed
134// with a size appropriate for circular convolution. These guidelines also
135// apply when using the setPsf functions.
136
137// <note role=tip>
138// If you are intending to do 'fullsize' linear convolutions
139// you should also set the fullsize option to True as the cached transfer
140// function is a different size for fullsize linear convolutions.
141// </note>
142
143// For linear convolution the psf can be larger, the same size or smaller
144// than the model but for circular convolution the psf must be smaller or the
145// same size.
146
147// The size of the cached transfer function (and also the length of the
148// FFT's calculated) depends on the sizes of the psf and the model, as well
149// as whether you are doing linear or circular convolution and the fullSize
150// option. It is always advantageous to use the smallest possible psf
151// (ie. do not pad the psf prior to supplying it to this class). Be aware
152// that using odd length images will lead to this class doing odd length
153// FFT's, which are less computationally effecient (particularly is the
154// length of the transform is a prime number) in general than even length
155// transforms.
156
157// There are only two valid template types namely,
158// <ol>
159// <li>FType=Float or
160// <li>FType=Double
161// </ol>
162// and the user may prefer to use the following typedef's:
163// <srcblock>
164// FloatConvolver (= Convolver<Float>) or
165// DoubleConvolver (= Convolver<Double>)
166// </srcblock>
167// rather than explicitly specifying the template arguements.
168// <note role=tip>
169// The typedefs need to be redeclared when using the gnu compiler making
170// them essentially useless.
171// </note>
172
173// When this class is constructed you may choose to have the psf
174// explicitly stored by the class (by setting cachePsf=True). This will
175// allow speedy access to the psf when using the getPsf function. However
176// the getPsf function can still be called even if the psf has not been
177// cached. Then the psf will be computed by FFT'ing the transfer
178// function, and the psf will also then be cached (unless
179// cachePsf=Flase). Cacheing the psf is also a good idea if you will be
180// switching between different sized transfer functions (eg. mixing
181// linear and circular convolution) as it will save one of the two
182// FFT's. Note that even though the psf is returned as a const Array, it
183// is possible to inadvertently modify it using the array copy constructor
184// as this uses reference symantics. Modifying the psf is NOT
185// recommended. eg.
186// <srcblock>
187// DoubleConvolver conv();
188// {
189// Matrix<Double> psf(20,20);
190// conv.setPsf(psf);
191// }
192// Matrix<Double> convPsf = conv.getPsf(); // Get the psf used by the convolver
193// convPsf(0,0) = -100; // And modify it. This modifies
194// // This internal psf used by the
195// // convolver also! (unless it is
196// // not caching the psf)
197// </srcblock>
198//
199// </synopsis>
200//
201// <example>
202// Calculate the convolution of two Matrices (psf and model);
203// <srcblock>
204// Matrix<Float> psf(4,4), model(12,12);
205// ...put meaningful values into the above two matrices...
206// FloatConvolver conv(psf, model.shape());
207// conv.linearConv(result, model); // result = Convolution(psf, model)
208// </srcblock>
209// </example>
210//
211// <motivation>
212// I needed to do linear convolution to write a clean algorithm. It
213// blossomed into this class.
214// </motivation>
215//
216// <thrown>
217// <li> AipsError: if psf has more dimensions than the model.
218// </thrown>
219//
220// <todo asof="yyyy/mm/dd">
221// <li> the class should detect if the psf or image is small and do the
222// convolution directly rather than use the Fourier domain
223// <li> Add a lattice interface, and more flexible iteration scheme
224// <li> Allow the psf to be specified with a
225// <linkto class=Function>Function</linkto>.
226// </todo>
227
228template<class FType> class Convolver
229{
230public:
231 // When using the default constructor the psf MUST be specified using the
232 // setPsf function prior to doing any convolution.
233 // <group>
235 // </group>
236 // Create the cached Transfer function assuming that circular convolution
237 // will be done
238 // <group>
239 Convolver(const Array<FType>& psf, Bool cachePsf=False);
240 // </group>
241 // Create the cached Transfer function assuming that linear convolution
242 // with an array of size imageSize will be done.
243 // <group>
244 Convolver(const Array<FType>& psf, const IPosition& imageSize,
245 Bool fullSize=False, Bool cachePsf=False);
246 // </group>
247
248 // The copy constructor and the assignment operator make copies (and not
249 // references) of all the internal data arrays, as this object could get
250 // really screwed up if the private data was silently messed with.
251 // <group>
254 // </group>
255
256 // The destructor does nothing!
257 // <group>
259 // </group>
260
261 // Perform linear convolution of the model with the previously
262 // specified psf. Return the answer in result. Set fullSize to True if you
263 // want the full convolution, rather than the central portion (the same
264 // size as the model) returned.
265 // <group>
267 const Array<FType>& model,
268 Bool fullSize=False);
269 // </group>
270
271 // Perform circular convolution of the model with the previously
272 // specified psf. Return the answer in result.
273 // <group>
275 const Array<FType>& model);
276 // </group>
277
278 // Set the transfer function for future convolutions to psf.
279 // Assume circular convolution will be done
280 // <group>
281 void setPsf(const Array<FType>& psf, Bool cachePsf=False);
282 // </group>
283 // Set the transfer function for future convolutions to psf.
284 // Assume linear convolution with a model of size imageSize
285 // <group>
286 void setPsf(const Array<FType>& psf,
287 IPosition imageShape, Bool fullSize=False,
288 Bool cachePsf=False);
289 // </group>
290 // Get the psf currently used by this convolver
291 // <group>
292 const Array<FType> getPsf(Bool cachePsf=True);
293 // </group>
294
295 // Set to use convolution with lesser flips
296 // <group>
298 // </group>
299
300private:
307
308 void makeXfr(const Array<FType>& psf, const IPosition& imageSize,
309 Bool linear, Bool fullSize);
312 IPosition extractShape(IPosition& psfSize, const IPosition& imageSize);
314 const Array<FType>& model,
315 Bool fullSize);
316 void resizeXfr(const IPosition& imageShape, Bool linear, Bool fullSize);
317//# void padArray(Array<FType>& paddedArr, const Array<FType>& origArr,
318//# const IPosition & blc);
321 void validate();
322};
323
324} //# NAMESPACE CASACORE - END
325
326#ifndef CASACORE_NO_AUTO_TEMPLATES
327#include <casacore/scimath/Mathematics/Convolver.tcc>
328#endif //# CASACORE_NO_AUTO_TEMPLATES
329#endif
Forward Declarations.
Definition Convolver.h:229
Array< FType > thePsf
Definition Convolver.h:304
void setFastConvolve()
Set to use convolution with lesser flips.
Convolver< FType > & operator=(const Convolver< FType > &other)
void setPsf(const Array< FType > &psf, Bool cachePsf=False)
Set the transfer function for future convolutions to psf.
void makePsf(Array< FType > &psf)
FFTServer< FType, typename NumericTraits< FType >::ConjugateType > theIFFT
Definition Convolver.h:306
Convolver(const Array< FType > &psf, Bool cachePsf=False)
Create the cached Transfer function assuming that circular convolution will be done.
const Array< FType > getPsf(Bool cachePsf=True)
Get the psf currently used by this convolver.
void linearConv(Array< FType > &result, const Array< FType > &model, Bool fullSize=False)
Perform linear convolution of the model with the previously specified psf.
void circularConv(Array< FType > &result, const Array< FType > &model)
Perform circular convolution of the model with the previously specified psf.
void makeXfr(const Array< FType > &psf, const IPosition &imageSize, Bool linear, Bool fullSize)
Convolver(const Convolver< FType > &other)
The copy constructor and the assignment operator make copies (and not references) of all the internal...
void resizeXfr(const IPosition &imageShape, Bool linear, Bool fullSize)
IPosition extractShape(IPosition &psfSize, const IPosition &imageSize)
IPosition thePsfSize
Definition Convolver.h:301
~Convolver()
The destructor does nothing!
IPosition defaultShape(const Array< FType > &psf)
Convolver()
When using the default constructor the psf MUST be specified using the setPsf function prior to doing...
Definition Convolver.h:234
void setPsf(const Array< FType > &psf, IPosition imageShape, Bool fullSize=False, Bool cachePsf=False)
Set the transfer function for future convolutions to psf.
FFTServer< FType, typename NumericTraits< FType >::ConjugateType > theFFT
Definition Convolver.h:305
Array< typename NumericTraits< FType >::ConjugateType > theXfr
Definition Convolver.h:303
Convolver(const Array< FType > &psf, const IPosition &imageSize, Bool fullSize=False, Bool cachePsf=False)
Create the cached Transfer function assuming that linear convolution with an array of size imageSize ...
void doConvolution(Array< FType > &result, const Array< FType > &model, Bool fullSize)
IPosition theFFTSize
Definition Convolver.h:302
A class with methods for Fast Fourier Transforms.
Definition FFTServer.h:226
this file contains all the compiler specific defines
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
Convolver< Double > DoubleConvolver
Definition Convolver.h:43
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
Convolver< Float > FloatConvolver
Typedefs.
Definition Convolver.h:42
const Bool True
Definition aipstype.h:41