00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #ifdef HAVE_READLINK
00030 #define _BSD_SOURCE
00031 #include <unistd.h>
00032 #endif
00033 #include <cpl.h>
00034 #include <string.h>
00035 #include <math.h>
00036
00037 #include "muse_cplwrappers.h"
00038
00039
00040
00041
00042
00043 #define DEBUG_SQR 0
00044
00045
00055
00056
00059
00075
00076 cpl_error_code
00077 muse_cplimage_or(cpl_image *aTarget, const cpl_image *aImage, unsigned int mask)
00078 {
00079 cpl_ensure_code(aTarget && aImage, CPL_ERROR_NULL_INPUT);
00080 cpl_ensure_code(cpl_image_get_type(aTarget) == CPL_TYPE_INT,
00081 CPL_ERROR_INVALID_TYPE);
00082 cpl_ensure_code(cpl_image_get_type(aImage) == CPL_TYPE_INT,
00083 CPL_ERROR_INVALID_TYPE);
00084 cpl_ensure_code(cpl_image_get_size_x(aTarget) == cpl_image_get_size_x(aImage),
00085 CPL_ERROR_ILLEGAL_INPUT);
00086 cpl_ensure_code(cpl_image_get_size_y(aTarget) == cpl_image_get_size_y(aImage),
00087 CPL_ERROR_ILLEGAL_INPUT);
00088
00089 int *target = cpl_image_get_data_int(aTarget);
00090 const int *data = cpl_image_get_data_int_const(aImage);
00091 cpl_size nData = cpl_image_get_size_x(aImage) * cpl_image_get_size_y(aImage);
00092 cpl_size i;
00093 for (i = 0; i < nData; i++, data++, target++) {
00094 *target |= *data & mask;
00095 }
00096 return CPL_ERROR_NONE;
00097 }
00098
00099
00113
00114 cpl_image *
00115 muse_cplimage_concat_y(const cpl_image *aImage1, const cpl_image *aImage2)
00116 {
00117 cpl_ensure(aImage1 || aImage2, CPL_ERROR_NULL_INPUT, NULL);
00118 if (aImage1 == NULL) {
00119 return cpl_image_duplicate(aImage2);
00120 }
00121 if (aImage2 == NULL) {
00122 return cpl_image_duplicate(aImage1);
00123 }
00124 cpl_type type = cpl_image_get_type(aImage1);
00125 cpl_ensure(type == cpl_image_get_type(aImage2), CPL_ERROR_ILLEGAL_INPUT, NULL);
00126 cpl_size xsize = cpl_image_get_size_x(aImage1);
00127 cpl_ensure(xsize == cpl_image_get_size_x(aImage2), CPL_ERROR_ILLEGAL_INPUT, NULL);
00128
00129 cpl_size ysize1 = cpl_image_get_size_y(aImage1);
00130 cpl_size ysize2 = cpl_image_get_size_y(aImage2);
00131 cpl_image *res = cpl_image_new(xsize, ysize1 + ysize2, type);
00132 void *resdata = cpl_image_get_data(res);
00133 const void *data1 = cpl_image_get_data_const(aImage1);
00134 cpl_size size1 = xsize * ysize1 * cpl_type_get_sizeof(type);
00135 const void *data2 = cpl_image_get_data_const(aImage2);
00136 cpl_size size2 = xsize * ysize2 * cpl_type_get_sizeof(type);
00137 memcpy(resdata, data1, size1);
00138 memcpy((char *)resdata+size1, data2, size2);
00139
00140 return res;
00141 }
00142
00143
00157
00158 cpl_image *
00159 muse_cplimage_concat_x(const cpl_image *aImage1, const cpl_image *aImage2)
00160 {
00161 cpl_ensure(aImage1 || aImage2, CPL_ERROR_NULL_INPUT, NULL);
00162 if (aImage1 == NULL) {
00163 return cpl_image_duplicate(aImage2);
00164 }
00165 if (aImage2 == NULL) {
00166 return cpl_image_duplicate(aImage1);
00167 }
00168 cpl_type type = cpl_image_get_type(aImage1);
00169 cpl_ensure(type == cpl_image_get_type(aImage2), CPL_ERROR_ILLEGAL_INPUT, NULL);
00170 cpl_size ysize = cpl_image_get_size_y(aImage1);
00171 cpl_ensure(ysize == cpl_image_get_size_y(aImage2), CPL_ERROR_ILLEGAL_INPUT, NULL);
00172
00173 cpl_size xsize1 = cpl_image_get_size_x(aImage1);
00174 cpl_size xsize2 = cpl_image_get_size_x(aImage2);
00175 cpl_image *res = cpl_image_new(xsize1 + xsize2, ysize, type);
00176 void *resdata = cpl_image_get_data(res);
00177 const void *data1 = cpl_image_get_data_const(aImage1);
00178 cpl_size size1 = xsize1 * cpl_type_get_sizeof(type);
00179 const void *data2 = cpl_image_get_data_const(aImage2);
00180 cpl_size size2 = xsize2 * cpl_type_get_sizeof(type);
00181 cpl_size size = (size1 + size2) * ysize;
00182 cpl_size y, y3, y4;
00183 for (y = 0, y3 = 0, y4 = 0; y < size; y+=size1+size2, y3+=size1, y4+=size2) {
00184 memcpy((char *)resdata + y, (char *)data1 + y3, size1);
00185 memcpy((char *)resdata + y + size1, (char *)data2 + y4, size2);
00186 }
00187 return res;
00188 }
00189
00190
00201
00202 cpl_image *
00203 muse_cplimage_filter_median_subtract(cpl_image *aImage,
00204 unsigned int aNX, unsigned int aNY)
00205 {
00206 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
00207
00208 cpl_ensure((aNX & 1) && (aNY & 1), CPL_ERROR_ILLEGAL_INPUT, NULL);
00209
00210
00211 cpl_image *filtered = cpl_image_new(cpl_image_get_size_x(aImage),
00212 cpl_image_get_size_y(aImage),
00213 CPL_TYPE_FLOAT);
00214
00215 cpl_mask *mask = cpl_mask_new(aNX, aNY);
00216 cpl_mask_not(mask);
00217 cpl_errorstate prestate = cpl_errorstate_get();
00218 cpl_image_filter_mask(filtered, aImage, mask, CPL_FILTER_MEDIAN,
00219 CPL_BORDER_FILTER);
00220 if (!cpl_errorstate_is_equal(prestate)) {
00221 cpl_msg_error(__func__, "filtering failed: %s", cpl_error_get_message());
00222 cpl_mask_delete(mask);
00223 cpl_image_delete(filtered);
00224 return NULL;
00225 }
00226 cpl_mask_delete(mask);
00227
00228
00229 cpl_image *subtracted = cpl_image_subtract_create(aImage, filtered);
00230 cpl_image_delete(filtered);
00231
00232 return subtracted;
00233 }
00234
00235
00256
00257 cpl_vector *
00258 muse_cplimage_slope_window(const cpl_image *aImage, const cpl_size *aWindow)
00259 {
00260 cpl_ensure(aImage && aWindow, CPL_ERROR_NULL_INPUT, NULL);
00261
00262 cpl_image *image = cpl_image_duplicate(aImage);
00263 cpl_image_accept_all(image);
00264
00265 cpl_vector *slopes = cpl_vector_new(2);
00266 unsigned char k;
00267 for (k = 0; k <= 1; k++) {
00268
00269 cpl_image *coll = cpl_image_collapse_window_create(image,
00270 aWindow[0], aWindow[2],
00271 aWindow[1], aWindow[3],
00272 k);
00273 if (!coll) {
00274 cpl_image_delete(image);
00275 cpl_vector_delete(slopes);
00276 return NULL;
00277 }
00278
00279 if (k == 0) {
00280 cpl_image_divide_scalar(coll, aWindow[3] - aWindow[2] + 1);
00281 } else {
00282 cpl_image_divide_scalar(coll, aWindow[1] - aWindow[0] + 1);
00283 }
00284 int npx = k == 0 ? cpl_image_get_size_x(coll) : cpl_image_get_size_y(coll);
00285
00286 cpl_matrix *coords = cpl_matrix_new(1, npx);
00287 cpl_vector *values = cpl_vector_new(npx);
00288 float *data = cpl_image_get_data_float(coll);
00289 int i;
00290 for (i = 0; i < npx; i++) {
00291 cpl_matrix_set(coords, 0, i, i + 1);
00292
00293
00294 cpl_vector_set(values, i, data[i]);
00295 }
00296
00297 cpl_polynomial *fit = cpl_polynomial_new(1);
00298 const cpl_boolean sym = CPL_FALSE;
00299 const cpl_size mindeg = 0, maxdeg = 1;
00300 cpl_error_code err = cpl_polynomial_fit(fit, coords, &sym, values, NULL,
00301 CPL_FALSE, &mindeg, &maxdeg);
00302 cpl_matrix_delete(coords);
00303 cpl_vector_delete(values);
00304 cpl_image_delete(coll);
00305
00306 if (err != CPL_ERROR_NONE) {
00307 cpl_msg_warning(__func__, "Could not fit %s slope: %s",
00308 k == 0 ? "horizontal" : "vertical",
00309 cpl_error_get_message());
00310 cpl_polynomial_delete(fit);
00311 cpl_vector_delete(slopes);
00312 cpl_image_delete(image);
00313 return NULL;
00314 }
00315 #if 0
00316 printf("%s: fit (%s)\n", __func__, k == 0 ? "rows" : "cols");
00317 cpl_polynomial_dump(fit, stdout);
00318 fflush(stdout);
00319 #endif
00320 const cpl_size pows = { 1 };
00321 cpl_vector_set(slopes, k, cpl_polynomial_get_coeff(fit, &pows));
00322 cpl_polynomial_delete(fit);
00323 }
00324 cpl_image_delete(image);
00325 #if 0
00326 printf("slopes vector:\n");
00327 cpl_vector_dump(slopes, stdout);
00328 fflush(stdout);
00329 #endif
00330
00331 return slopes;
00332 }
00333
00334
00345
00346 double
00347 muse_cplimage_get_percentile(const cpl_image *aImage, double aFraction) {
00348 cpl_ensure(aImage != NULL, CPL_ERROR_NULL_INPUT, 0.0);
00349
00350 cpl_array *a = muse_cplarray_new_from_image(aImage);
00351 muse_cplarray_erase_invalid(a);
00352 cpl_size n = cpl_array_get_size(a);
00353 muse_cplarray_sort(a, TRUE);
00354 if (aFraction < 0) aFraction = 0;
00355 if (aFraction > 1) aFraction = 1;
00356 n = lround(n * aFraction);
00357 double res = cpl_array_get(a, n-1, NULL);
00358 cpl_array_delete(a);
00359 return res;
00360
00361 }
00362
00363
00377
00378 cpl_image *
00379 muse_cplimagelist_collapse_or_create(const cpl_imagelist *imlist)
00380 {
00381 cpl_ensure(imlist, CPL_ERROR_NULL_INPUT, NULL);
00382 int count = cpl_imagelist_get_size(imlist);
00383 cpl_ensure(count > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00384 cpl_image *res = cpl_image_duplicate(cpl_imagelist_get_const(imlist, 0));
00385 int i;
00386 unsigned int mask = 0xffffffff;
00387 for (i = 1; i < count; i++) {
00388 int r = muse_cplimage_or(res, cpl_imagelist_get_const(imlist, i), mask);
00389 if (r != CPL_ERROR_NONE) {
00390 cpl_image_delete(res);
00391 return NULL;
00392 }
00393 }
00394 return res;
00395 }
00396
00397
00414
00415 cpl_mask *
00416 muse_cplmask_adapt_to_image(const cpl_mask *aMask, const cpl_image *aImage)
00417 {
00418 cpl_ensure(aMask && aImage, CPL_ERROR_NULL_INPUT, NULL);
00419
00420
00421 enum corner { NONE = 0,
00422 BOTTOMLEFT = 1, BOTTOMRIGHT = 2,
00423 TOPRIGHT = 3, TOPLEFT = 4 };
00424 const char *cnames[] = { "none",
00425 "bottom left", "bottom right",
00426 "top right", "top left" };
00427 int nx = cpl_mask_get_size_x(aMask),
00428 ny = cpl_mask_get_size_y(aMask),
00429 nximage = cpl_image_get_size_x(aImage),
00430 nyimage = cpl_image_get_size_y(aImage),
00431 nmax = 0;
00432 enum corner nmaxcorner = NONE;
00433 int ncount = cpl_mask_count_window(aMask, 1, 1, nx/2, ny/2);
00434 if (ncount > nmax) {
00435 nmaxcorner = BOTTOMLEFT;
00436 nmax = ncount;
00437 }
00438 ncount = cpl_mask_count_window(aMask, nx/2, 1, nx, ny/2);
00439 if (ncount > nmax) {
00440 nmaxcorner = BOTTOMRIGHT;
00441 nmax = ncount;
00442 }
00443 ncount = cpl_mask_count_window(aMask, nx/2, ny/2, nx, ny);
00444 if (ncount > nmax) {
00445 nmaxcorner = TOPRIGHT;
00446 nmax = ncount;
00447 }
00448 ncount = cpl_mask_count_window(aMask, 1, ny/2, nx/2, ny);
00449 if (ncount > nmax) {
00450 nmaxcorner = TOPLEFT;
00451 nmax = ncount;
00452 }
00453 if (nmaxcorner == NONE) {
00454 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND, "No masked "
00455 "quadrant found, cannot adapt %dx%d mask to %dx%d "
00456 "image size!", nx, ny, nximage, nyimage);
00457 return NULL;
00458 }
00459 cpl_msg_debug(__func__, "Adapting %dx%d mask in %s quadrant (%d masked pixels)"
00460 " to %dx%d image", nx, ny, cnames[nmaxcorner], nmax,
00461 nximage, nyimage);
00462
00463 cpl_mask *xmask;
00464 switch (nmaxcorner) {
00465 case BOTTOMLEFT:
00466 xmask = cpl_mask_extract(aMask, 1, 1, nx/2, ny/2);
00467 break;
00468 case BOTTOMRIGHT:
00469 xmask = cpl_mask_extract(aMask, nx/2, 1, nx, ny/2);
00470 break;
00471 case TOPRIGHT:
00472 xmask = cpl_mask_extract(aMask, nx/2, ny/2, nx, ny);
00473 break;
00474 default:
00475 xmask = cpl_mask_extract(aMask, 1, ny/2, nx/2, ny);
00476 }
00477
00478 nx = cpl_mask_get_size_x(xmask);
00479 ny = cpl_mask_get_size_y(xmask);
00480
00481
00482 cpl_mask *outmask = cpl_mask_new(nximage, nyimage);
00483
00484 cpl_error_code rc = CPL_ERROR_NONE;
00485 switch (nmaxcorner) {
00486 case BOTTOMLEFT:
00487 rc = cpl_mask_copy(outmask, xmask, 1, 1);
00488 break;
00489 case BOTTOMRIGHT:
00490 rc = cpl_mask_copy(outmask, xmask, nximage - nx + 1, 1);
00491 break;
00492 case TOPRIGHT:
00493 rc = cpl_mask_copy(outmask, xmask, nximage - nx + 1, nyimage - ny + 1);
00494 break;
00495 default:
00496 rc = cpl_mask_copy(outmask, xmask, 1, nyimage - ny + 1);
00497 }
00498 cpl_mask_delete(xmask);
00499 if (rc != CPL_ERROR_NONE) {
00500 cpl_mask_delete(outmask);
00501 cpl_error_set_message(__func__, rc, "Could not copy %dx%d quadrant with "
00502 "masked region into new %dx%d mask", nx, ny,
00503 nximage, nyimage);
00504 return NULL;
00505 }
00506
00507 return outmask;
00508 }
00509
00510
00528
00529 cpl_matrix *
00530 muse_cplmatrix_multiply_create(const cpl_matrix *aMatrix1,
00531 const cpl_matrix *aMatrix2)
00532 {
00533 cpl_ensure(aMatrix1 && aMatrix2, CPL_ERROR_NULL_INPUT, NULL);
00534
00535 cpl_matrix *result = cpl_matrix_duplicate(aMatrix1);
00536
00537 if (cpl_matrix_multiply(result, aMatrix2) != CPL_ERROR_NONE) {
00538 cpl_error_set_where(__func__);
00539 cpl_matrix_delete(result);
00540 return NULL;
00541 }
00542 return result;
00543 }
00544
00545
00561
00562 cpl_array *
00563 muse_cplmatrix_where(const cpl_matrix *aMatrix, double aValue,
00564 muse_cplmatrix_element_compare_func aCondition)
00565 {
00566
00567 cpl_ensure(aMatrix, CPL_ERROR_NULL_INPUT, NULL);
00568 cpl_ensure(aCondition, CPL_ERROR_NULL_INPUT, NULL);
00569
00570 cpl_size i;
00571 cpl_size count = 0;
00572 cpl_size size = cpl_matrix_get_nrow(aMatrix) * cpl_matrix_get_ncol(aMatrix);
00573
00574 const double *mdata = cpl_matrix_get_data_const(aMatrix);
00575
00576 cpl_size *selection = cpl_malloc(size * sizeof *selection);
00577 cpl_size *_selection = selection;
00578
00579 for (i = 0; i < size; ++i) {
00580 if (aCondition(mdata[i], aValue)) {
00581 *_selection++ = i;
00582 ++count;
00583 }
00584 }
00585 cpl_array *where = cpl_array_new(count, CPL_TYPE_SIZE);
00586 cpl_array_copy_data_cplsize(where, selection);
00587 cpl_free(selection);
00588
00589 return where;
00590
00591 }
00592
00593
00613
00614 cpl_matrix *
00615 muse_cplmatrix_extract_selected(const cpl_matrix *aMatrix,
00616 const cpl_array *aIndices)
00617 {
00618 cpl_ensure(aMatrix, CPL_ERROR_NULL_INPUT, NULL);
00619 cpl_ensure(aIndices, CPL_ERROR_NULL_INPUT, NULL);
00620 cpl_ensure(cpl_array_get_type(aIndices) == CPL_TYPE_SIZE,
00621 CPL_ERROR_INVALID_TYPE, NULL);
00622
00623 cpl_size maxpos = cpl_matrix_get_nrow(aMatrix) * cpl_matrix_get_ncol(aMatrix);
00624 cpl_size sz = cpl_array_get_size(aIndices);
00625 cpl_matrix *subset = cpl_matrix_new(1, sz);
00626
00627 double *sdata = cpl_matrix_get_data(subset);
00628 const double *mdata = cpl_matrix_get_data_const(aMatrix);
00629 const cpl_size *idata = cpl_array_get_data_cplsize_const(aIndices);
00630
00631 cpl_size i;
00632 for (i = 0; i < sz; ++i) {
00633 if ((idata[i] >= 0) && (idata[i] < maxpos)) {
00634 *sdata++ = mdata[idata[i]];
00635 }
00636 }
00637 return subset;
00638 }
00639
00640
00649
00650 double
00651 muse_cplvector_get_adev_const(const cpl_vector *aVector, double aCenter)
00652 {
00653 cpl_ensure(aVector, CPL_ERROR_NULL_INPUT, 0.);
00654 double mdev = 0;
00655 cpl_size i, n = cpl_vector_get_size(aVector);
00656 for (i = 0; i < n; i++) {
00657 mdev += fabs(cpl_vector_get(aVector, i) - aCenter);
00658 }
00659 return mdev / (double)n;
00660 }
00661
00662
00675
00676 double
00677 muse_cplvector_get_median_dev(cpl_vector *aVector, double *aMedian)
00678 {
00679 cpl_ensure(aVector, CPL_ERROR_NULL_INPUT, 0.);
00680 double median = cpl_vector_get_median(aVector),
00681 mdev = 0.;
00682 cpl_size i, n = cpl_vector_get_size(aVector);
00683 for (i = 0; i < n; i++) {
00684 mdev += fabs(cpl_vector_get(aVector, i) - median);
00685 }
00686 if (aMedian) {
00687 *aMedian = median;
00688 }
00689 return mdev / (double)n;
00690 }
00691
00692
00706
00707 double
00708 muse_cplvector_get_semiquartile(cpl_vector *aVector)
00709 {
00710 double sqr = 0;
00711 double median = cpl_vector_get_median_const(aVector);
00712 cpl_vector *v = cpl_vector_duplicate(aVector), *v2;
00713 int i, splitindex = 0;
00714
00715 cpl_vector_sort(v, +1);
00716 #if DEBUG_SQR
00717 cpl_vector_dump(v, stdout);
00718 fflush(stdout);
00719 printf("median=%f%d\n", median);
00720 fflush(stdout);
00721 #endif
00722
00723 splitindex = cpl_vector_find(v, median);
00724
00725
00726 v2 = cpl_vector_new(cpl_vector_get_size(v) - splitindex - 1);
00727 #if DEBUG_SQR
00728 printf("Copying elements %d to %d\n", splitindex+1, cpl_vector_get_size(v)-1);
00729 #endif
00730 for (i = splitindex; i < cpl_vector_get_size(v); i++){
00731 #if DEBUG_SQR
00732 printf(" %d %f\n", i+1, cpl_vector_get(v, i));
00733 #endif
00734 cpl_vector_set(v2, i-splitindex, cpl_vector_get(v, i));
00735 }
00736 #if DEBUG_SQR
00737 printf("\n");
00738 fflush(stdout);
00739 #endif
00740 sqr = cpl_vector_get_median(v2);
00741 cpl_vector_delete(v2);
00742
00743
00744 v2 = cpl_vector_new(splitindex - 1);
00745 #if DEBUG_SQR
00746 printf("Copying elements %d to %d\n", 1, splitindex+1);
00747 #endif
00748 for (i = 0; i <= splitindex; i++) {
00749 #if DEBUG_SQR
00750 printf(" %d %f\n", i+1, cpl_vector_get(v, i));
00751 #endif
00752 cpl_vector_set(v2, i, cpl_vector_get(v, i));
00753 }
00754 #if DEBUG_SQR
00755 printf("\n");
00756 fflush(stdout);
00757 #endif
00758 sqr -= cpl_vector_get_median(v2);
00759 cpl_vector_delete(v2);
00760
00761 return sqr/2.0;
00762 }
00763
00764
00784
00785 cpl_error_code
00786 muse_cplvector_threshold(cpl_vector *aVec, double aLoCut, double aHiCut,
00787 double aLoVal, double aHiVal)
00788 {
00789 cpl_ensure_code(aVec, CPL_ERROR_NULL_INPUT);
00790 cpl_ensure_code(aLoCut <= aHiCut, CPL_ERROR_ILLEGAL_INPUT);
00791
00792 double *data = cpl_vector_get_data(aVec);
00793 int i, n = cpl_vector_get_size(aVec);
00794 for (i = 0; i < n; i++) {
00795 if (data[i] > aHiCut) {
00796 data[i] = aHiVal;
00797 } else if (data[i] < aLoCut) {
00798 data[i] = aLoVal;
00799 }
00800 }
00801
00802 return CPL_ERROR_NONE;
00803 }
00804
00805
00817
00818 cpl_error_code
00819 muse_cplvector_erase_element(cpl_vector *aVector, int aElement)
00820 {
00821 cpl_ensure_code(aVector, CPL_ERROR_NULL_INPUT);
00822 int size = cpl_vector_get_size(aVector);
00823 cpl_ensure_code(aElement >= 0 && aElement < size, CPL_ERROR_ILLEGAL_INPUT);
00824
00825 if (aElement < size - 1) {
00826
00827
00828 double *data = cpl_vector_get_data(aVector);
00829 memmove(&data[aElement], &data[aElement+1],
00830 (size-1 - aElement) * sizeof(double));
00831 }
00832
00833
00834 return cpl_vector_set_size(aVector, size - 1);
00835 }
00836
00837
00845
00846 cpl_size
00847 muse_cplvector_count_unique(const cpl_vector *aVector)
00848 {
00849 cpl_ensure(aVector, CPL_ERROR_NULL_INPUT, -1);
00850 cpl_vector *sorted = cpl_vector_duplicate(aVector);
00851 cpl_vector_sort(sorted, CPL_SORT_ASCENDING);
00852 double *data = cpl_vector_get_data(sorted);
00853 cpl_size i, n = cpl_vector_get_size(sorted),
00854 nunique = 1;
00855 for (i = 1; i < n; i++) {
00856 if (data[i] != data[i - 1]) {
00857 nunique++;
00858 }
00859 }
00860 cpl_vector_delete(sorted);
00861 return nunique;
00862 }
00863
00864
00872
00873 cpl_vector *
00874 muse_cplvector_get_unique(const cpl_vector *aVector)
00875 {
00876 cpl_ensure(aVector, CPL_ERROR_NULL_INPUT, NULL);
00877 cpl_vector *sorted = cpl_vector_duplicate(aVector);
00878 cpl_vector_sort(sorted, CPL_SORT_ASCENDING);
00879 double *data = cpl_vector_get_data(sorted);
00880 cpl_size i, n = cpl_vector_get_size(sorted),
00881 iunique = 0;
00882 cpl_vector *vunique = cpl_vector_new(n);
00883 cpl_vector_set(vunique, iunique++, data[0]);
00884 for (i = 1; i < n; i++) {
00885 if (data[i] != data[i - 1]) {
00886 cpl_vector_set(vunique, iunique++, data[i]);
00887 }
00888 }
00889 cpl_vector_delete(sorted);
00890 cpl_vector_set_size(vunique, iunique);
00891 return vunique;
00892 }
00893
00894
00904
00905 cpl_table *
00906 muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
00907 {
00908 cpl_ensure(aDef, CPL_ERROR_NULL_INPUT, NULL);
00909 cpl_table *res = cpl_table_new(aLength);
00910 for (; aDef->name != NULL; aDef++) {
00911 cpl_error_code rc = CPL_ERROR_NONE;
00912 if (aDef->type & CPL_TYPE_POINTER) {
00913 rc = cpl_table_new_column_array(res, aDef->name, aDef->type, 2);
00914 } else {
00915 rc = cpl_table_new_column(res, aDef->name, aDef->type);
00916 }
00917 if (rc != CPL_ERROR_NONE) {
00918 cpl_table_delete(res);
00919 return NULL;
00920 }
00921 if (aDef->unit != NULL) {
00922 if (cpl_table_set_column_unit(res, aDef->name,
00923 aDef->unit) != CPL_ERROR_NONE) {
00924 return NULL;
00925 }
00926 }
00927 if (aDef->format != NULL) {
00928 if (cpl_table_set_column_format(res, aDef->name,
00929 aDef->format) != CPL_ERROR_NONE) {
00930 return NULL;
00931 }
00932 }
00933 }
00934 return res;
00935 }
00936
00937
00949
00950 cpl_table *
00951 muse_cpltable_load(const char *aFile, const char *aExtension,
00952 const muse_cpltable_def aDefinition[])
00953 {
00954 int extension = cpl_fits_find_extension(aFile, aExtension);
00955 if (extension <= 0) {
00956 cpl_error_set_message(__func__, cpl_error_get_code(), "%s['%s']: "
00957 "extension not found by EXTNAME", aFile, aExtension);
00958 return NULL;
00959 }
00960 cpl_msg_debug(__func__, "Loading %s['%s'] from extension %d", aFile,
00961 aExtension, extension);
00962 cpl_table *tbl = cpl_table_load(aFile, extension, 1);
00963 if (muse_cpltable_check(tbl, aDefinition) != CPL_ERROR_NONE) {
00964 cpl_table_delete(tbl);
00965 return NULL;
00966 }
00967 return tbl;
00968 }
00969
00970
00987
00988 cpl_error_code
00989 muse_cpltable_append_file(const cpl_table *aTable, const char *aFile,
00990 const char *aExtension,
00991 const muse_cpltable_def aDefinition[]) {
00992 cpl_ensure_code(aTable != NULL, CPL_ERROR_NULL_INPUT);
00993 cpl_ensure_code(aFile != NULL, CPL_ERROR_NULL_INPUT);
00994 cpl_ensure_code(aExtension != NULL, CPL_ERROR_NULL_INPUT);
00995 cpl_error_code r = muse_cpltable_check(aTable, aDefinition);
00996 if (r != CPL_ERROR_NONE) {
00997 cpl_msg_error(__func__, " %s['%s'] Table format error", aFile, aExtension);
00998 cpl_error_set(__func__, r);
00999 return r;
01000 }
01001 cpl_propertylist *props = cpl_propertylist_new();
01002 cpl_propertylist_update_string(props, "EXTNAME", aExtension);
01003 r = cpl_table_save(aTable, NULL, props, aFile, CPL_IO_EXTEND);
01004 cpl_propertylist_delete(props);
01005 if (r != CPL_ERROR_NONE) {
01006 cpl_msg_error(__func__, "%s[%s]: %s", aFile, aExtension,
01007 cpl_error_get_message());
01008 }
01009 return r;
01010 }
01011
01012
01013
01019
01020 cpl_error_code
01021 muse_cpltable_check(const cpl_table *aTable, const muse_cpltable_def *aDef)
01022 {
01023 if (aTable == NULL) {
01024 cpl_msg_error(__func__, "NULL table");
01025 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
01026 return CPL_ERROR_NULL_INPUT;
01027 }
01028 if (aDef == NULL) {
01029 return CPL_ERROR_NONE;
01030 }
01031 cpl_error_code rc = CPL_ERROR_NONE;
01032 for (; aDef->name != NULL; aDef++) {
01033 if (!cpl_table_has_column(aTable, aDef->name)) {
01034 if (aDef->required) {
01035 rc = CPL_ERROR_ILLEGAL_INPUT;
01036 cpl_error_set_message(__func__, rc, "table column '%s' not found",
01037 aDef->name);
01038 }
01039 continue;
01040 }
01041 cpl_type coltype = cpl_table_get_column_type(aTable, aDef->name);
01042 if (((coltype | CPL_TYPE_POINTER) != (aDef->type | CPL_TYPE_POINTER)) ||
01043 ((coltype & CPL_TYPE_POINTER) && !(aDef->type & CPL_TYPE_POINTER))) {
01044 rc = CPL_ERROR_ILLEGAL_INPUT;
01045 cpl_error_set_message(__func__, rc,
01046 "table column '%s' format '%s' is not '%s'",
01047 aDef->name, cpl_type_get_name(coltype),
01048 cpl_type_get_name(aDef->type));
01049 }
01050 }
01051 return rc;
01052 }
01053
01054
01071
01072 cpl_array *
01073 muse_cpltable_extract_column(cpl_table *aTable, const char *aColumn)
01074 {
01075 cpl_ensure(aTable && aColumn, CPL_ERROR_NULL_INPUT, NULL);
01076 cpl_size nRows = cpl_table_get_nrow(aTable);
01077
01078 cpl_type type = cpl_table_get_column_type(aTable, aColumn);
01079 if (nRows == 0) {
01080 return cpl_array_new(0, type);
01081 }
01082 if (type == CPL_TYPE_DOUBLE) {
01083 double *src = cpl_table_get_data_double(aTable, aColumn);
01084 return cpl_array_wrap_double(src, nRows);
01085 } else if (type == CPL_TYPE_FLOAT) {
01086 float *src = cpl_table_get_data_float(aTable, aColumn);
01087 return cpl_array_wrap_float(src, nRows);
01088 } else if (type == CPL_TYPE_INT) {
01089 int *src = cpl_table_get_data_int(aTable, aColumn);
01090 return cpl_array_wrap_int(src, nRows);
01091 } else {
01092 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01093 cpl_msg_error(__func__, "%s: %i - %s", cpl_error_get_message(), type,
01094 cpl_type_get_name(type));
01095 return NULL;
01096 }
01097 }
01098
01099
01109
01110 cpl_error_code
01111 muse_cpltable_copy_array(cpl_table *aTable, const char *aColumn,
01112 const cpl_array *aArray)
01113 {
01114 cpl_ensure_code(aTable && aColumn && aArray, CPL_ERROR_NULL_INPUT);
01115 cpl_size n_rows = cpl_table_get_nrow(aTable);
01116 cpl_size i;
01117 for (i = 0; i < n_rows; i++) {
01118 int flag;
01119 double d = cpl_array_get(aArray, i, &flag);
01120 if (flag == 0) {
01121 cpl_table_set(aTable, aColumn, i, d);
01122 } else {
01123 cpl_table_set_invalid(aTable, aColumn, i);
01124 }
01125 }
01126 return CPL_ERROR_NONE;
01127 }
01128
01129
01139
01140 cpl_array *
01141 muse_cpltable_get_array_copy(cpl_table *aTable, const char *aColumn,
01142 cpl_size aRow)
01143 {
01144 cpl_ensure(aTable && aColumn, CPL_ERROR_NULL_INPUT, NULL);
01145 if (cpl_table_get_column_type(aTable, aColumn) & CPL_TYPE_POINTER) {
01146 return cpl_array_duplicate(cpl_table_get_array(aTable, aColumn, aRow));
01147 } else {
01148 cpl_array *res
01149 = cpl_array_new(1, cpl_table_get_column_type(aTable, aColumn));
01150 int flag;
01151 cpl_array_set(res, 0, cpl_table_get(aTable, aColumn, aRow, &flag));
01152 if (flag) {
01153 cpl_array_delete(res);
01154 return NULL;
01155 } else {
01156 return res;
01157 }
01158 }
01159 }
01160
01174
01175
01176 cpl_size
01177 muse_cpltable_find_sorted(const cpl_table *aTable, const char *aColumn,
01178 double aValue) {
01179 cpl_ensure(aTable && aColumn, CPL_ERROR_NULL_INPUT, 0);
01180 cpl_array *array = muse_cpltable_extract_column((cpl_table *)aTable, aColumn);
01181 cpl_size res = muse_cplarray_find_sorted(array, aValue);
01182 cpl_array_unwrap(array);
01183 return res;
01184 }
01185
01186
01194
01195 cpl_array *
01196 muse_cplarray_new_from_image(const cpl_image *aImage) {
01197 cpl_size nx = cpl_image_get_size_x(aImage);
01198 cpl_size ny = cpl_image_get_size_y(aImage);
01199 cpl_array *array = cpl_array_new(nx*ny, cpl_image_get_type(aImage));
01200 cpl_size i = 0;
01201 cpl_size iy;
01202 for (iy = 1; iy <= ny; iy++) {
01203 int ix;
01204 for (ix = 1; ix <= nx; ix++, i++) {
01205 int rej;
01206 double d = cpl_image_get(aImage, ix, iy, &rej);
01207 cpl_array_set(array, i, d);
01208 if (rej) {
01209 cpl_array_set_invalid(array, i);
01210 }
01211 }
01212 }
01213 return array;
01214 }
01215
01216
01229
01230 cpl_error_code
01231 muse_cplarray_poly1d(cpl_array *aArray, const cpl_array *aCoeff)
01232 {
01233 cpl_ensure_code(aArray && aCoeff, CPL_ERROR_NULL_INPUT);
01234 const cpl_size nrows = cpl_array_get_size(aArray);
01235 cpl_size order = cpl_array_get_size(aCoeff);
01236 if (order == 0) {
01237 cpl_array_fill_window(aArray, 0, nrows, 0.0);
01238 return CPL_ERROR_NONE;
01239 }
01240 order--;
01241 cpl_array *x = cpl_array_duplicate(aArray);
01242 cpl_array_fill_window(aArray, 0, nrows, cpl_array_get(aCoeff, order, NULL));
01243
01244 int k;
01245 for (k = order-1; k >= 0; k--) {
01246 cpl_array_multiply(aArray, x);
01247 cpl_array_add_scalar(aArray, cpl_array_get(aCoeff, k, NULL));
01248 }
01249
01250 cpl_array_delete(x);
01251
01252 return CPL_ERROR_NONE;
01253 }
01254
01255
01267
01268 double
01269 muse_cplarray_poly1d_double(double aDouble, const cpl_array *aCoeff)
01270 {
01271 cpl_ensure(aCoeff, CPL_ERROR_NULL_INPUT, NAN);
01272 cpl_size order = cpl_array_get_size(aCoeff);
01273 if (order == 0) {
01274 return 0.0;
01275 }
01276 order--;
01277 double res = cpl_array_get(aCoeff, order, NULL);
01278 int k;
01279 for (k = order-1; k >= 0; k--) {
01280 res = res * aDouble + cpl_array_get(aCoeff, k, NULL);
01281 }
01282 return res;
01283 }
01284
01285
01294
01295 cpl_error_code
01296 muse_cplarray_dump_name(const cpl_array *aArray, const char *aName)
01297 {
01298 cpl_ensure_code(aArray && aName, CPL_ERROR_NULL_INPUT);
01299 cpl_size i, size = cpl_array_get_size(aArray);
01300 for (i = 0; i < size; i++) {
01301 printf("%s[%"CPL_SIZE_FORMAT"] = %g\n", aName, i,
01302 cpl_array_get(aArray, i, NULL));
01303 }
01304 return CPL_ERROR_NONE;
01305 }
01306
01307
01313
01314 cpl_error_code
01315 muse_cplarray_erase_invalid(cpl_array *aArray)
01316 {
01317 cpl_ensure_code(aArray != NULL, CPL_ERROR_NULL_INPUT);
01318 cpl_size n = cpl_array_get_size(aArray);
01319 cpl_size n_val = n - cpl_array_count_invalid(aArray);
01320 #if 0
01321 cpl_msg_debug(__func__, "size = %li, %li valid", (long)n, (long)n_val);
01322 #endif
01323 if (n_val == n) {
01324 return CPL_ERROR_NONE;
01325 }
01326 cpl_size i;
01327 cpl_size idx = 0;
01328 for (i = 0; (i < n) && (idx < n_val); i++) {
01329 int rej;
01330 double d = cpl_array_get(aArray, i, &rej);
01331 if (!rej) {
01332 if (idx < i) {
01333 cpl_array_set(aArray, idx, d);
01334 }
01335 idx++;
01336 }
01337 }
01338 cpl_array_set_size(aArray, n_val);
01339 return CPL_ERROR_NONE;
01340 }
01341
01342
01357
01358 cpl_size
01359 muse_cplarray_erase_outliers(cpl_array *aArray, const cpl_bivector *aHistogram,
01360 cpl_size aGap, double aLimit)
01361 {
01362 cpl_ensure(aArray && aHistogram, CPL_ERROR_NULL_INPUT, -1);
01363
01364 int err;
01365 double value = cpl_array_get(aArray, 0, &err);
01366 cpl_ensure(err >= 0, CPL_ERROR_ILLEGAL_INPUT, -2);
01367
01368
01369 const double *hpos = cpl_bivector_get_x_data_const(aHistogram),
01370 *hval = cpl_bivector_get_y_data_const(aHistogram);
01371 cpl_size nhist = cpl_bivector_get_size(aHistogram);
01372 cpl_array *ahist = cpl_array_wrap_double((double *)hval, nhist);
01373 cpl_size imax;
01374 cpl_array_get_maxpos(ahist, &imax);
01375 cpl_array_unwrap(ahist);
01376
01377
01378 double loval = hpos[0],
01379 hival = hpos[nhist - 1];
01380 cpl_size i, nlow = 0;
01381 for (i = imax; i >= 0; i--) {
01382 if (hval[i] <= aLimit) {
01383 if (nlow == 0) {
01384 loval = hpos[i];
01385 }
01386 nlow++;
01387 if (nlow == aGap) {
01388 break;
01389 }
01390 } else if (nlow > 0) {
01391 nlow = 0;
01392 loval = hpos[0];
01393 }
01394 }
01395
01396 for (i = imax; i < nhist; i++) {
01397 if (hval[i] <= aLimit) {
01398 if (nlow == 0) {
01399 hival = hpos[i];
01400 }
01401 nlow++;
01402 if (nlow == aGap) {
01403 break;
01404 }
01405 } else if (nlow > 0) {
01406 nlow = 0;
01407 hival = hpos[nhist - 1];
01408 }
01409 }
01410 cpl_msg_debug(__func__, "Histogram gaps (%"CPL_SIZE_FORMAT" consecutive "
01411 "entries <= %f) at %f and %f", aGap, aLimit, loval, hival);
01412
01413
01414
01415 cpl_size idx, narray = cpl_array_get_size(aArray);
01416 for (idx = 0; idx < narray; idx++) {
01417 value = cpl_array_get(aArray, idx, NULL);
01418 if (value > hival || value < loval) {
01419 cpl_array_set_invalid(aArray, idx);
01420 }
01421 }
01422
01423
01424 cpl_size nbad = cpl_array_count_invalid(aArray);
01425 muse_cplarray_erase_invalid(aArray);
01426 return nbad;
01427 }
01428
01429
01430
01431
01432
01434 static int cmp_double_asc(const void *p1, const void *p2) {
01435 double d = (*(const double *)p1 - *(const double *)p2);
01436 return (d < 0)?-1:(d>0)?1:0;
01437 }
01439 static int cmp_double_desc(const void *p1, const void *p2) {
01440 double d = (*(const double *)p1 - *(const double *)p2);
01441 return (d < 0)?1:(d>0)?-1:0;
01442 }
01444 static int cmp_float_asc(const void *p1, const void *p2) {
01445 float d = (*(const float *)p1 - *(const float *)p2);
01446 return (d < 0)?-1:(d>0)?1:0;
01447 }
01449 static int cmp_float_desc(const void *p1, const void *p2) {
01450 float d = (*(const float *)p1 - *(const float *)p2);
01451 return (d < 0)?1:(d>0)?-1:0;
01452 }
01454 static int cmp_int_asc(const void *p1, const void *p2) {
01455 return (*(const int *)p1 - *(const int *)p2);
01456 }
01458 static int cmp_int_desc(const void *p1, const void *p2) {
01459 return (*(const int *)p2 - *(const int *)p1);
01460 }
01461
01463 static int cmp_long_asc(const void *p1, const void *p2) {
01464 return (*(const long *)p1 - *(const long *)p2);
01465 }
01467 static int cmp_long_desc(const void *p1, const void *p2) {
01468 return (*(const long *)p2 - *(const long *)p1);
01469 }
01470
01472 static int cmp_string_asc(const void *p1, const void *p2) {
01473 return strcmp(*(const char **)p1, *(const char **)p2);
01474 }
01476 static int cmp_string_desc(const void *p1, const void *p2) {
01477 return strcmp(*(const char **)p2, *(const char **)p1);
01478 }
01479
01480
01490
01491 cpl_error_code
01492 muse_cplarray_sort(cpl_array *aArray, cpl_boolean aOrder)
01493 {
01494 cpl_ensure_code(aArray != NULL, CPL_ERROR_NULL_INPUT);
01495 cpl_ensure_code(!cpl_array_has_invalid(aArray), CPL_ERROR_NULL_INPUT);
01496
01497 cpl_size n = cpl_array_get_size(aArray);
01498 if (cpl_array_get_type(aArray) == CPL_TYPE_DOUBLE) {
01499 double *d = cpl_array_get_data_double(aArray);
01500 qsort(d, n, sizeof(double), (aOrder)?cmp_double_asc:cmp_double_desc);
01501 return CPL_ERROR_NONE;
01502 } else if (cpl_array_get_type(aArray) == CPL_TYPE_FLOAT) {
01503 float *d = cpl_array_get_data_float(aArray);
01504 qsort(d, n, sizeof(float), (aOrder)?cmp_float_asc:cmp_float_desc);
01505 return CPL_ERROR_NONE;
01506 } else if (cpl_array_get_type(aArray) == CPL_TYPE_INT) {
01507 int *d = cpl_array_get_data_int(aArray);
01508 qsort(d, n, sizeof(int), (aOrder)?cmp_int_asc:cmp_int_desc);
01509 return CPL_ERROR_NONE;
01510 } else if (cpl_array_get_type(aArray) == CPL_TYPE_LONG) {
01511 long *d = cpl_array_get_data_long(aArray);
01512 qsort(d, n, sizeof(long), (aOrder)?cmp_long_asc:cmp_long_desc);
01513 return CPL_ERROR_NONE;
01514 } else if (cpl_array_get_type(aArray) == CPL_TYPE_STRING) {
01515 char **d = cpl_array_get_data_string(aArray);
01516 qsort(d, n, sizeof(char *), (aOrder)?cmp_string_asc:cmp_string_desc);
01517 return CPL_ERROR_NONE;
01518 } else {
01519 return CPL_ERROR_ILLEGAL_INPUT;
01520 }
01521 }
01522
01523
01542
01543 cpl_bivector *
01544 muse_cplarray_histogram(const cpl_array *aArray, double aWidth,
01545 double aMin, double aMax)
01546 {
01547 cpl_ensure(aArray, CPL_ERROR_NULL_INPUT, NULL);
01548
01549 int err;
01550 double value = cpl_array_get(aArray, 0, &err);
01551 cpl_ensure(err >= 0, CPL_ERROR_INVALID_TYPE, NULL);
01552 if (!isnan(aMin) && !isnan(aMax) && aMin >= aMax) {
01553 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01554 return NULL;
01555 }
01556 if (isnan(aMin)) {
01557 aMin = cpl_array_get_min(aArray);
01558 }
01559 if (isnan(aMax)) {
01560 aMax = cpl_array_get_max(aArray);
01561 }
01562 cpl_size hlen = lround((aMax - aMin) / aWidth) + 1;
01563 cpl_bivector *histogram = cpl_bivector_new(hlen);
01564
01565
01566 double *hpos = cpl_bivector_get_x_data(histogram);
01567 cpl_size i;
01568 for (i = 0; i < hlen; i++) {
01569 hpos[i] = i * aWidth + aMin;
01570 }
01571
01572
01573 double *hval = cpl_bivector_get_y_data(histogram);
01574
01575 cpl_vector_fill(cpl_bivector_get_y(histogram), 0.);
01576 cpl_size n = cpl_array_get_size(aArray);
01577 for (i = 0; i < n; i++) {
01578 value = cpl_array_get(aArray, i, &err);
01579 if (err) {
01580 continue;
01581 }
01582
01583 cpl_size idx = lround((value - aMin) / aWidth);
01584 if (idx >= hlen || idx < 0) {
01585 continue;
01586 }
01587
01588 hval[idx] += 1;
01589 }
01590 #if 0
01591 printf("histogram %f...%f / %f\n", aMin, aMax, aWidth);
01592 cpl_bivector_dump(histogram, stdout);
01593 fflush(stdout);
01594 #endif
01595 return histogram;
01596 }
01597
01598
01611
01612 cpl_size
01613 muse_cplarray_find_sorted(const cpl_array *aArray, double aValue)
01614 {
01615 cpl_ensure(aArray, CPL_ERROR_NULL_INPUT, 0);
01616 cpl_size min = 0;
01617 cpl_size max = cpl_array_get_size(aArray);
01618 cpl_type type = cpl_array_get_type(aArray);
01619 if (type == CPL_TYPE_DOUBLE) {
01620 const double *data = cpl_array_get_data_double_const(aArray);
01621 while (max - min > 1) {
01622 int i = (max + min)/2;
01623 if (data[i] > aValue) {
01624 max = i;
01625 } else {
01626 min = i;
01627 }
01628 }
01629 } else if (type == CPL_TYPE_FLOAT) {
01630 const float *data = cpl_array_get_data_float_const(aArray);
01631 while (max - min > 1) {
01632 int i = (max + min)/2;
01633 if (data[i] > aValue) {
01634 max = i;
01635 } else {
01636 min = i;
01637 }
01638 }
01639 } else if (type == CPL_TYPE_INT) {
01640 const int *data = cpl_array_get_data_int_const(aArray);
01641 while (max - min > 1) {
01642 int i = (max + min)/2;
01643 if (data[i] > aValue) {
01644 max = i;
01645 } else {
01646 min = i;
01647 }
01648 }
01649 } else {
01650 cpl_msg_error(__func__, "illegal type %i", type);
01651 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01652 return 0;
01653 }
01654 return min;
01655 }
01656
01657
01672
01673 cpl_boolean
01674 muse_cplarray_has_duplicate(const cpl_array *aArray)
01675 {
01676 cpl_ensure(aArray, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01677 cpl_type type = cpl_array_get_type(aArray);
01678 switch (type) {
01679 case CPL_TYPE_INT:
01680 case CPL_TYPE_LONG:
01681 case CPL_TYPE_LONG_LONG:
01682 case CPL_TYPE_SIZE:
01683 break;
01684 default:
01685 cpl_error_set(__func__, CPL_ERROR_UNSUPPORTED_MODE);
01686 return CPL_FALSE;
01687 }
01688
01689 cpl_size idx, n = cpl_array_get_size(aArray);
01690 for (idx = 0; idx < n - 1; idx++) {
01691 int err;
01692 cpl_size v1 = cpl_array_get(aArray, idx, &err);
01693 if (err) {
01694 continue;
01695 }
01696 cpl_size idx2;
01697 for (idx2 = idx + 1; idx2 < n; idx2++) {
01698 cpl_size v2 = cpl_array_get(aArray, idx2, &err);
01699 if (err) {
01700 continue;
01701 }
01702 if (v2 == v1) {
01703 #if 0
01704 cpl_msg_debug(__func__, "entry[%"CPL_SIZE_FORMAT"] == entry[%"
01705 CPL_SIZE_FORMAT"] == %"CPL_SIZE_FORMAT, idx, idx2, v1);
01706 #endif
01707 return CPL_TRUE;
01708 }
01709 }
01710 }
01711 return CPL_FALSE;
01712 }
01713
01714
01727
01728 cpl_array *
01729 muse_cplarray_extract(cpl_array *aArray, cpl_size aStart, cpl_size aCount)
01730 {
01731 cpl_size nrows = cpl_array_get_size(aArray);
01732 if (aCount > nrows - aStart) {
01733 aCount = nrows - aStart;
01734 }
01735 cpl_type type = cpl_array_get_type(aArray);
01736 if (type == CPL_TYPE_DOUBLE) {
01737 return cpl_array_wrap_double(cpl_array_get_data_double(aArray) + aStart,
01738 aCount);
01739 } else if (type == CPL_TYPE_FLOAT) {
01740 return cpl_array_wrap_float(cpl_array_get_data_float(aArray) + aStart,
01741 aCount);
01742 } else if (type == CPL_TYPE_INT) {
01743 return cpl_array_wrap_int(cpl_array_get_data_int(aArray) + aStart,
01744 aCount);
01745 } else {
01746 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01747 return NULL;
01748 }
01749 }
01750
01764
01765 cpl_error_code
01766 muse_cplarray_add_window(cpl_array *aDest, cpl_size aStart,
01767 const cpl_array *aArray)
01768 {
01769 cpl_ensure_code(aDest && aArray, CPL_ERROR_NULL_INPUT);
01770 cpl_size count = cpl_array_get_size(aArray);
01771 cpl_array *destArray = muse_cplarray_extract(aDest, aStart, count);
01772 if (destArray == NULL) {
01773 return CPL_ERROR_ILLEGAL_INPUT;
01774 }
01775 cpl_array_add(destArray, aArray);
01776 cpl_array_unwrap(destArray);
01777
01778 return CPL_ERROR_NONE;
01779 }
01780
01781
01791
01792 cpl_array *
01793 muse_cplarray_diff(const cpl_array *aArray, int aOffset)
01794 {
01795 cpl_ensure(aArray, CPL_ERROR_NULL_INPUT, NULL);
01796 cpl_ensure(aOffset > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
01797 cpl_size nrows = cpl_array_get_size(aArray);
01798
01799 cpl_array *a1 = cpl_array_extract(aArray, 0, nrows - aOffset);
01800 cpl_array *a2 = cpl_array_extract(aArray, aOffset, nrows - aOffset);
01801 if (a1 == NULL || a2 == NULL) {
01802 cpl_array_delete(a1);
01803 cpl_array_delete(a2);
01804 return NULL;
01805 }
01806 cpl_array_subtract(a2, a1);
01807 cpl_array_delete(a1);
01808 return a2;
01809 }
01810
01811
01824
01825 cpl_error_code
01826 muse_cplarray_erf(cpl_array *aArray)
01827 {
01828 cpl_ensure_code(aArray, CPL_ERROR_NULL_INPUT);
01829 cpl_type type = cpl_array_get_type(aArray);
01830 cpl_size n = cpl_array_get_size(aArray);
01831 if (type == CPL_TYPE_DOUBLE) {
01832 double *d = cpl_array_get_data_double(aArray);
01833 cpl_size i;
01834 for (i = 0; i < n; i++, d++) {
01835 *d = erf(*d);
01836 }
01837 } else if (type == CPL_TYPE_FLOAT) {
01838 float *d = cpl_array_get_data_float(aArray);
01839 cpl_size i;
01840 for (i = 0; i < n; i++, d++) {
01841 *d = erf(*d);
01842 }
01843 } else {
01844 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01845 return CPL_ERROR_ILLEGAL_INPUT;
01846 }
01847 return CPL_ERROR_NONE;
01848 }
01849
01850
01863
01864 cpl_error_code
01865 muse_cplarray_exp(cpl_array *aArray)
01866 {
01867 cpl_ensure_code(aArray, CPL_ERROR_NULL_INPUT);
01868 cpl_type type = cpl_array_get_type(aArray);
01869 cpl_size n = cpl_array_get_size(aArray);
01870 if (type == CPL_TYPE_DOUBLE) {
01871 double *d = cpl_array_get_data_double(aArray);
01872 cpl_size i;
01873 for (i = 0; i < n; i++, d++) {
01874 *d = exp(*d);
01875 }
01876 } else if (type == CPL_TYPE_FLOAT) {
01877 float *d = cpl_array_get_data_float(aArray);
01878 cpl_size i;
01879 for (i = 0; i < n; i++, d++) {
01880 *d = expf(*d);
01881 }
01882 } else {
01883 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
01884 return CPL_ERROR_ILLEGAL_INPUT;
01885 }
01886 return CPL_ERROR_NONE;
01887 }
01888
01889
01913
01914 cpl_array *
01915 muse_cplarray_interpolate_linear(const cpl_array *aTargetAbscissa,
01916 const cpl_array *aSourceAbscissa,
01917 const cpl_array *aSourceOrdinate)
01918 {
01919 cpl_ensure(aTargetAbscissa && aSourceAbscissa && aSourceOrdinate,
01920 CPL_ERROR_NULL_INPUT, NULL);
01921
01922 double *targetX = cpl_array_get_data_double((cpl_array *)aTargetAbscissa);
01923 double *srcX = cpl_array_get_data_double((cpl_array *)aSourceAbscissa);
01924 double *srcY = cpl_array_get_data_double((cpl_array *)aSourceOrdinate);
01925 cpl_ensure(targetX && srcX && srcY, CPL_ERROR_ILLEGAL_INPUT, NULL);
01926
01927 cpl_array *targetOrdinate = cpl_array_duplicate(aTargetAbscissa);
01928 double *targetY = cpl_array_get_data_double(targetOrdinate);
01929
01930 cpl_size n_src = cpl_array_get_size(aSourceAbscissa);
01931 cpl_vector *srcX_vec = cpl_vector_wrap(n_src, srcX);
01932 cpl_vector *srcY_vec = cpl_vector_wrap(n_src, srcY);
01933 cpl_bivector *src_vec = cpl_bivector_wrap_vectors(srcX_vec, srcY_vec);
01934
01935 cpl_size offset = (srcX[0] <= targetX[0])?0:
01936 muse_cplarray_find_sorted(aTargetAbscissa, srcX[0]) + 1;
01937 cpl_size n_target =
01938 muse_cplarray_find_sorted(aTargetAbscissa, srcX[n_src-1]) - offset + 1;
01939
01940 cpl_vector *targetX_vec = cpl_vector_wrap(n_target, targetX + offset);
01941 cpl_vector *targetY_vec = cpl_vector_wrap(n_target, targetY + offset);
01942 cpl_bivector *target_vec = cpl_bivector_wrap_vectors(targetX_vec,
01943 targetY_vec);
01944 if (offset > 0) {
01945 cpl_array_fill_window_invalid(targetOrdinate, 0, offset);
01946 }
01947 if (offset + n_target < (unsigned)cpl_array_get_size(targetOrdinate)) {
01948 cpl_array_fill_window_invalid(targetOrdinate, offset + n_target,
01949 cpl_array_get_size(targetOrdinate)
01950 - (offset + n_target));
01951 }
01952 cpl_bivector_interpolate_linear(target_vec, src_vec);
01953 cpl_bivector_unwrap_vectors(target_vec);
01954 cpl_vector_unwrap(targetX_vec);
01955 cpl_vector_unwrap(targetY_vec);
01956 cpl_bivector_unwrap_vectors(src_vec);
01957 cpl_vector_unwrap(srcX_vec);
01958 cpl_vector_unwrap(srcY_vec);
01959
01960 return targetOrdinate;
01961 }
01962
01963
01982
01983 cpl_array *
01984 muse_cplarray_interpolate_table_linear(const cpl_array *aTargetAbscissa,
01985 const cpl_table *aSrcTable,
01986 const char *aSrcAbscissa,
01987 const char *aSrcOrdinate)
01988 {
01989 cpl_array *sabs = muse_cpltable_extract_column((cpl_table *)aSrcTable,
01990 aSrcAbscissa);
01991 cpl_array *sord = muse_cpltable_extract_column((cpl_table *)aSrcTable,
01992 aSrcOrdinate);
01993 cpl_array *ord = muse_cplarray_interpolate_linear(aTargetAbscissa, sabs, sord);
01994 cpl_array_unwrap(sabs);
01995 cpl_array_unwrap(sord);
01996 return ord;
01997 }
01998
01999
02013
02014 cpl_array *
02015 muse_cplarray_new_from_delimited_string(const char *aString, const char *aDelim)
02016 {
02017 cpl_ensure(aString && aDelim, CPL_ERROR_NULL_INPUT, NULL);
02018
02019 char *string = cpl_strdup(aString);
02020
02021
02022 char *prev = string, *next;
02023 cpl_array *out = cpl_array_new(0, CPL_TYPE_STRING);
02024 int ntok = 0;
02025 do {
02026 next = strstr(prev, aDelim);
02027 if (next) {
02028 *next = '\0';
02029 }
02030 if (strlen(prev)) {
02031 cpl_array_set_size(out, ++ntok);
02032 cpl_array_set_string(out, ntok - 1, prev);
02033 }
02034 prev = next + strlen(aDelim);
02035 } while (next);
02036 cpl_free(string);
02037
02038 #if 0
02039 printf("Input string %s and delimiter %s resulted in output\n",
02040 aString, aDelim);
02041 cpl_array_dump(out, 0, cpl_array_get_size(out), stdout);
02042 fflush(stdout);
02043 #endif
02044 return out;
02045 }
02046
02047
02062
02063 cpl_array *
02064 muse_cplarray_string_to_double(const cpl_array *aArray)
02065 {
02066 cpl_ensure(aArray, CPL_ERROR_NULL_INPUT, NULL);
02067 cpl_ensure(cpl_array_get_type(aArray) == CPL_TYPE_STRING,
02068 CPL_ERROR_ILLEGAL_INPUT, NULL);
02069
02070 cpl_size i, n = cpl_array_get_size(aArray);
02071 cpl_array *darray = cpl_array_new(n, CPL_TYPE_DOUBLE);
02072 for (i = 0; i < n; i++) {
02073 const char *string = cpl_array_get_string(aArray, i);
02074 if (!string) {
02075 continue;
02076 }
02077 cpl_array_set_double(darray, i, atof(string));
02078 }
02079 return darray;
02080 }
02081
02082
02096
02097 cpl_parameter *
02098 muse_cplparamerterlist_find_prefix(cpl_parameterlist *aParameters,
02099 const char *aPrefix, const char *aName)
02100 {
02101 char *fullname = cpl_sprintf("%s.%s", aPrefix, aName);
02102 cpl_parameter *p = cpl_parameterlist_find(aParameters, fullname);
02103 cpl_free(fullname);
02104 return p;
02105 }
02106
02107
02132
02133 cpl_parameterlist *
02134 muse_cplparameterlist_from_propertylist(const cpl_propertylist *aHeader,
02135 int aRecNum)
02136 {
02137 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
02138 cpl_ensure(aRecNum > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
02139
02140
02141 char *kw = cpl_sprintf("ESO PRO REC%d ID", aRecNum);
02142 const char *recipe = cpl_propertylist_get_string(aHeader, kw);
02143 cpl_free(kw);
02144 cpl_ensure(recipe, CPL_ERROR_ILLEGAL_INPUT, NULL);
02145
02146 kw = cpl_sprintf("ESO PRO REC%d PIPE ID", aRecNum);
02147 const char *pipeid = cpl_propertylist_get_string(aHeader, kw);
02148 cpl_free(kw);
02149 cpl_ensure(strstr(recipe, "muse_") && strstr(pipeid, "muse"),
02150 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
02151 char *context = cpl_sprintf("muse.%s", recipe);
02152
02153
02154 cpl_parameterlist *parlist = cpl_parameterlist_new();
02155 int npar;
02156 for (npar = 1; npar < cpl_propertylist_get_size(aHeader); npar++) {
02157 char *kwname = cpl_sprintf("ESO PRO REC%d PARAM%d NAME", aRecNum, npar),
02158 *kwvalue = cpl_sprintf("ESO PRO REC%d PARAM%d VALUE", aRecNum, npar);
02159 if (!cpl_propertylist_has(aHeader, kwname) ||
02160 !cpl_propertylist_has(aHeader, kwvalue)) {
02161 cpl_free(kwname);
02162 cpl_free(kwvalue);
02163 break;
02164 }
02165 const cpl_property *prop = cpl_propertylist_get_property_const(aHeader,
02166 kwvalue);
02167
02168
02169 const char *value = cpl_property_get_string(prop);
02170 cpl_type type = CPL_TYPE_STRING;
02171 if (!strncmp(value, "true", 5) || !strncmp(value, "false", 6)) {
02172 type = CPL_TYPE_BOOL;
02173 } else if (!strchr(value, ',') &&
02174 ((value[0] >= '0' && value[0] <= '9') ||
02175 value[0] == '-' || value[0] == '+')) {
02176
02177 if (strchr(value, '.') || strchr(value, 'E')) {
02178 type = CPL_TYPE_DOUBLE;
02179 } else {
02180 type = CPL_TYPE_INT;
02181 }
02182 }
02183 char *parname = cpl_sprintf("muse.%s.%s", recipe,
02184 cpl_propertylist_get_string(aHeader, kwname));
02185 const char *comment = cpl_property_get_comment(prop),
02186 *comname = cpl_propertylist_get_comment(aHeader, kwname);
02187 char defstr[41] = "true";
02188 if (comment) {
02189 sscanf(comment, "Default: %40s", defstr);
02190 }
02191 cpl_parameter *par = NULL;
02192 switch (type) {
02193 case CPL_TYPE_BOOL:
02194 par = cpl_parameter_new_value(parname, type, comname, context,
02195 !strncmp(defstr, "true", 5) ? CPL_TRUE : CPL_FALSE);
02196 if (!strncmp(value, "true", 5)) {
02197 cpl_parameter_set_bool(par, CPL_TRUE);
02198 } else {
02199 cpl_parameter_set_bool(par, CPL_FALSE);
02200 }
02201 break;
02202 case CPL_TYPE_INT:
02203 par = cpl_parameter_new_value(parname, type, comname, context, atoi(defstr));
02204 cpl_parameter_set_int(par, atoi(value));
02205 break;
02206 case CPL_TYPE_DOUBLE:
02207 par = cpl_parameter_new_value(parname, type, comname, context, atof(defstr));
02208 cpl_parameter_set_double(par, atof(value));
02209 break;
02210 case CPL_TYPE_STRING:
02211 par = cpl_parameter_new_value(parname, type, comname, context, defstr);
02212 cpl_parameter_set_string(par, value);
02213 break;
02214 default:
02215
02216 par = cpl_parameter_new_value(parname, type, comname, context, 0);
02217 cpl_msg_warning(__func__, "property of type %s (%d) found!",
02218 cpl_type_get_name(type), type);
02219 }
02220 cpl_parameterlist_append(parlist, par);
02221 cpl_free(parname);
02222 cpl_free(kwname);
02223 cpl_free(kwvalue);
02224 }
02225 cpl_free(context);
02226 return parlist;
02227 }
02228
02229
02241
02242 cpl_parameterlist *
02243 muse_cplparameterlist_duplicate(const cpl_parameterlist *aPList)
02244 {
02245 cpl_ensure(aPList, CPL_ERROR_NULL_INPUT, NULL);
02246
02247 cpl_parameterlist *list = cpl_parameterlist_new();
02248 const cpl_parameter *par = cpl_parameterlist_get_first_const(aPList);
02249 while (par) {
02250 cpl_parameterlist_append(list, cpl_parameter_duplicate(par));
02251 par = cpl_parameterlist_get_next_const(aPList);
02252 }
02253 return list;
02254 }
02255
02256
02274
02275 cpl_error_code
02276 muse_cplpropertylist_update_long_long(cpl_propertylist *aHeader,
02277 const char *aKeyword, cpl_size aValue)
02278 {
02279 cpl_ensure_code(aHeader && aKeyword, CPL_ERROR_NULL_INPUT);
02280 cpl_property *p = cpl_propertylist_get_property(aHeader, aKeyword);
02281 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
02282 cpl_error_code rc = CPL_ERROR_NONE;
02283 switch (cpl_property_get_type(p)) {
02284 case CPL_TYPE_LONG_LONG:
02285 rc = cpl_property_set_long_long(p, aValue);
02286 break;
02287 case CPL_TYPE_LONG:
02288 rc = cpl_property_set_long(p, aValue);
02289 break;
02290 default:
02291 rc = cpl_property_set_int(p, aValue);
02292 }
02293 return rc;
02294 }
02295
02296
02307
02308 cpl_error_code
02309 muse_cplframeset_erase_all(cpl_frameset *aFrames)
02310 {
02311 cpl_ensure_code(aFrames, CPL_ERROR_NULL_INPUT);
02312 cpl_error_code rc = CPL_ERROR_NONE;
02313
02314 while (cpl_frameset_get_size(aFrames) > 0 && rc == CPL_ERROR_NONE) {
02315 cpl_frame *frame = cpl_frameset_get_position(aFrames, 0);
02316 rc = cpl_frameset_erase_frame(aFrames, frame);
02317 }
02318 return rc;
02319 }
02320
02321
02338
02339 cpl_error_code
02340 muse_cplframeset_erase_duplicate(cpl_frameset *aFrames)
02341 {
02342 cpl_ensure_code(aFrames, CPL_ERROR_NULL_INPUT);
02343 #if 0
02344 printf("\n\n\n%s input frameset (with duplicates):\n", __func__);
02345 cpl_frameset_dump(aFrames, stdout);
02346 printf("---------------------------------------------------------------------------\n");
02347 fflush(stdout);
02348 #endif
02349 cpl_error_code rc = CPL_ERROR_NONE;
02350
02351
02352 cpl_size i;
02353 for (i = 0; i < cpl_frameset_get_size(aFrames) - 1; i++) {
02354 cpl_frame *fref = cpl_frameset_get_position(aFrames, i);
02355 cpl_size j;
02356 for (j = i + 1; j < cpl_frameset_get_size(aFrames); j++) {
02357 cpl_frame *fother = cpl_frameset_get_position(aFrames, j);
02358 cpl_boolean areequal = CPL_FALSE;
02359 cpl_errorstate state = cpl_errorstate_get();
02360 const char *fn1 = cpl_frame_get_filename(fref),
02361 *fn2 = cpl_frame_get_filename(fother);
02362 if (!cpl_errorstate_is_equal(state)) {
02363 cpl_errorstate_set(state);
02364 }
02365 if ((!fn1 && fn2) || (fn1 && !fn2)) {
02366 areequal = CPL_FALSE;
02367 } else if (!fn1 && !fn2) {
02368 areequal = CPL_TRUE;
02369 } else {
02370 areequal = !strcmp(fn1, fn2);
02371 }
02372 areequal = areequal
02373 && !strcmp(cpl_frame_get_tag(fref), cpl_frame_get_tag(fother));
02374 areequal = areequal
02375 && (cpl_frame_get_group(fref) == cpl_frame_get_group(fother));
02376 areequal = areequal
02377 && (cpl_frame_get_level(fref) == cpl_frame_get_level(fother));
02378 areequal = areequal
02379 && (cpl_frame_get_type(fref) == cpl_frame_get_type(fother));
02380 if (areequal) {
02381 #if 0
02382 printf("%ld/%ld are equal: %s/%s, %s/%s, %d/%d, %d/%d, %d/%d\n", i, j,
02383 fn1, fn2, tag1, tag2,
02384 cpl_frame_get_group(fref), cpl_frame_get_group(fother),
02385 cpl_frame_get_level(fref), cpl_frame_get_level(fother),
02386 cpl_frame_get_type(fref), cpl_frame_get_type(fother));
02387 fflush(stdout);
02388 #endif
02389
02390
02391 rc = cpl_frameset_erase_frame(aFrames, fref);
02392 i--;
02393 break;
02394 }
02395 }
02396 }
02397 #if 0
02398 printf("---------------------------------------------------------------------------\n");
02399 printf("%s input frameset (without duplicates):\n", __func__);
02400 cpl_frameset_dump(aFrames, stdout);
02401 printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n");
02402 fflush(stdout);
02403 #endif
02404 return rc;
02405 }
02406
02407
02419
02420 void
02421 muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
02422 {
02423 const cpl_boolean is_reverse = aFirst > aLast ? CPL_TRUE : CPL_FALSE;
02424 const char *revmsg = is_reverse ? " in reverse order" : "";
02425 const unsigned newest = is_reverse ? aFirst : aLast,
02426 nmax = labs((long int)aLast - (long int)aFirst) + 1;
02427 unsigned ndump = 20;
02428 if (getenv("MUSE_CPL_ERRORSTATE_NDUMP") &&
02429 atoi(getenv("MUSE_CPL_ERRORSTATE_NDUMP")) > 0) {
02430 ndump = atoi(getenv("MUSE_CPL_ERRORSTATE_NDUMP"));
02431 }
02432 ndump = nmax < ndump ? nmax : ndump;
02433
02434 if (newest) {
02435 if (aCurrent == aLast - (ndump-1)) {
02436 cpl_msg_error(__func__, "Dumping the %u most recent error(s) out of a "
02437 "total of %u errors%s:", ndump, newest, revmsg);
02438 cpl_msg_indent_more();
02439 }
02440 if (aCurrent >= aLast - (ndump-1)) {
02441 cpl_msg_error(__func__, "[%u/%u] '%s' (%u) at %s", aCurrent, newest,
02442 cpl_error_get_message(), cpl_error_get_code(),
02443 cpl_error_get_where());
02444 }
02445 if (aCurrent == aLast) {
02446 cpl_msg_indent_less();
02447 }
02448 } else {
02449 cpl_msg_info(__func__, "No error(s) to dump");
02450 }
02451 }
02452
02453
02454
02467
02468 muse_cplframework_type muse_cplframework(void) {
02469 #ifdef HAVE_READLINK
02470 char buffer[FILENAME_MAX] = "\0";
02471 int length = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1);
02472 if (length != -1) {
02473 buffer[length] = '\0';
02474 }
02475 if (strstr(buffer, "esorex")) {
02476 return MUSE_CPLFRAMEWORK_ESOREX;
02477 } else if (strstr(buffer, "python")) {
02478 return MUSE_CPLFRAMEWORK_PYTHONCPL;
02479 } else if (strstr(buffer, "jre")) {
02480 return MUSE_CPLFRAMEWORK_GASGANO;
02481 } else {
02482 return MUSE_CPLFRAMEWORK_UNKNOWN;
02483 }
02484 #else
02485 return MUSE_CPLFRAMEWORK_UNKNOWN;
02486 #endif
02487 }
02488