/* $Id: irplib_utils.c,v 1.42 2007/05/23 12:48:38 jmlarsen Exp $ * * This file is part of the irplib package * Copyright (C) 2002,2003 European Southern Observatory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */ /* * $Author: jmlarsen $ * $Date: 2007/05/23 12:48:38 $ * $Revision: 1.42 $ * $Name: uves-3_3_1 $ */ #ifdef HAVE_CONFIG_H #include #endif /*----------------------------------------------------------------------------- Includes -----------------------------------------------------------------------------*/ #include #include #include #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(3, 1, 90) #else /* FIXME: Remove once support for CPL 3.1 is dropped */ #include #include #endif #include #include "irplib_utils.h" /*----------------------------------------------------------------------------*/ /** * @defgroup irplib_utils Miscellaneous Utilities */ /*----------------------------------------------------------------------------*/ /**@{*/ /*----------------------------------------------------------------------------*/ /** @brief Reset IRPLIB state This function resets all static memory used by IRPLIB to a well-defined, initial state. The function should be called (during initialization) by any application using static memory facilities in IRPLIB. Currently, this function resets the IRPLIB error state, including the @em cpl_error_code. */ /*----------------------------------------------------------------------------*/ void irplib_reset(void) { irplib_error_reset(); return; } /*----------------------------------------------------------------------------*/ /** @brief Comparison function to identify different input frames @param frame1 first frame @param frame2 second frame @return 0 if frame1!=frame2, 1 if frame1==frame2, -1 in error case */ /*----------------------------------------------------------------------------*/ int irplib_compare_tags( cpl_frame * frame1, cpl_frame * frame2) { char * v1 ; char * v2 ; /* Test entries */ if (frame1==NULL || frame2==NULL) return -1 ; /* Get the tags */ if ((v1 = (char*)cpl_frame_get_tag(frame1)) == NULL) return -1 ; if ((v2 = (char*)cpl_frame_get_tag(frame2)) == NULL) return -1 ; /* Compare the tags */ if (strcmp(v1, v2)) return 0 ; else return 1 ; } /*----------------------------------------------------------------------------*/ /** @brief Find the filename with the given tag in a frame set. @param self A frame set. @param tag The frame tag to search for. @return The filename or NULL if none found and on error. @see cpl_frameset_find @note If called with a CPL error code, the location will be updated and NULL returned. NULL is returned and no error code set if the tag is not found. If the file is not unique, the name of the first one is returned and with a warning. */ /*----------------------------------------------------------------------------*/ const char * irplib_frameset_find_file(const cpl_frameset * self, const char * tag) { const cpl_frame * frame = cpl_frameset_find(self, tag); cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL); if (frame == NULL) return NULL; if (cpl_frameset_find(self, NULL)) cpl_msg_warning(cpl_func, "Frameset has more than one file with tag: %s", tag); return cpl_frame_get_filename(frame); } /*----------------------------------------------------------------------------*/ /** @brief Find the first frame belonging to the given group @param self The frameset @param group The group attribute @return The first frame belonging to the given group, or @c NULL if no such frame was found. The function returns @c NULL if an error occurs and sets the appropriate error code. */ /*----------------------------------------------------------------------------*/ cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset * self, cpl_frame_group group) { cpl_frame * frame; cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL); for (frame = cpl_frameset_get_first(self); frame != NULL ; frame = cpl_frameset_get_next(self)) { if (cpl_frame_get_group(frame) == group) break; } return frame; } /*----------------------------------------------------------------------------*/ /** @brief Find the aperture(s) with the greatest flux @param self The aperture object @param ind The aperture-indices in order of decreasing flux @param nfind Number of indices to find @return CPL_ERROR_NONE or the relevant _cpl_error_code_ on error nfind must be at least 1 and at most the size of the aperture object. The ind array must be able to hold (at least) nfind integers. On success the first nfind elements of ind point to indices of the aperture object. To find the single ind of the aperture with the maximum flux use simply: int ind; irplib_apertures_find_max_flux(self, &ind, 1); */ /*----------------------------------------------------------------------------*/ cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures * self, int * ind, int nfind) { const int nsize = cpl_apertures_get_size(self); int ifind; cpl_ensure_code(nsize > 0, cpl_error_get_code()); cpl_ensure_code(ind, CPL_ERROR_NULL_INPUT); cpl_ensure_code(nfind > 0, CPL_ERROR_ILLEGAL_INPUT); cpl_ensure_code(nfind <= nsize, CPL_ERROR_ILLEGAL_INPUT); for (ifind=0; ifind < nfind; ifind++) { double maxflux = -1; int maxind = -1; int i; for (i=1; i <= nsize; i++) { int k; /* The flux has to be the highest among those not already found */ for (k=0; k < ifind; k++) if (ind[k] == i) break; if (k == ifind) { /* i has not been inserted into ind */ const double flux = cpl_apertures_get_flux(self, i); if (maxind < 0 || flux > maxflux) { maxind = i; maxflux = flux; } } } ind[ifind] = maxind; } return CPL_ERROR_NONE; } #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(3, 1, 90) #else /* FIXME: Remove once support for CPL 3.1 is dropped */ /*----------------------------------------------------------------------------*/ /** @brief Create a string and fill it using vsnprintf() @param format The format string @param arglist The argument list for the format @param argcopy The argument list for the format - again @return The created string or NULL on error @note The created string must be deallocated with cpl_free() @note This function may only be called via irplib_vsprintf() @see vsnprintf() Possible CPL error codes set in this function: - CPL_ERROR_NULL_INPUT if the format string is NULL - CPL_ERROR_ILLEGAL_INPUT if the format string has an invalid format */ /*----------------------------------------------------------------------------*/ char * irplib_vsprintf_macro(const char * format, va_list arglist, va_list argcopy) { char *self; int nlen = cx_vasprintf(&self, format, arglist); #if 0 char * self; size_t selfsize; int nlen; cpl_ensure(format != NULL, CPL_ERROR_NULL_INPUT, NULL); /* A guess at the necessary length of the string */ selfsize = 1 + strlen(format); self = (char*)cpl_malloc(selfsize); va_list a2; va_copy(a2, arglist); nlen = cx_vsnprintf(self, (cxsize)selfsize, format, a2); va_end(a2); nlen = cx_vsnprintf(self, (cxsize)selfsize, format, arglist); fprintf(stderr, "format = '%s' nlen = %d selfsize = %d\n", format, nlen, selfsize); { va_list aq; va_copy(aq, arglist); size_t self_longsize = 10*selfsize; char *self_long = cpl_malloc(self_longsize); int nlen_long = cx_vsnprintf(self_long, (cxsize)self_longsize, format, aq); va_end(aq); fprintf(stderr, "long = '%s' nlen = %d selfsize = %d\n", format, nlen_long, self_longsize); cpl_free(self_long); } /* The format string may be invalid */ if (nlen < 0) { cpl_free(self); cpl_ensure(0, CPL_ERROR_ILLEGAL_INPUT, NULL); } if (selfsize < 1 + (size_t)nlen) { /* self was too short, extend it */ cpl_free(self); /* The exact size of self */ selfsize = 1 + (size_t)nlen; self = (char*)cpl_malloc(selfsize); nlen = cx_vsnprintf(self, (cxsize)selfsize, format, argcopy); fprintf(stderr, "format = '%s' nlen = %d selfsize = %d\n", format, nlen, selfsize); assert( nlen > 0); assert( selfsize == 1 + (size_t)nlen); } else if (selfsize > 1 + (size_t)nlen) { /* self was too long, shorten it */ /* The exact size of self */ selfsize = 1 + (size_t)nlen; self = (char*)cpl_realloc((void*)self, selfsize); } assert(selfsize == 1 + strlen(self)); #endif /* The format string may be invalid */ if (nlen < 0) { cx_free(self); self = NULL; cpl_ensure(0, CPL_ERROR_ILLEGAL_INPUT, NULL); } return self; } /*----------------------------------------------------------------------------*/ /** @brief Create a new string by concatenation @param format The format string @param ... Variable argument list for format @return The allocated string with the concatenation or NULL on error @note The returned string must be deallocated with cpl_free() @see irplib_vsprintf() Example of usage: @code int error; char * cp_cmd = irplib_sprintf("cp %s %s/%s", long_file, new_dir, new_file); assert( cp_cmd != NULL); error = system(cp_cmd); assert(!error); cpl_free(cp_cmd); @endcode Possible CPL error codes set in this function: - CPL_ERROR_NULL_INPUT if the format string is NULL - CPL_ERROR_ILLEGAL_INPUT if the format string has an invalid format */ /*----------------------------------------------------------------------------*/ char * irplib_sprintf(const char * format, ...) { char * self; va_list arglist; va_list argcopy; cpl_ensure(format != NULL, CPL_ERROR_NULL_INPUT, NULL); va_start(arglist, format); va_start(argcopy, format); self = irplib_vsprintf_macro(format, arglist, argcopy); va_end(arglist); va_end(argcopy); cpl_ensure(self != NULL, cpl_error_get_code(), NULL); return self; } #endif /*----------------------------------------------------------------------------*/ /** @brief Find the smallest BITPIX usable for the given integer range @param minval The minimum pixel value in the integer image @param maxval The maximum pixel value in the integer image @return The smallest CPL BITPIX value usable with the given range @note If minval exceeds maxval a CPL error is set and the result is undefined @note When possible, CPL_BPP_16_SIGNED is preferred over CPL_BPP_16_UNSIGNED @see cpl_image_save() */ /*----------------------------------------------------------------------------*/ cpl_type_bpp irplib_bpp_find(int minval, int maxval) { cpl_type_bpp self = CPL_BPP_32_SIGNED; /* Default value */ cpl_ensure(minval <= maxval, CPL_ERROR_ILLEGAL_INPUT, self); if (0 <= minval) { if (maxval <= 255) { self = CPL_BPP_8_UNSIGNED; } else if (maxval <= 32767) { self = CPL_BPP_16_SIGNED; } else if (maxval <= 65535) { self = CPL_BPP_16_UNSIGNED; } } else if (-32768 <= minval && maxval <= 32767) { self = CPL_BPP_16_SIGNED; } return self; } /*----------------------------------------------------------------------------*/ /** @brief portable isinf */ /*----------------------------------------------------------------------------*/ int irplib_isinf(double value) { #if defined HAVE_ISINF && HAVE_ISINF return isinf(value); #else return value != 0 && value == 2 * value; #endif } /*----------------------------------------------------------------------------*/ /** @brief portable isnan */ /*----------------------------------------------------------------------------*/ int irplib_isnan(double value) { #if defined HAVE_ISNAN && HAVE_ISNAN return isnan(value); #else return value != value; #endif } /**@}*/