29 #if HAVE_POPEN && HAVE_PCLOSE 37 #include "muse_tracing.h" 38 #include "muse_instrument.h" 40 #include "muse_cplwrappers.h" 41 #include "muse_pfits.h" 42 #include "muse_quadrants.h" 43 #include "muse_utils.h" 54 static const char *muse_trace_poly_strings[] = {
60 static void muse_trace_plot_located_slices(cpl_vector *, cpl_vector *,
double,
double,
double,
const unsigned char);
80 cpl_ensure(aImage && aImage->
data, CPL_ERROR_NULL_INPUT, NULL);
84 cpl_size ymid = cpl_image_get_size_y(aImage->
data) / 2,
90 int y1 = ymid - 1 - aNRows,
93 y4 = ymid + 1 + aNRows;
94 cpl_msg_debug(__func__,
"IFU %hhu: ymid=%"CPL_SIZE_FORMAT
", region=%d..%d, %d..%d",
98 int nx = cpl_image_get_size_x(aImage->
data);
99 cpl_image *tmp1 = cpl_image_collapse_window_create(aImage->
data, 1, y1, nx, y2, 0),
100 *tmp2 = cpl_image_collapse_window_create(aImage->
data, 1, y3, nx, y4, 0);
102 cpl_image_normalise(tmp1, CPL_NORM_MEAN);
103 cpl_image_normalise(tmp2, CPL_NORM_MEAN);
105 cpl_image *tmax = cpl_image_new(nx, 1, CPL_TYPE_FLOAT);
107 for (i = 1; i <= nx; i++) {
109 cpl_image_set(tmax, i, 1,
110 fmax(cpl_image_get(tmp1, i, 1, &err),
111 cpl_image_get(tmp2, i, 1, &err)));
114 cpl_image_save(tmp1,
"trace_tmp1.fits", CPL_TYPE_FLOAT, NULL, CPL_IO_CREATE);
115 cpl_image_save(tmp2,
"trace_tmp2.fits", CPL_TYPE_FLOAT, NULL, CPL_IO_CREATE);
116 cpl_image_save(tmax,
"trace_tmax.fits", CPL_TYPE_FLOAT, NULL, CPL_IO_CREATE);
117 cpl_msg_debug(__func__,
"Saved collapsed rows to trace_{tmp1,tmp2,tmax}.fits");
119 cpl_image_delete(tmp1);
120 cpl_image_delete(tmp2);
122 cpl_vector *cut = cpl_vector_new_from_image_row(tmax, 1);
123 cpl_image_delete(tmax);
163 double aFrac,
const unsigned char aIFU)
165 cpl_ensure(aRowVec, CPL_ERROR_NULL_INPUT, NULL);
166 cpl_ensure(aFrac > 0. && aFrac < 1., CPL_ERROR_ILLEGAL_INPUT, NULL);
167 cpl_vector *centers = cpl_vector_new(aNSlices),
168 *widths = cpl_vector_new(aNSlices);
174 double median = cpl_vector_get_median_const(aRowVec),
178 cpl_msg_debug(__func__,
"median=%f, mdev=%f, fraction=%f --> edge detection" 179 " limit=%f (IFU %hhu)", median, mdev, f, detlimit, aIFU);
183 double ledge = 0., redge = 0.;
185 for (i = 0; i <= kMuseSliceSearchRegion; i++) {
186 if (cpl_vector_get(aRowVec, i) >= detlimit) {
191 if (i == kMuseSliceSearchRegion) {
192 cpl_msg_error(__func__,
"Search for first slice (left-edge) failed in IFU" 194 cpl_vector_delete(centers);
201 for (i = ledge + 1.5; i <= ledge + kMuseSliceMaxWidth; i++) {
202 if (cpl_vector_get(aRowVec, i) <= detlimit) {
207 if (i == ledge + kMuseSliceMaxWidth) {
208 cpl_msg_error(__func__,
"Search for first slice (right-edge) failed in " 210 cpl_vector_delete(centers);
215 double width = redge - ledge;
216 if (width < kMuseSliceLoLikelyWidth) {
217 cpl_msg_error(__func__,
"Initial slice is too narrow (%.2f pix, %.1f..%.1f)" 218 " -> search failed in IFU %hhu", width, ledge, redge, aIFU);
219 cpl_error_set(__func__, CPL_ERROR_ACCESS_OUT_OF_RANGE);
220 cpl_vector_delete(centers);
224 if (width > kMuseSliceHiLikelyWidth) {
225 cpl_msg_error(__func__,
"Initial slice is too wide (%.2f pix, %.1f..%.1f)" 226 " -> search failed in IFU %hhu", width, ledge, redge, aIFU);
227 cpl_error_set(__func__, CPL_ERROR_ACCESS_OUT_OF_RANGE);
228 cpl_vector_delete(centers);
234 cpl_vector_set(centers, 0, round((ledge + redge) / 2.) + 1);
235 cpl_vector_set(widths, 0, width);
239 for (j = 1; j < aNSlices; j++) {
240 for (i = redge + 1.5; i <= redge + kMuseSliceMaxWidth; i++) {
241 if (cpl_vector_get(aRowVec, i) >= detlimit) {
246 if (i == redge + kMuseSliceMaxWidth) {
247 cpl_msg_error(__func__,
"Search for slice %hu (left-edge) failed in IFU" 249 cpl_vector_delete(centers);
250 cpl_vector_delete(widths);
254 for (i = ledge + 1.5; i <= ledge + kMuseSliceMaxWidth; i++) {
255 if (cpl_vector_get(aRowVec, i) <= detlimit) {
260 if (i == ledge + kMuseSliceMaxWidth) {
261 cpl_msg_error(__func__,
"Search for slice %hu (right-edge) failed in" 262 " IFU %hhu", j, aIFU);
263 cpl_vector_delete(centers);
264 cpl_vector_delete(widths);
269 width = redge - ledge;
270 cpl_vector_set(widths, j, width);
272 cpl_msg_debug(__func__,
"slice %hu: left=%f, right=%f --> width %f, center %f",
273 j+1, ledge, redge, width, (ledge + redge) / 2.);
276 cpl_vector_set(centers, j, round((ledge + redge) / 2.) + 1);
280 char *doplot = getenv(
"MUSE_PLOT_TRACE");
281 if (doplot && (atoi(doplot) & 0x1)) {
282 muse_trace_plot_located_slices(aRowVec, centers, median, mdev, detlimit,
287 for (i = 1; i < cpl_vector_get_size(centers); i++) {
288 double step = cpl_vector_get(centers, i) - cpl_vector_get(centers, i-1);
289 if (step < kMuseSliceLoLikelyWidth) {
302 if (f < DBL_EPSILON) {
303 cpl_msg_error(__func__,
"Still detected %d unlikely slice locations, but " 304 "the cut-off fraction has become unrealistically small in " 305 "IFU %hhu (initial %f, now %f)", failures, aIFU, aFrac, f);
311 int i, n = !centers ? -1 : cpl_vector_get_size(widths);
312 for (i = 0; i < n; i++) {
313 float width = cpl_vector_get(widths, i);
314 if (width < kMuseSliceLoLikelyWidth) {
315 cpl_msg_warning(__func__,
"From the initial guess, slice %d appears to be" 316 " only %f pix wide in IFU %hhu, please cross-check!", i+1,
319 if (width > kMuseSliceHiLikelyWidth) {
320 cpl_msg_warning(__func__,
"From the initial guess, slice %d appears to be" 321 " very wide in IFU %hhu (%f pix), please cross-check!",
325 double step = cpl_vector_get(centers, i) - cpl_vector_get(centers, i-1);
326 if (step < kMuseSliceLoLikelyWidth) {
327 cpl_msg_warning(__func__,
"Slice %d is only %.2f pix farther than the " 328 "previous one in IFU %hhu!", i + 1, step, aIFU);
332 cpl_vector_delete(widths);
373 double *aLeft,
double *aRight, cpl_boolean *aHighSN,
374 const unsigned char aIFU)
376 int size = cpl_vector_get_size(aDataVec);
378 cpl_ensure(size > 5, CPL_ERROR_ILLEGAL_INPUT, -3);
379 cpl_ensure(aFrac > 0. && aFrac < 1., CPL_ERROR_ILLEGAL_INPUT, -4);
380 cpl_ensure(aLeft && aRight, CPL_ERROR_NULL_INPUT, -5);
384 double median = cpl_vector_get_median_const(aDataVec),
386 mean = cpl_vector_get_mean(aDataVec),
387 stdev = cpl_vector_get_stdev(aDataVec),
388 detlimit = aFrac * median;
392 cpl_boolean significant = median > mdev && mean > stdev;
394 *aHighSN = significant;
397 cpl_msg_debug(__func__,
"median=%f+/-%f, mean=%f+/-%f, aFrac=%f --> edge " 398 "detection limit=%f (%ssignificant), IFU %hhu", median, mdev,
399 mean, stdev, aFrac, detlimit, significant ?
"" :
"NOT ", aIFU);
406 const double *ydata = cpl_vector_get_data_const(aDataVec);
414 cpl_msg_debug(__func__,
"Iterating edge search with offset = %d pix (IFU " 415 "%hhu)", offset, aIFU);
421 for (i = size/2 + offset; i < size; i++) {
422 if (ydata[i] < detlimit) {
426 *aRight = i-1 + (detlimit - ydata[i-1]) / (ydata[i] - ydata[i-1]);
428 cpl_msg_debug(__func__,
"r: %d..._%d_, %f/_%f_ ===> %f", i-1, i,
429 ydata[i-1], ydata[i], *aRight);
433 if (fabs(*aRight - i) > 1.) {
438 if (significant && (i - (size/2 + offset)) > 2) {
439 cpl_msg_debug(__func__,
"Faulty interpolation of right-hand edge in " 440 "IFU %hhu: i=%d (start %d), *aRight=%f (%f..%f > %f > " 441 "%f)", aIFU, i, size/2 + offset, *aRight, ydata[i-2],
442 ydata[i-1], detlimit, ydata[i]);
456 for (i = size/2 - offset; i >= 0; i--) {
457 if (ydata[i] < detlimit) {
459 *aLeft = i + (detlimit - ydata[i]) / (ydata[i+1] - ydata[i]);
461 cpl_msg_debug(__func__,
"l: %d..._%d_, %f/_%f_ ===> %f", i+1, i,
462 ydata[i+1], ydata[i], *aLeft);
464 if (fabs(*aLeft - i) > 1.) {
465 if (significant && (size/2 - offset - i) > 2) {
467 cpl_msg_debug(__func__,
"Faulty interpolation of left-hand edge in " 468 "IFU %hhu: i=%d (start %d), *aLeft=%f (%f < %f < %f..%f" 469 ")", aIFU, i, size/2 - offset, *aLeft, ydata[i],
470 detlimit, ydata[i+1], ydata[i+2]);
485 int offsetold = offset;
486 if ((size/2 - *aLeft) > (*aRight - size/2)) {
487 offset = *aRight - size/2 + 2;
489 offset = size/2 - *aLeft + 2;
491 if (offset <= offsetold) {
496 if (offset > size/2) {
501 }
while ((*aRight - *aLeft + 1) < kMuseSliceLoLikelyWidth || (offset > size/2));
504 cpl_msg_debug(__func__,
"result in IFU %hhu: %f %f --> %f", aIFU, *aLeft,
505 *aRight, (*aLeft + *aRight)/2.);
507 return (*aLeft + *aRight)/2.;
542 int aOffset,
double aY,
const unsigned short aSlice,
543 const unsigned char aIFU)
545 #define TRACE_REFINE_MAX_SHIFT 0.25 546 #define TRACE_REFINE_RANGE 5 547 int size = cpl_vector_get_size(aDiffVec);
548 cpl_ensure(size > 5, CPL_ERROR_ILLEGAL_INPUT, -3);
549 cpl_ensure(aLeft && aRight, CPL_ERROR_NULL_INPUT, -5);
550 cpl_ensure(*aLeft > 0 && *aLeft < size &&
551 *aRight > 0 && *aRight < size && *aRight > *aLeft,
552 CPL_ERROR_ILLEGAL_INPUT, -6);
555 double left = *aLeft,
557 mid = (*aLeft + *aRight) / 2.;
561 int nel = 2 * TRACE_REFINE_RANGE + 1;
562 cpl_vector *vl = cpl_vector_new(nel),
563 *vr = cpl_vector_new(nel),
564 *pl = cpl_vector_new(nel),
565 *pr = cpl_vector_new(nel);
567 int loffset = (int)(left + 0.5)- TRACE_REFINE_RANGE + 1,
568 roffset = (int)(right + 0.5) - TRACE_REFINE_RANGE + 1;
570 cpl_msg_debug(__func__,
"input: %f/%f -> %d/%d",
571 left, right, loffset, roffset);
573 double *diff = cpl_vector_get_data(aDiffVec);
575 for (i = 0; i < nel; i++ ) {
576 double d = diff[i + loffset - 1];
578 cpl_msg_debug(__func__,
"l i=%d / %d: %f", i, i + loffset, d);
580 cpl_vector_set(pl, i, i + loffset - 1);
582 cpl_vector_set(vl, i, d > 0 ? d : 0);
584 for (i = 0; i < nel; i++ ) {
586 double d = -diff[i + roffset - 1];
588 cpl_msg_debug(__func__,
"r i=%d / %d: %f", i, i + roffset, d);
590 cpl_vector_set(pr, i, i + roffset - 1);
592 cpl_vector_set(vr, i, d > 0 ? d : 0);
596 cpl_errorstate state = cpl_errorstate_get();
599 double center, sigma, area, bglevel = 0, mse;
600 cpl_fit_mode fitmode = CPL_FIT_CENTROID | CPL_FIT_STDEV | CPL_FIT_AREA;
601 cpl_error_code rc1 = cpl_vector_fit_gaussian(pl, NULL, vl, NULL, fitmode,
602 ¢er, &sigma, &area, &bglevel,
606 if (rc1 == CPL_ERROR_CONTINUE || rc1 == CPL_ERROR_SINGULAR_MATRIX) {
609 if (fabs(center - *aLeft) < TRACE_REFINE_MAX_SHIFT) {
613 if (rc1 != CPL_ERROR_NONE) {
615 cpl_errorstate_set(state);
620 cpl_msg_debug(__func__,
"fit l: %f %f %f (%f)", center, sigma, area, sqrt(mse));
622 cpl_error_code rc2 = cpl_vector_fit_gaussian(pr, NULL, vr, NULL, fitmode,
623 ¢er, &sigma, &area, &bglevel,
626 if (rc2 == CPL_ERROR_CONTINUE || rc2 == CPL_ERROR_SINGULAR_MATRIX) {
629 if (fabs(center - *aRight) < TRACE_REFINE_MAX_SHIFT) {
633 if (rc2 != CPL_ERROR_NONE) {
635 cpl_errorstate_set(state);
640 cpl_msg_debug(__func__,
"fit r: %f %f %f (%f)", center, sigma, area, sqrt(mse));
644 cpl_vector_dump(aDiffVec, stdout);
646 cpl_bivector *biv = cpl_bivector_wrap_vectors(pl, vl);
647 cpl_bivector_dump(biv, stdout);
648 cpl_bivector_unwrap_vectors(biv);
650 biv = cpl_bivector_wrap_vectors(pr, vr);
651 cpl_bivector_dump(biv, stdout);
652 cpl_bivector_unwrap_vectors(biv);
655 cpl_vector_delete(vl);
656 cpl_vector_delete(vr);
657 cpl_vector_delete(pl);
658 cpl_vector_delete(pr);
660 double midpoint = (*aLeft + *aRight)/2.;
662 cpl_msg_debug(__func__,
"refine: %f %f %f %f %f %f",
663 *aLeft, midpoint, *aRight,
664 left - *aLeft, mid - midpoint, right - *aRight);
668 if (fabs(mid - midpoint) > TRACE_REFINE_MAX_SHIFT) {
669 cpl_msg_debug(__func__,
"large refined shift around y=%.1f in slice %hu of " 670 "IFU %hhu: %f %f %f (%f %f %f) trace point will not be used",
671 aY, aSlice, aIFU, left + aOffset, midpoint + aOffset,
672 right + aOffset, left - *aLeft, mid - midpoint, right - *aRight);
714 static cpl_polynomial **
716 const unsigned short aSlice,
const unsigned char aIFU,
717 const unsigned int aFitorder,
const float aWSigma,
718 const float aRSigma, cpl_vector *aMSE)
720 cpl_ensure(cpl_vector_get_size(aWidths) >= 3, CPL_ERROR_ILLEGAL_INPUT, NULL);
722 cpl_ensure(aSlice >= 1 && aSlice <= kMuseSlicesPerCCD,
723 CPL_ERROR_ILLEGAL_INPUT, NULL);
726 double wmean = cpl_vector_get_mean(aWidths),
727 wmedian = cpl_vector_get_median_const(aWidths),
728 wstdev = cpl_vector_get_stdev(aWidths),
731 cpl_msg_debug(__func__,
"width (1st): mean %6.3f +/- %5.3f, median %6.3f +/- " 732 "%5.3f (%"CPL_SIZE_FORMAT
" points)", wmean, wstdev, wmedian, wmdev,
733 cpl_vector_get_size(aWidths));
735 if ((wmean - wstdev < kMuseSliceLoLikelyWidth ||
736 wmedian - wmdev < kMuseSliceLoLikelyWidth) &&
737 (wmean < kMuseSliceLoLikelyWidth || wmedian < kMuseSliceLoLikelyWidth)) {
738 cpl_msg_debug(__func__,
"slice %hu of IFU %hhu seems to be very narrow " 739 "initially (widths: mean %6.3f +/- %5.3f, median %6.3f +/- " 740 "%5.3f)!", aSlice, aIFU, wmean, wstdev, wmedian, wmdev);
742 if ((wmean + wstdev > kMuseSliceHiLikelyWidth ||
743 wmedian + wmdev > kMuseSliceHiLikelyWidth) &&
744 (wmean > kMuseSliceHiLikelyWidth || wmedian > kMuseSliceHiLikelyWidth)) {
745 cpl_msg_debug(__func__,
"slice %hu of IFU %hhu seems to be very wide " 746 "initially (widths: mean %6.3f +/- %5.3f, median %6.3f +/- " 747 "%5.3f)!", aSlice, aIFU, wmean, wstdev, wmedian, wmdev);
753 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
754 double width = cpl_vector_get(aWidths, i);
755 if (width > kMuseSliceLoLikelyWidth && width < kMuseSliceHiLikelyWidth) {
760 if (cpl_vector_get_size(aWidths) == 1) {
761 cpl_msg_warning(__func__,
"trying to remove the last vector/matrix " 762 "element in slice %hu of IFU %hhu when checking widths",
767 cpl_matrix_erase_columns(aX, i, 1);
773 wmean = cpl_vector_get_mean(aWidths);
774 wmedian = cpl_vector_get_median_const(aWidths);
775 wstdev = cpl_vector_get_stdev(aWidths);
778 cpl_msg_debug(__func__,
"width (2nd): mean %6.3f+/-%5.3f, median %6.3f+/-%5.3f (%d points)",
779 wmean, wstdev, wmedian, wmdev, cpl_vector_get_size(aWidths));
781 if ((wmean - wstdev < kMuseSliceLoLikelyWidth ||
782 wmedian - wmdev < kMuseSliceLoLikelyWidth) &&
783 (wmean < kMuseSliceLoLikelyWidth || wmedian < kMuseSliceLoLikelyWidth)) {
784 cpl_msg_warning(__func__,
"slice %hu of IFU %hhu seems to be very narrow " 785 "after iteration (widths: mean %6.3f +/- %5.3f, median %6.3f" 786 " +/- %5.3f)!", aSlice, aIFU, wmean, wstdev, wmedian, wmdev);
788 if ((wmean + wstdev > kMuseSliceHiLikelyWidth ||
789 wmedian + wmdev > kMuseSliceHiLikelyWidth) &&
790 (wmean > kMuseSliceHiLikelyWidth || wmedian > kMuseSliceHiLikelyWidth)) {
791 cpl_msg_warning(__func__,
"slice %hu of IFU %hhu seems to be very wide " 792 "after iteration (widths: mean %6.3f +/- %5.3f, median %6.3f" 793 " +/- %5.3f)!", aSlice, aIFU, wmean, wstdev, wmedian, wmdev);
797 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
798 double width = cpl_vector_get(aWidths, i);
800 cpl_msg_debug(__func__,
"i=%d: %f <? %f <? %f", i,
801 wmedian - aWSigma * wmdev, width, wmedian + aWSigma * wmdev);
803 if (width > (wmedian - aWSigma * wmdev) &&
804 width < (wmedian + aWSigma * wmdev)) {
809 if (cpl_vector_get_size(aWidths) == 1) {
810 cpl_msg_warning(__func__,
"trying to remove the last vector/matrix " 811 "element in slice %hu of IFU %hhu when checking fit " 812 "sigma", aSlice, aIFU);
816 cpl_matrix_erase_columns(aX, i, 1);
823 cpl_table *wtable = cpl_table_new(cpl_vector_get_size(aWidths));
824 cpl_table_new_column(wtable,
"widths", CPL_TYPE_DOUBLE);
825 memcpy(cpl_table_get_data_double(wtable,
"widths"),
826 cpl_vector_get_data(aWidths), cpl_vector_get_size(aWidths));
832 cpl_vector_set_size(aWidths, cpl_vector_get_size(aY));
833 memcpy(cpl_vector_get_data(aWidths), cpl_table_get_data_double(wtable,
"widths"),
834 cpl_vector_get_size(aWidths));
835 cpl_table_delete(wtable);
837 cpl_vector_fill(aMSE, FLT_MAX);
841 cpl_vector_set(aMSE, MUSE_TRACE_CENTER, mse);
843 char *dodebug = getenv(
"MUSE_DEBUG_TRACE");
844 if (dodebug && atoi(dodebug) > 0) {
845 printf(
"Polynomial trace fit for slice %hu of IFU %hhu (mse=%g, " 846 "chi**2=%g):\n", aSlice, aIFU, mse, chisq);
847 cpl_polynomial_dump(tracefit, stdout);
854 cpl_vector *edge[MUSE_TRACE_NPOLY - 1] = {
855 cpl_vector_new(cpl_vector_get_size(aY)),
856 cpl_vector_new(cpl_vector_get_size(aY))
858 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
859 double x = cpl_vector_get(aY, i),
860 halfwidth = cpl_vector_get(aWidths, i) / 2.;
862 cpl_msg_debug(__func__,
"x=%f (%f...%f)", x, x - halfwidth, x + halfwidth);
864 cpl_vector_set(edge[MUSE_TRACE_LEFT - 1], i, x - halfwidth);
865 cpl_vector_set(edge[MUSE_TRACE_RIGHT - 1], i, x + halfwidth);
869 cpl_vector_dump(edge[0], stdout);
871 cpl_vector_dump(edge[1], stdout);
875 cpl_polynomial **fit = cpl_calloc(MUSE_TRACE_NPOLY,
sizeof(cpl_polynomial *));
876 fit[MUSE_TRACE_CENTER] = tracefit;
879 for (ipoly = 1; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
882 NULL, aFitorder, FLT_MAX,
884 cpl_vector_set(aMSE, ipoly, mse);
886 cpl_vector_delete(edge[ipoly - 1]);
890 printf(
"resulting polynomials (center, left, and right):\n");
891 cpl_polynomial_dump(fit[MUSE_TRACE_CENTER], stdout);
892 cpl_polynomial_dump(fit[MUSE_TRACE_LEFT], stdout);
893 cpl_polynomial_dump(fit[MUSE_TRACE_RIGHT], stdout);
895 cpl_vector_dump(aMSE, stdout);
908 {
"slice", CPL_TYPE_INT,
"",
"%02d",
"slice number", CPL_TRUE},
909 {
"y", CPL_TYPE_FLOAT,
"pix",
"%6.1f",
"y position on CCD", CPL_TRUE},
910 {
"mid", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
911 "midpoint of the slice at this y position", CPL_TRUE},
912 {
"left", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
913 "left edge of the slice at this y position", CPL_TRUE},
914 {
"right", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
915 "right edge of the slice at this y position", CPL_TRUE},
916 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
968 cpl_table **aSamples)
970 cpl_ensure(aImage && aImage->
data, CPL_ERROR_NULL_INPUT, NULL);
971 cpl_ensure(aNSum > 0 && aEdgeFrac > 0. && aEdgeFrac < 1. && aFitorder > 0,
972 CPL_ERROR_ILLEGAL_INPUT, NULL);
975 int ny = cpl_image_get_size_y(aImage->
data),
976 npoints = (ny - 1) / aNSum;
977 unsigned short nsearchslices = kMuseSlicesPerCCD;
978 cpl_boolean slice_number_hack = getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")
979 && atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")) > 0
980 && atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")) < 49;
982 if (slice_number_hack) {
983 nsearchslices = atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER"));
984 cpl_msg_warning(__func__,
"Overriding number of slices to search in IFU " 985 "%hhu to %hu!", ifu, nsearchslices);
987 cpl_msg_info(__func__,
"Working with %hu slices, %d image rows, and %d " 988 "tracepoints in IFU %hhu", nsearchslices, ny, npoints, ifu);
992 cpl_boolean chan24paranal = (ifu == 24);
994 if (chan24paranal && dateobs) {
995 chan24paranal = atoi(dateobs) >= 2014;
998 cpl_msg_info(__func__,
"Using overrides for IFU 24 since 2014: due to field" 999 " vignetting, left-hand edges (as seen on the CCD) of slices " 1000 "37 to 48 may be only approximate!");
1005 image->
data = cpl_image_duplicate(aImage->
data);
1007 image->
dq = cpl_image_duplicate(aImage->
dq);
1009 image->
dq = cpl_image_new(cpl_image_get_size_x(aImage->
data), ny, CPL_TYPE_INT);
1012 image->
header = cpl_propertylist_duplicate(aImage->
header);
1016 cpl_detector_interpolate_rejected(image->
data);
1019 #define NROWCOLLAPSE 15 1023 cpl_vector_delete(cut);
1025 cpl_msg_error(__func__,
"Could not carry out first guess of slice positions " 1026 "in IFU %hhu!", ifu);
1032 cpl_table *tracetable = cpl_table_new(kMuseSlicesPerCCD);
1034 cpl_msg_error(__func__,
"Could not create output trace table for IFU %hhu: " 1035 "%s", ifu, cpl_error_get_message());
1041 cpl_table_new_column(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, CPL_TYPE_INT);
1042 cpl_table_set_column_unit(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO,
"No");
1043 cpl_table_set_column_format(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO,
"%2d");
1044 cpl_table_new_column(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, CPL_TYPE_FLOAT);
1045 cpl_table_set_column_unit(tracetable, MUSE_TRACE_TABLE_COL_WIDTH,
"pix");
1046 cpl_table_set_column_format(tracetable, MUSE_TRACE_TABLE_COL_WIDTH,
"%6.3f");
1048 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1051 for (j = 0; j <= aFitorder; j++) {
1053 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, j);
1054 cpl_table_new_column(tracetable, colname, CPL_TYPE_DOUBLE);
1056 cpl_table_set_column_unit(tracetable, colname,
"pix");
1057 cpl_table_set_column_format(tracetable, colname,
"%12.5e");
1060 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_MSE, ipoly);
1061 cpl_table_new_column(tracetable, colname, CPL_TYPE_DOUBLE);
1062 cpl_table_set_column_unit(tracetable, colname,
"pix");
1063 cpl_table_set_column_format(tracetable, colname,
"%12.5e");
1067 int isamplesrow = -1;
1071 kMuseSlicesPerCCD * npoints);
1076 cpl_image *shiftdiff = cpl_image_duplicate(image->
data);
1077 cpl_image_shift(shiftdiff, 1, 0);
1079 cpl_image_multiply_scalar(shiftdiff, -1);
1080 cpl_image_add(shiftdiff, image->
data);
1083 unsigned short islice;
1084 for (islice = 0; islice < kMuseSlicesPerCCD; islice++) {
1086 cpl_matrix *xtrace = cpl_matrix_new(1, npoints);
1087 cpl_vector *ytrace = cpl_vector_new(npoints);
1089 cpl_vector *widths = cpl_vector_new(npoints);
1093 for (j = 1, k = 0, knum = 1; j <= ny - aNSum; j += aNSum, k++, knum++) {
1096 int noffset = (int)cpl_vector_get(centers, islice) - TRACE_BINSIZE,
1098 ihi = (int)cpl_vector_get(centers, islice) + TRACE_BINSIZE,
1100 jhi = j + aNSum - 1;
1102 cpl_msg_debug(__func__,
"slice=%d, center=%f, cut region: %d,%d,%d,%d",
1103 (
int)islice + 1, cpl_vector_get(centers, islice), ilo, ihi, jlo, jhi);
1105 cpl_image *tmp = cpl_image_collapse_window_create(image->
data,
1108 cpl_image_divide_scalar(tmp, aNSum);
1109 cut = cpl_vector_new_from_image_row(tmp, 1);
1110 cpl_image_delete(tmp);
1114 cpl_boolean highSN = CPL_TRUE;
1117 cpl_vector_delete(cut);
1120 double left1 = left + noffset;
1122 cpl_errorstate state = cpl_errorstate_get();
1125 tmp = cpl_image_collapse_window_create(shiftdiff, ilo, jlo, ihi, jhi,
1127 cpl_image_divide_scalar(tmp, aNSum);
1128 cut = cpl_vector_new_from_image_row(tmp, 1);
1129 cpl_image_delete(tmp);
1131 (jlo + jhi) / 2., islice + 1, ifu);
1132 cpl_vector_delete(cut);
1135 if (midpoint < 0 && midpoint > -2 && islice+1 >= 37 && chan24paranal) {
1136 cpl_msg_debug(__func__,
"IFU24 problem? slice %d, y = %f: refined " 1137 "%f < %f < %f", islice+1, ((
double)jlo + jhi) / 2.,
1138 left, midpoint, right);
1143 cpl_msg_debug(__func__,
"IFU24 problem! slice %d y = %f: corrected " 1144 "%f < %f < %f", islice+1, ((
double)jlo + jhi) / 2.,
1145 left, (left + right) / 2., right);
1148 midpoint = (left + right) / 2.;
1152 cpl_matrix_set(xtrace, 0, k, (jlo + jhi) / 2.);
1153 cpl_vector_set(ytrace, k, midpoint);
1154 cpl_vector_set(widths, k, right - left);
1158 if (++isamplesrow+1 > cpl_table_get_nrow(*aSamples)) {
1159 cpl_table_set_size(*aSamples, isamplesrow+1);
1161 cpl_table_set_int(*aSamples,
"slice", isamplesrow, islice + 1);
1162 cpl_table_set_float(*aSamples,
"y", isamplesrow, (jlo + jhi) / 2.);
1163 cpl_table_set_float(*aSamples,
"mid", isamplesrow, midpoint);
1164 cpl_table_set_float(*aSamples,
"left", isamplesrow, left);
1165 cpl_table_set_float(*aSamples,
"right", isamplesrow, right);
1175 cpl_errorstate_set(state);
1180 cpl_msg_debug(__func__,
"slice=%d, nfailed=%d, tracepoint=%d, midpoint=" 1181 "%f, y=%d", (
int)islice + 1, nfailed, knum, midpoint, j);
1183 if (nfailed > 0.1*npoints && midpoint == -1.) {
1184 cpl_msg_warning(__func__,
"failure %d in slice %d of IFU %hhu: lost " 1185 "trace at y=%d (tracepoint %d of %d)", nfailed,
1186 (
int)islice + 1, ifu, j, knum, npoints);
1190 int oldsize = cpl_vector_get_size(ytrace);
1191 cpl_vector_set_size(ytrace, oldsize - 1);
1192 cpl_matrix_resize(xtrace, 0, 0, 0, -1);
1193 cpl_vector_set_size(widths, oldsize - 1);
1199 printf(
"k=%d tracepoints (should be equal to %d)\n", k, npoints);
1200 cpl_matrix_dump(xtrace, stdout), fflush(stdout);
1201 cpl_vector_dump(ytrace, stdout), fflush(stdout);
1205 const float kWSigma = 5, kRSigma = 5;
1206 cpl_msg_debug(__func__,
"Working on slice %d of IFU %hhu (kWSigma=%f, " 1207 "kRSigma=%f)", (
int)islice + 1, ifu, kWSigma, kRSigma);
1208 cpl_vector *mse = cpl_vector_new(MUSE_TRACE_NPOLY);
1209 cpl_vector_fill(mse, -1.);
1211 islice + 1, ifu, aFitorder,
1212 kWSigma, kRSigma, mse);
1214 double wmean = cpl_vector_get_mean(widths);
1217 cpl_matrix_delete(xtrace);
1218 cpl_vector_delete(ytrace);
1219 cpl_vector_delete(widths);
1223 cpl_msg_error(__func__,
"The trace fit in slice %d of IFU %hhu failed",
1224 (
int)islice + 1, ifu);
1225 cpl_vector_delete(mse);
1230 cpl_table_set_int(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, islice,
1232 cpl_table_set_float(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, islice, wmean);
1233 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1234 if (!tracefits[ipoly]) {
1235 cpl_msg_error(__func__,
"The fit %d in slice %d of IFU %hhu failed",
1236 ipoly, (
int)islice + 1, ifu);
1239 char *colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_MSE, ipoly);
1240 cpl_table_set_double(tracetable, colname, islice,
1241 cpl_vector_get(mse, ipoly));
1244 for (j = 0; j <= aFitorder; j++) {
1245 cpl_size pows[1] = { j };
1247 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, j);
1248 cpl_errorstate prestate = cpl_errorstate_get();
1249 double coeff = cpl_polynomial_get_coeff(tracefits[ipoly], pows);
1250 #define SLOPE_WARN_LIMIT 0.015 1251 if (j == 1 && fabs(coeff) > SLOPE_WARN_LIMIT) {
1252 cpl_msg_warning(__func__,
"1st order coefficient of the %s tracing " 1253 "polynomial is unexpectedly large in slice %d of IFU" 1254 " %hhu: |%f| > %f", muse_trace_poly_strings[ipoly],
1255 (
int)islice + 1, ifu, coeff, SLOPE_WARN_LIMIT);
1257 cpl_table_set_double(tracetable, colname, islice, coeff);
1258 if (!cpl_errorstate_is_equal(prestate)) {
1259 cpl_msg_warning(__func__,
"Problem writing to field %s in trace table" 1260 " for IFU %hhu: %s", colname, ifu,
1261 cpl_error_get_message());
1266 cpl_vector_delete(mse);
1269 cpl_vector_delete(centers);
1270 cpl_image_delete(shiftdiff);
1273 cpl_table_set_size(*aSamples, ++isamplesrow);
1276 if (slice_number_hack) {
1277 cpl_msg_warning(__func__,
"Will try to fix the slices in IFU %hhu, %" 1278 CPL_SIZE_FORMAT
" seem to be bad!", ifu,
1279 cpl_table_count_invalid(tracetable, MUSE_TRACE_TABLE_COL_WIDTH));
1280 cpl_table_dump(tracetable, 0, 100, stdout);
1283 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1284 double width = cpl_table_get(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, islice, NULL);
1286 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"slice %d of " 1287 "IFU %hhu was narrow (%f), erased it", (
int)islice + 1,
1289 cpl_table_erase_window(tracetable, islice--, 1);
1293 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1294 double cen = cpl_table_get(tracetable,
"tc0_00", islice, NULL);
1295 if (cen - last > 100) {
1296 unsigned short iref = islice - 1;
1297 cpl_table *row = cpl_table_extract(tracetable, iref, 1);
1299 double offset = 84.5;
1300 cpl_table_add_scalar(row, MUSE_TRACE_TABLE_COL_SLICE_NO, 1);
1301 cpl_table_add_scalar(row,
"tc0_00", offset);
1302 cpl_table_add_scalar(row,
"tc1_00", offset);
1303 cpl_table_add_scalar(row,
"tc2_00", offset);
1304 cpl_table_add_scalar(row,
"MSE0", 1.);
1305 cpl_table_add_scalar(row,
"MSE1", 1.);
1306 cpl_table_add_scalar(row,
"MSE2", 1.);
1307 cpl_table_insert(tracetable, row, islice);
1309 printf(
"rowtable (islice=%hu):\n", islice);
1310 cpl_table_dump(row, 0, 100, stdout);
1312 printf(
"tracetable (islice=%hu):\n", islice);
1313 cpl_table_dump(tracetable, islice - 2, 10, stdout);
1316 cen = cpl_table_get(row,
"tc0_00", 0, NULL);
1317 cpl_table_delete(row);
1318 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"slice was " 1319 "missing before slice %d of IFU %hhu, copied " 1320 "from slice %d", (
int)islice + 1, ifu, (
int)iref + 1);
1324 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1325 unsigned short sliceno = cpl_table_get_int(tracetable,
1326 MUSE_TRACE_TABLE_COL_SLICE_NO,
1328 if (sliceno != islice + 1) {
1329 cpl_msg_warning(__func__,
"Resetting entry at table row index %hu to " 1330 "correct slice number in IFU %hhu (%d instead of %hu)",
1331 islice, ifu, (
int)islice + 1, sliceno);
1332 cpl_table_set_int(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, islice,
1339 cpl_msg_info(__func__,
"Found %"CPL_SIZE_FORMAT
" slices of width %4.1f+/-%3.1f" 1340 " pix (%4.1f pix...%4.1f pix) in IFU %hhu",
1341 cpl_table_get_nrow(tracetable),
1342 cpl_table_get_column_mean(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1343 cpl_table_get_column_stdev(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1344 cpl_table_get_column_min(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1345 cpl_table_get_column_max(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1369 return (cpl_table_get_ncol(aTable) - 2) / MUSE_TRACE_NPOLY - 2;
1394 const unsigned short aSlice)
1396 cpl_ensure(aTable, CPL_ERROR_NULL_INPUT, NULL);
1397 cpl_ensure(aSlice >= 1 && aSlice <= kMuseSlicesPerCCD,
1398 CPL_ERROR_ILLEGAL_INPUT, NULL);
1401 int irow, nrow = cpl_table_get_nrow(aTable);
1402 for (irow = 0; irow < nrow; irow++) {
1404 unsigned short slice = cpl_table_get_int(aTable,
1405 MUSE_TRACE_TABLE_COL_SLICE_NO,
1407 if (slice == aSlice && !err) {
1411 cpl_ensure(irow < nrow, CPL_ERROR_DATA_NOT_FOUND, NULL);
1413 cpl_polynomial **ptrace = cpl_calloc(MUSE_TRACE_NPOLY,
1414 sizeof(cpl_polynomial *));
1417 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1419 ptrace[ipoly] = cpl_polynomial_new(1);
1423 for (k = 0; k <= traceorder; k++) {
1424 cpl_size pows[1] = { k };
1425 sprintf(colname, MUSE_TRACE_TABLE_COL_COEFF, ipoly, k);
1427 cpl_polynomial_set_coeff(ptrace[ipoly], pows,
1428 cpl_table_get(aTable, colname, irow, &err));
1430 cpl_polynomial_delete(ptrace[MUSE_TRACE_CENTER]);
1431 cpl_polynomial_delete(ptrace[MUSE_TRACE_LEFT]);
1432 cpl_polynomial_delete(ptrace[MUSE_TRACE_RIGHT]);
1434 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"Trace table " 1435 "broken in slice %hu (row index %d) column %s",
1436 aSlice, irow, colname);
1457 cpl_polynomial_delete(aPolys[MUSE_TRACE_CENTER]);
1458 cpl_polynomial_delete(aPolys[MUSE_TRACE_LEFT]);
1459 cpl_polynomial_delete(aPolys[MUSE_TRACE_RIGHT]);
1465 muse_trace_plot_located_slices(cpl_vector *aRowVec, cpl_vector *aCenters,
1466 double aMedian,
double aMDev,
double aLimit,
1467 const unsigned char aIFU)
1469 #if HAVE_POPEN && HAVE_PCLOSE 1470 FILE *gp = popen(
"gnuplot -persist",
"w");
1472 cpl_msg_error(__func__,
"could not open gnuplot for plotting");
1477 char dirtemplate[] =
"/tmp/muse_trace_plot_located_slices_XXXXXX";
1478 char *dirname = mkdtemp(dirtemplate);
1483 char dirname[] =
"/tmp";
1485 char *out1 = cpl_sprintf(
"%s/row.dat", dirname);
1486 FILE *fp = fopen(out1,
"w");
1487 cpl_vector_dump(aRowVec, fp);
1489 char *out2 = cpl_sprintf(
"%s/centers.dat", dirname);
1490 fp = fopen(out2,
"w");
1491 cpl_vector_dump(aCenters, fp);
1494 fprintf(gp,
"set title \"located slices (IFU %hhu): median %.2f+/-%.2f, limit" 1495 " %.2f\"\nunset key\nset style fill solid 0.5\n", aIFU, aMedian, aMDev,
1497 fprintf(gp,
"median(x)=%e\nlimit(x)=%e\nlo(x)=%e\n",
1498 aMedian, aLimit, aMedian - aMDev);
1499 fprintf(gp,
"set xrange [%d:%"CPL_SIZE_FORMAT
"]\n", 1, cpl_vector_get_size(aRowVec));
1500 fprintf(gp,
"set yrange [%e:%e]\n", aLimit - 0.5*aMDev, aMedian + 1.3*aMDev);
1501 fprintf(gp,
"plot lo(x) w filledcu y1=%e, " 1502 " median(x) t \"median\", limit(x) t \"limit\" w l lw 2, " 1503 " \"%s\" w l lt 7, \"%s\" u 2:(%e):1 w p lt -1, " 1504 " \"%s\" u 2:(%e):1 w labels\n",
1505 aMedian+aMDev, out1, out2, aMedian, out2, aMedian+200);
1512 #if HAVE_MKDTEMP && HAVE_UNISTD_H 1513 int rc = rmdir(dirname);
1515 cpl_msg_warning(__func__,
"Used %s for plotting, please clean it manually!",
1547 unsigned short aSlice1,
unsigned short aSlice2,
1550 #if HAVE_POPEN && HAVE_PCLOSE 1551 cpl_ensure_code(aSamples, CPL_ERROR_NULL_INPUT);
1553 cpl_ensure_code(rc == CPL_ERROR_NONE, rc);
1555 if (aSlice1 < 1 || aSlice1 > kMuseSlicesPerCCD || aSlice1 > aSlice2 ||
1556 aSlice2 < 1 || aSlice2 > kMuseSlicesPerCCD) {
1557 fprintf(stderr,
"Warning: resetting slice numbers (%hu to %hu does not make" 1558 " sense)!\n", aSlice1, aSlice2);
1559 aSlice1 = kMuseSlicesPerCCD / 2;
1560 aSlice2 = kMuseSlicesPerCCD / 2 + 1;
1562 if (aSlice2 - aSlice1 > 10) {
1563 fprintf(stderr,
"Warning: plotting %d slices may take a long time and " 1564 "RAM/disk space!\n", (
int)aSlice2 - (
int)aSlice1 + 1);
1566 printf(
"Plotting ");;
1568 printf(
"IFU %hhu, ", aIFU);
1570 printf(
"slices %hu to %hu\n", aSlice1, aSlice2);
1572 FILE *gp = popen(
"gnuplot",
"w");
1574 return CPL_ERROR_ASSIGNING_STREAM;
1577 int nx = -1, ny = kMuseOutputYTop;
1578 const float *data = NULL;
1580 nx = cpl_image_get_size_x(aImage->
data);
1581 ny = cpl_image_get_size_x(aImage->
data);
1582 data = cpl_image_get_data_float_const(aImage->
data);
1588 char dirtemplate[] =
"/tmp/muse_trace_plot_samples_XXXXXX";
1589 char *dirname = mkdtemp(dirtemplate);
1591 return CPL_ERROR_FILE_NOT_CREATED;
1594 char dirname[] =
"/tmp";
1596 FILE *tf = NULL, *sf = NULL;
1599 t_out = cpl_sprintf(
"%s/muse_trace_plot_flatimage.dat", dirname);
1600 tf = fopen(t_out,
"w+");
1602 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_CREATED,
"\"%s\"",
1605 return CPL_ERROR_FILE_NOT_CREATED;
1608 char *s_out = cpl_sprintf(
"%s/muse_trace_plot_samples.dat", dirname);
1609 sf = fopen(s_out,
"w+");
1611 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_CREATED,
"%s", s_out);
1614 return CPL_ERROR_FILE_NOT_CREATED;
1618 int i, lplot = INT_MAX, rplot = INT_MIN;
1619 unsigned short nslice;
1620 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1622 for (i = 0; i < cpl_table_get_nrow(aSamples); i++) {
1623 if (nslice != cpl_table_get_int(aSamples,
"slice", i, NULL)) {
1627 float l = cpl_table_get_float(aSamples,
"left", i, NULL),
1628 r = cpl_table_get_float(aSamples,
"right", i, NULL);
1629 fprintf(sf,
"%g %g %g %g\n",
1630 cpl_table_get_float(aSamples,
"y", i, NULL),
1631 cpl_table_get_float(aSamples,
"mid", i, NULL), l, r);
1632 if ((
int)floor(l) < lplot) {
1635 if ((
int)floor(r) > rplot) {
1645 double *c = (
double *)cpl_calloc(order + 1,
sizeof(
double));
1648 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1649 for (i = 0; i <= order; i++) {
1650 char *colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, i);
1651 c[i] = cpl_table_get_double(aTrace, colname, nslice-1, NULL);
1656 fprintf(gp,
"p%02hu%1d(x) = (%g)", nslice, ipoly, c[0]);
1657 for (i = 1; i <= order; i++) {
1658 fprintf(gp,
" + (%g) * x**(%d)", c[i], i);
1667 for (i = lplot - 1; i < rplot; i++) {
1669 for (j = 0; j < ny; j++) {
1670 if (i < 0 || i >= nx || j < 0 || j >= ny) {
1673 fprintf(tf,
"%d %d %f\n", i+1, j+1, data[i + j*nx]);
1676 printf(
"Written \"%s\".\n", t_out);
1679 printf(
"Written \"%s\".\n", s_out);
1683 fprintf(gp,
"set title \"trace result, ");
1685 fprintf(gp,
"IFU %hhu, ", aIFU);
1687 fprintf(gp,
"slices %hu to %hu\"\n", aSlice1, aSlice2);
1688 fprintf(gp,
"set palette gray\n");
1689 fprintf(gp,
"unset key\n");
1692 fprintf(gp,
"set samples %d\n", ny);
1694 fprintf(gp,
"set parametric\n");
1696 fprintf(gp,
"set xrange [%d:%d]\n", lplot, rplot);
1697 fprintf(gp,
"set yrange [%d:%d]\n", 1, ny);
1698 fprintf(gp,
"set trange [%d:%d]\n", 1, ny);
1700 fprintf(gp,
"set cbrange [1e-4:1.5]\n");
1703 fprintf(gp,
"plot ");
1705 fprintf(gp,
"\"%s\" w image, ", t_out);
1707 fprintf(gp,
"\"%s\" u 2:1 t \"center points\" w p pt 2 lt rgb \"blue\" ps 1.2, " 1708 "\"%s\" u 3:1 t \"edge points left\" w p pt 2 lt rgb \"red\" ps 0.8, " 1709 "\"%s\" u 4:1 t \"edge points right\" w p pt 2 lt rgb \"green\" ps 0.8",
1710 s_out, s_out, s_out);
1713 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1714 fprintf(gp,
", p%02hu0(t),t t \"center\" w l lt rgb \"dark-blue\" lw 2, " 1715 "p%02hu1(t),t t \"left\" w l lt rgb \"dark-red\" lw 1, " 1716 "p%02hu2(t),t t \"right\" w l lt rgb \"forest-green\" lw 1",
1717 nslice, nslice, nslice);
1725 printf(
"Press ENTER to end program and close plot\n");
1735 return CPL_ERROR_NONE;
1737 return CPL_ERROR_UNSUPPORTED_MODE;
1767 unsigned short aSlice2,
unsigned char aIFU)
1769 #if HAVE_POPEN && HAVE_PCLOSE 1770 cpl_ensure_code(aSamples, CPL_ERROR_NULL_INPUT);
1772 cpl_ensure_code(rc == CPL_ERROR_NONE, rc);
1774 if (aSlice1 < 1 || aSlice1 > kMuseSlicesPerCCD || aSlice1 > aSlice2 ||
1775 aSlice2 < 1 || aSlice2 > kMuseSlicesPerCCD) {
1776 fprintf(stderr,
"Warning: resetting slice numbers (%hu to %hu does not make" 1777 " sense)!\n", aSlice1, aSlice2);
1778 aSlice1 = kMuseSlicesPerCCD / 2;
1779 aSlice2 = kMuseSlicesPerCCD / 2 + 1;
1781 printf(
"Plotting ");;
1783 printf(
"IFU %hhu, ", aIFU);
1785 printf(
"slices %hu to %hu\n", aSlice1, aSlice2);
1787 FILE *gp = popen(
"gnuplot",
"w");
1789 return CPL_ERROR_ASSIGNING_STREAM;
1792 int nrow = cpl_table_get_nrow(aSamples);
1793 const int *sdata = cpl_table_get_data_int_const(aSamples,
"slice");
1794 const float *ydata = cpl_table_get_data_float_const(aSamples,
"y"),
1795 *ldata = cpl_table_get_data_float_const(aSamples,
"left"),
1796 *rdata = cpl_table_get_data_float_const(aSamples,
"right");
1799 fprintf(gp,
"set title \"trace slice widths, ");
1801 fprintf(gp,
"IFU %hhu, ", aIFU);
1803 fprintf(gp,
"slices %hu to %hu\"\n", aSlice1, aSlice2);
1804 fprintf(gp,
"set key outside below\n");
1806 fprintf(gp,
"set xrange [%d:%d]\n", 1, kMuseOutputYTop);
1807 fprintf(gp,
"set yrange [%f:%f]\n", kMuseSliceLoLikelyWidth,
1808 kMuseSliceHiLikelyWidth);
1809 fprintf(gp,
"set xlabel \"y position on CCD [pix]\"\n");
1810 fprintf(gp,
"set ylabel \"slice width at y position [pix]\"\n");
1813 double dslice = (aSlice2 - aSlice1) / 255.;
1818 fprintf(gp,
"plot ");
1819 unsigned short nslice;
1820 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1823 fprintf(gp,
"\"-\" t \"slice %02hu\" w lp ps 0.8 lt rgb \"#%02x%02x%02x\"",
1825 (
int)((nslice - aSlice1) / dslice),
1826 (
int)((aSlice2 - nslice) / dslice),
1828 if (nslice == aSlice2) {
1835 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1837 for (i = 0; i < nrow; i++) {
1838 if (nslice == sdata[i]) {
1839 fprintf(gp,
"%f %f\n", ydata[i], rdata[i]-ldata[i]);
1842 fprintf(gp,
"EOF\n");
1849 printf(
"Press ENTER to end program and close plot\n");
1852 return CPL_ERROR_NONE;
1854 return CPL_ERROR_UNSUPPORTED_MODE;
cpl_polynomial ** muse_trace_table_get_polys_for_slice(const cpl_table *aTable, const unsigned short aSlice)
construct polynomial from the trace table entry for the given slice
static cpl_polynomial ** muse_trace_iterate_fit(cpl_matrix *aX, cpl_vector *aY, cpl_vector *aWidths, const unsigned short aSlice, const unsigned char aIFU, const unsigned int aFitorder, const float aWSigma, const float aRSigma, cpl_vector *aMSE)
iterate the tracing solution to remove outliers
int muse_trace_table_get_order(const cpl_table *aTable)
determine order of tracing polynomial from table
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
cpl_size * muse_quadrants_get_window(const muse_image *aImage, unsigned char aQuadrant)
Determine the data window of a given quadrant on the CCD.
cpl_table * muse_trace(const muse_image *aImage, int aNSum, double aEdgeFrac, int aFitorder, cpl_table **aSamples)
carry out the tracing of the slices on CCD, save parameters in table
unsigned char muse_utils_get_ifu(const cpl_propertylist *aHeaders)
Find out the IFU/channel from which this header originated.
cpl_image * data
the data extension
static cpl_vector * muse_trace_horizontal_cut(const muse_image *aImage, unsigned int aNRows)
Create a vector containing a representative horizontal image cut.
const char * muse_pfits_get_dateobs(const cpl_propertylist *aHeaders)
find out the date of observations
Structure definition of MUSE three extension FITS file.
cpl_propertylist * header
the FITS header
double muse_trace_edgefinder(const cpl_vector *aDataVec, double aFrac, double *aLeft, double *aRight, cpl_boolean *aHighSN, const unsigned char aIFU)
Find the midpoint and edges of a cut through a slice.
cpl_error_code muse_cpltable_check(const cpl_table *aTable, const muse_cpltable_def *aDef)
Check whether the table contains the fields of the definition.
static double muse_trace_refine_edge(cpl_vector *aDiffVec, double *aLeft, double *aRight, int aOffset, double aY, const unsigned short aSlice, const unsigned char aIFU)
Find more exact midpoint and edge positions using a difference vector of the input data...
void muse_trace_polys_delete(cpl_polynomial *aPolys[])
Delete the multi-polynomial array created in relation to tracing.
cpl_image * dq
the data quality extension
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
cpl_error_code muse_cplvector_erase_element(cpl_vector *aVector, int aElement)
delete the given element from the input vector
cpl_error_code muse_trace_plot_samples(cpl_table *aSamples, cpl_table *aTrace, unsigned short aSlice1, unsigned short aSlice2, unsigned char aIFU, muse_image *aImage)
Plotting of trace sample points and solution using gnuplot.
cpl_polynomial * muse_utils_iterate_fit_polynomial(cpl_matrix *aPos, cpl_vector *aVal, cpl_vector *aErr, cpl_table *aExtra, const unsigned int aOrder, const double aRSigma, double *aMSE, double *aChiSq)
Iterate a polynomial fit.
const muse_cpltable_def muse_tracesamples_def[]
MUSE tracing sample points table definition.
cpl_error_code muse_image_reject_from_dq(muse_image *aImage)
Reject pixels of a muse_image depending on its DQ data.
Definition of a cpl table structure.
double muse_cplvector_get_adev_const(const cpl_vector *aVector, double aCenter)
Compute the average absolute deviation of a (constant) vector.
muse_image * muse_image_new(void)
Allocate memory for a new muse_image object.
cpl_vector * muse_trace_locate_slices(cpl_vector *aRowVec, const unsigned short aNSlices, double aFrac, const unsigned char aIFU)
Find all slice midpoints across a CCD.
cpl_error_code muse_trace_plot_widths(cpl_table *aSamples, unsigned short aSlice1, unsigned short aSlice2, unsigned char aIFU)
Plotting the width from trace sample points using gnuplot.