26 #include "FitsError.h"
39 Image(
const Image< T > &right);
40 Image (
const std::valarray<T>& imageArray = std::valarray<T>());
42 Image< T > & operator=(
const Image< T > &right);
44 const std::valarray<T>& readImage (fitsfile* fPtr,
long first,
long nElements, T* nullValue,
const std::vector<long>& naxes,
bool& nulls);
45 const std::valarray<T>& readImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride, T* nullValue,
const std::vector<long>& naxes,
bool& nulls);
47 void writeImage (fitsfile* fPtr,
long first,
long nElements,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN, T* nullValue = 0);
48 void writeImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN);
49 void writeImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN);
54 void scalingHasChanged();
58 const std::valarray< T >& image ()
const;
66 std::valarray<T>& image ();
67 void prepareForSubset (
const std::vector<long>& naxes,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
const std::valarray<T>& inData, std::valarray<T>& subset);
68 void loop (
size_t iDim,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
size_t iPos,
const std::vector<size_t>& incr,
const std::valarray<T>& inData,
size_t& iDat,
const std::vector<size_t>& subIncr, std::valarray<T>& subset,
size_t iSub);
69 bool isNullValChanged(T* newNull)
const;
70 void setLastNullInfo(T* newNull);
85 std::valarray< T > m_fullImageCache;
86 std::valarray<T> m_currentRead;
95 inline bool Image<T>::isRead ()
const
100 template <
typename T>
101 inline const std::valarray< T >& Image<T>::image ()
const
103 return m_fullImageCache;
109 template <
typename T>
110 Image<T>::Image(
const Image<T> &right)
111 : m_isRead(right.m_isRead),
112 m_usingNullVal(right.m_usingNullVal),
113 m_lastNullVal(right.m_lastNullVal),
114 m_fullImageCache(right.m_fullImageCache),
115 m_currentRead(right.m_currentRead)
119 template <
typename T>
120 Image<T>::Image (
const std::valarray<T>& imageArray)
122 m_usingNullVal(false),
124 m_fullImageCache(imageArray),
130 template <
typename T>
136 template <
typename T>
137 Image<T> & Image<T>::operator=(
const Image<T> &right)
140 m_isRead = right.m_isRead;
141 m_usingNullVal = right.m_usingNullVal,
142 m_lastNullVal = right.m_lastNullVal,
143 m_fullImageCache.resize(right.m_fullImageCache.size());
144 m_fullImageCache = right.m_fullImageCache;
145 m_currentRead.resize(right.m_currentRead.size());
146 m_currentRead = right.m_currentRead;
151 template <
typename T>
152 const std::valarray<T>& Image<T>::readImage (fitsfile* fPtr,
long first,
long nElements, T* nullValue,
const std::vector<long>& naxes,
bool& nulls)
156 m_currentRead.resize(0);
157 return m_currentRead;
159 unsigned long init(1);
160 unsigned long nTotalElements(std::accumulate(naxes.begin(),naxes.end(),init,
161 std::multiplies<long>()));
165 string errMsg(
"*** CCfits Error: For image read, lowest allowed value for first element is 1.\n");
167 throw FitsException(errMsg, silent);
170 unsigned long start = (
unsigned long)first - 1;
171 if (start >= nTotalElements)
173 string errMsg(
"*** CCfits Error: For image read, starting element is out of range.\n");
175 throw FitsException(errMsg, silent);
179 string errMsg(
"*** CCfits Error: Negative nElements value specified for image read.\n");
181 throw FitsException(errMsg, silent);
183 const unsigned long elementsRequested = (
unsigned long)nElements;
187 FITSUtil::MatchType<T> imageType;
190 unsigned long elementsToRead(std::min(elementsRequested,
191 nTotalElements - start));
192 if ( elementsToRead < elementsRequested)
195 "***CCfits Warning: data request exceeds image size, truncating\n";
197 const bool isFullRead = (elementsToRead == nTotalElements);
198 const bool isDifferentNull = isNullValChanged(nullValue);
199 if (!m_isRead || isDifferentNull)
205 m_fullImageCache.resize(elementsToRead);
206 if (fits_read_img(fPtr,imageType(),first,elementsToRead,
207 nullValue,&m_fullImageCache[0],&any,&status) != 0)
throw FitsError(status);
215 m_fullImageCache.resize(0);
216 m_currentRead.resize(elementsToRead);
217 if (fits_read_img(fPtr,imageType(),first,elementsToRead,
218 nullValue,&m_currentRead[0],&any,&status) != 0)
throw FitsError(status);
221 setLastNullInfo(nullValue);
227 m_currentRead.resize((
size_t)elementsToRead);
230 m_currentRead = m_fullImageCache[std::slice((
size_t)start, (
size_t)elementsToRead,1)];
234 return m_fullImageCache;
236 return m_currentRead;
240 template <
typename T>
241 const std::valarray<T>& Image<T>::readImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride, T* nullValue,
const std::vector<long>& naxes,
bool& nulls)
243 const size_t N = naxes.size();
246 m_currentRead.resize(0);
247 return m_currentRead;
249 if (N != firstVertex.size() || N != lastVertex.size() || N != stride.size())
251 string errMsg(
"*** CCfits Error: Image read function requires that naxes, firstVertex,");
252 errMsg +=
" \nlastVertex, and stride vectors all be the same size.\n";
254 throw FitsException(errMsg, silent);
257 FITSUtil::CVarray<long> carray;
260 long requestedSize=1;
263 for (
size_t j = 0; j < N; ++j)
266 requestedSize *= ((lastVertex[j] - firstVertex[j])/stride[j] + 1);
267 nTotalSize *= naxes[j];
268 if (firstVertex[j] < 1 || lastVertex[j] > naxes[j])
270 string errMsg(
"*** CCfits Error: Out-of-bounds vertex value.\n");
272 throw FitsException(errMsg,silent);
274 if (firstVertex[j] > lastVertex[j])
276 string errMsg(
"*** CCfits Error: firstVertex values must not be larger than corresponding lastVertex values.\n");
278 throw FitsException(errMsg,silent);
281 const bool isFullRead = (requestedSize == nTotalSize);
282 const bool isDifferentNull = isNullValChanged(nullValue);
283 if (!m_isRead || isDifferentNull)
286 FITSUtil::auto_array_ptr<long> pFpixel(carray(firstVertex));
287 FITSUtil::auto_array_ptr<long> pLpixel(carray(lastVertex));
288 FITSUtil::auto_array_ptr<long> pStride(carray(stride));
290 FITSUtil::MatchType<T> imageType;
294 m_fullImageCache.resize(requestedSize);
295 if (fits_read_subset(fPtr,imageType(),
296 pFpixel.get(),pLpixel.get(),
297 pStride.get(),nullValue,&m_fullImageCache[0],&any,&status) != 0)
298 throw FitsError(status);
303 m_currentRead.resize(requestedSize);
304 if (fits_read_subset(fPtr,imageType(),
305 pFpixel.get(),pLpixel.get(),
306 pStride.get(),nullValue,&m_currentRead[0],&any,&status) != 0)
307 throw FitsError(status);
310 setLastNullInfo(nullValue);
321 std::valarray<size_t> gsliceLength(
size_t(0),N);
322 std::valarray<size_t> gsliceStride(
size_t(0),N);
324 std::vector<long> naxesProducts(N);
326 for (
size_t i=0; i<N; ++i)
328 naxesProducts[i] = accum;
332 for (
size_t i=0; i<N; ++i)
334 startPos +=
static_cast<size_t>((firstVertex[i]-1)*naxesProducts[i]);
336 const size_t gsPos = N-1-i;
338 gsliceLength[gsPos] =
static_cast<size_t>((1 + (lastVertex[i]-firstVertex[i])/stride[i]));
339 gsliceStride[gsPos] =
static_cast<size_t>(stride[i]*naxesProducts[i]);
341 m_currentRead.resize(requestedSize);
342 m_currentRead = m_fullImageCache[std::gslice(startPos, gsliceLength, gsliceStride)];
346 return m_fullImageCache;
347 return m_currentRead;
350 template <
typename T>
351 void Image<T>::writeImage (fitsfile* fPtr,
long first,
long nElements,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN, T* nullValue)
354 if (first < 1 || nElements < 1)
356 string errMsg(
"*** CCfits Error: first and nElements values must be > 0\n");
358 throw FitsException(errMsg, silent);
360 FITSUtil::CAarray<T> convert;
361 FITSUtil::auto_array_ptr<T> pArray(convert(inData));
362 T* array = pArray.get();
367 FITSUtil::MatchType<T> imageType;
368 long type(imageType());
370 if (fits_write_imgnull(fPtr,type,first,nElements,array,
371 nullValue,&status)!= 0)
373 throw FitsError(status);
375 const size_t nDim=naxes.size();
377 for (
size_t i=0; i<nDim; ++i)
378 origTotSize *= naxes[i];
379 const long highestOutputElem = first + nElements - 1;
380 if (highestOutputElem > origTotSize)
383 std::ostringstream oss;
384 oss <<
"NAXIS" << nDim;
385 string keyname(oss.str());
386 long newVal = 1 + (highestOutputElem-1)/(origTotSize/naxes[nDim-1]);
387 if (newVal != naxes[nDim-1])
389 if (fits_update_key(fPtr,TLONG,(
char *)keyname.c_str(),&newVal,0,&status) != 0)
391 throw FitsError(status);
396 if (fits_flush_file(fPtr,&status) != 0)
397 throw FitsError(status);
401 template <
typename T>
402 void Image<T>::writeImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN)
405 const size_t nDim = naxes.size();
406 FITSUtil::auto_array_ptr<long> pFPixel(
new long[nDim]);
407 FITSUtil::auto_array_ptr<long> pLPixel(
new long[nDim]);
408 std::valarray<T> subset;
411 prepareForSubset(naxes,firstVertex,lastVertex,stride,inData,subset);
413 long* fPixel = pFPixel.get();
414 long* lPixel = pLPixel.get();
415 for (
size_t i=0; i<nDim; ++i)
417 fPixel[i] = firstVertex[i];
418 lPixel[i] = lastVertex[i];
421 FITSUtil::CAarray<T> convert;
422 FITSUtil::auto_array_ptr<T> pArray(convert(subset));
423 T* array = pArray.get();
424 FITSUtil::MatchType<T> imageType;
427 if ( fits_write_subset(fPtr,imageType(),fPixel,lPixel,array,&status) )
428 throw FitsError(status);
430 if (lPixel[nDim-1] > naxes[nDim-1])
432 std::ostringstream oss;
433 oss <<
"NAXIS" << nDim;
434 string keyname(oss.str());
435 long newVal = lPixel[nDim-1];
436 if (fits_update_key(fPtr,TLONG,(
char *)keyname.c_str(),&newVal,0,&status) != 0)
438 throw FitsError(status);
440 newNaxisN = lPixel[nDim-1];
442 if (fits_flush_file(fPtr,&status) != 0)
443 throw FitsError(status);
447 template <
typename T>
448 std::valarray<T>& Image<T>::image ()
451 return m_fullImageCache;
454 template <
typename T>
455 void Image<T>::prepareForSubset (
const std::vector<long>& naxes,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
const std::valarray<T>& inData, std::valarray<T>& subset)
459 const size_t N = naxes.size();
460 if (N != firstVertex.size() || N != lastVertex.size() || N != stride.size())
462 string errMsg(
"*** CCfits Error: Image write function requires that naxes, firstVertex,");
463 errMsg +=
" \nlastVertex, and stride vectors all be the same size.\n";
465 throw FitsException(errMsg, silent);
467 for (
size_t i=0; i<N; ++i)
472 throw FitsException(
"*** CCfits Error: Invalid naxes value sent to image write function.\n", silent);
474 string rangeErrMsg(
"*** CCfits Error: Out-of-range value sent to image write function in arg: ");
475 if (firstVertex[i] < 1 || (firstVertex[i] > naxes[i] && i != N-1))
478 rangeErrMsg +=
"firstVertex\n";
479 throw FitsException(rangeErrMsg, silent);
481 if (lastVertex[i] < firstVertex[i] || (lastVertex[i] > naxes[i] && i != N-1))
484 rangeErrMsg +=
"lastVertex\n";
485 throw FitsException(rangeErrMsg, silent);
490 rangeErrMsg +=
"stride\n";
491 throw FitsException(rangeErrMsg, silent);
498 size_t subSizeWithStride = 1;
500 std::vector<size_t> subIncr(N);
501 for (
size_t i=0; i<N; ++i)
503 subIncr[i] = nPoints;
504 nPoints *=
static_cast<size_t>(1+lastVertex[i]-firstVertex[i]);
505 subSizeWithStride *=
static_cast<size_t>(1+(lastVertex[i]-firstVertex[i])/stride[i]);
507 subset.resize(nPoints, 0);
509 if (subSizeWithStride != inData.size())
512 string errMsg(
"*** CCfits Error: Data array size is not consistent with the values");
513 errMsg +=
"\n in range and stride vectors sent to the image write function.\n";
514 throw FitsException(errMsg, silent);
517 size_t startPoint = 0;
519 std::vector<size_t> incr(N);
520 for (
size_t j = 0; j < N; ++j)
522 startPoint += dimMult*(firstVertex[j]-1);
524 dimMult *=
static_cast<size_t>(naxes[j]);
527 size_t inDataPos = 0;
529 loop(N-1, firstVertex, lastVertex, stride, startPoint, incr, inData, inDataPos, subIncr, subset, iSub);
532 template <
typename T>
533 void Image<T>::loop (
size_t iDim,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::vector<long>& stride,
size_t iPos,
const std::vector<size_t>& incr,
const std::valarray<T>& inData,
size_t& iDat,
const std::vector<size_t>& subIncr, std::valarray<T>& subset,
size_t iSub)
535 size_t start =
static_cast<size_t>(firstVertex[iDim]);
536 size_t stop =
static_cast<size_t>(lastVertex[iDim]);
537 size_t skip =
static_cast<size_t>(stride[iDim]);
540 size_t length = stop - start + 1;
541 for (
size_t i=0; i<length; i+=skip)
543 subset[i+iSub] = inData[iDat++];
548 size_t jump = incr[iDim]*skip;
549 size_t subJump = subIncr[iDim]*skip;
550 for (
size_t i=start; i<=stop; i+=skip)
552 loop(iDim-1, firstVertex, lastVertex, stride, iPos, incr, inData, iDat, subIncr, subset, iSub);
559 template <
typename T>
560 bool Image<T>::isNullValChanged(T* newNull)
const
562 bool isChanged =
false;
569 if (newVal != m_lastNullVal)
577 if (newNull && (*newNull != 0))
584 template <
typename T>
585 void Image<T>::setLastNullInfo(T* newNull)
587 if (!newNull || *newNull == 0)
589 m_usingNullVal =
false;
594 m_usingNullVal =
true;
595 m_lastNullVal = *newNull;
599 template <
typename T>
600 void Image<T>::writeImage (fitsfile* fPtr,
const std::vector<long>& firstVertex,
const std::vector<long>& lastVertex,
const std::valarray<T>& inData,
const std::vector<long>& naxes,
long& newNaxisN)
602 std::vector<long> stride(firstVertex.size(), 1);
603 writeImage(fPtr, firstVertex, lastVertex, stride, inData, naxes, newNaxisN);
606 template <
typename T>
607 void Image<T>::scalingHasChanged()
612 template <
typename T>
613 void Image<T>::resetRead()
Namespace enclosing all CCfits classes and globals definitions.
Definition: AsciiTable.cxx:26