diff --git a/data-access/engine/src/vlkb/src/imcopy.cpp b/data-access/engine/src/vlkb/src/imcopy.cpp index 37f3fdbc38c92b5b882fea1777b00f8ef359636f..a1c210308ea3a9527685a7be92d4b5d652d0e78c 100644 --- a/data-access/engine/src/vlkb/src/imcopy.cpp +++ b/data-access/engine/src/vlkb/src/imcopy.cpp @@ -88,25 +88,58 @@ void imcopy(std::string filename, int extnum, std::string pixfilter, std::string throw runtime_error("fits_open_file " + filename + " failed: " + errmsg); } + /* cfitsio(v4.2.0) manual: 10.2.3 Notes about the stream filetype driver + * "-" writes to stdout: but first loads all file into mem + * "stream://" keeps NIOBUF=40 buffers, and header must fit into it */ fits_create_file(&newfptr, "stream://", &status); if (status) { string errmsg{ fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, status) }; + + int tstatus = 0; + fits_close_file(fptr, &tstatus); + if(tstatus) LOG_STREAM << fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, tstatus) << tstatus<< endl; + throw runtime_error("fits_open_file to stream failed: " + errmsg); } + /* err codes 1..1000 reserved by cfitsio */ + #define HEADER_TOO_LONG (10000) + #define MAX_CARD_COUNT (1400) + /* see notes about stream driver in cfitsio manual */ fits_copy_image_section2(fptr, newfptr, expr, &status); if (status) { - string errmsg{fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, status)}; - throw runtime_error("fits_copy_image_section " + filename - + " to cut-file with " + string{expr} + " failed: " + errmsg); + int tstatus = 0; + fits_close_file(fptr, &tstatus); + if(tstatus) LOG_STREAM << fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, tstatus) << tstatus<< endl; + tstatus = 0; + fits_close_file(newfptr, &tstatus); + if(tstatus) LOG_STREAM << fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, tstatus) << tstatus<< endl; + + if(status == HEADER_TOO_LONG) + { + throw runtime_error("Cutout from " + filename + + " failed: header is too long. Direct streaming in current build support max " + + to_string(MAX_CARD_COUNT) + " cards in header."); + } + else + { + string errmsg{fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, status)}; + throw runtime_error("fits_copy_image_section " + filename + + " to cut-file with " + string{expr} + " failed: " + errmsg); + } } fits_close_file(fptr, &status); if (status) { string errmsg{fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, status)}; + + int tstatus = 0; + fits_close_file(newfptr, &tstatus); + if(tstatus) LOG_STREAM << fitsfiles::cfitsio_errmsg(__FILE__, __LINE__, tstatus) << tstatus<< endl; + throw runtime_error("fits_close_file " + filename + " failed: " + errmsg); } @@ -120,20 +153,17 @@ void imcopy(std::string filename, int extnum, std::string pixfilter, std::string /* ---- version 3.49 ------- */ -/* - * Currently this is a direct copy from cfitsio-lib. It will be modified in two ways: - * - allow bigger buffer the first row (use sub-cube up to dimension k: volume[1.k] < LIMIT) - * - duplicate buffer and run reader on parallel-thread to avoid reader-write wait for each other - */ +/* Currently this is a direct copy from cfitsio-lib. + * Ensures read-by-rows on systems (CentOS7) with old cfitsio lib. + * Also consider to duplicate the buffer and run reader + * on parallel-thread to avoid reader-write wait for each other. */ int fits_copy_image_section2( fitsfile *fptr, /* I - pointer to input image */ fitsfile *newptr, /* I - pointer to output image */ char *expr, /* I - Image section expression */ int *status) { - /* - copies an image section from the input file to a new output HDU - */ + /* copies an image section from the input file to a new output HDU */ int bitpix, naxis, numkeys, nkey; long naxes[] = {1,1,1,1,1,1,1,1,1}, smin, smax, sinc; @@ -172,12 +202,21 @@ int fits_copy_image_section2( /* copy all other non-structural keywords from the input to output file */ fits_get_hdrspace(fptr, &numkeys, NULL, status); + int cards_written = 4; for (nkey = 4; nkey <= numkeys; nkey++) /* skip the first few keywords */ { fits_read_record(fptr, nkey, card, status); + /* cfitsio(v4.2.0) manual: 10.2.3 Notes about the stream filetype driver + * stream:// driver has internal buffer NIOBUF=40 blocks e.g. 1400 cards + * TYP_COMM_KEY: skip HISTORY COMMENT and empty keys */ + if(numkeys > MAX_CARD_COUNT) + if (fits_get_keyclass(card) == TYP_COMM_KEY) continue; + if (fits_get_keyclass(card) > TYP_CMPRS_KEY) { + if(++cards_written > MAX_CARD_COUNT) return(HEADER_TOO_LONG); + /* write the record to the output file */ fits_write_record(newptr, card, status); }