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);
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__,
"ymid=%"CPL_SIZE_FORMAT
", region=%d..%d, %d..%d",
95 ymid, y1, y2, y3, y4);
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);
164 cpl_ensure(aRowVec, CPL_ERROR_NULL_INPUT, NULL);
165 cpl_ensure(aFrac > 0. && aFrac < 1., CPL_ERROR_ILLEGAL_INPUT, NULL);
166 cpl_vector *centers = cpl_vector_new(aNSlices),
167 *widths = cpl_vector_new(aNSlices);
173 double median = cpl_vector_get_median_const(aRowVec),
177 cpl_msg_debug(__func__,
"median=%f, mdev=%f, fraction=%f --> edge detection"
178 " limit=%f", median, mdev, f, detlimit);
182 double ledge = 0., redge = 0.;
184 for (i = 0; i <= kMuseSliceSearchRegion; i++) {
185 if (cpl_vector_get(aRowVec, i) >= detlimit) {
190 if (i == kMuseSliceSearchRegion) {
191 cpl_msg_error(__func__,
"Search for first slice (left-edge) failed");
192 cpl_vector_delete(centers);
199 for (i = ledge + 1.5; i <= ledge + kMuseSliceMaxWidth; i++) {
200 if (cpl_vector_get(aRowVec, i) <= detlimit) {
205 if (i == ledge + kMuseSliceMaxWidth) {
206 cpl_msg_error(__func__,
"Search for first slice (right-edge) failed");
207 cpl_vector_delete(centers);
212 double width = redge - ledge;
213 if (width < kMuseSliceLoLikelyWidth) {
214 cpl_msg_error(__func__,
"Initial slice is too narrow (%.2f pix, %.1f..%.1f)"
215 " -> search failed", width, ledge, redge);
216 cpl_error_set(__func__, CPL_ERROR_ACCESS_OUT_OF_RANGE);
217 cpl_vector_delete(centers);
221 if (width > kMuseSliceHiLikelyWidth) {
222 cpl_msg_error(__func__,
"Initial slice is too wide (%.2f pix, %.1f..%.1f)"
223 " -> search failed", width, ledge, redge);
224 cpl_error_set(__func__, CPL_ERROR_ACCESS_OUT_OF_RANGE);
225 cpl_vector_delete(centers);
231 cpl_vector_set(centers, 0, round((ledge + redge) / 2.) + 1);
232 cpl_vector_set(widths, 0, width);
236 for (j = 1; j < aNSlices; j++) {
237 for (i = redge + 1.5; i <= redge + kMuseSliceMaxWidth; i++) {
238 if (cpl_vector_get(aRowVec, i) >= detlimit) {
243 if (i == redge + kMuseSliceMaxWidth) {
244 cpl_msg_error(__func__,
"Search for slice %hu (left-edge) failed", j);
245 cpl_vector_delete(centers);
246 cpl_vector_delete(widths);
250 for (i = ledge + 1.5; i <= ledge + kMuseSliceMaxWidth; i++) {
251 if (cpl_vector_get(aRowVec, i) <= detlimit) {
256 if (i == ledge + kMuseSliceMaxWidth) {
257 cpl_msg_error(__func__,
"Search for slice %hu (right-edge) failed", j);
258 cpl_vector_delete(centers);
259 cpl_vector_delete(widths);
264 width = redge - ledge;
265 cpl_vector_set(widths, j, width);
267 cpl_msg_debug(__func__,
"slice %hu: left=%f, right=%f --> width %f, center %f",
268 j+1, ledge, redge, width, (ledge + redge) / 2.);
271 cpl_vector_set(centers, j, round((ledge + redge) / 2.) + 1);
275 char *doplot = getenv(
"MUSE_PLOT_TRACE");
276 if (doplot && atoi(doplot) & 0x1) {
277 muse_trace_plot_located_slices(aRowVec, centers, median, mdev, detlimit);
281 for (i = 1; i < cpl_vector_get_size(centers); i++) {
282 double step = cpl_vector_get(centers, i) - cpl_vector_get(centers, i-1);
283 if (step < kMuseSliceLoLikelyWidth) {
296 if (f < DBL_EPSILON) {
297 cpl_msg_error(__func__,
"Still detected %d unlikely slice locations, but "
298 "the cut-off fraction has become unrealistically small "
299 "(initial %f, now %f)", failures, aFrac, f);
305 int i, n = !centers ? -1 : cpl_vector_get_size(widths);
306 for (i = 0; i < n; i++) {
307 float width = cpl_vector_get(widths, i);
308 if (width < kMuseSliceLoLikelyWidth) {
309 cpl_msg_warning(__func__,
"From the initial guess, slice %d appears to be"
310 " only %f pix wide, please cross-check!", i+1, width);
312 if (width > kMuseSliceHiLikelyWidth) {
313 cpl_msg_warning(__func__,
"From the initial guess, slice %d appears to be"
314 " very wide (%f pix), please cross-check!", i+1, width);
317 double step = cpl_vector_get(centers, i) - cpl_vector_get(centers, i-1);
318 if (step < kMuseSliceLoLikelyWidth) {
319 cpl_msg_warning(__func__,
"Slice %d is only %.2f pix farther than the "
320 "previous one!", i + 1, step);
324 cpl_vector_delete(widths);
364 double *aLeft,
double *aRight, cpl_boolean *aHighSN)
366 int size = cpl_vector_get_size(aDataVec);
368 cpl_ensure(size > 5, CPL_ERROR_ILLEGAL_INPUT, -3);
369 cpl_ensure(aFrac > 0. && aFrac < 1., CPL_ERROR_ILLEGAL_INPUT, -4);
370 cpl_ensure(aLeft && aRight, CPL_ERROR_NULL_INPUT, -5);
374 double median = cpl_vector_get_median_const(aDataVec),
376 mean = cpl_vector_get_mean(aDataVec),
377 stdev = cpl_vector_get_stdev(aDataVec),
378 detlimit = aFrac * median;
382 cpl_boolean significant = median > mdev && mean > stdev;
384 *aHighSN = significant;
387 cpl_msg_debug(__func__,
"median=%f+/-%f, mean=%f+/-%f, aFrac=%f --> edge "
388 "detection limit=%f (%ssignificant)", median, mdev, mean, stdev,
389 aFrac, detlimit, significant ?
"" :
"NOT ");
396 const double *ydata = cpl_vector_get_data_const(aDataVec);
400 for (i = size/2; i < size; i++) {
401 if (ydata[i] < detlimit) {
405 *aRight = i-1 + (detlimit - ydata[i-1]) / (ydata[i] - ydata[i-1]);
407 cpl_msg_debug(__func__,
"r: %d..._%d_, %f/_%f_ ===> %f", i-1, i,
408 ydata[i-1], ydata[i], *aRight);
412 if (fabs(*aRight - i) > 1.) {
417 if (significant && i - size/2 > 2) {
418 cpl_msg_debug(__func__,
"Faulty interpolation of right-hand edge: i=%d"
419 " (start %d), *aRight=%f (%f..%f > %f > %f)", i, size/2,
420 *aRight, ydata[i-2], ydata[i-1], detlimit, ydata[i]);
434 for (i = size/2; i >= 0; i--) {
435 if (ydata[i] < detlimit) {
437 *aLeft = i + (detlimit - ydata[i]) / (ydata[i+1] - ydata[i]);
439 cpl_msg_debug(__func__,
"l: %d..._%d_, %f/_%f_ ===> %f", i+1, i,
440 ydata[i+1], ydata[i], *aLeft);
442 if (fabs(*aLeft - i) > 1.) {
443 if (significant && size/2 - i > 2) {
445 cpl_msg_debug(__func__,
"Faulty interpolation of left-hand edge: i=%d"
446 " (start %d), *aLeft=%f (%f < %f < %f..%f)", i, size/2,
447 *aLeft, ydata[i], detlimit, ydata[i+1], ydata[i+2]);
461 cpl_msg_debug(__func__,
"result: %f %f --> %f", *aLeft, *aRight,
462 (*aLeft + *aRight)/2.);
464 return (*aLeft + *aRight)/2.;
497 int aOffset,
double aY)
499 #define TRACE_REFINE_MAX_SHIFT 0.25
500 #define TRACE_REFINE_RANGE 5
501 int size = cpl_vector_get_size(aDiffVec);
502 cpl_ensure(size > 5, CPL_ERROR_ILLEGAL_INPUT, -3);
503 cpl_ensure(aLeft && aRight, CPL_ERROR_NULL_INPUT, -5);
504 cpl_ensure(*aLeft > 0 && *aLeft < size &&
505 *aRight > 0 && *aRight < size && *aRight > *aLeft,
506 CPL_ERROR_ILLEGAL_INPUT, -6);
509 double left = *aLeft,
511 mid = (*aLeft + *aRight) / 2.;
515 int nel = 2 * TRACE_REFINE_RANGE + 1;
516 cpl_vector *vl = cpl_vector_new(nel),
517 *vr = cpl_vector_new(nel),
518 *pl = cpl_vector_new(nel),
519 *pr = cpl_vector_new(nel);
521 int loffset = (int)(left + 0.5)- TRACE_REFINE_RANGE + 1,
522 roffset = (int)(right + 0.5) - TRACE_REFINE_RANGE + 1;
524 cpl_msg_debug(__func__,
"input: %f/%f -> %d/%d",
525 left, right, loffset, roffset);
527 double *diff = cpl_vector_get_data(aDiffVec);
529 for (i = 0; i < nel; i++ ) {
530 double d = diff[i + loffset - 1];
532 cpl_msg_debug(__func__,
"l i=%d / %d: %f", i, i + loffset, d);
534 cpl_vector_set(pl, i, i + loffset - 1);
536 cpl_vector_set(vl, i, d > 0 ? d : 0);
538 for (i = 0; i < nel; i++ ) {
540 double d = -diff[i + roffset - 1];
542 cpl_msg_debug(__func__,
"r i=%d / %d: %f", i, i + roffset, d);
544 cpl_vector_set(pr, i, i + roffset - 1);
546 cpl_vector_set(vr, i, d > 0 ? d : 0);
550 cpl_errorstate state = cpl_errorstate_get();
553 double center, sigma, area, bglevel = 0, mse;
554 cpl_fit_mode fitmode = CPL_FIT_CENTROID | CPL_FIT_STDEV | CPL_FIT_AREA;
555 cpl_error_code rc1 = cpl_vector_fit_gaussian(pl, NULL, vl, NULL, fitmode,
556 ¢er, &sigma, &area, &bglevel,
560 if (rc1 == CPL_ERROR_CONTINUE || rc1 == CPL_ERROR_SINGULAR_MATRIX) {
563 if (fabs(center - *aLeft) < TRACE_REFINE_MAX_SHIFT) {
567 if (rc1 != CPL_ERROR_NONE) {
569 cpl_errorstate_set(state);
574 cpl_msg_debug(__func__,
"fit l: %f %f %f (%f)", center, sigma, area, sqrt(mse));
576 cpl_error_code rc2 = cpl_vector_fit_gaussian(pr, NULL, vr, NULL, fitmode,
577 ¢er, &sigma, &area, &bglevel,
580 if (rc2 == CPL_ERROR_CONTINUE || rc2 == CPL_ERROR_SINGULAR_MATRIX) {
583 if (fabs(center - *aRight) < TRACE_REFINE_MAX_SHIFT) {
587 if (rc2 != CPL_ERROR_NONE) {
589 cpl_errorstate_set(state);
594 cpl_msg_debug(__func__,
"fit r: %f %f %f (%f)", center, sigma, area, sqrt(mse));
598 cpl_vector_dump(aDiffVec, stdout);
600 cpl_bivector *biv = cpl_bivector_wrap_vectors(pl, vl);
601 cpl_bivector_dump(biv, stdout);
602 cpl_bivector_unwrap_vectors(biv);
604 biv = cpl_bivector_wrap_vectors(pr, vr);
605 cpl_bivector_dump(biv, stdout);
606 cpl_bivector_unwrap_vectors(biv);
609 cpl_vector_delete(vl);
610 cpl_vector_delete(vr);
611 cpl_vector_delete(pl);
612 cpl_vector_delete(pr);
614 double midpoint = (*aLeft + *aRight)/2.;
616 cpl_msg_debug(__func__,
"refine: %f %f %f %f %f %f",
617 *aLeft, midpoint, *aRight,
618 left - *aLeft, mid - midpoint, right - *aRight);
622 if (fabs(mid - midpoint) > TRACE_REFINE_MAX_SHIFT) {
623 cpl_msg_debug(__func__,
"large refined shift around y=%.1f: %f %f %f "
624 "(%f %f %f) trace point will not be used", aY,
625 left + aOffset, midpoint + aOffset, right + aOffset,
626 left - *aLeft, mid - midpoint, right - *aRight);
667 static cpl_polynomial **
669 const unsigned short aSlice,
const unsigned int aFitorder,
670 const float aWSigma,
const float aRSigma,
673 cpl_ensure(cpl_vector_get_size(aWidths) >= 3, CPL_ERROR_ILLEGAL_INPUT, NULL);
675 cpl_ensure(aSlice >= 1 && aSlice <= kMuseSlicesPerCCD,
676 CPL_ERROR_ILLEGAL_INPUT, NULL);
679 double wmean = cpl_vector_get_mean(aWidths),
680 wmedian = cpl_vector_get_median_const(aWidths),
681 wstdev = cpl_vector_get_stdev(aWidths),
684 cpl_msg_debug(__func__,
"width (1st): mean %6.3f +/- %5.3f, median %6.3f +/- "
685 "%5.3f (%"CPL_SIZE_FORMAT
" points)", wmean, wstdev, wmedian, wmdev,
686 cpl_vector_get_size(aWidths));
688 if ((wmean - wstdev < kMuseSliceLoLikelyWidth ||
689 wmedian - wmdev < kMuseSliceLoLikelyWidth) &&
690 (wmean < kMuseSliceLoLikelyWidth || wmedian < kMuseSliceLoLikelyWidth)) {
691 cpl_msg_debug(__func__,
"slice %hu seems to be very narrow initially "
692 "(widths: mean %6.3f +/- %5.3f, median %6.3f +/- %5.3f)!",
693 aSlice, wmean, wstdev, wmedian, wmdev);
695 if ((wmean + wstdev > kMuseSliceHiLikelyWidth ||
696 wmedian + wmdev > kMuseSliceHiLikelyWidth) &&
697 (wmean > kMuseSliceHiLikelyWidth || wmedian > kMuseSliceHiLikelyWidth)) {
698 cpl_msg_debug(__func__,
"slice %hu seems to be very wide initially "
699 "(widths: mean %6.3f +/- %5.3f, median %6.3f +/- %5.3f)!",
700 aSlice, wmean, wstdev, wmedian, wmdev);
706 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
707 double width = cpl_vector_get(aWidths, i);
708 if (width > kMuseSliceLoLikelyWidth && width < kMuseSliceHiLikelyWidth) {
713 if (cpl_vector_get_size(aWidths) == 1) {
714 cpl_msg_warning(__func__,
"trying to remove the last vector/matrix "
715 "element in slice %hu when checking widths", aSlice);
719 cpl_matrix_erase_columns(aX, i, 1);
725 wmean = cpl_vector_get_mean(aWidths);
726 wmedian = cpl_vector_get_median_const(aWidths);
727 wstdev = cpl_vector_get_stdev(aWidths);
730 cpl_msg_debug(__func__,
"width (2nd): mean %6.3f+/-%5.3f, median %6.3f+/-%5.3f (%d points)",
731 wmean, wstdev, wmedian, wmdev, cpl_vector_get_size(aWidths));
733 if ((wmean - wstdev < kMuseSliceLoLikelyWidth ||
734 wmedian - wmdev < kMuseSliceLoLikelyWidth) &&
735 (wmean < kMuseSliceLoLikelyWidth || wmedian < kMuseSliceLoLikelyWidth)) {
736 cpl_msg_warning(__func__,
"slice %hu seems to be very narrow after iteration"
737 " (widths: mean %6.3f +/- %5.3f, median %6.3f +/- %5.3f)!",
738 aSlice, wmean, wstdev, wmedian, wmdev);
740 if ((wmean + wstdev > kMuseSliceHiLikelyWidth ||
741 wmedian + wmdev > kMuseSliceHiLikelyWidth) &&
742 (wmean > kMuseSliceHiLikelyWidth || wmedian > kMuseSliceHiLikelyWidth)) {
743 cpl_msg_warning(__func__,
"slice %hu seems to be very wide after iteration "
744 "(widths: mean %6.3f +/- %5.3f, median %6.3f +/- %5.3f)!",
745 aSlice, wmean, wstdev, wmedian, wmdev);
749 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
750 double width = cpl_vector_get(aWidths, i);
752 cpl_msg_debug(__func__,
"i=%d: %f <? %f <? %f", i,
753 wmedian - aWSigma * wmdev, width, wmedian + aWSigma * wmdev);
755 if (width > (wmedian - aWSigma * wmdev) &&
756 width < (wmedian + aWSigma * wmdev)) {
761 if (cpl_vector_get_size(aWidths) == 1) {
762 cpl_msg_warning(__func__,
"trying to remove the last vector/matrix "
763 "element in slice %hu when checking fit sigma", aSlice);
767 cpl_matrix_erase_columns(aX, i, 1);
774 cpl_table *wtable = cpl_table_new(cpl_vector_get_size(aWidths));
775 cpl_table_new_column(wtable,
"widths", CPL_TYPE_DOUBLE);
776 memcpy(cpl_table_get_data_double(wtable,
"widths"),
777 cpl_vector_get_data(aWidths), cpl_vector_get_size(aWidths));
783 cpl_vector_set_size(aWidths, cpl_vector_get_size(aY));
784 memcpy(cpl_vector_get_data(aWidths), cpl_table_get_data_double(wtable,
"widths"),
785 cpl_vector_get_size(aWidths));
786 cpl_table_delete(wtable);
788 cpl_vector_fill(aMSE, FLT_MAX);
792 cpl_vector_set(aMSE, MUSE_TRACE_CENTER, mse);
794 char *dodebug = getenv(
"MUSE_DEBUG_TRACE");
795 if (dodebug && atoi(dodebug) > 0) {
796 printf(
"Polynomial trace fit for slice %hu (mse=%g, chi^2=%g):\n", aSlice,
798 cpl_polynomial_dump(tracefit, stdout);
805 cpl_vector *edge[MUSE_TRACE_NPOLY - 1] = {
806 cpl_vector_new(cpl_vector_get_size(aY)),
807 cpl_vector_new(cpl_vector_get_size(aY))
809 for (i = 0; i < cpl_vector_get_size(aWidths); i++) {
810 double x = cpl_vector_get(aY, i),
811 halfwidth = cpl_vector_get(aWidths, i) / 2.;
813 cpl_msg_debug(__func__,
"x=%f (%f...%f)", x, x - halfwidth, x + halfwidth);
815 cpl_vector_set(edge[MUSE_TRACE_LEFT - 1], i, x - halfwidth);
816 cpl_vector_set(edge[MUSE_TRACE_RIGHT - 1], i, x + halfwidth);
820 cpl_vector_dump(edge[0], stdout);
822 cpl_vector_dump(edge[1], stdout);
826 cpl_polynomial **fit = cpl_calloc(MUSE_TRACE_NPOLY,
sizeof(cpl_polynomial *));
827 fit[MUSE_TRACE_CENTER] = tracefit;
830 for (ipoly = 1; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
833 NULL, aFitorder, FLT_MAX,
835 cpl_vector_set(aMSE, ipoly, mse);
837 cpl_vector_delete(edge[ipoly - 1]);
841 printf(
"resulting polynomials (center, left, and right):\n");
842 cpl_polynomial_dump(fit[MUSE_TRACE_CENTER], stdout);
843 cpl_polynomial_dump(fit[MUSE_TRACE_LEFT], stdout);
844 cpl_polynomial_dump(fit[MUSE_TRACE_RIGHT], stdout);
846 cpl_vector_dump(aMSE, stdout);
859 {
"slice", CPL_TYPE_INT,
"",
"%02d",
"slice number", CPL_TRUE},
860 {
"y", CPL_TYPE_FLOAT,
"pix",
"%6.1f",
"y position on CCD", CPL_TRUE},
861 {
"mid", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
862 "midpoint of the slice at this y position", CPL_TRUE},
863 {
"left", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
864 "left edge of the slice at this y position", CPL_TRUE},
865 {
"right", CPL_TYPE_FLOAT,
"pix",
"%8.3f",
866 "right edge of the slice at this y position", CPL_TRUE},
867 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
919 cpl_table **aSamples)
921 cpl_ensure(aImage && aImage->
data, CPL_ERROR_NULL_INPUT, NULL);
922 cpl_ensure(aNSum > 0 && aEdgeFrac > 0. && aEdgeFrac < 1. && aFitorder > 0,
923 CPL_ERROR_ILLEGAL_INPUT, NULL);
926 int ny = cpl_image_get_size_y(aImage->
data),
927 npoints = (ny - 1) / aNSum;
928 unsigned short nsearchslices = kMuseSlicesPerCCD;
929 cpl_boolean slice_number_hack = getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")
930 && atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")) > 0
931 && atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER")) < 49;
933 if (slice_number_hack) {
934 nsearchslices = atoi(getenv(
"MUSE_AIT_HACK_SLICE_NUMBER"));
935 cpl_msg_warning(__func__,
"Overriding number of slices to search in IFU "
936 "%hhu to %hu!", ifu, nsearchslices);
938 cpl_msg_info(__func__,
"Working with %hu slices, %d image rows, and %d "
939 "tracepoints in IFU %hhu", nsearchslices, ny, npoints, ifu);
941 cpl_boolean chan24in2014 = (ifu == 24)
944 cpl_msg_warning(__func__,
"Using overrides for IFU 24 in 2014: positions of"
945 " slices 37 to 48 may be only approximate!");
950 image->
data = cpl_image_duplicate(aImage->
data);
952 image->
dq = cpl_image_duplicate(aImage->
dq);
954 image->
dq = cpl_image_new(cpl_image_get_size_x(aImage->
data), ny, CPL_TYPE_INT);
957 image->
header = cpl_propertylist_duplicate(aImage->
header);
961 cpl_detector_interpolate_rejected(image->
data);
964 #define NROWCOLLAPSE 15
967 cpl_vector_delete(cut);
969 cpl_msg_error(__func__,
"Could not carry out first guess of slice positions "
970 "in IFU %hhu!", ifu);
976 cpl_table *tracetable = cpl_table_new(kMuseSlicesPerCCD);
978 cpl_msg_error(__func__,
"Could not create output trace table for IFU %hhu: "
979 "%s", ifu, cpl_error_get_message());
985 cpl_table_new_column(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, CPL_TYPE_INT);
986 cpl_table_set_column_unit(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO,
"No");
987 cpl_table_set_column_format(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO,
"%2d");
988 cpl_table_new_column(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, CPL_TYPE_FLOAT);
989 cpl_table_set_column_unit(tracetable, MUSE_TRACE_TABLE_COL_WIDTH,
"pix");
990 cpl_table_set_column_format(tracetable, MUSE_TRACE_TABLE_COL_WIDTH,
"%6.3f");
992 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
995 for (j = 0; j <= aFitorder; j++) {
997 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, j);
998 cpl_table_new_column(tracetable, colname, CPL_TYPE_DOUBLE);
1000 cpl_table_set_column_unit(tracetable, colname,
"pix");
1001 cpl_table_set_column_format(tracetable, colname,
"%12.5e");
1004 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_MSE, ipoly);
1005 cpl_table_new_column(tracetable, colname, CPL_TYPE_DOUBLE);
1006 cpl_table_set_column_unit(tracetable, colname,
"pix");
1007 cpl_table_set_column_format(tracetable, colname,
"%12.5e");
1011 int isamplesrow = -1;
1015 kMuseSlicesPerCCD * npoints);
1020 cpl_image *shiftdiff = cpl_image_duplicate(image->
data);
1021 cpl_image_shift(shiftdiff, 1, 0);
1023 cpl_image_multiply_scalar(shiftdiff, -1);
1024 cpl_image_add(shiftdiff, image->
data);
1027 unsigned short islice;
1028 for (islice = 0; islice < kMuseSlicesPerCCD; islice++) {
1030 cpl_matrix *xtrace = cpl_matrix_new(1, npoints);
1031 cpl_vector *ytrace = cpl_vector_new(npoints);
1033 cpl_vector *widths = cpl_vector_new(npoints);
1037 for (j = 1, k = 0, knum = 1; j <= ny - aNSum; j += aNSum, k++, knum++) {
1040 int noffset = (int)cpl_vector_get(centers, islice) - TRACE_BINSIZE,
1042 ihi = (int)cpl_vector_get(centers, islice) + TRACE_BINSIZE,
1044 jhi = j + aNSum - 1;
1046 cpl_msg_debug(__func__,
"slice=%hu, center=%f, cut region: %d,%d,%d,%d",
1047 islice + 1, cpl_vector_get(centers, islice), ilo, ihi, jlo, jhi);
1049 cpl_image *tmp = cpl_image_collapse_window_create(image->
data,
1052 cpl_image_divide_scalar(tmp, aNSum);
1053 cut = cpl_vector_new_from_image_row(tmp, 1);
1054 cpl_image_delete(tmp);
1058 cpl_boolean highSN = CPL_TRUE;
1061 cpl_vector_delete(cut);
1064 double left1 = left + noffset;
1066 cpl_errorstate state = cpl_errorstate_get();
1069 tmp = cpl_image_collapse_window_create(shiftdiff, ilo, jlo, ihi, jhi,
1071 cpl_image_divide_scalar(tmp, aNSum);
1072 cut = cpl_vector_new_from_image_row(tmp, 1);
1073 cpl_image_delete(tmp);
1076 cpl_vector_delete(cut);
1079 if (midpoint < 0 && midpoint > -2 && islice+1 >= 37 && chan24in2014) {
1080 cpl_msg_debug(__func__,
"IFU24 problem? slice %d, y = %f: refined "
1081 "%f < %f < %f", islice+1, ((
double)jlo + jhi) / 2.,
1082 left, midpoint, right);
1087 cpl_msg_debug(__func__,
"IFU24 problem! slice %d y = %f: corrected "
1088 "%f < %f < %f", islice+1, ((
double)jlo + jhi) / 2.,
1089 left, (left + right) / 2., right);
1092 midpoint = (left + right) / 2.;
1096 cpl_matrix_set(xtrace, 0, k, (jlo + jhi) / 2.);
1097 cpl_vector_set(ytrace, k, midpoint);
1098 cpl_vector_set(widths, k, right - left);
1102 if (++isamplesrow+1 > cpl_table_get_nrow(*aSamples)) {
1103 cpl_table_set_size(*aSamples, isamplesrow+1);
1105 cpl_table_set_int(*aSamples,
"slice", isamplesrow, islice + 1);
1106 cpl_table_set_float(*aSamples,
"y", isamplesrow, (jlo + jhi) / 2.);
1107 cpl_table_set_float(*aSamples,
"mid", isamplesrow, midpoint);
1108 cpl_table_set_float(*aSamples,
"left", isamplesrow, left);
1109 cpl_table_set_float(*aSamples,
"right", isamplesrow, right);
1119 cpl_errorstate_set(state);
1124 cpl_msg_debug(__func__,
"slice=%hu, nfailed=%d, tracepoint=%d, midpoint="
1125 "%f, y=%d", islice + 1, nfailed, knum, midpoint, j);
1127 if (nfailed > 0.1*npoints && midpoint == -1.) {
1128 cpl_msg_warning(__func__,
"failure %d in slice %hu of IFU %hhu: lost "
1129 "trace at y=%d (tracepoint %d of %d)", nfailed,
1130 islice + 1, ifu, j, knum, npoints);
1134 int oldsize = cpl_vector_get_size(ytrace);
1135 cpl_vector_set_size(ytrace, oldsize - 1);
1136 cpl_matrix_resize(xtrace, 0, 0, 0, -1);
1137 cpl_vector_set_size(widths, oldsize - 1);
1143 printf(
"k=%d tracepoints (should be equal to %d)\n", k, npoints);
1144 cpl_matrix_dump(xtrace, stdout), fflush(stdout);
1145 cpl_vector_dump(ytrace, stdout), fflush(stdout);
1149 const float kWSigma = 5, kRSigma = 5;
1150 cpl_msg_debug(__func__,
"Working on slice %hu (kWSigma=%f, kRSigma=%f)",
1151 islice + 1, kWSigma, kRSigma);
1152 cpl_vector *mse = cpl_vector_new(MUSE_TRACE_NPOLY);
1153 cpl_vector_fill(mse, -1.);
1155 islice + 1, aFitorder,
1156 kWSigma, kRSigma, mse);
1158 double wmean = cpl_vector_get_mean(widths);
1161 cpl_matrix_delete(xtrace);
1162 cpl_vector_delete(ytrace);
1163 cpl_vector_delete(widths);
1167 cpl_msg_error(__func__,
"The trace fit in slice %hu of IFU %hhu failed",
1169 cpl_vector_delete(mse);
1174 cpl_table_set_int(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, islice,
1176 cpl_table_set_float(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, islice, wmean);
1177 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1178 if (!tracefits[ipoly]) {
1179 cpl_msg_error(__func__,
"The fit %d in slice %hu of IFU %hhu failed",
1180 ipoly, islice + 1, ifu);
1183 char *colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_MSE, ipoly);
1184 cpl_table_set_double(tracetable, colname, islice,
1185 cpl_vector_get(mse, ipoly));
1188 for (j = 0; j <= aFitorder; j++) {
1189 cpl_size pows[1] = { j };
1191 colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, j);
1192 cpl_errorstate prestate = cpl_errorstate_get();
1193 double coeff = cpl_polynomial_get_coeff(tracefits[ipoly], pows);
1194 #define SLOPE_WARN_LIMIT 0.015
1195 if (j == 1 && fabs(coeff) > SLOPE_WARN_LIMIT) {
1196 cpl_msg_warning(__func__,
"1st order coefficient of the %s tracing "
1197 "polynomial is unexpectedly large in slice %hu of IFU"
1198 " %hhu: |%f| > %f", muse_trace_poly_strings[ipoly],
1199 islice + 1, ifu, coeff, SLOPE_WARN_LIMIT);
1201 cpl_table_set_double(tracetable, colname, islice, coeff);
1202 if (!cpl_errorstate_is_equal(prestate)) {
1203 cpl_msg_warning(__func__,
"Problem writing to field %s in trace table"
1204 " for IFU %hhu: %s", colname, ifu,
1205 cpl_error_get_message());
1210 cpl_vector_delete(mse);
1213 cpl_vector_delete(centers);
1214 cpl_image_delete(shiftdiff);
1217 cpl_table_set_size(*aSamples, ++isamplesrow);
1220 if (slice_number_hack) {
1221 cpl_msg_warning(__func__,
"Will try to fix the slices, %"CPL_SIZE_FORMAT
1222 " seem to be bad!", cpl_table_count_invalid(tracetable,
1223 MUSE_TRACE_TABLE_COL_WIDTH));
1224 cpl_table_dump(tracetable, 0, 100, stdout);
1227 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1228 double width = cpl_table_get(tracetable, MUSE_TRACE_TABLE_COL_WIDTH, islice, NULL);
1230 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"slice %hu of "
1231 "IFU %hhu was narrow (%f), erased it", islice + 1,
1233 cpl_table_erase_window(tracetable, islice--, 1);
1237 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1238 double cen = cpl_table_get(tracetable,
"tc0_00", islice, NULL);
1239 if (cen - last > 100) {
1240 unsigned short iref = islice - 1;
1241 cpl_table *row = cpl_table_extract(tracetable, iref, 1);
1243 double offset = 84.5;
1244 cpl_table_add_scalar(row, MUSE_TRACE_TABLE_COL_SLICE_NO, 1);
1245 cpl_table_add_scalar(row,
"tc0_00", offset);
1246 cpl_table_add_scalar(row,
"tc1_00", offset);
1247 cpl_table_add_scalar(row,
"tc2_00", offset);
1248 cpl_table_add_scalar(row,
"MSE0", 1.);
1249 cpl_table_add_scalar(row,
"MSE1", 1.);
1250 cpl_table_add_scalar(row,
"MSE2", 1.);
1251 cpl_table_insert(tracetable, row, islice);
1253 printf(
"rowtable (islice=%hu):\n", islice);
1254 cpl_table_dump(row, 0, 100, stdout);
1256 printf(
"tracetable (islice=%hu):\n", islice);
1257 cpl_table_dump(tracetable, islice - 2, 10, stdout);
1260 cen = cpl_table_get(row,
"tc0_00", 0, NULL);
1261 cpl_table_delete(row);
1262 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"slice was "
1263 "missing before slice %hu of IFU %hhu, copied "
1264 "from slice %hu", islice + 1, ifu, iref + 1);
1268 for (islice = 0; islice < cpl_table_get_nrow(tracetable); islice++) {
1269 unsigned short sliceno = cpl_table_get_int(tracetable,
1270 MUSE_TRACE_TABLE_COL_SLICE_NO,
1272 if (sliceno != islice + 1) {
1273 cpl_msg_warning(__func__,
"Resetting entry at table row index %hu to "
1274 "correct slice number (%hu instead of %hu)", islice,
1275 islice + 1, sliceno);
1276 cpl_table_set_int(tracetable, MUSE_TRACE_TABLE_COL_SLICE_NO, islice,
1283 cpl_msg_info(__func__,
"Found %"CPL_SIZE_FORMAT
" slices of width %4.1f+/-%3.1f"
1284 " pix (%4.1f pix...%4.1f pix) in IFU %hhu",
1285 cpl_table_get_nrow(tracetable),
1286 cpl_table_get_column_mean(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1287 cpl_table_get_column_stdev(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1288 cpl_table_get_column_min(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1289 cpl_table_get_column_max(tracetable, MUSE_TRACE_TABLE_COL_WIDTH),
1313 return (cpl_table_get_ncol(aTable) - 2) / MUSE_TRACE_NPOLY - 2;
1338 const unsigned short aSlice)
1340 cpl_ensure(aTable, CPL_ERROR_NULL_INPUT, NULL);
1341 cpl_ensure(aSlice >= 1 && aSlice <= kMuseSlicesPerCCD,
1342 CPL_ERROR_ILLEGAL_INPUT, NULL);
1345 int irow, nrow = cpl_table_get_nrow(aTable);
1346 for (irow = 0; irow < nrow; irow++) {
1348 unsigned short slice = cpl_table_get_int(aTable,
1349 MUSE_TRACE_TABLE_COL_SLICE_NO,
1351 if (slice == aSlice && !err) {
1355 cpl_ensure(irow < nrow, CPL_ERROR_DATA_NOT_FOUND, NULL);
1357 cpl_polynomial **ptrace = cpl_calloc(MUSE_TRACE_NPOLY,
1358 sizeof(cpl_polynomial *));
1361 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1363 ptrace[ipoly] = cpl_polynomial_new(1);
1367 for (k = 0; k <= traceorder; k++) {
1368 cpl_size pows[1] = { k };
1369 sprintf(colname, MUSE_TRACE_TABLE_COL_COEFF, ipoly, k);
1371 cpl_polynomial_set_coeff(ptrace[ipoly], pows,
1372 cpl_table_get(aTable, colname, irow, &err));
1374 cpl_polynomial_delete(ptrace[MUSE_TRACE_CENTER]);
1375 cpl_polynomial_delete(ptrace[MUSE_TRACE_LEFT]);
1376 cpl_polynomial_delete(ptrace[MUSE_TRACE_RIGHT]);
1378 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"Trace table "
1379 "broken in slice %hu (row index %d) column %s",
1380 aSlice, irow, colname);
1401 cpl_polynomial_delete(aPolys[MUSE_TRACE_CENTER]);
1402 cpl_polynomial_delete(aPolys[MUSE_TRACE_LEFT]);
1403 cpl_polynomial_delete(aPolys[MUSE_TRACE_RIGHT]);
1409 muse_trace_plot_located_slices(cpl_vector *aRowVec, cpl_vector *aCenters,
1410 double aMedian,
double aMDev,
double aLimit)
1412 #if HAVE_POPEN && HAVE_PCLOSE
1413 FILE *gp = popen(
"gnuplot -persist",
"w");
1415 cpl_msg_error(__func__,
"could not open gnuplot for plotting");
1420 char dirtemplate[] =
"/tmp/muse_trace_plot_located_slices_XXXXXX";
1421 char *dirname = mkdtemp(dirtemplate);
1426 char dirname[] =
"/tmp";
1428 char *out1 = cpl_sprintf(
"%s/row.dat", dirname);
1429 FILE *fp = fopen(out1,
"w");
1430 cpl_vector_dump(aRowVec, fp);
1432 char *out2 = cpl_sprintf(
"%s/centers.dat", dirname);
1433 fp = fopen(out2,
"w");
1434 cpl_vector_dump(aCenters, fp);
1437 fprintf(gp,
"set title \"located slices: median %.2f+/-%.2f, limit %.2f\"\n"
1438 "unset key\nset style fill solid 0.5\n", aMedian, aMDev, aLimit);
1439 fprintf(gp,
"median(x)=%e\nlimit(x)=%e\nlo(x)=%e\n",
1440 aMedian, aLimit, aMedian - aMDev);
1441 fprintf(gp,
"set xrange [%d:%"CPL_SIZE_FORMAT
"]\n", 1, cpl_vector_get_size(aRowVec));
1442 fprintf(gp,
"set yrange [%e:%e]\n", aLimit - 0.5*aMDev, aMedian + 1.3*aMDev);
1443 fprintf(gp,
"plot lo(x) w filledcu y1=%e, "
1444 " median(x) t \"median\", limit(x) t \"limit\" w l lw 2, "
1445 " \"%s\" w l lt 7, \"%s\" u 2:(%e):1 w p lt -1, "
1446 " \"%s\" u 2:(%e):1 w labels\n",
1447 aMedian+aMDev, out1, out2, aMedian, out2, aMedian+200);
1454 #if HAVE_MKDTEMP && HAVE_UNISTD_H
1455 int rc = rmdir(dirname);
1457 cpl_msg_warning(__func__,
"Used %s for plotting, please clean it manually!",
1488 unsigned short aSlice1,
unsigned short aSlice2,
1491 #if HAVE_POPEN && HAVE_PCLOSE
1492 cpl_ensure_code(aSamples, CPL_ERROR_NULL_INPUT);
1494 cpl_ensure_code(rc == CPL_ERROR_NONE, rc);
1496 if (aSlice1 < 1 || aSlice1 > kMuseSlicesPerCCD || aSlice1 > aSlice2 ||
1497 aSlice2 < 1 || aSlice2 > kMuseSlicesPerCCD) {
1498 fprintf(stderr,
"Warning: resetting slice numbers (%hu to %hu does not make"
1499 " sense)!\n", aSlice1, aSlice2);
1500 aSlice1 = kMuseSlicesPerCCD / 2;
1501 aSlice2 = kMuseSlicesPerCCD / 2 + 1;
1503 if (aSlice2 - aSlice1 > 10) {
1504 fprintf(stderr,
"Warning: plotting %hu slices may take a long time and "
1505 "RAM/disk space!\n", aSlice2 - aSlice1 + 1);
1507 printf(
"Plotting slices %hu to %hu\n", aSlice1, aSlice2);
1509 FILE *gp = popen(
"gnuplot",
"w");
1511 return CPL_ERROR_ASSIGNING_STREAM;
1514 int nx = -1, ny = kMuseOutputYTop;
1515 const float *data = NULL;
1517 nx = cpl_image_get_size_x(aImage->
data);
1518 ny = cpl_image_get_size_x(aImage->
data);
1519 data = cpl_image_get_data_float_const(aImage->
data);
1525 char dirtemplate[] =
"/tmp/muse_trace_plot_samples_XXXXXX";
1526 char *dirname = mkdtemp(dirtemplate);
1528 return CPL_ERROR_FILE_NOT_CREATED;
1531 char dirname[] =
"/tmp";
1533 FILE *tf = NULL, *sf = NULL;
1536 t_out = cpl_sprintf(
"%s/muse_trace_plot_flatimage.dat", dirname);
1537 tf = fopen(t_out,
"w+");
1539 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_CREATED,
"\"%s\"",
1542 return CPL_ERROR_FILE_NOT_CREATED;
1545 char *s_out = cpl_sprintf(
"%s/muse_trace_plot_samples.dat", dirname);
1546 sf = fopen(s_out,
"w+");
1548 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_CREATED,
"%s", s_out);
1551 return CPL_ERROR_FILE_NOT_CREATED;
1555 int i, lplot = INT_MAX, rplot = INT_MIN;
1556 unsigned short nslice;
1557 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1559 for (i = 0; i < cpl_table_get_nrow(aSamples); i++) {
1560 if (nslice != cpl_table_get_int(aSamples,
"slice", i, NULL)) {
1564 float l = cpl_table_get_float(aSamples,
"left", i, NULL),
1565 r = cpl_table_get_float(aSamples,
"right", i, NULL);
1566 fprintf(sf,
"%g %g %g %g\n",
1567 cpl_table_get_float(aSamples,
"y", i, NULL),
1568 cpl_table_get_float(aSamples,
"mid", i, NULL), l, r);
1569 if ((
int)floor(l) < lplot) {
1572 if ((
int)floor(r) > rplot) {
1582 double *c = (
double *)cpl_calloc(order + 1,
sizeof(
double));
1585 for (ipoly = 0; ipoly < MUSE_TRACE_NPOLY; ipoly++) {
1586 for (i = 0; i <= order; i++) {
1587 char *colname = cpl_sprintf(MUSE_TRACE_TABLE_COL_COEFF, ipoly, i);
1588 c[i] = cpl_table_get_double(aTrace, colname, nslice-1, NULL);
1593 fprintf(gp,
"p%02hu%1d(x) = (%g)", nslice, ipoly, c[0]);
1594 for (i = 1; i <= order; i++) {
1595 fprintf(gp,
" + (%g) * x**(%d)", c[i], i);
1604 for (i = lplot - 1; i < rplot; i++) {
1606 for (j = 0; j < ny; j++) {
1607 if (i < 0 || i >= nx || j < 0 || j >= ny) {
1610 fprintf(tf,
"%d %d %f\n", i+1, j+1, data[i + j*nx]);
1613 printf(
"Written \"%s\".\n", t_out);
1616 printf(
"Written \"%s\".\n", s_out);
1620 fprintf(gp,
"set title \"trace result, slices %hu to %hu\"\n", aSlice1, aSlice2);
1621 fprintf(gp,
"set palette gray\n");
1622 fprintf(gp,
"unset key\n");
1625 fprintf(gp,
"set samples %d\n", ny);
1627 fprintf(gp,
"set parametric\n");
1629 fprintf(gp,
"set xrange [%d:%d]\n", lplot, rplot);
1630 fprintf(gp,
"set yrange [%d:%d]\n", 1, ny);
1631 fprintf(gp,
"set trange [%d:%d]\n", 1, ny);
1633 fprintf(gp,
"set cbrange [1e-4:1.5]\n");
1636 fprintf(gp,
"plot ");
1638 fprintf(gp,
"\"%s\" w image, ", t_out);
1640 fprintf(gp,
"\"%s\" u 2:1 t \"center points\" w p pt 2 lt rgb \"blue\" ps 1.2, "
1641 "\"%s\" u 3:1 t \"edge points left\" w p pt 2 lt rgb \"red\" ps 0.8, "
1642 "\"%s\" u 4:1 t \"edge points right\" w p pt 2 lt rgb \"green\" ps 0.8",
1643 s_out, s_out, s_out);
1646 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1647 fprintf(gp,
", p%02hu0(t),t t \"center\" w l lt rgb \"dark-blue\" lw 2, "
1648 "p%02hu1(t),t t \"left\" w l lt rgb \"dark-red\" lw 1, "
1649 "p%02hu2(t),t t \"right\" w l lt rgb \"forest-green\" lw 1",
1650 nslice, nslice, nslice);
1658 printf(
"Press ENTER to end program and close plot\n");
1668 return CPL_ERROR_NONE;
1670 return CPL_ERROR_UNSUPPORTED_MODE;
1699 unsigned short aSlice2)
1701 #if HAVE_POPEN && HAVE_PCLOSE
1702 cpl_ensure_code(aSamples, CPL_ERROR_NULL_INPUT);
1704 cpl_ensure_code(rc == CPL_ERROR_NONE, rc);
1706 if (aSlice1 < 1 || aSlice1 > kMuseSlicesPerCCD || aSlice1 > aSlice2 ||
1707 aSlice2 < 1 || aSlice2 > kMuseSlicesPerCCD) {
1708 fprintf(stderr,
"Warning: resetting slice numbers (%hu to %hu does not make"
1709 " sense)!\n", aSlice1, aSlice2);
1710 aSlice1 = kMuseSlicesPerCCD / 2;
1711 aSlice2 = kMuseSlicesPerCCD / 2 + 1;
1713 printf(
"Plotting slices %hu to %hu\n", aSlice1, aSlice2);
1715 FILE *gp = popen(
"gnuplot",
"w");
1717 return CPL_ERROR_ASSIGNING_STREAM;
1720 int nrow = cpl_table_get_nrow(aSamples);
1721 const int *sdata = cpl_table_get_data_int_const(aSamples,
"slice");
1722 const float *ydata = cpl_table_get_data_float_const(aSamples,
"y"),
1723 *ldata = cpl_table_get_data_float_const(aSamples,
"left"),
1724 *rdata = cpl_table_get_data_float_const(aSamples,
"right");
1727 fprintf(gp,
"set title \"trace slice widths, slices %hu to %hu\"\n",
1729 fprintf(gp,
"set key outside below\n");
1731 fprintf(gp,
"set xrange [%d:%d]\n", 1, kMuseOutputYTop);
1732 fprintf(gp,
"set yrange [%f:%f]\n", kMuseSliceLoLikelyWidth,
1733 kMuseSliceHiLikelyWidth);
1734 fprintf(gp,
"set xlabel \"y position on CCD [pix]\"\n");
1735 fprintf(gp,
"set ylabel \"slice width at y position [pix]\"\n");
1738 double dslice = (aSlice2 - aSlice1) / 255.;
1743 fprintf(gp,
"plot ");
1744 unsigned short nslice;
1745 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1748 fprintf(gp,
"\"-\" t \"slice %02hu\" w lp ps 0.8 lt rgb \"#%02x%02x%02x\"",
1750 (
int)((nslice - aSlice1) / dslice),
1751 (
int)((aSlice2 - nslice) / dslice),
1753 if (nslice == aSlice2) {
1760 for (nslice = aSlice1; nslice <= aSlice2; nslice++) {
1762 for (i = 0; i < nrow; i++) {
1763 if (nslice == sdata[i]) {
1764 fprintf(gp,
"%f %f\n", ydata[i], rdata[i]-ldata[i]);
1767 fprintf(gp,
"EOF\n");
1774 printf(
"Press ENTER to end program and close plot\n");
1777 return CPL_ERROR_NONE;
1779 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
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_error_code muse_trace_plot_samples(cpl_table *aSamples, cpl_table *aTrace, unsigned short aSlice1, unsigned short aSlice2, muse_image *aImage)
Plotting of trace sample points and solution using gnuplot.
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
cpl_vector * muse_trace_locate_slices(cpl_vector *aRowVec, const unsigned short aNSlices, double aFrac)
Find all slice midpoints across a CCD.
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 exposure time
Structure definition of MUSE three extension FITS file.
cpl_propertylist * header
the FITS header
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.
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.
static cpl_polynomial ** muse_trace_iterate_fit(cpl_matrix *aX, cpl_vector *aY, cpl_vector *aWidths, const unsigned short aSlice, const unsigned int aFitorder, const float aWSigma, const float aRSigma, cpl_vector *aMSE)
iterate the tracing solution to remove outliers
cpl_error_code muse_cplvector_erase_element(cpl_vector *aVector, int aElement)
delete the given element from the input vector
double muse_trace_edgefinder(const cpl_vector *aDataVec, double aFrac, double *aLeft, double *aRight, cpl_boolean *aHighSN)
Find the midpoint and edges of a cut through a slice.
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.
static double muse_trace_refine_edge(cpl_vector *aDiffVec, double *aLeft, double *aRight, int aOffset, double aY)
Find more exact midpoint and edge positions using a difference vector of the input data...
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_error_code muse_trace_plot_widths(cpl_table *aSamples, unsigned short aSlice1, unsigned short aSlice2)
Plotting the width from trace sample points using gnuplot.