casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
VisBufferImpl2.h
Go to the documentation of this file.
00001 //# VisBuffer.h: buffer for iterating through MS in large blocks
00002 //# Copyright (C) 1996,1997,1998,1999,2000,2002,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 
00027 #ifndef MSVIS_VISBUFFERIMPL2_H
00028 #define MSVIS_VISBUFFERIMPL2_H
00029 
00030 #include <casa/aips.h>
00031 
00032 //#warning "Remove next line later"
00033 //#    include <synthesis/MSVis/VisBuffer.h>
00034 
00035 #include <casa/Arrays/Cube.h>
00036 #include <casa/Arrays/Vector.h>
00037 #include <casa/Arrays/Matrix.h>
00038 #include <casa/BasicSL/Complex.h>
00039 #include <synthesis/MSVis/VisBufferComponents2.h>
00040 #include <synthesis/MSVis/VisBuffer2.h>
00041 //#include <synthesis/TransformMachines/VisModelData.h>
00042 
00043 using casa::vi::VisBufferComponent2;
00044 using casa::vi::VisBufferComponents2;
00045 
00046 namespace casa { //# NAMESPACE CASA - BEGIN
00047 
00048 class VisModelData;
00049 
00050 namespace asyncio {
00051     class VLAT;
00052 } // end namespace asyncio
00053 
00054 namespace vi {
00055 
00056 //#forward
00057 
00058 class VbCacheItemBase;
00059 class VisBufferCache;
00060 class VisBufferState;
00061 class VisBufferImpl2;
00062 class VisibilityIterator2;
00063 class VisibilityIterator2;
00064 
00065 
00066 
00067 //<summary>VisBufferImpls encapsulate one chunk of visibility data for processing.</summary>
00068 //
00069 // <use visibility=export>
00070 //
00071 // <reviewed reviewer="" date="" tests="" demos="">
00072 
00073 // <prerequisite>
00074 //   <li> <linkto class="VisSet">VisSet</linkto>
00075 //   <li> <linkto class="VisibilityIterator2">VisibilityIterator2</linkto>
00076 //   <li> <linkto class="VisBufferImplAutoPtr">VisBufferImplAutoPtr</linkto>
00077 //   <li> <linkto class="VbDirtyComponents">VbDirtyComponents</linkto>
00078 // </prerequisite>
00079 //
00080 // <etymology>
00081 // VisBufferImpl is a buffer for visibility data
00082 // </etymology>
00083 //
00084 //<synopsis>
00085 // This class contains 'one iteration' of the
00086 // <linkto class="VisibilityIterator2">VisibilityIterator2</linkto>
00087 // It is a modifiable
00088 // buffer of values to which calibration and averaging can be applied.
00089 // This allows processing of the data in larger blocks, avoiding some
00090 // overheads for processing per visibility point or spectrum.
00091 //
00092 // See <linkto module="MeasurementEquations">MeasurementEquations</linkto>
00093 // for more details on how the VisBufferImpl is to be used.
00094 //
00095 // When the user intends to allow asynchronous I/O they will need to use
00096 // the VisBufferImplAsync and VisBufferImplAsyncWrapper classes; these are
00097 // publicly derived from VisBufferImpl.  Normally, the user should not
00098 // explicitly use these classes but should use the helper class
00099 // VisBufferImplAutoPtr which will ensure that the appropriate class is
00100 // used.
00101 //
00102 //</synopsis>
00103 
00104 //<todo>
00105 //</todo>
00106 
00107 class VisBufferImpl2 : public VisBuffer2 {
00108 
00109     friend class VLAT; // for async i/o
00110     friend class VbCacheItemBase;
00111     friend class VisBufferCache;
00112     friend class VisBufferState;
00113     friend class VisBuffer2;
00114     friend class VisBufferImpl2Async; // for async i/o
00115     friend class VisBufferImpl2AsyncWrapper; // for async i/o
00116     friend class ViReadImpl;
00117     friend class ViReadImplAsync; // for async I/O
00118 
00119 public:
00120 
00121     // Create empty VisBufferImpl2 you can assign to or attach.
00122     VisBufferImpl2();
00123     // Construct VisBufferImpl2 for a particular VisibilityIterator2
00124     // The buffer will remain synchronized with the iterator.
00125 
00126     // Copy construct, looses synchronization with iterator: only use buffer for
00127     // current iteration (or reattach).
00128 
00129     VisBufferImpl2(VisibilityIterator2 * iter, VisBufferOptions options);
00130 
00131     // Destructor (detaches from VisIter)
00132 
00133     virtual ~VisBufferImpl2();
00134 
00135     virtual void associateWithVisibilityIterator2 (const VisibilityIterator2 & vi);
00136 
00137     // Copies all of the components (or just the one in the cache) from
00138     // the specified VisBuffer into this one.
00139 
00140     virtual void copy (const VisBuffer2 & other, Bool fetchIfNeeded = True);
00141 
00142     // Copies the specified components (or just the one in the cache) from
00143     // the specified VisBuffer into this one.
00144 
00145     virtual void copyComponents (const VisBuffer2 & other,
00146                                  const VisBufferComponents2 & components,
00147                                  Bool fetchIfNeeded = True);
00148 
00149     virtual void copyCoordinateInfo (const VisBuffer2 * vb, Bool dirDependent, Bool fetchIfNeeded = True);
00150 
00151     virtual Vector<Int> getCorrelationNumbers () const;
00152     virtual String getFillErrorMessage () const;
00153     virtual Double getFrequency (Int rowInBuffer, Int frequencyIndex, Int frame = FrameNotSpecified) const;
00154     virtual const Vector<Double> & getFrequencies (Int rowInBuffer,
00155                                                    Int frame = FrameNotSpecified) const;
00156     virtual Int getChannelNumber (Int rowInBuffer, Int frequencyIndex) const;
00157     virtual const Vector<Int> & getChannelNumbers (Int rowInBuffer) const;
00158 
00159     virtual const VisibilityIterator2 * getVi () const;
00160 
00161     virtual void invalidate();
00162 
00163     virtual Bool isAttached () const;
00164     virtual Bool isFillable () const;
00165     virtual void setShape (Int nCorrelations, Int nChannels, Int nRows, Bool clearTheCache = True);
00166     virtual void validateShapes () const;
00167 
00168 
00169     virtual void writeChangesBack ();
00170 
00171     //--> This needs to be removed: virtual Bool fetch(const asyncio::PrefetchColumns *pfc);
00172 
00173     // feed1_pa() and feed2_pa() return an array of parallactic angles
00174     // (each corresponds to the first receptor of the feed) one for each
00175     // row in the current buffer. In contrast, feed_pa() calculates
00176     // the angles for each antenna. These methods are implemented for
00177     // VisBufferImpl2 only to benefit from caching of the feed and antenna IDs.
00178 
00179     // Note that feed_pa is a function instead of a cached value
00180     virtual const Vector<Float> & feedPa (Double time) const;
00181 
00182     // NOMINAL parallactic angle (feed p.a. offset NOT included)
00183     virtual Float parang0(Double time) const;
00184     virtual const Vector<Float> & parang(Double time) const;
00185 
00186     virtual MDirection azel0(Double time) const; // function rather than cached value
00187     virtual const Vector<MDirection> & azel(Double time) const;
00188 
00189     // Hour angle for specified time
00190     virtual Double hourang(Double time) const;
00191 
00192     // Sort/unsort the correlations, if necessary
00193     //  (Rudimentary handling of non-canonically sorted correlations--use with care!)
00194     virtual void sortCorr ();
00195     virtual void unSortCorr();
00196 
00197     // Normalize the visCube by the modelVisCube
00198     //   (and optionally also divide visCube_p by its normalized amp)
00199 
00200     virtual void normalize ();
00201 
00202     // Fill weightMat according to sigma column
00203     virtual void resetWeightsUsingSigma ();//virtual void resetWeightMat();
00204 
00205     // Rotate visibility phase for given vector (dim = nrow of vb) of phases (metres)
00206 
00207     // Update coordinate info - useful for copied VisBufferImpl2s that need
00208     // to retain some state for later reference.
00209     // Presently this fills antenna, array, field and spectralWindow ids, time,
00210     // frequency and number of rows.
00211     // if dirDependent is set to False the expensive direction dependent calculation of parallactic or direction of
00212     // antenna from pointing table is avoided
00213     //Add more as needed.
00214 
00215     virtual Bool isNewArrayId () const;
00216     virtual Bool isNewFieldId () const;
00217     virtual Bool isNewMs() const;
00218     virtual Bool isNewSpectralWindow () const;
00219     virtual Bool isRekeyable () const;
00220     virtual Bool isWritable () const;
00221     virtual Int msId() const;
00222     virtual String msName (Bool stripPath = False) const;
00223     virtual Subchunk getSubchunk () const;
00224 
00225     virtual Bool areCorrelationsSorted() const;
00226     virtual IPosition getValidShape (Int) const;
00227     virtual VisModelData getVisModelData() const;
00228 
00230     //
00231     //  Data accessors and setters (where appropriate)
00232     //
00233     //  There are the methods that allows access to the items cached in the
00234     //  VisBuffer.  The straight accessors provide read-only access to the
00235     //  item.  Where the item is allowed to be modified, one or more set
00236     //  methods are provided.  N.B.: the VB usually caches the information
00237     //  in the representation requested so that using a setter to modify
00238     //  a value (e.g., weight vs. weightMat) will not modify the cached value
00239     //  in a different representation.
00240 
00241     virtual const Vector<Int> & antenna1 () const;
00242     virtual void setAntenna1 (const Vector<Int> & value);
00243     virtual const Vector<Int> & antenna2 () const;
00244     virtual void setAntenna2 (const Vector<Int> & value);
00245     virtual const Vector<Int> & arrayId () const;
00246     virtual void setArrayId (const Vector<Int> &);
00247     virtual const Vector<SquareMatrix<Complex, 2> > & cjones () const;
00248     virtual const Vector<Int> & correlationTypes () const;
00249 //    virtual Int dataDescriptionId () const;
00250 //    virtual void setDataDescriptionId (Int value);
00251     virtual const Vector<Int> & dataDescriptionIds () const;
00252     virtual void setDataDescriptionIds (const Vector<Int> & ); // [nR]
00253     virtual const Vector<MDirection> & direction1 () const;
00254     virtual const Vector<MDirection> & direction2 () const;
00255     virtual const Vector<Double> & exposure () const;
00256     virtual void setExposure (const Vector<Double> & value);
00257     virtual const Vector<Int> & feed1 () const;
00258     virtual void setFeed1 (const Vector<Int> & value);
00259     virtual const Vector<Float> & feedPa1 () const;
00260     virtual const Vector<Int> & feed2 () const;
00261     virtual void setFeed2 (const Vector<Int> & value);
00262     virtual const Vector<Float> & feedPa2 () const;
00263     virtual const Vector<Int> & fieldId () const;
00264     virtual void setFieldId (const Vector<Int> &);
00265     virtual const Matrix<Bool> & flag () const;
00266     virtual void setFlag (const Matrix<Bool>&);
00267     virtual const Array<Bool> & flagCategory () const;
00268     virtual void setFlagCategory (const Array<Bool>&);
00269     virtual const Cube<Bool> & flagCube () const;
00270     virtual void setFlagCube (const Cube<Bool>&);
00271     virtual const Vector<Bool> & flagRow () const;
00272     virtual void setFlagRow (const Vector<Bool>&);
00273     virtual const Matrix<Float> & imagingWeight () const;
00274     virtual Int nAntennas () const;
00275     virtual Int nChannels () const;
00276     virtual Int nCorrelations () const;
00277     virtual Int nRows () const;
00278     virtual const Vector<Int> & observationId () const;
00279     virtual void setObservationId (const Vector<Int> & value);
00280     virtual const MDirection& phaseCenter () const;
00281     virtual Int polarizationFrame () const;
00282     virtual Int polarizationId () const;
00283     virtual const Vector<Int> & processorId () const;
00284     virtual void setProcessorId (const Vector<Int> & value);
00285     virtual const Vector<uInt> & rowIds () const;
00286     virtual const Vector<Int> & scan () const;
00287     virtual void setScan (const Vector<Int> & value);
00288     virtual const Matrix<Float> & sigma () const;
00289     virtual void setSigma (const Matrix<Float> &);
00290     //virtual const Matrix<Float> & sigmaMat () const;
00291     //virtual Int spectralWindow () const;
00292     virtual const Vector<Int> & spectralWindows () const;
00293     //virtual void setSpectralWindows (const Vector<Int> & spectralWindows);
00294     virtual const Vector<Int> & stateId () const;
00295     virtual void setStateId (const Vector<Int> & value);
00296     virtual const Vector<Double> & time () const;
00297     virtual void setTime (const Vector<Double> & value);
00298     virtual const Vector<Double> & timeCentroid () const;
00299     virtual void setTimeCentroid (const Vector<Double> & value);
00300     virtual const Vector<Double> & timeInterval () const;
00301     virtual void setTimeInterval (const Vector<Double> & value);
00302     virtual const Matrix<Double> & uvw () const;
00303     virtual void setUvw (const Matrix<Double> & value);
00304     virtual const Cube<Complex> & visCubeCorrected () const;
00305     virtual void setVisCubeCorrected (const Cube<Complex> &);
00306 //    virtual const Matrix<CStokesVector> & visCorrected () const;
00307 //    virtual void setVisCorrected (const Matrix<CStokesVector> &);
00308     virtual const Cube<Float> & visCubeFloat () const;
00309     virtual void setVisCubeFloat (const Cube<Float> &);
00310     virtual const Cube<Complex> & visCubeModel () const;
00311     virtual void setVisCubeModel (const Complex & c);
00312     virtual void setVisCubeModel (const Cube<Complex>& vis);
00313 //    virtual void setVisCubeModel(const Vector<Float>& stokes);
00314 //    virtual const Matrix<CStokesVector> & visModel () const;
00315 //    virtual void setVisModel (Matrix<CStokesVector> &);
00316     virtual const Cube<Complex> & visCube () const;
00317     virtual void setVisCube(const Complex & c);
00318     virtual void setVisCube (const Cube<Complex> &);
00319 //    virtual const Matrix<CStokesVector> & vis () const;
00320 //    virtual void setVis (Matrix<CStokesVector> &);
00321     virtual const Matrix<Float> & weight () const;
00322     virtual void setWeight (const Matrix<Float>&);
00323 //    virtual const Matrix<Float> & weightMat () const;
00324 //    virtual void setWeightMat (const Matrix<Float>&);
00325     virtual const Cube<Float> & weightSpectrum () const;
00326     virtual void setWeightSpectrum (const Cube<Float>&);
00327 
00328 
00329 protected:
00330 
00331 
00332     // Attach to a VisIter. Detaches itself first if already attached
00333     // to a VisIter. Will remain synchronized with iterator.
00334 
00335     //virtual void cacheCopy (const VisBufferImpl2 & other, Bool markAsCached);
00336 
00337     void adjustWeightFactorsAndFlags (Matrix <Float> & rowWeightFactors,
00338                                       Bool useWeightSpectrum,
00339                                       Int nRows,
00340                                       Int nCorrelations,
00341                                       Int nChannelsOut);
00342     void adjustWeightAndSigmaMatrices (Int nChannelsAveraged, Int nChannelsOut, Int nRows,
00343                                        Int nCorrelations, Int nChannelsSelected,
00344                                        const Matrix <Float> & rowWeightFactors);
00345 
00346     Int averageChannelFrequencies (Int nChannelsOut,
00347                                    const Vector<Int> & channels,
00348                                    const Matrix<Int> & averagingBounds);
00349 
00350     void averageFlagInfoChannels (const Matrix<Int> & averagingBounds,
00351                                   Int nChannelsOut, Bool useWeightSpectrum);
00352 
00353     template<typename T>
00354     void averageVisCubeChannels (T & dataCache,
00355                                  Int nChanOut,
00356                                  const Matrix<Int>& averagingbounds);
00357 
00358     virtual void cacheClear (Bool markAsCached = False);
00359     virtual void cacheResizeAndZero (const VisBufferComponents2 & exclusions = VisBufferComponents2());
00360 
00361     virtual void checkVisIter (const char * func, const char * file, int line, const char * extra = "") const;
00362     void computeRowWeightFactors (Matrix <Float> & rowWeightFactors, Bool useWeightSpectrum);
00363     virtual void configureNewSubchunk (Int msId, const String & msName, Bool isNewMs,
00364                                        Bool isNewArrayId, Bool isNewFieldId,
00365                                        Bool isNewSpectralWindow, const Subchunk & subchunk,
00366                                        Int nRows, Int nChannels, Int nCorrelations,
00367                                        const Vector<Int> & correlations);
00368 
00369     virtual void copyRow (Int sourceRow, Int destinationRow);
00370     virtual void deleteRows (const Vector<Int> & rowsToDelete);
00371     virtual void dirtyComponentsAdd (const VisBufferComponents2 & additionalDirtyComponents);
00372     virtual void dirtyComponentsAdd (VisBufferComponent2 component);
00373     virtual void dirtyComponentsClear ();
00374     virtual VisBufferComponents2 dirtyComponentsGet () const;
00375     virtual void dirtyComponentsSet (const VisBufferComponents2 & dirtyComponents);
00376     virtual void dirtyComponentsSet (VisBufferComponent2 component);
00377     void normalizeRow (Int row, Int nCorrelations, const Matrix<Bool> & flagged,
00378                        Cube<Complex> & visCube, Cube<Complex> & modelCube,
00379                         Matrix<Float> & weightMat);
00380 
00381     virtual void sortCorrelationsAux (Bool makeSorted);
00382     virtual VisibilityIterator2 * getViP () const; // protected, non-const access to VI
00383     void registerCacheItem (VbCacheItemBase *);
00384     virtual void resizeRows (Int newNRows);
00385     virtual void stateCopy (const VisBufferImpl2 & other); // copy relevant noncached members
00386     virtual void setFillable (Bool isFillable);
00387     virtual void setRekeyable (Bool isRekeyable);
00388     virtual void setupValidShapes ();
00389     template <typename Coord>
00390     void updateCoord (Coord & item, const Coord & otherItem);
00391 
00392     virtual Vector<Bool> & flagRowRef ();  // [nR]
00393     virtual Cube<Bool> & flagCubeRef ();  // [nC,nF,nR]
00394     virtual Cube<Complex> & visCubeRef (); // [nC,nF,nR]
00395     virtual Cube<Complex> & visCubeCorrectedRef (); // [nC,nF,nR]
00396     virtual Cube<Complex> & visCubeModelRef (); // [nC,nF,nR]
00397     virtual Cube<Float> & weightSpectrumRef (); // [nC,nF,nR]
00398 
00399 private:
00400 
00401     virtual Bool areCorrelationsInCanonicalOrder () const;
00402     void checkVisIterBase (const char * func, const char * file, int line, const char * extra = "") const;
00403     void construct(VisibilityIterator2 * vi, VisBufferOptions options);
00404     void constructCache();
00405     void setIterationInfo (Int msId, const String & msName, Bool isNewMs,
00406                            Bool isNewArrayId, Bool isNewFieldId, Bool isNewSpectralWindow,
00407                            const Subchunk & subchunk, const Vector<Int> & correlations);
00408     virtual void validate();
00409 
00411     //
00412     //  Fillers
00413     //
00414     // These methods fill the needed value into the cache.  This
00415     // usually means getting it from the attached VisibilityIterator2
00416     // but the needed value can be generated as well.
00417     //
00418     // The name of the filler should match up with the accessor method
00419     // (see above) as well as the member name in the cache (see
00420     // VisBufferCache class in VisBuffer.cc).
00421 
00422 
00423     virtual void fillAntenna1 (Vector<Int>& value) const;
00424     virtual void fillAntenna2 (Vector<Int>& value) const;
00425     virtual void fillArrayId (Vector<Int>& value) const;
00426     virtual void fillCorrType (Vector<Int>& value) const;
00427     virtual void fillCubeCorrected (Cube <Complex> & value) const;
00428     virtual void fillCubeModel (Cube <Complex> & value) const;
00429     virtual void fillCubeObserved (Cube <Complex> & value) const;
00430     virtual void fillDataDescriptionId  (Int& value) const;
00431     virtual void fillDataDescriptionIds  (Vector<Int>& value) const;
00432     virtual void fillDirection1 (Vector<MDirection>& value) const;
00433     virtual void fillDirection2 (Vector<MDirection>& value) const;
00434     virtual void fillDirectionAux (Vector<MDirection>& value,
00435                            const Vector<Int> & antenna,
00436                            const Vector<Int> &feed,
00437                            const Vector<Float> & feedPa) const;
00438     virtual void fillExposure (Vector<Double>& value) const;
00439     virtual void fillFeed1 (Vector<Int>& value) const;
00440     virtual void fillFeed2 (Vector<Int>& value) const;
00441     virtual void fillFeedPa1 (Vector <Float> & feedPa) const;
00442     virtual void fillFeedPa2 (Vector <Float> & feedPa) const;
00443     virtual void fillFeedPaAux (Vector <Float> & feedPa,
00444                         const Vector <Int> & antenna,
00445                         const Vector <Int> & feed) const;
00446     virtual void fillFieldId (Vector<Int>& value) const;
00447     virtual void fillFlag (Matrix<Bool>& value) const;
00448     virtual void fillFlagCategory (Array<Bool>& value) const;
00449     virtual void fillFlagCube (Cube<Bool>& value) const;
00450     virtual void fillFlagRow (Vector<Bool>& value) const;
00451     virtual void fillFloatData (Cube<Float>& value) const;
00452     virtual void fillImagingWeight (Matrix<Float> & value) const;
00453     virtual void fillJonesC (Vector<SquareMatrix<Complex, 2> >& value) const;
00454     virtual void fillNAntennas (Int& value) const;
00455     virtual void fillNChannel (Int& value) const;
00456     virtual void fillNCorr (Int& value) const;
00457     virtual void fillNRow (Int& value) const;
00458     virtual void fillObservationId (Vector<Int>& value) const;
00459     virtual void fillPhaseCenter (MDirection& value) const;
00460     virtual void fillPolFrame (Int& value) const;
00461     virtual void fillPolarizationId (Int& value) const;
00462     virtual void fillProcessorId (Vector<Int>& value) const;
00463     virtual void fillRowIds (Vector<uInt>& value) const;
00464     virtual void fillScan (Vector<Int>& value) const;
00465     virtual void fillSigma (Matrix<Float>& value) const;
00466     //virtual void fillSigmaMat (Matrix<Float>& value) const;
00467     //virtual void fillSpectralWindow (Int& value) const;
00468     virtual void fillSpectralWindows  (Vector<Int>& value) const;
00469     virtual void fillStateId (Vector<Int>& value) const;
00470     virtual void fillTime (Vector<Double>& value) const;
00471     virtual void fillTimeCentroid (Vector<Double>& value) const;
00472     virtual void fillTimeInterval (Vector<Double>& value) const;
00473     virtual void fillUvw (Matrix<Double>& value) const;
00474 //    virtual void fillVisibilityCorrected (Matrix<CStokesVector>& value) const;
00475 //    virtual void fillVisibilityModel (Matrix<CStokesVector>& value) const;
00476 //    virtual void fillVisibilityObserved (Matrix<CStokesVector>& value) const;
00477     virtual void fillWeight (Matrix<Float>& value) const;
00478     //virtual void fillWeightMat (Matrix<Float>& value) const;
00479     virtual void fillWeightSpectrum (Cube<Float>& value) const;
00480 
00481     VisBufferCache * cache_p;
00482     VisBufferState * state_p;
00483 };
00484 
00485 } // end namespace vi
00486 
00487 } // end namespace casa
00488 
00489 
00490 #endif
00491