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