Loading...
Searching...
No Matches
Lattice.h
Go to the documentation of this file.
//# Lattice.h: Lattice is an abstract base class for array-like classes
//# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2003
//# Associated Universities, Inc. Washington DC, USA.
//#
//# This library is free software; you can redistribute it and/or modify it
//# under the terms of the GNU Library General Public License as published by
//# the Free Software Foundation; either version 2 of the License, or (at your
//# option) any later version.
//#
//# This library 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 Library General Public
//# License for more details.
//#
//# You should have received a copy of the GNU Library General Public License
//# along with this library; if not, write to the Free Software Foundation,
//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
//#
//# Correspondence concerning AIPS++ should be addressed as follows:
//# Internet email: casa-feedback@nrao.edu.
//# Postal address: AIPS++ Project Office
//# National Radio Astronomy Observatory
//# 520 Edgemont Road
//# Charlottesville, VA 22903-2475 USA
#ifndef LATTICES_LATTICE_H
#define LATTICES_LATTICE_H
//# Includes
#include <casacore/casa/aips.h>
#include <casacore/casa/Arrays/ArrayFwd.h>
#include <casacore/lattices/Lattices/LatticeBase.h>
#include <casacore/casa/Arrays/Slicer.h>
namespace casacore { //# NAMESPACE CASACORE - BEGIN
//# Forward Declarations
class IPosition;
class LatticeNavigator;
template <class T> class COWPtr;
template <class Domain, class Range> class Functional;
template <class T> class LatticeIterInterface;
// <summary>
// A templated, abstract base class for array-like objects.
// </summary>
// <use visibility=export>
// <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tArrayLattice.cc" demos="dLattice.cc">
// </reviewed>
// <prerequisite>
// <li> <linkto class="IPosition"> IPosition </linkto>
// <li> <linkto class="Array"> Array </linkto>
// <li> <linkto class="LatticeBase"> LatticeBase </linkto>
// <li> Abstract Base class Inheritance - try "Advanced C++" by James
// O. Coplien, Ch. 5.
// </prerequisite>
// <etymology>
// Lattice: "A regular, periodic configuration of points, particles,
// or objects, throughout an area of a space..." (American Heritage Directory)
// This definition matches our own: an n-dimensional arrangement of items,
// on regular orthogonal axes.
// </etymology>
// <synopsis>
// This pure abstract base class defines the operations which may be performed
// on any concrete class derived from it. It has only a few non-pure virtual
// member functions.
// The fundamental contribution of this class, therefore, is that it
// defines the operations derived classes must provide:
// <ul>
// <li> how to extract a "slice" (or sub-array, or subsection) from
// a Lattice.
// <li> how to copy a slice in.
// <li> how to get and put a single element
// <li> how to apply a function to all elements
// <li> various shape related functions.
// </ul>
// The base class <linkto class=LatticeBase>LatticeBase</linkto> contains
// several functions not dependent on the template parameter.
// <note role=tip> Lattices always have a zero origin. </note>
// </synopsis>
// <example>
// Because Lattice is an abstract base class, an actual instance of this
// class cannot be constructed. However the interface it defines can be used
// inside a function. This is always recommended as it allows functions
// which have Lattices as arguments to work for any derived class.
// <p>
// I will give a few examples here and then refer the reader to the
// <linkto class="ArrayLattice">ArrayLattice</linkto> class (a memory resident
// Lattice) and the <linkto class="PagedArray">PagedArray</linkto> class (a
// disk based Lattice) which contain further examples with concrete
// classes (rather than an abstract one). All the examples shown below are used
// in the <src>dLattice.cc</src> demo program.
//
// <h4>Example 1:</h4>
// This example calculates the mean of the Lattice. Because Lattices can be too
// large to fit into physical memory it is not good enough to simply use
// <src>getSlice</src> to read all the elements into an Array. Instead the
// Lattice is accessed in chunks which can fit into memory (the size is
// determined by the <src>advisedMaxPixels</src> and <src>niceCursorShape</src>
// functions). The <src>LatticeIterator::cursor()</src> function then returns
// each of these chunks as an Array and the standard Array based functions are
// used to calculate the mean on each of these chunks. Functions like this one
// are the recommended way to access Lattices as the
// <linkto class="LatticeIterator">LatticeIterator</linkto> will correctly
// setup any required caches.
//
// <srcblock>
// Complex latMean(const Lattice<Complex>& lat) {
// const uInt cursorSize = lat.advisedMaxPixels();
// const IPosition cursorShape = lat.niceCursorShape(cursorSize);
// const IPosition latticeShape = lat.shape();
// Complex currentSum = 0.0f;
// size_t nPixels = 0u;
// RO_LatticeIterator<Complex> iter(lat,
// LatticeStepper(latticeShape, cursorShape));
// for (iter.reset(); !iter.atEnd(); iter++){
// currentSum += sum(iter.cursor());
// nPixels += iter.cursor().nelements();
// }
// return currentSum/nPixels;
// }
// </srcblock>
//
// <h4>Example 2:</h4>
// Sometimes it will be neccesary to access slices of a Lattice in a nearly
// random way. Often this can be done using the subSection commands in the
// <linkto class="LatticeStepper">LatticeStepper</linkto> class. But it is also
// possible to use the getSlice and putSlice functions. The following example
// does a two-dimensional Real to Complex Fourier transform. This example is
// restricted to four-dimensional Arrays (unlike the previous example) and does
// not set up any caches (caching is currently only used with PagedArrays). So
// only use getSlice and putSlice when things cannot be done using
// LatticeIterators.
//
// <srcblock>
// void FFT2DReal2Complex(Lattice<Complex>& result,
// const Lattice<Float>& input){
// AlwaysAssert(input.ndim() == 4, AipsError);
// const IPosition shape = input.shape();
// const uInt nx = shape(0);
// AlwaysAssert (nx > 1, AipsError);
// const uInt ny = shape(1);
// AlwaysAssert (ny > 1, AipsError);
// const uInt npol = shape(2);
// const uInt nchan = shape(3);
// const IPosition resultShape = result.shape();
// AlwaysAssert(resultShape.nelements() == 4, AipsError);
// AlwaysAssert(resultShape(3) == nchan, AipsError);
// AlwaysAssert(resultShape(2) == npol, AipsError);
// AlwaysAssert(resultShape(1) == ny, AipsError);
// AlwaysAssert(resultShape(0) == nx/2 + 1, AipsError);
//
// const IPosition inputSliceShape(4,nx,ny,1,1);
// const IPosition resultSliceShape(4,nx/2+1,ny,1,1);
// COWPtr<Array<Float>>
// inputArrPtr(new Array<Float>(inputSliceShape.nonDegenerate()));
// Array<Complex> resultArray(resultSliceShape.nonDegenerate());
// FFTServer<Float, Complex> FFT2D(inputSliceShape.nonDegenerate());
//
// IPosition start(4,0);
// Bool isARef;
// for (uInt c = 0; c < nchan; c++){
// for (uInt p = 0; p < npol; p++){
// isARef = input.getSlice(inputArrPtr,
// Slicer(start,inputSliceShape), True);
// FFT2D.fft(resultArray, *inputArrPtr);
// result.putSlice(resultArray, start);
// start(2) += 1;
// }
// start(2) = 0;
// start(3) += 1;
// }
// }
// </srcblock>
// Note that the <linkto class=LatticeFFT>LatticeFFT</linkto> class
// offers a nice way to do lattice based FFTs.
//
// <h4>Example 3:</h4>
// Occasionally you may want to access a few elements of a Lattice without
// all the difficulty involved in setting up Iterators or calling getSlice
// and putSlice. This is demonstrated in the example below.
// Setting a single element can be done with the <src>putAt</src> function,
// while getting a single element can be done with the parenthesis operator.
// Using these functions to access many elements of a Lattice is not
// recommended as this is the slowest access method.
//
// In this example an ideal point spread function will be inserted into an
// empty Lattice. As with the previous examples all the action occurs
// inside a function because Lattice is an interface (abstract) class.
//
// <srcblock>
// void makePsf(Lattice<Float>& psf) {
// const IPosition centrePos = psf.shape()/2;
// psf.set(0.0f); // this sets all the elements to zero
// // As it uses a LatticeIterator it is efficient
// psf.putAt (1, centrePos); // This sets just the centre element to one
// AlwaysAssert(near(psf(centrePos), 1.0f, 1E-6), AipsError);
// AlwaysAssert(near(psf(centrePos*0), 0.0f, 1E-6), AipsError);
// }
// </srcblock>
// </example>
// <motivation>
// Creating an abstract base class which provides a common interface between
// memory and disk based arrays has a number of advantages.
// <ul>
// <li> It allows functions common to all arrays to be written independent
// of the way the data is stored. This is illustrated in the three examples
// above.
// <li> It reduces the learning curve for new users who only have to become
// familiar with one interface (ie. Lattice) rather than distinct interfaces
// for different array types.
// </ul>
// </motivation>
// <todo asof="1996/07/01">
// <li> Make PagedArray cache functions virtual in this base class.
// </todo>
template <class T> class Lattice : public LatticeBase
{
public:
// a virtual destructor is needed so that it will use the actual destructor
// in the derived class
virtual ~Lattice();
// Make a copy of the derived object (reference semantics).
virtual Lattice<T>* clone() const = 0;
// Get the data type of the lattice.
virtual DataType dataType() const;
// Return the value of the single element located at the argument
// IPosition.
// <br> The default implementation uses getSlice.
// <group>
T operator() (const IPosition& where) const;
virtual T getAt (const IPosition& where) const;
// </group>
// Put the value of a single element.
// <br> The default implementation uses putSlice.
virtual void putAt (const T& value, const IPosition& where);
// Functions which extract an Array of values from a Lattice. All the
// IPosition arguments must have the same number of axes as the underlying
// Lattice, otherwise, an exception is thrown. <br>
// The parameters are:
// <ul>
// <li> buffer: a <src>COWPtr<Array<T>></src> or an
// <src>Array<T></src>. See example 2 above for an example.
// <li> start: The starting position (or Bottom Left Corner), within
// the Lattice, of the data to be extracted.
// <li> shape: The shape of the data to be extracted. This is not a
// position within the Lattice but the actual shape the buffer will
// have after this function is called. This argument added
// to the "start" argument should be the "Top Right Corner".
// <li> stride: The increment for each axis. A stride of
// one will return every data element, a stride of two will return
// every other element. The IPosition elements may be different for
// each respective axis. Thus, a stride of IPosition(3,1,2,3) says:
// fill the buffer with every element whose position has a first
// index between start(0) and start(0)+shape(0), a second index
// which is every other element between start(1) and
// (start(1)+shape(1))*2, and a third index of every third element
// between start(2) and (start(2)+shape(2))*3.
// <li> section: Another way of specifying the start, shape and stride
// <li> removeDegenerateAxes: a Bool which dictates whether to remove
// "empty" axis created in buffer. (e.g. extracting an n-dimensional
// from an (n+1)-dimensional will fill 'buffer' with an array that
// has a degenerate axis (i.e. one axis will have a length = 1.)
// Setting removeDegenerateAxes = True will return a buffer with
// a shape that doesn't reflect these superfluous axes.)
// </ul>
//
// The derived implementations of these functions return
// 'True' if "buffer" is a reference to Lattice data and 'False' if it
// is a copy.
// <group>
Bool get (COWPtr<Array<T>>& buffer,
Bool removeDegenerateAxes=False) const;
Bool getSlice (COWPtr<Array<T>>& buffer, const Slicer& section,
Bool removeDegenerateAxes=False) const;
Bool getSlice (COWPtr<Array<T>>& buffer, const IPosition& start,
const IPosition& shape,
Bool removeDegenerateAxes=False) const;
Bool getSlice (COWPtr<Array<T>>& buffer, const IPosition& start,
const IPosition& shape, const IPosition& stride,
Bool removeDegenerateAxes=False) const;
Bool get (Array<T>& buffer,
Bool removeDegenerateAxes=False);
Bool getSlice (Array<T>& buffer, const Slicer& section,
Bool removeDegenerateAxes=False);
Bool getSlice (Array<T>& buffer, const IPosition& start,
const IPosition& shape,
Bool removeDegenerateAxes=False);
Bool getSlice (Array<T>& buffer, const IPosition& start,
const IPosition& shape, const IPosition& stride,
Bool removeDegenerateAxes=False);
Array<T> get (Bool removeDegenerateAxes=False) const;
Array<T> getSlice (const Slicer& section,
Bool removeDegenerateAxes=False) const;
Array<T> getSlice (const IPosition& start,
const IPosition& shape,
Bool removeDegenerateAxes=False) const;
Array<T> getSlice (const IPosition& start,
const IPosition& shape, const IPosition& stride,
Bool removeDegenerateAxes=False) const;
// </group>
// A function which places an Array of values within this instance of the
// Lattice at the location specified by the IPosition "where", incrementing
// by "stride". All of the IPosition arguments must be of the same
// dimensionality as the Lattice. The sourceBuffer array may (and probably
// will) have less axes than the Lattice. The stride defaults to one if
// not specified.
// <group>
void putSlice (const Array<T>& sourceBuffer, const IPosition& where,
const IPosition& stride)
{ doPutSlice (sourceBuffer, where, stride); }
void putSlice (const Array<T>& sourceBuffer, const IPosition& where);
void put (const Array<T>& sourceBuffer);
// </group>
// Set all elements in the Lattice to the given value.
virtual void set (const T& value);
// Replace every element, x, of the Lattice with the result of f(x). You
// must pass in the address of the function -- so the function must be
// declared and defined in the scope of your program. All versions of
// apply require a function that accepts a single argument of type T (the
// Lattice template type) and return a result of the same type. The first
// apply expects a function with an argument passed by value; the second
// expects the argument to be passed by const reference; the third
// requires an instance of the class <src>Functional<T,T></src>. The
// first form ought to run faster for the built-in types, which may be an
// issue for large Lattices stored in memory, where disk access is not an
// issue.
// <group>
virtual void apply (T (*function)(T));
virtual void apply (T (*function)(const T&));
virtual void apply (const Functional<T,T>& function);
// </group>
// Add, subtract, multiple, or divide by another Lattice.
// The other Lattice can be a scalar (e.g. the result of LatticeExpr).
// Possible masks are not taken into account.
// <group>
void operator+= (const Lattice<T>& other)
{ handleMath (other, 0); }
void operator-= (const Lattice<T>& other)
{ handleMath (other, 1); }
void operator*= (const Lattice<T>& other)
{ handleMath (other, 2); }
void operator/= (const Lattice<T>& other)
{ handleMath (other, 3); }
// </group>
// Copy the data from the given lattice to this one.
// The default implementation uses function <src>copyDataTo</src>.
virtual void copyData (const Lattice<T>& from);
// Copy the data from this lattice to the given lattice.
// The default implementation only copies data (thus no mask, etc.).
virtual void copyDataTo (Lattice<T>& to) const;
// This function returns the advised maximum number of pixels to
// include in the cursor of an iterator. The default implementation
// returns a number that is a power of two and includes enough pixels to
// consume between 4 and 8 MBytes of memory.
virtual uInt advisedMaxPixels() const;
// These functions are used by the LatticeIterator class to generate an
// iterator of the correct type for a specified Lattice. Not recommended
// for general use.
// <br>The default implementation creates a LatticeIterInterface object.
virtual LatticeIterInterface<T>* makeIter (const LatticeNavigator& navigator,
Bool useRef) const;
// The functions (in the derived classes) doing the actual work.
// These functions are public, so they can be used internally in the
// various Lattice classes, which is especially useful for doGetSlice.
// <br>However, doGetSlice does not call Slicer::inferShapeFromSource
// to fill in possible unspecified section values. Therefore one
// should normally use one of the get(Slice) functions. doGetSlice
// should be used with care and only when performance is an issue.
// <group>
virtual Bool doGetSlice (Array<T>& buffer, const Slicer& section) = 0;
virtual void doPutSlice (const Array<T>& buffer, const IPosition& where,
const IPosition& stride) = 0;
// </group>
protected:
// Define default constructor to satisfy compiler.
Lattice() {};
// Handle the Math operators (+=, -=, *=, /=).
// They work similarly to copyData(To).
// However, they are not defined for Bool types, thus specialized below.
// <group>
virtual void handleMath (const Lattice<T>& from, int oper);
virtual void handleMathTo (Lattice<T>& to, int oper) const;
// </group>
// Copy constructor and assignment can only be used by derived classes.
// <group>
Lattice (const Lattice<T>&)
: LatticeBase() {}
Lattice<T>& operator= (const Lattice<T>&)
{ return *this; }
// </group>
};
template<> inline
void Lattice<Bool>::handleMathTo (Lattice<Bool>&, int) const
{ throwBoolMath(); }
//# Declare extern templates for often used types.
extern template class Lattice<Float>;
extern template class Lattice<Complex>;
} //# NAMESPACE CASACORE - END
//# There is a problem in including Lattice.tcc, because it needs
//# LatticeIterator.h which in its turn includes Lattice.h again.
//# So in a source file including LatticeIterator.h, Lattice::set fails
//# to compile, because the LatticeIterator declarations are not seen yet.
//# Therefore LatticeIterator.h is included here, while LatticeIterator.h
//# includes Lattice.tcc.
#ifndef CASACORE_NO_AUTO_TEMPLATES
#include <casacore/lattices/Lattices/LatticeIterator.h>
#endif //# CASACORE_NO_AUTO_TEMPLATES
#endif
casacore::Array
Definition Array.h:155
casacore::COWPtr
Definition COWPtr.h:183
casacore::Functional
Definition Functional.h:120
casacore::IPosition
Definition IPosition.h:117
casacore::LatticeBase::shape
virtual IPosition shape() const =0
Return the shape of the Lattice including all degenerate axes (ie.
casacore::LatticeBase::LatticeBase
LatticeBase()
Define default constructor to be used by derived classes.
Definition LatticeBase.h:257
casacore::LatticeBase::throwBoolMath
void throwBoolMath() const
Throw an exception for arithmetic on a Bool Lattice.
casacore::LatticeIterInterface
Definition LatticeIterInterface.h:112
casacore::LatticeNavigator
Definition LatticeNavigator.h:180
casacore::Lattice
Definition Lattice.h:230
casacore::Lattice::putSlice
void putSlice(const Array< T > &sourceBuffer, const IPosition &where)
casacore::Lattice::operator-=
void operator-=(const Lattice< T > &other)
Definition Lattice.h:361
casacore::Lattice::apply
virtual void apply(T(*function)(const T &))
casacore::Lattice::getSlice
Bool getSlice(COWPtr< Array< T > > &buffer, const Slicer &section, Bool removeDegenerateAxes=False) const
casacore::Lattice::get
Bool get(COWPtr< Array< T > > &buffer, Bool removeDegenerateAxes=False) const
Functions which extract an Array of values from a Lattice.
casacore::Lattice::handleMath
virtual void handleMath(const Lattice< T > &from, int oper)
Handle the Math operators (+=, -=, *=, /=).
casacore::Lattice::put
void put(const Array< T > &sourceBuffer)
casacore::Lattice::getSlice
Array< T > getSlice(const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False) const
casacore::Lattice::copyData
virtual void copyData(const Lattice< T > &from)
Copy the data from the given lattice to this one.
casacore::Lattice::getSlice
Bool getSlice(Array< T > &buffer, const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False)
casacore::Lattice::getAt
virtual T getAt(const IPosition &where) const
casacore::Lattice::getSlice
Bool getSlice(COWPtr< Array< T > > &buffer, const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False) const
casacore::Lattice::operator=
Lattice< T > & operator=(const Lattice< T > &)
Definition Lattice.h:419
casacore::Lattice::Lattice
Lattice()
Define default constructor to satisfy compiler.
Definition Lattice.h:405
casacore::Lattice::apply
virtual void apply(T(*function)(T))
Replace every element, x, of the Lattice with the result of f(x).
casacore::Lattice::get
Bool get(Array< T > &buffer, Bool removeDegenerateAxes=False)
casacore::Lattice::~Lattice
virtual ~Lattice()
a virtual destructor is needed so that it will use the actual destructor in the derived class
casacore::Lattice::Lattice
Lattice(const Lattice< T > &)
Copy constructor and assignment can only be used by derived classes.
Definition Lattice.h:417
casacore::Lattice::clone
virtual Lattice< T > * clone() const =0
Make a copy of the derived object (reference semantics).
casacore::Lattice::doGetSlice
virtual Bool doGetSlice(Array< T > &buffer, const Slicer &section)=0
The functions (in the derived classes) doing the actual work.
casacore::Lattice::getSlice
Bool getSlice(Array< T > &buffer, const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False)
casacore::Lattice::makeIter
virtual LatticeIterInterface< T > * makeIter(const LatticeNavigator &navigator, Bool useRef) const
These functions are used by the LatticeIterator class to generate an iterator of the correct type for...
casacore::Lattice::putAt
virtual void putAt(const T &value, const IPosition &where)
Put the value of a single element.
casacore::Lattice::operator/=
void operator/=(const Lattice< T > &other)
Definition Lattice.h:365
casacore::Lattice::getSlice
Array< T > getSlice(const IPosition &start, const IPosition &shape, Bool removeDegenerateAxes=False) const
casacore::Lattice::operator*=
void operator*=(const Lattice< T > &other)
Definition Lattice.h:363
casacore::Lattice::set
virtual void set(const T &value)
Set all elements in the Lattice to the given value.
casacore::Lattice::handleMathTo
virtual void handleMathTo(Lattice< T > &to, int oper) const
casacore::Lattice::operator+=
void operator+=(const Lattice< T > &other)
Add, subtract, multiple, or divide by another Lattice.
Definition Lattice.h:359
casacore::Lattice::putSlice
void putSlice(const Array< T > &sourceBuffer, const IPosition &where, const IPosition &stride)
A function which places an Array of values within this instance of the Lattice at the location specif...
Definition Lattice.h:327
casacore::Lattice::getSlice
Bool getSlice(Array< T > &buffer, const Slicer &section, Bool removeDegenerateAxes=False)
casacore::Lattice::doPutSlice
virtual void doPutSlice(const Array< T > &buffer, const IPosition &where, const IPosition &stride)=0
casacore::Lattice::getSlice
Array< T > getSlice(const Slicer &section, Bool removeDegenerateAxes=False) const
casacore::Lattice::apply
virtual void apply(const Functional< T, T > &function)
casacore::Lattice::copyDataTo
virtual void copyDataTo(Lattice< T > &to) const
Copy the data from this lattice to the given lattice.
casacore::Lattice::advisedMaxPixels
virtual uInt advisedMaxPixels() const
This function returns the advised maximum number of pixels to include in the cursor of an iterator.
casacore::Lattice::get
Array< T > get(Bool removeDegenerateAxes=False) const
casacore::Lattice::getSlice
Bool getSlice(COWPtr< Array< T > > &buffer, const IPosition &start, const IPosition &shape, const IPosition &stride, Bool removeDegenerateAxes=False) const
casacore::Lattice::operator()
T operator()(const IPosition &where) const
Return the value of the single element located at the argument IPosition.
casacore::Lattice::dataType
virtual DataType dataType() const
Get the data type of the lattice.
casacore::Slicer
Definition Slicer.h:287
casacore
this file contains all the compiler specific defines
Definition mainpage.dox:28
casacore::False
const Bool False
Definition aipstype.h:42
casacore::uInt
unsigned int uInt
Definition aipstype.h:49
casacore::Bool
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
casacore::value
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:369