26
#include "FitsError.h"
34
template
<
typename
T>
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);
50
bool
isRead ()
const
;
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;
94
template
<
typename
T>
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"
);
166
bool
silent =
false
;
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"
);
174
bool
silent =
false
;
175
throw
FitsException(errMsg, silent);
179
string
errMsg(
"*** CCfits Error: Negative nElements value specified for image read.\n"
);
180
bool
silent =
false
;
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"
;
253
bool
silent =
false
;
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"
);
277
bool
silent =
false
;
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"
);
357
bool
silent =
false
;
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"
;
464
bool
silent =
false
;
465
throw
FitsException(errMsg, silent);
467
for
(
size_t
i=0; i<N; ++i)
471
bool
silent =
false
;
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))
477
bool
silent =
false
;
478
rangeErrMsg +=
"firstVertex\n"
;
479
throw
FitsException(rangeErrMsg, silent);
481
if
(lastVertex[i] < firstVertex[i] || (lastVertex[i] > naxes[i] && i != N-1))
483
bool
silent =
false
;
484
rangeErrMsg +=
"lastVertex\n"
;
485
throw
FitsException(rangeErrMsg, silent);
489
bool
silent =
false
;
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())
511
bool
silent =
false
;
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()