Changeset 30631 for branches/czw_branch/20101203/psModules
- Timestamp:
- Feb 14, 2011, 1:05:28 PM (15 years ago)
- Location:
- branches/czw_branch/20101203
- Files:
-
- 55 edited
- 1 copied
-
. (modified) (1 prop)
-
psModules/src/extras/pmVisual.c (modified) (2 diffs)
-
psModules/src/extras/pmVisual.h (modified) (1 diff)
-
psModules/src/imcombine/Makefile.am (modified) (1 diff)
-
psModules/src/imcombine/pmReadoutCombine.c (modified) (1 diff)
-
psModules/src/imcombine/pmStackReject.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtraction.c (modified) (14 diffs)
-
psModules/src/imcombine/pmSubtraction.h (modified) (4 diffs)
-
psModules/src/imcombine/pmSubtractionAnalysis.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionDeconvolve.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionEquation.c (modified) (42 diffs)
-
psModules/src/imcombine/pmSubtractionEquation.h (modified) (3 diffs)
-
psModules/src/imcombine/pmSubtractionEquation.v0.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionHermitian.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionIO.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionKernels.c (modified) (18 diffs)
-
psModules/src/imcombine/pmSubtractionKernels.h (modified) (3 diffs)
-
psModules/src/imcombine/pmSubtractionMask.c (modified) (1 diff)
-
psModules/src/imcombine/pmSubtractionMatch.c (modified) (28 diffs)
-
psModules/src/imcombine/pmSubtractionMatch.h (modified) (3 diffs)
-
psModules/src/imcombine/pmSubtractionParams.c (modified) (2 diffs)
-
psModules/src/imcombine/pmSubtractionStamps.c (modified) (12 diffs)
-
psModules/src/imcombine/pmSubtractionStamps.h (modified) (3 diffs)
-
psModules/src/imcombine/pmSubtractionThreads.c (modified) (2 diffs)
-
psModules/src/imcombine/pmSubtractionTypes.h (copied) (copied from trunk/psModules/src/imcombine/pmSubtractionTypes.h )
-
psModules/src/imcombine/pmSubtractionVisual.c (modified) (13 diffs)
-
psModules/src/imcombine/pmSubtractionVisual.h (modified) (1 diff)
-
psModules/src/objects (modified) (1 prop)
-
psModules/src/objects/pmFootprint.c (modified) (1 diff)
-
psModules/src/objects/pmFootprint.h (modified) (1 diff)
-
psModules/src/objects/pmFootprintAssignPeaks.c (modified) (4 diffs)
-
psModules/src/objects/pmFootprintCullPeaks.c (modified) (3 diffs)
-
psModules/src/objects/pmModel.c (modified) (2 diffs)
-
psModules/src/objects/pmModel.h (modified) (1 diff)
-
psModules/src/objects/pmPCMdata.h (modified) (1 diff)
-
psModules/src/objects/pmPSFtry.c (modified) (1 diff)
-
psModules/src/objects/pmPSFtryFitEXT.c (modified) (3 diffs)
-
psModules/src/objects/pmPSFtryFitPSF.c (modified) (1 diff)
-
psModules/src/objects/pmPSFtryModel.c (modified) (2 diffs)
-
psModules/src/objects/pmSource.c (modified) (10 diffs)
-
psModules/src/objects/pmSource.h (modified) (5 diffs)
-
psModules/src/objects/pmSourceExtendedPars.c (modified) (1 diff)
-
psModules/src/objects/pmSourceFitPCM.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO.c (modified) (13 diffs)
-
psModules/src/objects/pmSourceIO.h (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c (modified) (7 diffs)
-
psModules/src/objects/pmSourceIO_CMF_PS1_V1.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_CMF_PS1_V2.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_CMF_PS1_V3.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_PS1_CAL_0.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_PS1_DEV_0.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_PS1_DEV_1.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_SMPDATA.c (modified) (1 diff)
-
psModules/src/psmodules.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/czw_branch/20101203
- Property svn:mergeinfo changed
-
branches/czw_branch/20101203/psModules/src/extras/pmVisual.c
r29545 r30631 16 16 #include <pslib.h> 17 17 18 #include "pmHDU.h" 19 #include "pmFPA.h" 20 #include "pmFPAfile.h" 21 #include "pmAstrometryObjects.h" 22 #include "pmSubtractionStamps.h" 23 24 #include "pmTrend2D.h" 25 #include "pmResiduals.h" 26 #include "pmGrowthCurve.h" 27 #include "pmSpan.h" 28 #include "pmFootprintSpans.h" 29 #include "pmFootprint.h" 30 #include "pmPeaks.h" 31 #include "pmMoments.h" 32 #include "pmModelFuncs.h" 33 #include "pmModel.h" 34 #include "pmSourceMasks.h" 35 #include "pmSourceExtendedPars.h" 36 #include "pmSourceDiffStats.h" 37 #include "pmSource.h" 38 #include "pmSourceFitModel.h" 39 #include "pmPSF.h" 40 #include "pmPSFtry.h" 41 42 #include "pmFPAExtent.h" 43 44 #include "pmAstrometryVisual.h" 45 #include "pmSubtractionVisual.h" 46 #include "pmStackVisual.h" 47 #include "pmSourceVisual.h" 18 bool pmSubtractionVisualClose(void); 19 bool pmAstromVisualClose(void); 20 bool pmSubtractionVisualClose(void); 21 bool pmStackVisualClose(void); 22 bool pmSourceVisualClose(void); 23 24 // #include "pmHDU.h" 25 // #include "pmFPA.h" 26 // #include "pmFPAfile.h" 27 // #include "pmAstrometryObjects.h" 28 // #include "pmSubtractionStamps.h" 29 // #include "pmTrend2D.h" 30 // #include "pmResiduals.h" 31 // #include "pmGrowthCurve.h" 32 // #include "pmSpan.h" 33 // #include "pmFootprintSpans.h" 34 // #include "pmFootprint.h" 35 // #include "pmPeaks.h" 36 // #include "pmMoments.h" 37 // #include "pmModelFuncs.h" 38 // #include "pmModel.h" 39 // #include "pmSourceMasks.h" 40 // #include "pmSourceExtendedPars.h" 41 // #include "pmSourceDiffStats.h" 42 // #include "pmSource.h" 43 // #include "pmSourceFitModel.h" 44 // #include "pmPSF.h" 45 // #include "pmPSFtry.h" 46 // #include "pmFPAExtent.h" 47 // #include "pmAstrometryVisual.h" 48 // #include "pmSubtractionVisual.h" 49 // #include "pmStackVisual.h" 50 // #include "pmSourceVisual.h" 48 51 49 52 # if (HAVE_KAPA) … … 306 309 } 307 310 311 bool pmVisualRangeImage (int kapaFD, psImage *inImage, const char *name, int channel, float min, float max) { 312 313 KiiImage image; 314 KapaImageData data; 315 Coords coords; 316 317 strcpy (coords.ctype, "RA---TAN"); 318 319 image.data2d = inImage->data.F32; 320 image.Nx = inImage->numCols; 321 image.Ny = inImage->numRows; 322 323 strcpy (data.name, name); 324 strcpy (data.file, name); 325 data.zero = min; 326 data.range = max - min; 327 data.logflux = 0; 328 329 KiiSetChannel (kapaFD, channel); 330 KiiNewPicture2D (kapaFD, &image, &data, &coords); 331 332 return true; 333 } 308 334 309 335 psImage* pmVisualImageToFloat(psImage *image) { -
branches/czw_branch/20101203/psModules/src/extras/pmVisual.h
r23242 r30631 64 64 const char *name, int channel, bool clip); 65 65 66 bool pmVisualRangeImage (int kapaFD, psImage *inImage, const char *name, int channel, float min, float max); 66 67 67 68 /** Calculate statistics on an image. -
branches/czw_branch/20101203/psModules/src/imcombine/Makefile.am
r26893 r30631 30 30 pmStackReject.h \ 31 31 pmSubtraction.h \ 32 pmSubtractionTypes.h \ 32 33 pmSubtractionAnalysis.h \ 33 34 pmSubtractionEquation.h \ -
branches/czw_branch/20101203/psModules/src/imcombine/pmReadoutCombine.c
r24907 r30631 33 33 params->blank = 0; 34 34 params->nKeep = 0; 35 params->frac High= 0.0;35 params->fracLow = 0.0; 36 36 params->fracHigh = 0.0; 37 37 params->iter = 1; -
branches/czw_branch/20101203/psModules/src/imcombine/pmStackReject.c
r28405 r30631 7 7 #include <pslib.h> 8 8 9 #include "pmFPA.h" 10 #include "pmSubtractionTypes.h" 9 11 #include "pmSubtraction.h" 10 12 #include "pmSubtractionThreads.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtraction.c
r29777 r30631 20 20 #include "pmHDU.h" // Required for pmFPA.h 21 21 #include "pmFPA.h" 22 #include "pmSubtractionTypes.h" 22 23 #include "pmSubtractionStamps.h" 23 24 #include "pmSubtractionEquation.h" 24 25 #include "pmSubtractionVisual.h" 25 26 #include "pmSubtractionThreads.h" 27 28 bool psFitsWriteImageSimple (char *filename, psImage *image, psMetadata *header); 26 29 27 30 #include "pmSubtraction.h" … … 773 776 774 777 if (convolutions) { 775 // Already done776 778 return convolutions; 777 779 } … … 787 789 } 788 790 791 792 bool pmSubtractionConvolveStampThread(psThreadJob *job) 793 { 794 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 795 796 pmSubtractionStamp *stamp = job->args->data[0]; // List of stamps 797 pmSubtractionKernels *kernels = job->args->data[1]; // Kernels 798 int footprint = PS_SCALAR_VALUE(job->args->data[2], S32); // Stamp index 799 800 return pmSubtractionConvolveStamp(stamp, kernels, footprint); 801 } 789 802 790 803 bool pmSubtractionConvolveStamp (pmSubtractionStamp *stamp, pmSubtractionKernels *kernels, int footprint) … … 818 831 } 819 832 833 #ifdef TESTING 834 for (int j = 0; j < kernels->num; j++) { 835 if (stamp->convolutions1) { 836 psString convName = NULL; 837 psStringAppend(&convName, "conv1_%03d_%03d.fits", index, j); 838 psFits *fits = psFitsOpen(convName, "w"); 839 psFree(convName); 840 psKernel *conv = stamp->convolutions1->data[j]; 841 psFitsWriteImage(fits, NULL, conv->image, 0, NULL); 842 psFitsClose(fits); 843 } 844 845 if (stamp->convolutions2) { 846 psString convName = NULL; 847 psStringAppend(&convName, "conv2_%03d_%03d.fits", index, j); 848 psFits *fits = psFitsOpen(convName, "w"); 849 psFree(convName); 850 psKernel *conv = stamp->convolutions2->data[j]; 851 psFitsWriteImage(fits, NULL, conv->image, 0, NULL); 852 psFitsClose(fits); 853 } 854 } 855 #endif 856 820 857 return true; 821 858 } 822 859 860 bool pmSubtractionConvolveStamps(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels) 861 { 862 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 863 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 864 865 psTimerStart("pmSubtractionConvolveStamps"); 866 867 int footprint = stamps->footprint; // Half-size of stamps 868 869 // We iterate over each stamp and generate the convolution if needed. We do NOT need the 870 // convolution if (a) it has already been calculated or (b) the stamp is not available for 871 // use (available = USED or CALCULATE) 872 873 for (int i = 0; i < stamps->num; i++) { 874 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 875 876 bool keep = false; 877 keep |= (stamp->status == PM_SUBTRACTION_STAMP_USED); 878 keep |= (stamp->status == PM_SUBTRACTION_STAMP_CALCULATE); 879 if (!keep) continue; 880 881 bool haveConvolutions = false; 882 if (kernels->mode == PM_SUBTRACTION_MODE_1) { 883 haveConvolutions = (stamp->convolutions1 != NULL); 884 } 885 if (kernels->mode == PM_SUBTRACTION_MODE_2) { 886 haveConvolutions = (stamp->convolutions2 != NULL); 887 } 888 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 889 haveConvolutions = (stamp->convolutions1 != NULL) && (stamp->convolutions2 != NULL); 890 } 891 if (haveConvolutions) { 892 continue; 893 } 894 895 if (pmSubtractionThreaded()) { 896 psThreadJob *job = psThreadJobAlloc("PSMODULES_SUBTRACTION_CONVOLVE_STAMP"); 897 psArrayAdd(job->args, 1, stamp); 898 psArrayAdd(job->args, 1, kernels); 899 PS_ARRAY_ADD_SCALAR(job->args, footprint, PS_TYPE_S32); 900 if (!psThreadJobAddPending(job)) { 901 return false; 902 } 903 } else { 904 pmSubtractionConvolveStamp(stamp, kernels, footprint); 905 } 906 } 907 if (!psThreadPoolWait(true)) { 908 psError(psErrorCodeLast(), false, "Error waiting for threads."); 909 return false; 910 } 911 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolve stamps: %f sec", psTimerClear("pmSubtractionConvolveStamps")); 912 return true; 913 } 823 914 824 915 int pmSubtractionRejectStamps(pmSubtractionKernels *kernels, pmSubtractionStampList *stamps, 825 const psVector *deviations, psImage *subMask, float sigmaRej)916 pmSubtractionQuality *match, psImage *subMask, float sigmaRej) 826 917 { 827 918 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 828 919 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, -1); 829 PS_ASSERT_VECTOR_NON_NULL(deviations, -1);830 PS_ASSERT_VECTOR_TYPE(deviations, PS_TYPE_F32, -1);831 920 PS_ASSERT_IMAGE_NON_EMPTY(subMask, -1); 832 921 PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_IMAGE_MASK, -1); 833 922 834 // I used to measure the rms deviation about zero, and use that as the sigma against which to clip, but 835 // the distribution is actually something like a chi^2 or Student's t, both of which become Gaussian-like 836 // with large N. Therefore, let's just treat this as a Gaussian distribution. 923 // Comment from PAP (r18287): I used to measure the rms deviation about zero, and use that as the 924 // sigma against which to clip, but the distribution is actually something like a chi^2 or 925 // Student's t, both of which become Gaussian-like with large N. Therefore, let's just 926 // treat this as a Gaussian distribution. 927 928 // Comment from EAM (r29777): The residual distribution is only chisq-like if the model is 929 // a good fit to the data. In the (likely) case that there is a systematic difference 930 // between the model and the data, the squared-residual distribution grows quadratically 931 // with increasing flux: the systematic residual flux is a constant factor times the source 932 // flux; the squared-residual is then of the form (k0 + k1*flux)^2, where k0 comes from the 933 // Gaussian distributed residual and k1*flux is the systematic residual error. 934 935 // By rejecting sources with the largest squared-residuals, the rejection biases against 936 // the brighter sources; in severe cases, this pushes the measurement to the weakest 937 // sources with the most noise. To account for this, let's fit a 2nd order polynomial to 938 // the distribution of flux vs squared-residual, subtract that fit, and reject sources 939 // which are significantly deviant from that distribution. 837 940 838 941 kernels->mean = NAN; … … 840 943 kernels->numStamps = -1; 841 944 842 int numStamps = 0; // Number of used stamps 843 psVector *mask = psVectorAlloc(stamps->num, PS_TYPE_VECTOR_MASK); // Mask, for statistics 844 psVectorInit(mask, 0); 845 for (int i = 0; i < stamps->num; i++) { 846 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 847 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { 848 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xff; 849 continue; 850 } 851 numStamps++; 852 } 853 psTrace("psModules.imcombine", 1, "Number of good stamps: %d\n", numStamps); 854 855 if (numStamps == 0) { 856 psError(PM_ERR_STAMPS, true, "No good stamps found."); 857 psFree(mask); 858 return -1; 859 } 860 861 psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV | 862 PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE); // Statistics for deviatns 863 if (!psVectorStats(stats, deviations, NULL, mask, 0xff)) { 864 psError(PM_ERR_DATA, false, "Unable to measure statistics for deviations."); 945 psTrace("psModules.imcombine", 1, "Number of good stamps: %d\n", match->nGood); 946 947 // the chisq & flux vectors are calculated by pmSubtractionCalculateChisqAndMoments 948 949 // use 3hi/3lo sigma clipping on the chisq fit 950 psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV); 951 stats->clipSigma = 5.0; 952 stats->clipIter = 2; 953 psPolynomial1D *model = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2); 954 955 bool result = psVectorClipFitPolynomial1D(model, stats, match->stampMask, 0xff, match->chisq, NULL, match->fluxes); 956 if (!result) { 957 psError(PM_ERR_DATA, false, "Unable to measure statistics for deviations."); 958 psFree(model); 865 959 psFree(stats); 866 psFree(mask); 867 return -1; 868 } 869 psFree(mask); 870 871 // XXX raise an error? 960 return -1; 961 } 872 962 if (isnan(stats->sampleMean)) { 963 psError(PM_ERR_DATA, false, "Unable to measure statistics for deviations."); 964 psFree(model); 873 965 psFree(stats); 874 966 return -1; 875 967 } 876 968 877 double mean, rms; // Mean and RMS of deviations 878 if (numStamps < MIN_SAMPLE_STATS) { 879 mean = stats->sampleMean; 880 rms = stats->sampleStdev; 881 } else { 882 mean = stats->sampleMedian; 883 rms = 0.74 * (stats->sampleUQ - stats->sampleLQ); 884 } 885 psFree(stats); 886 887 psTrace("psModules.imcombine", 1, "Mean: %f\n", mean); 888 psTrace("psModules.imcombine", 1, "RMS deviation: %f\n", rms); 889 890 kernels->mean = mean; 891 kernels->rms = rms; 892 kernels->numStamps = numStamps; 893 894 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Mean deviation from %d stamps: %lf +/- %lf", 895 numStamps, mean, rms); 896 897 if (!isfinite(sigmaRej) || sigmaRej <= 0.0) { 898 // User just wanted to calculate and record the deviation for posterity 899 return 0; 900 } 901 902 float limit = sigmaRej * rms; // Limit on maximum deviation 903 psTrace("psModules.imcombine", 1, "Deviation limit: %f\n", limit); 904 969 kernels->mean = stats->sampleMean; 970 kernels->rms = stats->sampleStdev; 971 kernels->numStamps = stats->clippedNvalues; 972 973 psLogMsg ("pmPSFtry", 4, "chisq vs flux model: %e + %e flux + %e flux^2\n", model->coeff[0], model->coeff[1], model->coeff[2]); 974 psLogMsg ("pmPSFtry", 4, "chisq vs flux resid: %f +/- %f\n", stats->sampleMean, stats->sampleStdev); 975 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Mean deviation from %d stamps: %lf +/- %lf", kernels->numStamps, kernels->mean, kernels->rms); 905 976 906 977 psString ds9name = NULL; // Filename for ds9 region file … … 914 985 int numRejected = 0; // Number of stamps rejected 915 986 int numGood = 0; // Number of good stamps 916 double newMean = 0.0; // New mean917 987 psString log = NULL; // Log message 918 psStringAppend(&log, "Rejecting stamps, mean = %f, threshold = %f\n", mean, limit); 988 989 // save DS9 region files for the stamps and mark for rejection and replacement 919 990 for (int i = 0; i < stamps->num; i++) { 920 991 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 921 if (stamp->status == PM_SUBTRACTION_STAMP_USED) { 992 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { continue; } 993 if (match->stampMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) { 922 994 // Should we reject stars with low deviation? Well, if this is really a Gaussian-like 923 995 // distribution and they're low, then we have the right to ask why. Isn't it suspicious that … … 926 998 // subtract well, in which case very few (if any) stars will be legitimately rejected for being 927 999 // low. 928 if (fabsf(deviations->data.F32[i] - mean) > limit) { 929 // Mask out the stamp in the image so you it's not found again 930 psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d)\n", i, 931 (int)(stamp->x - 0.5), (int)(stamp->y - 0.5)); 932 psStringAppend(&log, "Stamp %d (%d,%d): %f\n", i, 933 (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), 934 fabsf(deviations->data.F32[i] - mean)); 935 numRejected++; 936 for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) { 937 for (int x = stamp->x - footprint; x <= stamp->x + footprint; x++) { 938 subMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= PM_SUBTRACTION_MASK_REJ; 939 } 940 } 941 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red"); 942 943 // Set stamp for replacement 944 stamp->x = 0; 945 stamp->y = 0; 946 stamp->xNorm = NAN; 947 stamp->yNorm = NAN; 948 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 949 // Recalculate convolutions 950 psFree(stamp->convolutions1); 951 psFree(stamp->convolutions2); 952 stamp->convolutions1 = stamp->convolutions2 = NULL; 953 psFree(stamp->image1); 954 psFree(stamp->image2); 955 psFree(stamp->weight); 956 stamp->image1 = stamp->image2 = stamp->weight = NULL; 957 psFree(stamp->matrix); 958 stamp->matrix = NULL; 959 psFree(stamp->vector); 960 stamp->vector = NULL; 961 } else { 962 numGood++; 963 newMean += deviations->data.F32[i]; 964 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 965 } 966 } 967 } 968 newMean /= numGood; 1000 psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d)\n", i, 1001 (int)(stamp->x - 0.5), (int)(stamp->y - 0.5)); 1002 psStringAppend(&log, "Stamp %d (%d,%d): %f : %f : %f\n", 1003 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), 1004 match->chisq->data.F32[i], match->fluxes->data.F32[i], match->chisq->data.F32[i] - psPolynomial1DEval(model, match->fluxes->data.F32[i])); 1005 numRejected++; 1006 for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) { 1007 for (int x = stamp->x - footprint; x <= stamp->x + footprint; x++) { 1008 subMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= PM_SUBTRACTION_MASK_REJ; 1009 } 1010 } 1011 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red"); 1012 1013 // Set stamp for replacement 1014 stamp->x = 0; 1015 stamp->y = 0; 1016 stamp->xNorm = NAN; 1017 stamp->yNorm = NAN; 1018 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 1019 // Recalculate convolutions 1020 psFree(stamp->convolutions1); 1021 psFree(stamp->convolutions2); 1022 stamp->convolutions1 = stamp->convolutions2 = NULL; 1023 psFree(stamp->image1); 1024 psFree(stamp->image2); 1025 psFree(stamp->weight); 1026 stamp->image1 = stamp->image2 = stamp->weight = NULL; 1027 psFree(stamp->matrix); 1028 stamp->matrix = NULL; 1029 psFree(stamp->vector); 1030 stamp->vector = NULL; 1031 } else { 1032 numGood++; 1033 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 1034 } 1035 } 969 1036 970 1037 if (numRejected == 0) { … … 978 1045 } 979 1046 1047 psFree(model); 1048 psFree(stats); 1049 980 1050 if (numRejected > 0) { 981 psLogMsg("psModules.imcombine", PS_LOG_INFO, 982 "%d good stamps; %d rejected.\nMean deviation: %lf --> %lf\n", 983 numGood, numRejected, mean, newMean); 1051 psLogMsg("psModules.imcombine", PS_LOG_INFO, "%d good stamps; %d rejected.\n", numGood, numRejected); 984 1052 } else { 985 psLogMsg("psModules.imcombine", PS_LOG_INFO, 986 "%d good stamps; 0 rejected.\nMean deviation: %lf\n", 987 numGood, mean); 1053 psLogMsg("psModules.imcombine", PS_LOG_INFO, "%d good stamps; 0 rejected.\n", numGood); 988 1054 } 989 1055 … … 1373 1439 psFree(kernelErr2); 1374 1440 1441 static int nOut1 = 0; 1442 static int nOut2 = 0; 1443 1375 1444 // Calculate covariances 1376 1445 // This can be fairly involved, so we only do it for a small number of instances … … 1386 1455 psKernelTruncate(kernel, covarFrac); 1387 1456 covars->data[i] = psImageCovarianceCalculate(kernel, ro1->covariance); 1457 if (0) { 1458 char name[128]; 1459 snprintf (name, 128, "covar.sample1.%03d.fits", nOut1); 1460 psKernel *cov = covars->data[i]; 1461 psFitsWriteImageSimple (name, cov->image, NULL); 1462 1463 snprintf (name, 128, "incovar.sample1.%03d.fits", nOut1); 1464 psFitsWriteImageSimple (name, ro1->covariance->image, NULL); 1465 1466 snprintf (name, 128, "conv.sample1.%03d.fits", nOut1); 1467 psFitsWriteImageSimple (name, kernel->image, NULL); 1468 1469 fprintf (stderr, "incov: %d,%d; kern: %d,%d, outcov: %d,%d\n", 1470 ro1->covariance->image->numCols, ro1->covariance->image->numRows, 1471 kernel->image->numCols, kernel->image->numRows, 1472 cov->image->numCols, cov->image->numRows); 1473 1474 nOut1 ++; 1475 } 1388 1476 psFree(kernel); 1389 1477 } … … 1407 1495 psKernelTruncate(kernel, covarFrac); 1408 1496 covars->data[i] = psImageCovarianceCalculate(kernel, ro2->covariance); 1497 if (0) { 1498 char name[128]; 1499 snprintf (name, 128, "covar.sample2.%03d.fits", nOut2); 1500 psKernel *cov = covars->data[i]; 1501 psFitsWriteImageSimple (name, cov->image, NULL); 1502 1503 snprintf (name, 128, "incovar.sample2.%03d.fits", nOut2); 1504 psFitsWriteImageSimple (name, ro2->covariance->image, NULL); 1505 1506 snprintf (name, 128, "conv.sample2.%03d.fits", nOut2); 1507 psFitsWriteImageSimple (name, kernel->image, NULL); 1508 1509 fprintf (stderr, "incov: %d,%d; kern: %d,%d, outcov: %d,%d\n", 1510 ro2->covariance->image->numCols, ro2->covariance->image->numRows, 1511 kernel->image->numCols, kernel->image->numRows, 1512 cov->image->numCols, cov->image->numRows); 1513 1514 nOut2 ++; 1515 } 1409 1516 psFree(kernel); 1410 1517 } … … 1422 1529 psImageCovarianceSetThreads(oldThreads); 1423 1530 1424 // Copy anything that wasn't convolved 1531 // Copy anything that wasn't convolved (they may have been allocated though, so free them) 1425 1532 switch (kernels->mode) { 1426 1533 case PM_SUBTRACTION_MODE_1: 1427 1534 if (out2) { 1535 psFree(out2->image); 1536 psFree(out2->variance); 1537 psFree(out2->mask); 1538 psFree(out2->covariance); 1428 1539 out2->image = psMemIncrRefCounter(ro2->image); 1429 1540 out2->variance = psMemIncrRefCounter(ro2->variance); … … 1434 1545 case PM_SUBTRACTION_MODE_2: 1435 1546 if (out1) { 1547 psFree(out1->image); 1548 psFree(out1->variance); 1549 psFree(out1->mask); 1550 psFree(out1->covariance); 1436 1551 out1->image = psMemIncrRefCounter(ro1->image); 1437 1552 out1->variance = psMemIncrRefCounter(ro1->variance); … … 1479 1594 return true; 1480 1595 } 1596 1597 static void pmSubtractionQualityFree(pmSubtractionQuality *quality) { 1598 1599 psFree (quality->fluxes); 1600 psFree (quality->chisq); 1601 psFree (quality->moments); 1602 psFree (quality->stampMask); 1603 } 1604 1605 pmSubtractionQuality *pmSubtractionQualityAlloc() { 1606 1607 pmSubtractionQuality *quality = psAlloc(sizeof(pmSubtractionQuality)); // Stamp list to return 1608 psMemSetDeallocator(quality, (psFreeFunc)pmSubtractionQualityFree); 1609 1610 quality->fluxes = NULL; 1611 quality->chisq = NULL; 1612 quality->moments = NULL; 1613 quality->stampMask = NULL; 1614 1615 quality->score = NAN; 1616 quality->mode = PM_SUBTRACTION_MODE_ERR; 1617 quality->spatialOrder = -1; 1618 quality->nGood = 0; 1619 1620 return quality; 1621 } -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtraction.h
r29601 r30631 14 14 #define PM_SUBTRACTION_H 15 15 16 #include <pslib.h> 17 18 #include <pmHDU.h> 19 #include <pmFPA.h> 20 #include <pmSubtractionKernels.h> 21 #include <pmSubtractionStamps.h> 16 // #include <pslib.h> 17 // #include <pmHDU.h> 18 // #include <pmFPA.h> 19 // #include <pmSubtractionKernels.h> 20 // #include <pmSubtractionStamps.h> 22 21 23 22 // if we use the original ppSub implementation, we subtract a central delta-function for all … … 30 29 /// @addtogroup imcombine Image Combinations 31 30 /// @{ 32 33 /// Mask values for the subtraction mask34 typedef enum {35 PM_SUBTRACTION_MASK_CLEAR = 0x00, // No masking36 PM_SUBTRACTION_MASK_BAD_1 = 0x01, // Image 1 is bad37 PM_SUBTRACTION_MASK_BAD_2 = 0x02, // Image 2 is bad38 PM_SUBTRACTION_MASK_CONVOLVE_1 = 0x04, // If image 1 is convolved, would be poor or bad39 PM_SUBTRACTION_MASK_CONVOLVE_2 = 0x08, // If image 2 is convolved, would be poor or bad40 PM_SUBTRACTION_MASK_CONVOLVE_BAD_1 = 0x10, // If image 1 is convolved, would be bad41 PM_SUBTRACTION_MASK_CONVOLVE_BAD_2 = 0x20, // If image 2 is convolved, would be bad42 PM_SUBTRACTION_MASK_BORDER = 0x40, // Image border43 PM_SUBTRACTION_MASK_REJ = 0x80, // Previously tried as a stamp, and rejected44 } pmSubtractionMasks;45 46 31 47 32 /// Number of terms in a polynomial … … 70 55 ); 71 56 57 bool pmSubtractionConvolveStamps(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels); 58 59 bool pmSubtractionConvolveStampThread(psThreadJob *job); 60 72 61 /// Reject stamps 73 62 int pmSubtractionRejectStamps(pmSubtractionKernels *kernels, ///< Kernel parameters to update 74 63 pmSubtractionStampList *stamps, ///< Stamps 75 const psVector *deviations, ///< Deviations for each stamp64 pmSubtractionQuality *match, ///< data on the subtraction quality 76 65 psImage *subMask, ///< Subtraction mask 77 66 float sigmaRej ///< Number of RMS deviations above zero at which to reject … … 167 156 bool pmSubtractionSetFWHMs(float fwhm1, float fwhm2); 168 157 158 pmSubtractionQuality *pmSubtractionQualityAlloc(); 159 169 160 /// @} 170 161 #endif -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionAnalysis.c
r29595 r30631 7 7 8 8 #include "pmFPA.h" 9 #include "pmSubtractionTypes.h" 9 10 #include "pmSubtraction.h" 10 11 #include "pmSubtractionKernels.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionDeconvolve.c
r26893 r30631 10 10 11 11 #include "pmFPA.h" 12 #include "pmSubtractionTypes.h" 12 13 #include "pmSubtractionKernels.h" 13 14 #include "pmSubtractionDeconvolve.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionEquation.c
r29598 r30631 8 8 9 9 #include "pmErrorCodes.h" 10 #include "pmVisual.h" 11 #include "pmFPA.h" 12 #include "pmSubtractionTypes.h" 10 13 #include "pmSubtraction.h" 11 14 #include "pmSubtractionKernels.h" … … 16 19 #include "pmSubtractionVisual.h" 17 20 18 //#define TESTING // TESTING output for debugging; may not work with threads! 19 20 //#define USE_WEIGHT // Include weight (1/variance) in equation? 21 22 // XXX TEST: 23 //# define USE_WINDOW // window to avoid neighbor contamination 21 //# define TESTING // TESTING output for debugging; may not work with threads! 22 # define USE_WEIGHT // Include weight (1/variance) in equation? 23 # define USE_WINDOW // window to avoid neighbor contamination 24 25 /* I believe we want to apply the WEIGHT to the chisq portions of the calculation (but not the WINDOW), 26 * and the WINDOW to the moments portiosn of the calculations (but not the WEIGHT) 27 * 28 */ 24 29 25 30 # define PENALTY false 26 31 # define MOMENTS (!PENALTY) 27 # define MOMENTS_PENALTY_SCALE 2 e-5 // XXX this value is not completely arbitrary, but I don't understand why it needs to be this value...32 # define MOMENTS_PENALTY_SCALE 20 // up-weight the moments somewhat 28 33 29 34 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 107 112 cc *= weight->kernel[y][x]; 108 113 } 109 if (window) { 114 // XXX NOTE: do NOT apply the window to the chisq portions of the calculation 115 if (false && window) { 110 116 cc *= window->kernel[y][x]; 111 117 } … … 138 144 rc *= wtVal; 139 145 } 140 if (window) { 146 // XXX NOTE: do NOT apply the window to the chisq portions of the calculation 147 if (false && window) { 141 148 float winVal = window->kernel[y][x]; 142 149 ic *= winVal; … … 173 180 } 174 181 182 # define RENORM_BY_FLUX 0 175 183 176 184 // Calculate the least-squares matrix and vector for dual convolution … … 268 276 for (int y = - footprint; y <= footprint; y++) { 269 277 for (int x = - footprint; x <= footprint; x++) { 278 279 // XXX NOTE: clipping low S/N pixels does not seem to work very well 280 if (false && weight) { 281 float i1 = image1->kernel[y][x]; 282 float i2 = image2->kernel[y][x]; 283 float sn = (i1 + i2) / sqrt (weight->kernel[y][x]); 284 if (sn < 0.5) continue; 285 } 286 270 287 double aa = iConv1->kernel[y][x] * jConv1->kernel[y][x] * PS_SQR(normValue); 271 288 double bb = iConv2->kernel[y][x] * jConv2->kernel[y][x]; 272 289 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] * normValue; 273 if (weight) { 274 float wtVal = weight->kernel[y][x]; 275 aa *= wtVal; 276 bb *= wtVal; 277 ab *= wtVal; 278 } 279 if (window) { 280 float wtVal = window->kernel[y][x]; 281 aa *= wtVal; 282 bb *= wtVal; 283 ab *= wtVal; 284 } 285 sumAA += aa; 286 sumBB += bb; 287 sumAB += ab; 290 291 float wtVal = (weight) ? weight->kernel[y][x] : 1.0; 292 sumAA += wtVal*aa; 293 sumBB += wtVal*bb; 294 sumAB += wtVal*ab; 288 295 289 296 if (MOMENTS) { 290 MxxAA += x*x*aa; 291 MyyAA += y*y*aa; 292 MxxBB += x*x*bb; 293 MyyBB += y*y*bb; 297 float winVal = (window) ? window->kernel[y][x] : 1.0; 298 MxxAA += winVal*x*x*aa; 299 MyyAA += winVal*y*y*aa; 300 MxxBB += winVal*x*x*bb; 301 MyyBB += winVal*y*y*bb; 294 302 } 295 303 } 296 304 } 297 305 306 // XXX does normSquare1,2 mess up the relative scaling? 307 // XXX no: normSquare1,2 is the sum of the flux^2 for the source 298 308 if (MOMENTS) { 299 309 MxxAA /= stamp->normSquare1 * PS_SQR(normValue); … … 305 315 // XXX this makes the Chisq portion independent of the normalization and star flux 306 316 // but may be mis-scaling between stars of different fluxes 317 # if (RENORM_BY_FLUX) 307 318 sumAA /= PS_SQR(stamp->normI2); 308 319 sumAB /= PS_SQR(stamp->normI2); 309 320 sumBB /= PS_SQR(stamp->normI2); 321 # endif 310 322 311 323 // fprintf (stderr, "i,j : %d %d : M(xx,yy)(AA,BB) : %f %f %f %f\n", i, j, MxxAA, MyyAA, MxxBB, MyyBB); … … 328 340 matrix->data.F64[iIndex][jIndex] += kernels->penalty * MxxAA * MOMENTS_PENALTY_SCALE; 329 341 matrix->data.F64[iIndex][jIndex] += kernels->penalty * MyyAA * MOMENTS_PENALTY_SCALE; 330 331 342 matrix->data.F64[jIndex][iIndex] += kernels->penalty * MxxAA * MOMENTS_PENALTY_SCALE; 332 343 matrix->data.F64[jIndex][iIndex] += kernels->penalty * MyyAA * MOMENTS_PENALTY_SCALE; … … 334 345 matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MxxBB * MOMENTS_PENALTY_SCALE; 335 346 matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MyyBB * MOMENTS_PENALTY_SCALE; 336 337 347 matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MxxBB * MOMENTS_PENALTY_SCALE; 338 348 matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MyyBB * MOMENTS_PENALTY_SCALE; … … 354 364 ab *= weight->kernel[y][x]; 355 365 } 356 if (window) { 366 // XXX NOTE: do NOT apply the window to the chisq portions of the calculation 367 if (false && window) { 357 368 ab *= window->kernel[y][x]; 358 369 } … … 363 374 // XXX this makes the Chisq portion independent of the normalization and star flux 364 375 // but may be mis-scaling between stars of different fluxes 376 # if (RENORM_BY_FLUX) 365 377 sumAB /= PS_SQR(stamp->normI2); 378 # endif 366 379 367 380 // Spatial variation of kernel coeffs … … 391 404 float i2 = image2->kernel[y][x]; 392 405 406 // XXX NOTE: clipping low S/N pixels does not seem to work very well 407 if (false && weight) { 408 float sn = (i1 + i2) / sqrt (weight->kernel[y][x]); 409 if (sn < 0.5) continue; 410 } 411 393 412 double ai2 = a * i2 * normValue; 394 413 double bi2 = b * i2; … … 396 415 double bi1 = b * i1 * normValue; 397 416 398 if (weight) { 399 float wtVal = weight->kernel[y][x]; 400 ai2 *= wtVal; 401 bi2 *= wtVal; 402 ai1 *= wtVal; 403 bi1 *= wtVal; 404 } 405 if (window) { 406 float wtVal = window->kernel[y][x]; 407 ai2 *= wtVal; 408 bi2 *= wtVal; 409 ai1 *= wtVal; 410 bi1 *= wtVal; 411 } 412 sumAI2 += ai2; 413 sumBI2 += bi2; 414 sumAI1 += ai1; 415 sumBI1 += bi1; 417 float wtVal = (weight) ? weight->kernel[y][x] : 1.0; 418 sumAI2 += wtVal*ai2; 419 sumBI2 += wtVal*bi2; 420 sumAI1 += wtVal*ai1; 421 sumBI1 += wtVal*bi1; 416 422 417 423 if (MOMENTS) { 418 MxxAI1 += x*x*ai1; 419 MyyAI1 += y*y*ai1; 420 MxxBI2 += x*x*bi2; 421 MyyBI2 += y*y*bi2; 424 float winVal = (window) ? window->kernel[y][x] : 1.0; 425 MxxAI1 += winVal*x*x*ai1; 426 MyyAI1 += winVal*y*y*ai1; 427 MxxBI2 += winVal*x*x*bi2; 428 MyyBI2 += winVal*y*y*bi2; 422 429 } 423 430 } … … 435 442 // XXX this makes the Chisq portion independent of the normalization and star flux 436 443 // but may be mis-scaling between stars of different fluxes 444 # if (RENORM_BY_FLUX) 437 445 sumAI1 /= PS_SQR(stamp->normI2); 438 446 sumBI1 /= PS_SQR(stamp->normI2); 439 447 sumAI2 /= PS_SQR(stamp->normI2); 440 448 sumBI2 /= PS_SQR(stamp->normI2); 449 # endif 441 450 442 451 // Spatial variation … … 788 797 stamp->normSquare2 = normSquare2; 789 798 790 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "normValue: %f %f %f (%f %f)\n", normI1, normI2, stamp->norm, normSquare1, normSquare2);799 // psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "normValue: %f %f %f (%f %f)\n", normI1, normI2, stamp->norm, normSquare1, normSquare2); 791 800 792 801 return true; … … 800 809 pmSubtractionKernels *kernels = job->args->data[1]; // Kernels 801 810 int index = PS_SCALAR_VALUE(job->args->data[2], S32); // Stamp index 802 pmSubtractionEquationCalculationMode mode = PS_SCALAR_VALUE(job->args->data[3], S32); // calculation model 803 804 return pmSubtractionCalculateEquationStamp(stamps, kernels, index, mode); 805 } 806 807 bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels, 808 int index, const pmSubtractionEquationCalculationMode mode) 811 812 return pmSubtractionCalculateEquationStamp(stamps, kernels, index); 813 } 814 815 bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels, int index) 809 816 { 810 817 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); … … 833 840 psAssert(stamp->status == PM_SUBTRACTION_STAMP_CALCULATE, "We only operate on stamps with this state."); 834 841 835 // Generate convolutions: these are generated once and saved 836 if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) { 837 psError(psErrorCodeLast(), false, "Unable to convolve stamp %d.", index); 838 return NULL; 839 } 840 841 #ifdef TESTING 842 for (int j = 0; j < numKernels; j++) { 843 if (stamp->convolutions1) { 844 psString convName = NULL; 845 psStringAppend(&convName, "conv1_%03d_%03d.fits", index, j); 846 psFits *fits = psFitsOpen(convName, "w"); 847 psFree(convName); 848 psKernel *conv = stamp->convolutions1->data[j]; 849 psFitsWriteImage(fits, NULL, conv->image, 0, NULL); 850 psFitsClose(fits); 851 } 852 853 if (stamp->convolutions2) { 854 psString convName = NULL; 855 psStringAppend(&convName, "conv2_%03d_%03d.fits", index, j); 856 psFits *fits = psFitsOpen(convName, "w"); 857 psFree(convName); 858 psKernel *conv = stamp->convolutions2->data[j]; 859 psFitsWriteImage(fits, NULL, conv->image, 0, NULL); 860 psFitsClose(fits); 861 } 862 } 863 #endif 864 865 // XXX visualize the set of convolved stamps 866 867 psImage *polyValues = p_pmSubtractionPolynomial(NULL, spatialOrder, 868 stamp->xNorm, stamp->yNorm); // Polynomial terms 869 870 bool new = stamp->vector ? false : true; // Is this a new run? 842 psImage *polyValues = p_pmSubtractionPolynomial(NULL, spatialOrder, stamp->xNorm, stamp->yNorm); // Polynomial terms 843 844 // Is this a new run? Have we allocated the correct sized vector/matrix? 845 bool new = stamp->vector ? false : true; 846 if (!new && (stamp->vector->n != numParams)) { 847 psFree (stamp->vector); 848 psFree (stamp->matrix); 849 new = true; 850 } 851 871 852 if (new) { 872 853 stamp->matrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); … … 941 922 } 942 923 943 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels, 944 const pmSubtractionEquationCalculationMode mode) 924 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels) 945 925 { 946 926 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); … … 953 933 for (int i = 0; i < stamps->num; i++) { 954 934 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 935 955 936 if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) { 956 937 continue; … … 969 950 psArrayAdd(job->args, 1, (pmSubtractionKernels*)kernels); // Casting away const to put on array 970 951 PS_ARRAY_ADD_SCALAR(job->args, i, PS_TYPE_S32); 971 PS_ARRAY_ADD_SCALAR(job->args, mode, PS_TYPE_S32);972 952 if (!psThreadJobAddPending(job)) { 973 953 return false; 974 954 } 975 955 } else { 976 pmSubtractionCalculateEquationStamp(stamps, kernels, i , mode);956 pmSubtractionCalculateEquationStamp(stamps, kernels, i); 977 957 } 978 958 } … … 983 963 } 984 964 985 pmSubtractionVisualPlotLeastSquares(stamps);986 965 pmSubtractionVisualShowKernels((pmSubtractionKernels *)kernels); 987 966 pmSubtractionVisualShowBasis(stamps); 988 989 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate equation: %f sec", 990 psTimerClear("pmSubtractionCalculateEquation")); 991 967 pmSubtractionVisualPlotLeastSquares(stamps); 968 969 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate equation: %f sec", psTimerClear("pmSubtractionCalculateEquation")); 992 970 993 971 return true; … … 998 976 bool psFitsWriteImageSimple (char *filename, psImage *image, psMetadata *header); 999 977 1000 psImage *p_pmSubSolve_wUt (psVector *w, psImage *U); 1001 psImage *p_pmSubSolve_VwUt (psImage *V, psImage *wUt); 1002 1003 bool p_pmSubSolve_SetWeights (psVector *wApply, psVector *w, psVector *wMask); 1004 1005 bool p_pmSubSolve_UtB (psVector **UtB, psImage *U, psVector *B); 1006 bool p_pmSubSolve_wUtB (psVector **wUtB, psVector *w, psVector *UtB); 1007 bool p_pmSubSolve_VwUtB (psVector **VwUtB, psImage *V, psVector *wUtB); 1008 1009 bool p_pmSubSolve_Ax (psVector **B, psImage *A, psVector *x); 1010 bool p_pmSubSolve_VdV (double *value, psVector *x, psVector *y); 1011 bool p_pmSubSolve_y2 (double *y2, pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps); 1012 1013 psImage *p_pmSubSolve_Xvar (psImage *V, psVector *w); 1014 1015 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps); 1016 1017 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, 1018 const pmSubtractionStampList *stamps, 1019 const pmSubtractionEquationCalculationMode mode) 978 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps) 1020 979 { 1021 980 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 1022 981 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 982 983 psTimerStart("pmSubtractionSolveEquation"); 1023 984 1024 985 // Check inputs … … 1042 1003 } 1043 1004 1005 if (stamp->vector->n != numParams) { 1006 fprintf (stderr, "mismatch length\n"); 1007 } 1044 1008 PS_ASSERT_VECTOR_NON_NULL(stamp->vector, false); 1045 1009 PS_ASSERT_VECTOR_SIZE(stamp->vector, (long)numParams, false); … … 1080 1044 } 1081 1045 1046 pmSubtractionVisualPlotLeastSquaresResid(stamps, sumMatrix, numStamps); 1047 1082 1048 #if 0 1083 1049 psImage *save = psImageCopy(NULL, sumMatrix, PS_TYPE_F32); … … 1087 1053 #endif 1088 1054 1055 // XXX TEST : print the matrix & vector 1056 if (0) { 1057 for (int iy = 0; iy < sumMatrix->numRows; iy++) { 1058 for (int ix = 0; ix < sumMatrix->numCols; ix++) { 1059 fprintf (stderr, "%e ", sumMatrix->data.F64[iy][ix]); 1060 } 1061 fprintf (stderr, " : %e\n", sumVector->data.F64[iy]); 1062 } 1063 } 1064 1065 psImage *invMatrix = NULL; 1089 1066 psVector *solution = NULL; // Solution to equation! 1090 1067 solution = psVectorAlloc(numParams, PS_TYPE_F64); … … 1094 1071 // solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1095 1072 // SINGLE solution 1096 if (1) { 1097 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1098 } else { 1099 psVector *PERM = NULL; 1100 psImage *LU = psMatrixLUDecomposition(NULL, &PERM, sumMatrix); 1101 solution = psMatrixLUSolution(solution, LU, sumVector, PERM); 1102 psFree (LU); 1103 psFree (PERM); 1104 } 1073 # if (1) 1074 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, 1e-10); 1075 invMatrix = psMatrixInvert(NULL, sumMatrix, NULL); 1076 # endif 1077 # if (0) 1078 psMatrixLUSolve(sumMatrixLU, sumVector); 1079 solution = psMemIncrRefCounter(sumVector); 1080 invMatrix = psMemIncrRefCounter(sumMatrix); 1081 # endif 1082 # if (0) 1083 psMatrixGJSolve(sumMatrix, sumVector); 1084 invMatrix = psMemIncrRefCounter(sumMatrix); 1085 solution = psMemIncrRefCounter(sumVector); 1086 # endif 1105 1087 1106 1088 # if (0) 1107 1089 for (int i = 0; i < solution->n; i++) { 1108 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Single solution %d: %lf \n", i, solution->data.F64[i]);1090 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Single solution %d: %lf +/- %lf\n", i, solution->data.F64[i], sqrt(fabs(invMatrix->data.F64[i][i]))); 1109 1091 } 1110 1092 # endif 1111 1093 1112 if (!kernels->solution1) { 1113 kernels->solution1 = psVectorAlloc(sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1114 psVectorInit(kernels->solution1, 0.0); 1115 } 1094 // ensure we have a solution vector of the right size 1095 kernels->solution1 = psVectorRecycle(kernels->solution1, sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1096 kernels->solution1err = psVectorRecycle(kernels->solution1err, sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1097 psVectorInit(kernels->solution1, 0.0); 1098 psVectorInit(kernels->solution1err, 0.0); 1116 1099 1117 1100 int numKernels = kernels->num; 1118 1101 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1119 1102 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1103 1120 1104 for (int i = 0; i < numKernels * numPoly; i++) { 1121 1105 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1106 kernels->solution1err->data.F64[i] = sqrt(invMatrix->data.F64[i][i]); 1122 1107 } 1123 1108 … … 1131 1116 psFree(sumVector); 1132 1117 psFree(sumMatrix); 1118 psFree(invMatrix); 1133 1119 1134 1120 } else { … … 1160 1146 } 1161 1147 1148 pmSubtractionVisualPlotLeastSquaresResid(stamps, sumMatrix, numStamps); 1149 1162 1150 #if 0 1163 1151 psImage *save = psImageCopy(NULL, sumMatrix, PS_TYPE_F32); … … 1171 1159 } 1172 1160 1161 // XXX TEST : print the matrix & vector 1162 if (0) { 1163 for (int iy = 0; iy < sumMatrix->numRows; iy++) { 1164 for (int ix = 0; ix < sumMatrix->numCols; ix++) { 1165 fprintf (stderr, "%e ", sumMatrix->data.F64[iy][ix]); 1166 } 1167 fprintf (stderr, " : %e\n", sumVector->data.F64[iy]); 1168 } 1169 } 1170 1171 psImage *invMatrix = NULL; 1173 1172 psVector *solution = NULL; // Solution to equation! 1174 1173 solution = psVectorAlloc(numParams, PS_TYPE_F64); … … 1176 1175 1177 1176 // DUAL solution 1178 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1177 # if (1) 1178 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, 1e-10); 1179 invMatrix = psMatrixInvert(NULL, sumMatrix, NULL); 1180 # endif 1181 # if (0) 1182 psMatrixLUSolve(sumMatrix, sumVector); 1183 solution = psMemIncrRefCounter(sumVector); 1184 invMatrix = psMemIncrRefCounter(sumMatrix); 1185 # endif 1179 1186 1180 1187 #if (0) 1181 1188 for (int i = 0; i < solution->n; i++) { 1182 fprintf(stderr, "Dual solution %d: %lf \n", i, solution->data.F64[i]);1189 fprintf(stderr, "Dual solution %d: %lf +/- %lf\n", i, solution->data.F64[i], sqrt(invMatrix->data.F64[i][i])); 1183 1190 } 1184 1191 #endif 1185 1192 1186 if (!kernels->solution1) { 1187 kernels->solution1 = psVectorAlloc(numSolution1 + 2, PS_TYPE_F64); 1188 psVectorInit (kernels->solution1, 0.0); 1189 } 1190 if (!kernels->solution2) { 1191 kernels->solution2 = psVectorAlloc(numSolution2, PS_TYPE_F64); 1192 psVectorInit (kernels->solution2, 0.0); 1193 } 1193 // XXX TEST: manually set the coeffs to a desired solution 1194 // solution->data.F64[0] = +1.826; 1195 // solution->data.F64[1] = -0.115; 1196 // solution->data.F64[2] = 0.0; 1197 // solution->data.F64[3] = 0.0; 1198 1199 // ensure we have solution vectors of the right size 1200 kernels->solution1 = psVectorRecycle(kernels->solution1, numSolution1 + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1201 kernels->solution1err = psVectorRecycle(kernels->solution1err, numSolution1 + 2, PS_TYPE_F64); // 1 for norm, 1 for bg 1202 kernels->solution2 = psVectorRecycle(kernels->solution2, numSolution2, PS_TYPE_F64); // 1 for norm, 1 for bg 1203 kernels->solution2err = psVectorRecycle(kernels->solution2err, numSolution2, PS_TYPE_F64); // 1 for norm, 1 for bg 1204 1205 psVectorInit(kernels->solution1, 0.0); 1206 psVectorInit(kernels->solution1err, 0.0); 1207 psVectorInit(kernels->solution2, 0.0); 1208 psVectorInit(kernels->solution2err, 0.0); 1194 1209 1195 1210 // for DUAL convolution analysis, we apply the normalization to I1 as follows: … … 1205 1220 kernels->solution1->data.F64[i] = solution->data.F64[i] * stamps->normValue; 1206 1221 kernels->solution2->data.F64[i] = solution->data.F64[i + numSolution1]; 1222 1223 kernels->solution1err->data.F64[i] = sqrt(invMatrix->data.F64[i][i]) * stamps->normValue; 1224 int i2 = i + numSolution1; 1225 kernels->solution2err->data.F64[i] = sqrt(invMatrix->data.F64[i2][i2]); 1207 1226 } 1208 1227 … … 1213 1232 kernels->solution1->data.F64[bgIndex] = 0.0; 1214 1233 1234 psFree(solution); 1235 psFree(sumVector); 1215 1236 psFree(sumMatrix); 1216 psFree(sumVector); 1217 psFree(solution); 1237 psFree(invMatrix); 1218 1238 } 1219 1239 … … 1224 1244 if (psTraceGetLevel("psModules.imcombine") >= 7) { 1225 1245 for (int i = 0; i < kernels->solution1->n; i++) { 1226 psTrace("psModules.imcombine", 7, "Solution 1 %d: %f \n", i, kernels->solution1->data.F64[i]);1246 psTrace("psModules.imcombine", 7, "Solution 1 %d: %f +/- %f\n", i, kernels->solution1->data.F64[i], kernels->solution1err->data.F64[i]); 1227 1247 } 1228 1248 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1229 1249 for (int i = 0; i < kernels->solution2->n; i++) { 1230 psTrace("psModules.imcombine", 7, "Solution 2 %d: %f \n", i, kernels->solution2->data.F64[i]);1250 psTrace("psModules.imcombine", 7, "Solution 2 %d: %f +/- %f\n", i, kernels->solution2->data.F64[i], kernels->solution2err->data.F64[i]); 1231 1251 } 1232 1252 } 1233 1253 } 1254 1255 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Solve equation: %f sec", psTimerClear("pmSubtractionSolveEquation")); 1234 1256 1235 1257 // pmSubtractionVisualPlotLeastSquares((pmSubtractionStampList *) stamps); //casting away const … … 1283 1305 } 1284 1306 1285 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, 1286 pmSubtractionKernels *kernels) 1307 // given the convolved image(s) and the residual image, calculate the second moment(s) and the chisq 1308 bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqDVector, psVector *chisqRVector, psVector *momentVector, psVector *stampMask, psKernel *convolved1, psKernel *convolved2, psKernel *difference, psKernel *residual, psKernel *weight, psKernel *window) { 1309 1310 # ifndef USE_WEIGHT 1311 psAssert(weight == NULL, "impossible!"); 1312 # endif 1313 # ifndef USE_WINDOW 1314 psAssert(window == NULL, "impossible!"); 1315 # endif 1316 1317 int npix = 0; 1318 float chisqR = 0; 1319 float chisqD = 0; 1320 1321 // get the chisq 1322 for (int y = residual->yMin; y <= residual->yMax; y++) { 1323 for (int x = residual->xMin; x <= residual->xMax; x++) { 1324 float valueR = PS_SQR(residual->kernel[y][x]); 1325 if (weight) { 1326 valueR *= weight->kernel[y][x]; 1327 } 1328 // XXX NOTE: do NOT apply the window to the chisq portions of the calculation (that would bias the chisq) 1329 chisqR += valueR; 1330 1331 float valueD = PS_SQR(difference->kernel[y][x]); 1332 if (weight) { 1333 valueD *= weight->kernel[y][x]; 1334 } 1335 chisqD += valueD; 1336 npix ++; 1337 } 1338 } 1339 psVectorAppend(chisqRVector, chisqR / npix); 1340 psVectorAppend(chisqDVector, chisqD / npix); 1341 1342 float value1 = 0; 1343 float value2 = 0; 1344 float flux2 = 0; 1345 float fluxX = 0; 1346 float fluxY = 0; 1347 float fluxX2 = 0; 1348 float fluxY2 = 0; 1349 1350 float fluxC1 = 0; 1351 float fluxC2 = 0; 1352 1353 float moment = 0; 1354 1355 // get the moments from convolved1 1356 if (convolved1) { 1357 for (int y = residual->yMin; y <= residual->yMax; y++) { 1358 for (int x = residual->xMin; x <= residual->xMax; x++) { 1359 value1 = convolved1->kernel[y][x]; 1360 value2 = PS_SQR(value1); 1361 1362 if (window) { 1363 value1 *= window->kernel[y][x]; 1364 value2 *= window->kernel[y][x]; 1365 } 1366 1367 fluxC1 += value1; 1368 flux2 += value2; 1369 fluxX += x * value2; 1370 fluxY += y * value2; 1371 // fluxX2 += PS_SQR(x) * value2; 1372 // fluxY2 += PS_SQR(y) * value2; 1373 fluxX2 += PS_SQR(x) * value1; 1374 fluxY2 += PS_SQR(y) * value1; 1375 } 1376 } 1377 // float Mx = fluxX / flux2; 1378 // float My = fluxY / flux2; 1379 // float Mxx = fluxX2 / flux2; 1380 // float Myy = fluxY2 / flux2; 1381 float Mxx = fluxX2 / fluxC1; 1382 float Myy = fluxY2 / fluxC1; 1383 1384 // fprintf (stderr, "conv1, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix); 1385 moment += Mxx + Myy; 1386 } 1387 1388 // get the moments from convolved1 1389 if (convolved2) { 1390 for (int y = residual->yMin; y <= residual->yMax; y++) { 1391 for (int x = residual->xMin; x <= residual->xMax; x++) { 1392 value1 = convolved2->kernel[y][x]; 1393 value2 = PS_SQR(value1); 1394 1395 // XXX NOTE: do NOT apply the weight to the moments calculation 1396 if (false && weight) { 1397 value2 *= weight->kernel[y][x]; 1398 } 1399 if (window) { 1400 value1 *= window->kernel[y][x]; 1401 value2 *= window->kernel[y][x]; 1402 } 1403 1404 fluxC2 += value1; 1405 flux2 += value2; 1406 fluxX += x * value2; 1407 fluxY += y * value2; 1408 // fluxX2 += PS_SQR(x) * value2; 1409 // fluxY2 += PS_SQR(y) * value2; 1410 fluxX2 += PS_SQR(x) * value1; 1411 fluxY2 += PS_SQR(y) * value1; 1412 } 1413 } 1414 // float Mx = fluxX / flux2; 1415 // float My = fluxY / flux2; 1416 // float Mxx = fluxX2 / flux2; 1417 // float Myy = fluxY2 / flux2; 1418 float Mxx = fluxX2 / fluxC2; 1419 float Myy = fluxY2 / fluxC2; 1420 1421 // fprintf (stderr, "conv2, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix); 1422 moment += Mxx + Myy; 1423 } 1424 1425 float flux = fluxC1 + fluxC2; 1426 1427 if (convolved1 && convolved2) { 1428 moment *= 0.5; 1429 flux *= 0.5; 1430 } 1431 psVectorAppend(momentVector, moment); 1432 psVectorAppend(fluxesVector, flux); 1433 1434 // check that the last appended values are ok: 1435 int Nelem = fluxesVector->n - 1; 1436 bool valid = true; 1437 valid &= isfinite(chisqRVector->data.F32[Nelem]); 1438 valid &= isfinite(fluxesVector->data.F32[Nelem]); 1439 valid &= isfinite(momentVector->data.F32[Nelem]); 1440 if (valid) { 1441 psVectorAppend(stampMask, 0); 1442 } else { 1443 psVectorAppend(stampMask, 0x02); 1444 } 1445 return true; 1446 } 1447 1448 bool pmSubtractionCalculateChisqAndMoments(pmSubtractionQuality **bestMatch, 1449 pmSubtractionStampList *stamps, 1450 pmSubtractionKernels *kernels) 1287 1451 { 1288 1452 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL); 1289 1453 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL); 1290 1454 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL); 1455 1456 psTimerStart("pmSubtractionCalculateChisqAndMoments"); 1457 1458 // XXX need to save these somewhere 1459 psVector *fluxes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1460 psVector *chisqD = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1461 psVector *chisqR = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1462 psVector *moments = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1463 psVector *stampMask = psVectorAllocEmpty(stamps->num, PS_TYPE_VECTOR_MASK); 1464 1465 int footprint = stamps->footprint; // Half-size of stamps 1466 int numKernels = kernels->num; // Number of kernels 1467 1468 psImage *polyValues = NULL; // Polynomial values 1469 1470 // storage for the image (convolved2 is not used in SINGLE mode) 1471 psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image 1472 psKernel *difference = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image 1473 psKernel *convolved1 = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image 1474 psKernel *convolved2 = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image 1475 1476 int nGood = 0; 1477 for (int i = 0; i < stamps->num; i++) { 1478 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest 1479 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { 1480 // mark this stamp as unused (note that we have to append NANs to the other vectors to keep the lengths in sync) 1481 psVectorAppend(moments, NAN); 1482 psVectorAppend(fluxes, NAN); 1483 psVectorAppend(chisqD, NAN); 1484 psVectorAppend(chisqR, NAN); 1485 psVectorAppend(stampMask, 0x01); 1486 continue; 1487 } 1488 nGood ++; 1489 1490 // Calculate coefficients of the kernel basis functions 1491 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1492 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1493 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1494 1495 // Calculate residuals 1496 psImageInit(residual->image, 0.0); 1497 psImageInit(difference->image, 0.0); 1498 1499 psKernel *weight = NULL; 1500 psKernel *window = NULL; 1501 1502 #ifdef USE_WEIGHT 1503 weight = stamp->weight; 1504 #endif 1505 #ifdef USE_WINDOW 1506 window = stamps->window; 1507 #endif 1508 1509 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 1510 1511 // the single-direction psf match code attempts to find the kernel such that: 1512 // source * kernel = target. we need to assign 'source' and 'target' correctly 1513 // depending on which of image1 or image2 we asked to be convolved. 1514 1515 psKernel *target; // Target postage stamp (convolve source to match the target) 1516 psKernel *source; // Source postage stamp (convolve source to match the target) 1517 psArray *convolutions; // Convolution postage stamps for each kernel basis function 1518 1519 // init the accumulation image 1520 psImageInit(convolved1->image, 0.0); 1521 1522 switch (kernels->mode) { 1523 case PM_SUBTRACTION_MODE_1: 1524 target = stamp->image2; 1525 source = stamp->image1; 1526 convolutions = stamp->convolutions1; 1527 break; 1528 case PM_SUBTRACTION_MODE_2: 1529 target = stamp->image1; 1530 source = stamp->image2; 1531 convolutions = stamp->convolutions2; 1532 break; 1533 default: 1534 psAbort("Unsupported subtraction mode: %x", kernels->mode); 1535 } 1536 1537 // generate the convolved source image (sum over kernels) 1538 for (int j = 0; j < numKernels; j++) { 1539 psKernel *convolution = convolutions->data[j]; // Convolution 1540 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1541 for (int y = - footprint; y <= footprint; y++) { 1542 for (int x = - footprint; x <= footprint; x++) { 1543 convolved1->kernel[y][x] += convolution->kernel[y][x] * coefficient; 1544 } 1545 } 1546 } 1547 1548 // Generate the difference, residual, and convolved source images. Note the we 1549 // accumulate the convolution of (A-B), so we need to replace it to generate the 1550 // images of the convolved source image. 1551 for (int y = - footprint; y <= footprint; y++) { 1552 for (int x = - footprint; x <= footprint; x++) { 1553 difference->kernel[y][x] = target->kernel[y][x] - source->kernel[y][x] * norm - background; 1554 residual->kernel[y][x] = difference->kernel[y][x] - convolved1->kernel[y][x]; 1555 convolved1->kernel[y][x] += source->kernel[y][x] * norm; 1556 } 1557 } 1558 1559 // XXX if we want to have a weight and window, we'll need to pass through to here 1560 pmSubtractionChisqStats(fluxes, chisqD, chisqR, moments, stampMask, convolved1, NULL, difference, residual, weight, window); 1561 1562 } else { 1563 1564 // Dual convolution 1565 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image 1566 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image 1567 psKernel *image1 = stamp->image1; // The first image 1568 psKernel *image2 = stamp->image2; // The second image 1569 1570 // init the accumulation images 1571 psImageInit(convolved1->image, 0.0); 1572 psImageInit(convolved2->image, 0.0); 1573 1574 for (int j = 0; j < numKernels; j++) { 1575 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image 1576 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image 1577 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1 1578 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2 1579 1580 for (int y = - footprint; y <= footprint; y++) { 1581 for (int x = - footprint; x <= footprint; x++) { 1582 // NOTE sign for coeff2 1583 convolved1->kernel[y][x] += +conv1->kernel[y][x] * coeff1; 1584 convolved2->kernel[y][x] += -conv2->kernel[y][x] * coeff2; 1585 } 1586 } 1587 } 1588 1589 // Generate the difference, residual, and convolved source images. Note the we 1590 // accumulate the convolutions of (A-B), so we need to replace (A or B) to generate 1591 // the images of the convolved source images. 1592 for (int y = - footprint; y <= footprint; y++) { 1593 for (int x = - footprint; x <= footprint; x++) { 1594 difference->kernel[y][x] = image2->kernel[y][x] - image1->kernel[y][x] * norm - background; 1595 residual->kernel[y][x] = difference->kernel[y][x] + convolved2->kernel[y][x] - convolved1->kernel[y][x]; 1596 convolved1->kernel[y][x] += image1->kernel[y][x] * norm; 1597 convolved2->kernel[y][x] += image2->kernel[y][x]; 1598 } 1599 } 1600 1601 if (0) { 1602 psFitsWriteImageSimple("conv1.fits", convolved1->image, NULL); 1603 psFitsWriteImageSimple("conv2.fits", convolved2->image, NULL); 1604 psFitsWriteImageSimple("resid.fits", residual->image, NULL); 1605 pmVisualAskUser(NULL); 1606 } 1607 1608 pmSubtractionChisqStats(fluxes, chisqD, chisqR, moments, stampMask, convolved1, convolved2, difference, residual, weight, window); 1609 } 1610 } 1611 1612 // find the mean chisq and mean moment 1613 psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); 1614 psVectorStats (stats, chisqD, NULL, stampMask, 0xff); 1615 float chisqDValue = stats->sampleMean; 1616 1617 psStatsInit(stats); 1618 psVectorStats (stats, chisqR, NULL, stampMask, 0xff); 1619 float chisqRValue = stats->sampleMean; 1620 1621 psStatsInit(stats); 1622 psVectorStats (stats, moments, NULL, stampMask, 0xff); 1623 float momentValue = stats->sampleMean; 1624 1625 double sumKernel1 = 0.0, sumKernel2 = 0.0; // Sum of the kernel 1626 1627 // calculate the variance contribution from this smoothing kernel 1628 psKernel *modelKernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); 1629 for (int y = modelKernel->yMin; y <= modelKernel->yMax; y++) { 1630 for (int x = modelKernel->xMin; x <= modelKernel->xMax; x++) { 1631 if (!isfinite(modelKernel->kernel[y][x])) { 1632 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Non-finite covariance matrix element in kernel at %d,%d", x, y); 1633 return NULL; 1634 } 1635 sumKernel1 += PS_SQR(modelKernel->kernel[y][x]); 1636 } 1637 } 1638 psFree (modelKernel); 1639 1640 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1641 psKernel *modelKernel = pmSubtractionKernel(kernels, 0.0, 0.0, true); 1642 for (int y = modelKernel->yMin; y <= modelKernel->yMax; y++) { 1643 for (int x = modelKernel->xMin; x <= modelKernel->xMax; x++) { 1644 if (!isfinite(modelKernel->kernel[y][x])) { 1645 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Non-finite covariance matrix element in kernel at %d,%d", x, y); 1646 return NULL; 1647 } 1648 sumKernel2 += PS_SQR(modelKernel->kernel[y][x]); 1649 } 1650 } 1651 psFree (modelKernel); 1652 } else { 1653 sumKernel2 = 1.0; 1654 } 1655 1656 // if we modify the chisq value by the (sumKernel1 + sumKernel2), we account for the 1657 // smoothing coming from larger kernels adding additional spatial fit terms should be 1658 // penalized by increasing the score somewhat. the 0.01 value is not well-chosen. 1659 float orderFactor = 0.01 * kernels->spatialOrder; 1660 float score = 2.0 * chisqRValue / (sumKernel1 + sumKernel2) + orderFactor; 1661 psLogMsg("psModules.imcombine", PS_LOG_INFO, "chisq: %6.3f, chisqD: %6.3f, moment: %6.3f, sumKernel_1: %6.3f, sumKernel_2, score: %6.3f: %6.3f\n", chisqRValue, chisqDValue, momentValue, sumKernel1, sumKernel2, score); 1662 1663 // save this result if it is the first or the best (skip if bestMatch is NULL) 1664 if (bestMatch) { 1665 pmSubtractionQuality *match = *bestMatch; 1666 bool keep = false; 1667 if (match == NULL) { 1668 *bestMatch = match = pmSubtractionQualityAlloc(); 1669 keep = true; 1670 } else { 1671 if (score < match->score) { 1672 psFree(match->fluxes); 1673 psFree(match->chisq); 1674 psFree(match->moments); 1675 psFree(match->stampMask); 1676 keep = true; 1677 } 1678 } 1679 if (keep) { 1680 psLogMsg("psModules.imcombine", PS_LOG_INFO, "keeping order: %d, mode: %d, score: %f\n", kernels->spatialOrder, kernels->mode, score); 1681 match->score = score; 1682 match->spatialOrder = kernels->spatialOrder; 1683 match->mode = kernels->mode; 1684 match->nGood = nGood; 1685 match->fluxes = psMemIncrRefCounter(fluxes); 1686 match->chisq = psMemIncrRefCounter(chisqR); 1687 match->moments = psMemIncrRefCounter(moments); 1688 match->stampMask = psMemIncrRefCounter(stampMask); 1689 } 1690 } 1691 1692 pmSubtractionVisualPlotChisqAndMoments(fluxes, chisqR, moments); 1693 1694 psFree(stats); 1695 psFree(chisqR); 1696 psFree(chisqD); 1697 psFree(fluxes); 1698 psFree(moments); 1699 psFree(stampMask); 1700 1701 psFree(residual); 1702 psFree(difference); 1703 psFree(convolved1); 1704 psFree(convolved2); 1705 psFree(polyValues); 1706 1707 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate Chisq and Moments: %f sec", psTimerClear("pmSubtractionCalculateChisqAndMoments")); 1708 1709 return true; 1710 } 1711 1712 // XXX for now, let's not use this, and let's instead just use values from pmSubtractionCalculateChisqAndMoments 1713 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels) 1714 { 1715 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL); 1716 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL); 1717 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL); 1718 1719 psTimerStart("pmSubtractionCalculateDeviations"); 1291 1720 1292 1721 psVector *deviations = psVectorAlloc(stamps->num, PS_TYPE_F32); // Mean deviation for stamps … … 1298 1727 psImage *polyValues = NULL; // Polynomial values 1299 1728 psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image 1300 1301 // set up holding images for the visualization1302 pmSubtractionVisualShowFitInit (stamps);1303 1729 1304 1730 psVector *fResSigma = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); … … 1401 1827 } 1402 1828 1403 // XXX visualize the target, source, convolution and residual1404 pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i);1405 1406 1829 for (int y = - footprint; y <= footprint; y++) { 1407 1830 for (int x = - footprint; x <= footprint; x++) { … … 1438 1861 } 1439 1862 1440 // XXX visualize the target, source, convolution and residual1441 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i);1442 1443 1863 for (int y = - footprint; y <= footprint; y++) { 1444 1864 for (int x = - footprint; x <= footprint; x++) { … … 1455 1875 } 1456 1876 1877 double flux = 0.0; 1457 1878 double deviation = 0.0; // Sum of differences 1458 1879 for (int y = - footprint; y <= footprint; y++) { … … 1460 1881 double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x]; 1461 1882 deviation += dev; 1462 #ifdef TESTING 1463 residual->kernel[y][x] = dev; 1464 #endif 1883 flux += stamp->image1->kernel[y][x] + stamp->image2->kernel[y][x]; 1465 1884 } 1466 1885 } 1467 1886 deviations->data.F32[i] = devNorm * deviation; 1468 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d):%f\n",1469 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i] );1887 psTrace("psModules.imcombine", 5, "Deviation and Flux for stamp %d (%d,%d): %f %f\n", 1888 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i], flux); 1470 1889 psStringAppend(&log, "Stamp %d (%d,%d): %f\n", 1471 1890 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i]); 1472 1891 if (!isfinite(deviations->data.F32[i])) { 1473 1892 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 1474 psTrace("psModules.imcombine", 5, 1475 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n", 1476 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5)); 1893 psTrace("psModules.imcombine", 5, "Rejecting stamp %d (%d,%d) because of non-finite deviation\n", i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5)); 1477 1894 continue; 1478 1895 } 1479 1480 #ifdef TESTING1481 {1482 psString filename = NULL;1483 psStringAppend(&filename, "resid_%03d.fits", i);1484 psFits *fits = psFitsOpen(filename, "w");1485 psFree(filename);1486 psFitsWriteImage(fits, NULL, residual->image, 0, NULL);1487 psFitsClose(fits);1488 }1489 if (stamp->image1) {1490 psString filename = NULL;1491 psStringAppend(&filename, "stamp_image1_%03d.fits", i);1492 psFits *fits = psFitsOpen(filename, "w");1493 psFree(filename);1494 psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL);1495 psFitsClose(fits);1496 }1497 if (stamp->image2) {1498 psString filename = NULL;1499 psStringAppend(&filename, "stamp_image2_%03d.fits", i);1500 psFits *fits = psFitsOpen(filename, "w");1501 psFree(filename);1502 psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL);1503 psFitsClose(fits);1504 }1505 if (stamp->weight) {1506 psString filename = NULL;1507 psStringAppend(&filename, "stamp_weight_%03d.fits", i);1508 psFits *fits = psFitsOpen(filename, "w");1509 psFree(filename);1510 psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL);1511 psFitsClose(fits);1512 }1513 #endif1514 1515 1896 } 1516 1897 1517 1898 psFree(keepStamps); 1518 1899 1519 psLogMsg("psModules.imcombine", PS_LOG_ DETAIL, "%s", log);1900 psLogMsg("psModules.imcombine", PS_LOG_MINUTIA, "%s", log); 1520 1901 psFree(log); 1521 1902 … … 1527 1908 psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background); 1528 1909 1529 pmSubtractionVisualShowFit(norm);1530 pmSubtractionVisualPlotFit(kernels);1531 1532 1910 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 1533 1911 psVectorStats (stats, fResSigma, NULL, NULL, 0); … … 1560 1938 psFree(polyValues); 1561 1939 1940 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate Deviations: %f sec", psTimerClear("pmSubtractionCalculateDeviations")); 1941 1562 1942 return deviations; 1563 }1564 1565 // we are supplied U, not Ut; w represents a diagonal matrix (also, we apply 1/w instead of w)1566 psImage *p_pmSubSolve_wUt (psVector *w, psImage *U) {1567 1568 psAssert (w->n == U->numCols, "w and U dimensions do not match");1569 1570 // wUt has dimensions transposed relative to Ut.1571 psImage *wUt = psImageAlloc (U->numRows, U->numCols, PS_TYPE_F64);1572 psImageInit (wUt, 0.0);1573 1574 for (int i = 0; i < wUt->numCols; i++) {1575 for (int j = 0; j < wUt->numRows; j++) {1576 if (!isfinite(w->data.F64[j])) continue;1577 if (w->data.F64[j] == 0.0) continue;1578 wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j];1579 }1580 }1581 return wUt;1582 }1583 1584 // XXX this is just standard matrix multiplication: use psMatrixMultiply?1585 psImage *p_pmSubSolve_VwUt (psImage *V, psImage *wUt) {1586 1587 psAssert (V->numCols == wUt->numRows, "matrix dimensions do not match");1588 1589 psImage *Ainv = psImageAlloc (wUt->numCols, V->numRows, PS_TYPE_F64);1590 1591 for (int i = 0; i < Ainv->numCols; i++) {1592 for (int j = 0; j < Ainv->numRows; j++) {1593 double sum = 0.0;1594 for (int k = 0; k < V->numCols; k++) {1595 sum += V->data.F64[j][k] * wUt->data.F64[k][i];1596 }1597 Ainv->data.F64[j][i] = sum;1598 }1599 }1600 return Ainv;1601 }1602 1603 // we are supplied U, not Ut1604 bool p_pmSubSolve_UtB (psVector **UtB, psImage *U, psVector *B) {1605 1606 psAssert (U->numRows == B->n, "U and B dimensions do not match");1607 1608 UtB[0] = psVectorRecycle (UtB[0], U->numCols, PS_TYPE_F64);1609 1610 for (int i = 0; i < U->numCols; i++) {1611 double sum = 0.0;1612 for (int j = 0; j < U->numRows; j++) {1613 sum += B->data.F64[j] * U->data.F64[j][i];1614 }1615 UtB[0]->data.F64[i] = sum;1616 }1617 return true;1618 }1619 1620 // w is diagonal1621 bool p_pmSubSolve_wUtB (psVector **wUtB, psVector *w, psVector *UtB) {1622 1623 psAssert (w->n == UtB->n, "w and UtB dimensions do not match");1624 1625 // wUt has dimensions transposed relative to Ut.1626 wUtB[0] = psVectorRecycle (wUtB[0], w->n, PS_TYPE_F64);1627 psVectorInit (wUtB[0], 0.0);1628 1629 for (int i = 0; i < w->n; i++) {1630 if (!isfinite(w->data.F64[i])) continue;1631 if (w->data.F64[i] == 0.0) continue;1632 wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i];1633 }1634 return true;1635 }1636 1637 // this is basically matrix * vector1638 bool p_pmSubSolve_VwUtB (psVector **VwUtB, psImage *V, psVector *wUtB) {1639 1640 psAssert (V->numCols == wUtB->n, "V and wUtB dimensions do not match");1641 1642 VwUtB[0] = psVectorRecycle (*VwUtB, V->numRows, PS_TYPE_F64);1643 1644 for (int j = 0; j < V->numRows; j++) {1645 double sum = 0.0;1646 for (int i = 0; i < V->numCols; i++) {1647 sum += V->data.F64[j][i] * wUtB->data.F64[i];1648 }1649 VwUtB[0]->data.F64[j] = sum;1650 }1651 return true;1652 }1653 1654 // this is basically matrix * vector1655 bool p_pmSubSolve_Ax (psVector **B, psImage *A, psVector *x) {1656 1657 psAssert (A->numCols == x->n, "A and x dimensions do not match");1658 1659 B[0] = psVectorRecycle (*B, A->numRows, PS_TYPE_F64);1660 1661 for (int j = 0; j < A->numRows; j++) {1662 double sum = 0.0;1663 for (int i = 0; i < A->numCols; i++) {1664 sum += A->data.F64[j][i] * x->data.F64[i];1665 }1666 B[0]->data.F64[j] = sum;1667 }1668 return true;1669 }1670 1671 // this is basically Vector * vector1672 bool p_pmSubSolve_VdV (double *value, psVector *x, psVector *y) {1673 1674 psAssert (x->n == y->n, "x and y dimensions do not match");1675 1676 double sum = 0.0;1677 for (int i = 0; i < x->n; i++) {1678 sum += x->data.F64[i] * y->data.F64[i];1679 }1680 *value = sum;1681 return true;1682 }1683 1684 bool p_pmSubSolve_y2 (double *y2, pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps) {1685 1686 int footprint = stamps->footprint; // Half-size of stamps1687 1688 double sum = 0.0;1689 for (int i = 0; i < stamps->num; i++) {1690 1691 pmSubtractionStamp *stamp = stamps->stamps->data[i];1692 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1693 1694 psKernel *weight = NULL;1695 psKernel *window = NULL;1696 psKernel *input = NULL;1697 1698 #ifdef USE_WEIGHT1699 weight = stamp->weight;1700 #endif1701 #ifdef USE_WINDOW1702 window = stamps->window;1703 #endif1704 1705 switch (kernels->mode) {1706 // MODE_1 : convolve image 1 to match image 2 (and vice versa)1707 case PM_SUBTRACTION_MODE_1:1708 input = stamp->image2;1709 break;1710 case PM_SUBTRACTION_MODE_2:1711 input = stamp->image1;1712 break;1713 default:1714 psAbort ("programming error");1715 }1716 1717 for (int y = - footprint; y <= footprint; y++) {1718 for (int x = - footprint; x <= footprint; x++) {1719 double in = input->kernel[y][x];1720 double value = in*in;1721 if (weight) {1722 float wtVal = weight->kernel[y][x];1723 value *= wtVal;1724 }1725 if (window) {1726 float winVal = window->kernel[y][x];1727 value *= winVal;1728 }1729 sum += value;1730 }1731 }1732 }1733 *y2 = sum;1734 return true;1735 }1736 1737 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps) {1738 1739 int footprint = stamps->footprint; // Half-size of stamps1740 int numKernels = kernels->num; // Number of kernels1741 1742 double sum = 0.0;1743 1744 psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image1745 psImageInit(residual->image, 0.0);1746 1747 psImage *polyValues = NULL; // Polynomial values1748 1749 for (int i = 0; i < stamps->num; i++) {1750 1751 pmSubtractionStamp *stamp = stamps->stamps->data[i];1752 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1753 1754 psKernel *weight = NULL;1755 psKernel *window = NULL;1756 psKernel *target = NULL;1757 psKernel *source = NULL;1758 1759 psArray *convolutions = NULL;1760 1761 #ifdef USE_WEIGHT1762 weight = stamp->weight;1763 #endif1764 #ifdef USE_WINDOW1765 window = stamps->window;1766 #endif1767 1768 switch (kernels->mode) {1769 // MODE_1 : convolve image 1 to match image 2 (and vice versa)1770 case PM_SUBTRACTION_MODE_1:1771 target = stamp->image2;1772 source = stamp->image1;1773 convolutions = stamp->convolutions1;1774 break;1775 case PM_SUBTRACTION_MODE_2:1776 target = stamp->image1;1777 source = stamp->image2;1778 convolutions = stamp->convolutions2;1779 break;1780 default:1781 psAbort ("programming error");1782 }1783 1784 // Calculate coefficients of the kernel basis functions1785 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);1786 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation1787 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background1788 1789 psImageInit(residual->image, 0.0);1790 for (int j = 0; j < numKernels; j++) {1791 psKernel *convolution = convolutions->data[j]; // Convolution1792 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient1793 for (int y = - footprint; y <= footprint; y++) {1794 for (int x = - footprint; x <= footprint; x++) {1795 residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient;1796 }1797 }1798 }1799 1800 for (int y = - footprint; y <= footprint; y++) {1801 for (int x = - footprint; x <= footprint; x++) {1802 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x];1803 double value = PS_SQR(resid);1804 if (weight) {1805 float wtVal = weight->kernel[y][x];1806 value *= wtVal;1807 }1808 if (window) {1809 float winVal = window->kernel[y][x];1810 value *= winVal;1811 }1812 sum += value;1813 }1814 }1815 }1816 psFree (polyValues);1817 psFree (residual);1818 1819 return sum;1820 }1821 1822 bool p_pmSubSolve_SetWeights (psVector *wApply, psVector *w, psVector *wMask) {1823 1824 for (int i = 0; i < w->n; i++) {1825 wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i];1826 }1827 return true;1828 }1829 1830 // we are supplied V and w; w represents a diagonal matrix (also, we apply 1/w instead of w)1831 psImage *p_pmSubSolve_Xvar (psImage *V, psVector *w) {1832 1833 psAssert (w->n == V->numCols, "w and U dimensions do not match");1834 1835 psImage *Vn = psImageAlloc (V->numCols, V->numRows, PS_TYPE_F64);1836 psImageInit (Vn, 0.0);1837 1838 // generate Vn = V * w^{-1}1839 for (int j = 0; j < Vn->numRows; j++) {1840 for (int i = 0; i < Vn->numCols; i++) {1841 if (!isfinite(w->data.F64[i])) continue;1842 if (w->data.F64[i] == 0.0) continue;1843 Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i];1844 }1845 }1846 1847 psImage *Xvar = psImageAlloc (V->numCols, V->numRows, PS_TYPE_F64);1848 psImageInit (Xvar, 0.0);1849 1850 // generate Xvar = Vn * Vn^T1851 for (int j = 0; j < Vn->numRows; j++) {1852 for (int i = 0; i < Vn->numCols; i++) {1853 double sum = 0.0;1854 for (int k = 0; k < Vn->numCols; k++) {1855 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j];1856 }1857 Xvar->data.F64[j][i] = sum;1858 }1859 }1860 return Xvar;1861 1943 } 1862 1944 … … 1864 1946 // of the elements of an image A(x,y) = A->data.F64[y][x] = A_x,y, a matrix 1865 1947 // multiplication is: A_k,j * B_i,k = C_i,j 1866 1867 1948 1868 1949 bool psFitsWriteImageSimple (char *filename, psImage *image, psMetadata *header) { -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionEquation.h
r29543 r30631 4 4 #include "pmSubtractionStamps.h" 5 5 #include "pmSubtractionKernels.h" 6 7 typedef enum { 8 PM_SUBTRACTION_EQUATION_NONE = 0x00, 9 PM_SUBTRACTION_EQUATION_NORM = 0x01, 10 PM_SUBTRACTION_EQUATION_BG = 0x02, 11 PM_SUBTRACTION_EQUATION_KERNELS = 0x04, 12 PM_SUBTRACTION_EQUATION_ALL = 0x07, // value should be NORM | BG | KERNELS 13 } pmSubtractionEquationCalculationMode; 6 #include "pmSubtraction.h" 14 7 15 8 /// Execute a thread job to calculate the least-squares equation for a stamp … … 20 13 bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, ///< Stamps 21 14 pmSubtractionKernels *kernels, ///< Kernel parameters 22 int index, ///< Index of stamp 23 const pmSubtractionEquationCalculationMode mode 15 int index ///< Index of stamp 24 16 ); 25 17 26 18 /// Calculate the least-squares equation to match the image quality 27 19 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps 28 pmSubtractionKernels *kernels, ///< Kernel parameters 29 const pmSubtractionEquationCalculationMode mode 20 pmSubtractionKernels *kernels ///< Kernel parameters 30 21 ); 31 22 32 23 /// Solve the least-squares equation to match the image quality 33 24 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, ///< Kernel parameters 34 const pmSubtractionStampList *stamps, ///< Stamps 35 const pmSubtractionEquationCalculationMode mode 25 const pmSubtractionStampList *stamps ///< Stamps 36 26 ); 37 27 … … 92 82 bool pmSubtractionCalculateMomentsKernel(double *Mxx, double *Myy, psKernel *image, int footprint, int window); 93 83 84 bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqDVector, psVector *chisqRVector, psVector *momentVector, psVector *stampMask, psKernel *convolved1, psKernel *convolved2, psKernel *difference, psKernel *residual, psKernel *weight, psKernel *window); 85 86 bool pmSubtractionCalculateChisqAndMoments(pmSubtractionQuality **bestMatch, pmSubtractionStampList *stamps, pmSubtractionKernels *kernels); 94 87 #endif -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionEquation.v0.c
r29543 r30631 9 9 #include "pmErrorCodes.h" 10 10 #include "pmSubtraction.h" 11 #include "pmSubtractionTypes.h" 11 12 #include "pmSubtractionKernels.h" 12 13 #include "pmSubtractionStamps.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionHermitian.c
r26893 r30631 8 8 #include <pslib.h> 9 9 10 #include "pmSubtractionTypes.h" 10 11 #include "pmSubtractionHermitian.h" 11 12 -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionIO.c
r27321 r30631 12 12 #include "pmConceptsRead.h" 13 13 14 #include "pmSubtractionTypes.h" 14 15 #include "pmSubtraction.h" 15 16 #include "pmSubtractionKernels.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionKernels.c
r29597 r30631 8 8 #include <pslib.h> 9 9 10 #include "pmFPA.h" 11 #include "pmSubtractionTypes.h" 10 12 #include "pmSubtraction.h" 11 13 #include "pmSubtractionKernels.h" … … 20 22 { 21 23 psFree(kernels->description); 24 psFree(kernels->fwhms); 25 psFree(kernels->orders); 22 26 psFree(kernels->u); 23 27 psFree(kernels->v); … … 30 34 psFree(kernels->solution1); 31 35 psFree(kernels->solution2); 36 psFree(kernels->solution1err); 37 psFree(kernels->solution2err); 32 38 psFree(kernels->sampleStamps); 33 39 } … … 419 425 420 426 int num = 0; // Number of basis functions 421 psString params = NULL; // List of parameters422 427 for (int i = 0; i < numGaussians; i++) { 423 428 int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian 424 psStringAppend(¶ms, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]);425 429 num += (gaussOrder + 1) * (gaussOrder + 2) / 2; 426 430 } 427 431 428 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS, size, 429 spatialOrder, penalty, bounds, mode); // Kernels 430 psStringAppend(&kernels->description, "ISIS(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 431 432 psLogMsg("psModules.imcombine", PS_LOG_INFO, "ISIS kernel: %s,%d --> %d elements", 433 params, spatialOrder, num); 434 psFree(params); 432 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS, size, fwhms, orders, spatialOrder, penalty, bounds, mode); // Kernels 433 pmSubtractionKernelsMakeDescription(kernels); 434 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 435 435 436 436 # if (!CENTRAL_DELTA && !ZERO_KERNEL_ZERO_FLUX) … … 503 503 504 504 int num = 0; // Number of basis functions 505 psString params = NULL; // List of parameters506 505 for (int i = 0; i < numGaussians; i++) { 507 506 int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian 508 psStringAppend(¶ms, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]);509 507 num += (gaussOrder + 1) * (gaussOrder + 2) / 2; 510 508 num += (11 - gaussOrder - 1); // include all higher order radial terms 511 509 } 512 510 513 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS_RADIAL, size, 514 spatialOrder, penalty, bounds, mode); // Kernels 515 psStringAppend(&kernels->description, "ISIS_RADIAL(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 516 517 psLogMsg("psModules.imcombine", PS_LOG_INFO, "ISIS_RADIAL kernel: %s,%d --> %d elements", params, spatialOrder, num); 518 psFree(params); 511 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS_RADIAL, size, fwhms, orders, spatialOrder, penalty, bounds, mode); // Kernels 512 pmSubtractionKernelsMakeDescription(kernels); 513 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 519 514 520 515 // Set the kernel parameters … … 569 564 570 565 int num = 0; // Number of basis functions 571 psString params = NULL; // List of parameters572 566 for (int i = 0; i < numGaussians; i++) { 573 567 int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian 574 psStringAppend(¶ms, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]);575 568 num += (gaussOrder + 1) * (gaussOrder + 2) / 2; 576 569 } 577 570 578 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_HERM, size, 579 spatialOrder, penalty, bounds, mode); // Kernels 580 psStringAppend(&kernels->description, "HERM(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 581 582 psLogMsg("psModules.imcombine", PS_LOG_INFO, "HERM kernel: %s,%d --> %d elements", 583 params, spatialOrder, num); 584 psFree(params); 571 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_HERM, size, fwhms, orders, spatialOrder, penalty, bounds, mode); // Kernels 572 pmSubtractionKernelsMakeDescription(kernels); 573 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 585 574 586 575 // Set the kernel parameters … … 627 616 628 617 int num = 0; // Number of basis functions 629 psString params = NULL; // List of parameters630 618 for (int i = 0; i < numGaussians; i++) { 631 619 int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian 632 psStringAppend(¶ms, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]);633 620 num += PS_SQR(gaussOrder + 1); 634 621 } 635 622 636 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_DECONV_HERM, size, 637 spatialOrder, penalty, bounds, mode); // Kernels 638 psStringAppend(&kernels->description, "DECONV_HERM(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 639 640 psLogMsg("psModules.imcombine", PS_LOG_INFO, "DECONVOLVED HERM kernel: %s,%d --> %d elements", params, spatialOrder, num); 641 psFree(params); 623 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_DECONV_HERM, size, fwhms, orders, spatialOrder, penalty, bounds, mode); // Kernels 624 pmSubtractionKernelsMakeDescription(kernels); 625 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 642 626 643 627 // XXXXX hard-wired reference sigma for now of 1.7 pix (== 4.0 pix fwhm == 1.0 arcsec in simtest) … … 713 697 714 698 pmSubtractionKernels *pmSubtractionKernelsAlloc(int numBasisFunctions, pmSubtractionKernelsType type, 715 int size, int spatialOrder, float penalty, psRegion bounds,699 int size, psVector *fwhms, psVector *orders, int spatialOrder, float penalty, psRegion bounds, 716 700 pmSubtractionMode mode) 717 701 { … … 722 706 kernels->description = NULL; 723 707 kernels->num = numBasisFunctions; 708 kernels->fwhms = psMemIncrRefCounter(fwhms); 709 kernels->orders = psMemIncrRefCounter(orders); 724 710 kernels->u = psVectorAlloc(numBasisFunctions, PS_TYPE_S32); 725 711 kernels->v = psVectorAlloc(numBasisFunctions, PS_TYPE_S32); … … 740 726 kernels->size = size; 741 727 kernels->inner = 0; 728 kernels->binning = 0; 729 kernels->ringsOrder = 0; 742 730 kernels->spatialOrder = spatialOrder; 743 731 kernels->bgOrder = 0; … … 745 733 kernels->solution1 = NULL; 746 734 kernels->solution2 = NULL; 735 kernels->solution1err = NULL; 736 kernels->solution2err = NULL; 747 737 kernels->mean = NAN; 748 738 kernels->rms = NAN; … … 823 813 int num = PS_SQR(2 * size + 1) - 1; // Number of basis functions 824 814 825 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(0, PM_SUBTRACTION_KERNEL_POIS, size, 826 spatialOrder, penalty, bounds, mode); // Kernels 827 psStringAppend(&kernels->description, "POIS(%d,%d,%.2e)", size, spatialOrder, penalty); 828 psLogMsg("psModules.imcombine", PS_LOG_INFO, "POIS kernel: %d,%d --> %d elements", 829 size, spatialOrder, num); 815 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(0, PM_SUBTRACTION_KERNEL_POIS, size, NULL, NULL, spatialOrder, penalty, bounds, mode); // Kernels 816 pmSubtractionKernelsMakeDescription(kernels); 817 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 830 818 831 819 if (!p_pmSubtractionKernelsAddGrid(kernels, 0, size)) { … … 871 859 psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num); 872 860 873 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_SPAM, size, 874 spatialOrder, penalty, bounds, mode); // Kernels 861 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_SPAM, size, NULL, NULL, spatialOrder, penalty, bounds, mode); // Kernels 875 862 kernels->inner = inner; 876 psStringAppend(&kernels->description, "SPAM(%d,%d,%d,%d,%.2e)", size, inner, binning, spatialOrder, 877 penalty); 878 879 psLogMsg("psModules.imcombine", PS_LOG_INFO, "SPAM kernel: %d,%d,%d,%d --> %d elements", 880 size, inner, binning, spatialOrder, num); 863 kernels->binning = binning; 864 pmSubtractionKernelsMakeDescription(kernels); 865 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 881 866 882 867 kernels->uStop = psVectorAlloc(num, PS_TYPE_S32); … … 970 955 psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num); 971 956 972 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_FRIES, size, 973 spatialOrder, penalty, bounds, mode); // Kernels 957 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_FRIES, size, NULL, NULL, spatialOrder, penalty, bounds, mode); // Kernels 974 958 kernels->inner = inner; 975 psStringAppend(&kernels->description, "FRIES(%d,%d,%d,%.2e)", size, inner, spatialOrder, penalty); 976 977 psLogMsg("psModules.imcombine", PS_LOG_INFO, "FRIES kernel: %d,%d,%d --> %d elements", 978 size, inner, spatialOrder, num); 959 pmSubtractionKernelsMakeDescription(kernels); 960 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 979 961 980 962 kernels->uStop = psVectorAlloc(num, PS_TYPE_S32); … … 1053 1035 PS_ASSERT_INT_LESS_THAN(inner, size, NULL); 1054 1036 1055 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, 1056 penalty, bounds, mode); // Kernels 1037 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, penalty, bounds, mode); // Kernels 1057 1038 kernels->type = PM_SUBTRACTION_KERNEL_GUNK; 1058 psStringPrepend(&kernels->description, "GUNK="); 1059 psStringAppend(&kernels->description, "+POIS(%d,%d)", inner, spatialOrder); 1039 kernels->inner = inner; 1040 pmSubtractionKernelsMakeDescription(kernels); 1041 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, (int) kernels->num); 1060 1042 1061 1043 int numISIS = kernels->num; // Number of ISIS kernels … … 1100 1082 int num = numRings * numPoly; // Total number of basis functions 1101 1083 1102 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_RINGS, size, 1103 spatialOrder, penalty, bounds, mode); // Kernels 1084 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_RINGS, size, NULL, NULL, spatialOrder, penalty, bounds, mode); // Kernels 1104 1085 kernels->inner = inner; 1105 psStringAppend(&kernels->description, "RINGS(%d,%d,%d,%d,%.2e)", size, inner, ringsOrder, spatialOrder, 1106 penalty); 1107 1108 psLogMsg("psModules.imcombine", PS_LOG_INFO, "RINGS kernel: %d,%d,%d,%d --> %d elements", 1109 size, inner, ringsOrder, spatialOrder, num); 1086 kernels->ringsOrder = ringsOrder; 1087 pmSubtractionKernelsMakeDescription(kernels); 1088 psLogMsg("psModules.imcombine", PS_LOG_INFO, "kernel: %s --> %d elements", kernels->description, num); 1110 1089 1111 1090 // Set the Gaussian kernel parameters … … 1405 1384 } 1406 1385 1386 bool pmSubtractionKernelsMakeDescription(pmSubtractionKernels *kernels) { 1387 1388 // free if it exists 1389 psFree (kernels->description); 1390 1391 // generate the description parameter string 1392 psString params = NULL; 1393 if (kernels->fwhms) { 1394 for (int i = 0; i < kernels->fwhms->n; i++) { 1395 psStringAppend(¶ms, "(%.1f,%d)", kernels->fwhms->data.F32[i], kernels->orders->data.S32[i]); 1396 } 1397 } 1398 1399 switch (kernels->type) { 1400 case PM_SUBTRACTION_KERNEL_ISIS: 1401 psStringAppend (&kernels->description, "ISIS(%d,%s,%d,%.2e)", kernels->size, params, kernels->spatialOrder, kernels->penalty); 1402 break; 1403 1404 case PM_SUBTRACTION_KERNEL_ISIS_RADIAL: 1405 psStringAppend(&kernels->description, "ISIS_RADIAL(%d,%s,%d,%.2e)", kernels->size, params, kernels->spatialOrder, kernels->penalty); 1406 break; 1407 1408 case PM_SUBTRACTION_KERNEL_HERM: 1409 psStringAppend(&kernels->description, "HERM(%d,%s,%d,%.2e)", kernels->size, params, kernels->spatialOrder, kernels->penalty); 1410 break; 1411 1412 case PM_SUBTRACTION_KERNEL_DECONV_HERM: 1413 psStringAppend(&kernels->description, "DECONV_HERM(%d,%s,%d,%.2e)", kernels->size, params, kernels->spatialOrder, kernels->penalty); 1414 break; 1415 1416 case PM_SUBTRACTION_KERNEL_POIS: 1417 psStringAppend(&kernels->description, "POIS(%d,%d,%.2e)", kernels->size, kernels->spatialOrder, kernels->penalty); 1418 break; 1419 1420 case PM_SUBTRACTION_KERNEL_SPAM: 1421 psStringAppend(&kernels->description, "SPAM(%d,%d,%d,%d,%.2e)", kernels->size, kernels->inner, kernels->binning, kernels->spatialOrder, kernels->penalty); 1422 break; 1423 1424 case PM_SUBTRACTION_KERNEL_FRIES: 1425 psStringAppend(&kernels->description, "FRIES(%d,%d,%d,%.2e)", kernels->size, kernels->inner, kernels->spatialOrder, kernels->penalty); 1426 break; 1427 1428 // Grid United with Normal Kernel [description: GUNK=ISIS(...)+POIS(...)] 1429 case PM_SUBTRACTION_KERNEL_GUNK: 1430 psStringAppend(&kernels->description, "GUNK=ISIS(%d,%s,%d,%.2e)", kernels->size, params, kernels->spatialOrder, kernels->penalty); 1431 psStringAppend(&kernels->description, "+POIS(%d,%d)", kernels->inner, kernels->spatialOrder); 1432 break; 1433 1434 case PM_SUBTRACTION_KERNEL_RINGS: 1435 psStringAppend(&kernels->description, "RINGS(%d,%d,%d,%d,%.2e)", kernels->size, kernels->inner, kernels->ringsOrder, kernels->spatialOrder, kernels->penalty); 1436 break; 1437 1438 default: 1439 psAbort("unknown kernel"); 1440 } 1441 psFree (params); 1442 return true; 1443 } 1444 1407 1445 pmSubtractionKernels *pmSubtractionKernelsCopy(const pmSubtractionKernels *in) 1408 1446 { … … 1435 1473 out->solution1 = in->solution1 ? psVectorCopy(NULL, in->solution1, PS_TYPE_F64) : NULL; 1436 1474 out->solution2 = in->solution2 ? psVectorCopy(NULL, in->solution2, PS_TYPE_F64) : NULL; 1475 out->solution1err = in->solution1err ? psVectorCopy(NULL, in->solution1err, PS_TYPE_F64) : NULL; 1476 out->solution2err = in->solution2err ? psVectorCopy(NULL, in->solution2err, PS_TYPE_F64) : NULL; 1437 1477 out->sampleStamps = psMemIncrRefCounter(in->sampleStamps); 1438 1478 -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionKernels.h
r29601 r30631 2 2 #define PM_SUBTRACTION_KERNELS_H 3 3 4 #include <string.h> 5 #include <pslib.h> 6 7 /// Type of subtraction kernel 8 typedef enum { 9 PM_SUBTRACTION_KERNEL_NONE, ///< Nothing --- an error 10 PM_SUBTRACTION_KERNEL_POIS, ///< Pan-STARRS Optimal Image Subtraction --- delta functions 11 PM_SUBTRACTION_KERNEL_ISIS, ///< Traditional kernel --- gaussians modified by polynomials 12 PM_SUBTRACTION_KERNEL_ISIS_RADIAL, ///< ISIS + higher-order radial Hermitians 13 PM_SUBTRACTION_KERNEL_HERM, ///< Hermitian polynomial kernels 14 PM_SUBTRACTION_KERNEL_DECONV_HERM, ///< Deconvolved Hermitian polynomial kernels 15 PM_SUBTRACTION_KERNEL_SPAM, ///< Summed Pixels for Advanced Matching --- summed delta functions 16 PM_SUBTRACTION_KERNEL_FRIES, ///< Fibonacci Radius Increases Excellence of Subtraction 17 PM_SUBTRACTION_KERNEL_GUNK, ///< Grid United with Normal Kernel --- POIS and ISIS hybrid 18 PM_SUBTRACTION_KERNEL_RINGS, ///< Rings Instead of the Normal Gaussian Subtraction 19 } pmSubtractionKernelsType; 20 21 /// Modes --- specifies which image to convolve 22 typedef enum { 23 PM_SUBTRACTION_MODE_ERR, // Error in the mode 24 PM_SUBTRACTION_MODE_1, // Convolve image 1 25 PM_SUBTRACTION_MODE_2, // Convolve image 2 26 PM_SUBTRACTION_MODE_UNSURE, // Not sure yet which image to convolve so try to satisfy both 27 PM_SUBTRACTION_MODE_DUAL, // Dual convolution 28 } pmSubtractionMode; 29 30 /// Kernels specification 31 typedef struct { 32 pmSubtractionKernelsType type; ///< Type of kernels --- allowing the use of multiple kernels 33 psString description; ///< Description of the kernel parameters 34 int xMin, xMax, yMin, yMax; ///< Bounds of image (for normalisation) 35 long num; ///< Number of kernel components (not including the spatial ones) 36 psVector *u, *v; ///< Offset (for POIS) or polynomial order (for ISIS, HERM or DECONV_HERM) 37 psVector *widths; ///< Gaussian FWHMs (ISIS, HERM or DECONV_HERM) 38 psVector *uStop, *vStop; ///< Width of kernel element (SPAM,FRIES only) 39 psArray *preCalc; ///< Array of images containing pre-calculated kernel (for ISIS, HERM or DECONV_HERM) 40 float penalty; ///< Penalty for wideness 41 psVector *penalties1; ///< Penalty for each kernel component 42 psVector *penalties2; ///< Penalty for each kernel component 43 bool havePenalties; ///< flag to test if we have already calculated the penalties or not. 44 int size; ///< The half-size of the kernel 45 int inner; ///< The size of an inner region 46 int spatialOrder; ///< The spatial order of the kernels 47 int bgOrder; ///< The order for the background fitting 48 pmSubtractionMode mode; ///< Mode for subtraction 49 psVector *solution1, *solution2; ///< Solution for the PSF matching 50 // Quality information 51 float mean, rms; ///< Mean and RMS of chi^2 from stamps 52 int numStamps; ///< Number of good stamps 53 float fResSigmaMean; ///< mean fractional stdev of residuals 54 float fResSigmaStdev; ///< stdev of fractional stdev of residuals 55 float fResOuterMean; ///< mean fractional positive swing in residuals 56 float fResOuterStdev; ///< stdev of fractional positive swing in residuals 57 float fResTotalMean; ///< mean fractional negative swing in residuals 58 float fResTotalStdev; ///< stdev of fractional negative swing in residuals 59 psArray *sampleStamps; ///< array of brightest set of stamps for output visualizations 60 } pmSubtractionKernels; 61 62 // pmSubtractionKernels->preCalc is an array of pmSubtractionKernelPreCalc structures 63 typedef struct { 64 psVector *uCoords; // used by RINGS 65 psVector *vCoords; // used by RINGS 66 psVector *poly; // used by RINGS 67 68 psVector *xKernel; // used by ISIS, HERM, DECONV_HERM 69 psVector *yKernel; // used by ISIS, HERM, DECONV_HERM 70 psKernel *kernel; // used by ISIS, HERM, DECONV_HERM 71 } pmSubtractionKernelPreCalc; 4 // #include <string.h> 5 // #include <pslib.h> 72 6 73 7 // Assertion to check pmSubtractionKernels … … 162 96 pmSubtractionKernelsType type, ///< Kernel type 163 97 int size, ///< Half-size of kernel 98 psVector *fwhms, ///< requested kernel basis function 99 psVector *orders, 164 100 int spatialOrder, ///< Order of spatial variations 165 101 float penalty, ///< Penalty for wideness … … 303 239 ); 304 240 241 bool pmSubtractionKernelsMakeDescription(pmSubtractionKernels *kernels); 242 243 305 244 /// Copy kernels 306 245 /// -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionMask.c
r27402 r30631 7 7 8 8 #include "pmErrorCodes.h" 9 #include "pmFPA.h" 10 #include "pmSubtractionTypes.h" 9 11 #include "pmSubtraction.h" 10 12 #include "pmSubtractionKernels.h" -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionMatch.c
r29596 r30631 11 11 #include "pmFPA.h" 12 12 #include "pmHDUUtils.h" 13 #include "pmSubtractionTypes.h" 14 #include "pmSubtraction.h" 13 15 #include "pmSubtractionParams.h" 14 16 #include "pmSubtractionKernels.h" 15 17 #include "pmSubtractionStamps.h" 16 18 #include "pmSubtractionEquation.h" 17 #include "pmSubtraction.h"18 19 #include "pmSubtractionAnalysis.h" 19 20 #include "pmSubtractionMask.h" … … 27 28 28 29 static bool useFFT = true; // Do convolutions using FFT 29 30 # define SUBMODE PM_SUBTRACTION_EQUATION_ALL31 30 32 31 //#define TESTING … … 59 58 } 60 59 61 62 static bool subtractionGetStamps(pmSubtractionStampList **stamps, // Stamps to read63 const pmReadout *ro1, // Readout 164 const pmReadout *ro2, // Readout 265 const psImage *subMask, // Mask for subtraction, or NULL66 psImage *variance, // Variance map67 const psRegion *region, // Region of interest68 float thresh1, // Threshold for stamp finding on readout 169 float thresh2, // Threshold for stamp finding on readout 270 float stampSpacing, // Spacing between stamps71 float normFrac, // Fraction of flux in window for normalisation window72 float sysError, // Relative systematic error in images73 float skyError, // Relative systematic error in images74 int size, // Kernel half-size75 int footprint, // Convolution footprint for stamps76 pmSubtractionMode mode // Mode for subtraction77 )78 {79 PS_ASSERT_PTR_NON_NULL(stamps, false);80 PM_ASSERT_READOUT_NON_NULL(ro1, false);81 PM_ASSERT_READOUT_NON_NULL(ro2, false);82 PS_ASSERT_IMAGE_NON_NULL(subMask, false);83 PS_ASSERT_IMAGE_NON_NULL(variance, false);84 PS_ASSERT_PTR_NON_NULL(region, false);85 86 psTrace("psModules.imcombine", 3, "Finding stamps...\n");87 88 psImage *image1 = ro1 ? ro1->image : NULL, *image2 = ro2 ? ro2->image : NULL; // Images of interest89 90 *stamps = pmSubtractionStampsFind(*stamps, image1, image2, subMask, region, thresh1, thresh2,91 size, footprint, stampSpacing, normFrac, sysError, skyError, mode);92 if (!*stamps) {93 psError(psErrorCodeLast(), false, "Unable to find stamps.");94 return false;95 }96 97 memCheck(" find stamps");98 99 psTrace("psModules.imcombine", 3, "Extracting stamps...\n");100 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2->image, variance, size, *region)) {101 psError(psErrorCodeLast(), false, "Unable to extract stamps.");102 return false;103 }104 105 memCheck(" extract stamps");106 pmSubtractionVisualPlotStamps(*stamps, (pmReadout *) ro1);107 return true;108 }109 110 60 // Check input arguments 111 61 static bool subtractionMatchCheck(pmReadout *conv1, pmReadout *conv2, // Convolved images … … 123 73 float badFrac, // Maximum fraction of bad input pixels to accept 124 74 pmSubtractionMode subMode // Mode of subtraction 125 )75 ) 126 76 { 127 77 if (subMode != PM_SUBTRACTION_MODE_2) { … … 473 423 } 474 424 425 bool pmSubtractionMatchAttempt(pmSubtractionQuality **bestMatch, pmSubtractionKernels *kernels, pmSubtractionStampList *stamps, pmSubtractionMode mode, int spatialOrder, bool final) { 426 427 pmSubtractionMode nativeMode = kernels->mode; 428 pmSubtractionMode nativeOrder = kernels->spatialOrder; 429 430 kernels->mode = mode; 431 kernels->spatialOrder = spatialOrder; 432 433 // we always need to recalculate the matrix equation elements... 434 pmSubtractionStampsResetStatus(stamps); 435 436 psTrace("psModules.imcombine", 3, "Convolving stamps as needed...\n"); 437 if (!pmSubtractionConvolveStamps(stamps, kernels)) { 438 psError(psErrorCodeLast(), false, "Unable to convolve stamps."); 439 return false; 440 } 441 442 // step 1: generate the elements of the matrix equation Ax = B 443 psTrace("psModules.imcombine", 3, "Calculating kernel equations...\n"); 444 if (!pmSubtractionCalculateEquation(stamps, kernels)) { 445 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 446 return false; 447 } 448 449 // step 2: solve the matrix equation Ax = B 450 psTrace("psModules.imcombine", 3, "Solving kernel equations...\n"); 451 if (!pmSubtractionSolveEquation(kernels, stamps)) { 452 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 453 return false; 454 } 455 memCheck(" solve equation"); 456 457 // calculate the score for this model fit attempt 458 // XXX store the chisq, flux and moments for stamp rejection 459 pmSubtractionCalculateChisqAndMoments(bestMatch, stamps, kernels); // Stamp deviations 460 461 // display the input and model stamps 462 pmSubtractionVisualShowFit(stamps, kernels); 463 pmSubtractionVisualPlotFit(kernels); 464 pmSubtractionVisualPlotConvKernels(kernels); 465 466 // reset the kernel if desired (on final pass, do not reset) 467 if (!final) { 468 kernels->mode = nativeMode; 469 kernels->spatialOrder = nativeOrder; 470 } else { 471 pmSubtractionKernelsMakeDescription(kernels); 472 psLogMsg("psModules.imcombine", PS_LOG_INFO, "final kernel: %s", kernels->description); 473 } 474 return true; 475 } 475 476 476 477 bool pmSubtractionMatch(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2, … … 478 479 const psArray *sources, const char *stampsName, 479 480 pmSubtractionKernelsType type, int size, int spatialOrder, 480 constpsVector *isisWidths, const psVector *isisOrders,481 psVector *isisWidths, const psVector *isisOrders, 481 482 int inner, int ringsOrder, int binning, float penalty, 482 483 bool optimum, const psVector *optFWHMs, int optOrder, float optThreshold, … … 559 560 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator 560 561 562 pmSubtractionQuality *bestMatch = NULL; 563 564 int N_TEST_MODES; 565 int N_TEST_ORDER = spatialOrder; 566 567 pmSubtractionMode TestModes[3]; 568 switch (subMode) { 569 case PM_SUBTRACTION_MODE_1: 570 N_TEST_MODES = 1; 571 TestModes[0] = PM_SUBTRACTION_MODE_1; 572 break; 573 case PM_SUBTRACTION_MODE_2: 574 N_TEST_MODES = 1; 575 TestModes[0] = PM_SUBTRACTION_MODE_2; 576 break; 577 case PM_SUBTRACTION_MODE_DUAL: 578 N_TEST_MODES = 3; 579 TestModes[0] = PM_SUBTRACTION_MODE_1; 580 TestModes[1] = PM_SUBTRACTION_MODE_2; 581 TestModes[2] = PM_SUBTRACTION_MODE_DUAL; 582 break; 583 default: 584 psError(psErrorCodeLast(), false, "For now, only modes 1, 2, and DUAL are supported."); 585 goto MATCH_ERROR; 586 } 587 561 588 memCheck("start"); 562 589 … … 628 655 regionString = psRegionToString(*region); 629 656 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Iso-kernel region: %s out of %d,%d\n", 630 regionString, numCols, numRows);657 regionString, numCols, numRows); 631 658 632 659 if (stampsName && strlen(stampsName) > 0) { … … 640 667 } 641 668 642 // We get the stamps here; we will also attempt to get stamps at the first iteration, but it 643 // doesn't matter. 644 if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, region, stampThresh1, stampThresh2, 645 stampSpacing, normFrac, sysError, skyError, size, footprint, subMode)) { 646 goto MATCH_ERROR; 647 } 648 649 650 // generate the window function from the set of stamps 651 if (!pmSubtractionStampsGetWindow(stamps, size)) { 652 psError(psErrorCodeLast(), false, "Unable to get stamp window."); 653 goto MATCH_ERROR; 654 } 655 656 // Define kernel basis functions 657 if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) { 658 kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, 659 optFWHMs, optOrder, stamps, footprint, 660 optThreshold, penalty, bounds, subMode); 661 if (!kernels) { 662 psErrorClear(); 663 psWarning("Unable to derive optimum ISIS kernel --- switching to default."); 664 } 665 } 666 if (kernels == NULL) { 667 // Not an ISIS/GUNK kernel, or the optimum kernel search failed 668 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders, 669 inner, binning, ringsOrder, penalty, bounds, subMode); 670 } 671 672 memCheck("kernels"); 673 674 if (subMode == PM_SUBTRACTION_MODE_UNSURE) { 675 pmSubtractionMode newMode = pmSubtractionBestMode(&stamps, &kernels, subMask, rej); 676 switch (newMode) { 677 case PM_SUBTRACTION_MODE_1: 678 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 1 to match image 2."); 679 break; 680 case PM_SUBTRACTION_MODE_2: 681 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 2 to match image 1."); 682 break; 683 default: 684 psError(psErrorCodeLast(), false, "Unable to determine subtraction order."); 685 goto MATCH_ERROR; 686 } 687 subMode = newMode; 688 } 689 690 int numRejected = -1; // Number of rejected stamps in each iteration 691 for (int k = 0; k < iter && numRejected != 0; k++) { 692 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Iteration %d.", k); 693 694 if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, region, 695 stampThresh1, stampThresh2, stampSpacing, normFrac, 696 sysError, skyError, size, footprint, subMode)) { 697 goto MATCH_ERROR; 698 } 699 700 // generate the window function from the set of stamps 701 if (!pmSubtractionStampsGetWindow(stamps, size)) { 702 psError(psErrorCodeLast(), false, "Unable to get stamps window."); 703 goto MATCH_ERROR; 704 } 669 bool tryAgain = true; 670 while (tryAgain) { 671 // We get the stamps here; we will also attempt to get stamps at the first iteration, but it 672 // doesn't matter. 673 if (!pmSubtractionStampsSelect(&stamps, ro1, ro2, subMask, variance, region, stampThresh1, stampThresh2, 674 stampSpacing, normFrac, sysError, skyError, size, footprint, subMode)) { 675 goto MATCH_ERROR; 676 } 677 678 // generate the window function from the set of stamps 679 if (!pmSubtractionStampsGetWindow(&tryAgain, stamps, size)) { 680 // if we failed, it might be due to the desired normWindow being larger than the current footprint. 681 // in this case, just adjust the footprint and try again. 682 if (tryAgain) { 683 // keep the border constant 684 int border = footprint - size; 685 size = PS_MAX(stamps->normWindow1, stamps->normWindow2) + 2; 686 footprint = size + border; 687 688 // we need to reconstruct everything, so just free the stamps here and retry 689 psFree(stamps); 690 } else { 691 // unrecoverable error 692 psError(psErrorCodeLast(), false, "Unable to get stamp window."); 693 goto MATCH_ERROR; 694 } 695 } 696 } 697 698 // check on the kernel scaling -- if the kron-based radial moments are very different, adjust to match them 699 { 700 // float fwhm1; 701 // float fwhm2; 702 // pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 703 // psAssert(isfinite(fwhm1), "fwhm 1 not set"); 704 // psAssert(isfinite(fwhm2), "fwhm 2 not set"); 705 706 // XXX this is BAD: depends on the relationship below: 707 // stamps->normWindow1 = 2.75*R1; 708 // stamps->normWindow2 = 2.75*R2; 709 float radMoment1 = stamps->normWindow1 / 2.75; 710 float radMoment2 = stamps->normWindow2 / 2.75; 711 pmSubtractionParamsScale(NULL, NULL, isisWidths, radMoment1, radMoment2); 712 713 // float maxFWHM = PS_MAX(fwhm1, fwhm2); 714 // float maxRadial = PS_MAX(radMoment1, radMoment2); 715 716 // if (fabs(2.0*(maxFWHM - maxRadial)/(maxFWHM + maxRadial)) > 0.25) { 717 // if (1) { 718 // 719 // float scale = maxRadial / maxFWHM; 720 // psLogMsg ("psModules.imcombine", PS_LOG_INFO, "Kron and FWHM scales are quite different, re-scale by %f to use Kron", scale); 721 // 722 // for (int i = 0; i < isisWidths->n; i++) { 723 // isisWidths->data.F32[i] *= scale; 724 // } 725 // } 726 } 727 728 // Define kernel basis functions 729 if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) { 730 kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, 731 optFWHMs, optOrder, stamps, footprint, 732 optThreshold, penalty, bounds, subMode); 733 if (!kernels) { 734 psErrorClear(); 735 psWarning("Unable to derive optimum ISIS kernel --- switching to default."); 736 } 737 } 738 if (kernels == NULL) { 739 // Not an ISIS/GUNK kernel, or the optimum kernel search failed 740 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders, 741 inner, binning, ringsOrder, penalty, bounds, subMode); 742 } 743 744 memCheck("kernels"); 745 746 if (subMode == PM_SUBTRACTION_MODE_UNSURE) { 747 pmSubtractionMode newMode = pmSubtractionBestMode(&stamps, &kernels, subMask, rej); 748 switch (newMode) { 749 case PM_SUBTRACTION_MODE_1: 750 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 1 to match image 2."); 751 break; 752 case PM_SUBTRACTION_MODE_2: 753 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolving image 2 to match image 1."); 754 break; 755 default: 756 psError(psErrorCodeLast(), false, "Unable to determine subtraction order."); 757 goto MATCH_ERROR; 758 } 759 subMode = newMode; 760 } 761 762 int numRejected = -1; // Number of rejected stamps in each iteration 763 for (int k = 0; (k < iter) && (numRejected != 0); k++) { 764 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Iteration %d.", k); 765 766 bool tryAgain = true; 767 while (tryAgain) { 768 // We get the stamps here; we will also attempt to get stamps at the first iteration, but it 769 // doesn't matter. 770 if (!pmSubtractionStampsSelect(&stamps, ro1, ro2, subMask, variance, region, stampThresh1, stampThresh2, 771 stampSpacing, normFrac, sysError, skyError, size, footprint, subMode)) { 772 goto MATCH_ERROR; 773 } 774 775 // generate the window function from the set of stamps 776 if (!pmSubtractionStampsGetWindow(&tryAgain, stamps, size)) { 777 // if we failed, it might be due to the desired normWindow being larger than the current footprint. 778 // in this case, just adjust the footprint and try again. 779 if (tryAgain) { 780 footprint = PS_MAX(stamps->normWindow1, stamps->normWindow2) + 2; 781 782 // we need to reconstruct everything, so just free the stamps here and retry 783 psFree(stamps); 784 } else { 785 // unrecoverable error 786 psError(psErrorCodeLast(), false, "Unable to get stamp window."); 787 goto MATCH_ERROR; 788 } 789 } 790 } 705 791 706 792 // step 0 : calculate the normalizations, pass along to the next steps via stamps->normValue 707 psTrace("psModules.imcombine", 3, "Calculating normalization...\n"); 708 if (!pmSubtractionCalculateNormalization(stamps, kernels->mode)) { 709 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 710 goto MATCH_ERROR; 711 } 712 713 // step 0b : calculate the moments, pass along to the next steps via stamps->normValue 714 // XXX this step is now skipped -- delete 715 psTrace("psModules.imcombine", 3, "Calculating normalization...\n"); 716 if (!pmSubtractionCalculateMoments(kernels, stamps)) { 717 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 718 goto MATCH_ERROR; 719 } 720 721 // step 1: generate the elements of the matrix equation Ax = B 722 psTrace("psModules.imcombine", 3, "Calculating kernel equations...\n"); 723 if (!pmSubtractionCalculateEquation(stamps, kernels, SUBMODE)) { 724 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 725 goto MATCH_ERROR; 726 } 727 728 // step 2: solve the matrix equation Ax = B 729 psTrace("psModules.imcombine", 3, "Solving kernel equations...\n"); 730 if (!pmSubtractionSolveEquation(kernels, stamps, SUBMODE)) { 731 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 732 goto MATCH_ERROR; 733 } 734 memCheck(" solve equation"); 735 736 pmSubtractionVisualPlotConvKernels(kernels); 737 738 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 739 if (!deviations) { 740 psError(psErrorCodeLast(), false, "Unable to calculate deviations."); 741 goto MATCH_ERROR; 742 } 743 memCheck(" calculate deviations"); 744 745 psTrace("psModules.imcombine", 3, "Rejecting stamps...\n"); 746 numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, rej); 747 if (numRejected < 0) { 748 psError(psErrorCodeLast(), false, "Unable to reject stamps."); 749 psFree(deviations); 750 goto MATCH_ERROR; 751 } 752 psFree(deviations); 753 754 memCheck(" reject stamps"); 755 } 756 757 // if we hit the max number of iterations and we have rejected stamps, re-solve 758 if (numRejected > 0) { 759 760 // step 1: generate the elements of the matrix equation Ax = B 761 psTrace("psModules.imcombine", 3, "Calculating equation for normalization...\n"); 762 if (!pmSubtractionCalculateEquation(stamps, kernels, SUBMODE)) { 763 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 764 goto MATCH_ERROR; 765 } 766 767 // step 2: solve the matrix equation Ax = B 768 psTrace("psModules.imcombine", 3, "Solving equation for kernels...\n"); 769 if (!pmSubtractionSolveEquation(kernels, stamps, SUBMODE)) { 770 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 771 goto MATCH_ERROR; 772 } 773 774 pmSubtractionVisualPlotConvKernels(kernels); 775 776 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 777 if (!deviations) { 778 psError(psErrorCodeLast(), false, "Unable to calculate deviations."); 779 goto MATCH_ERROR; 780 } 781 pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN); 782 psFree(deviations); 783 } 784 psFree(stamps); 785 stamps = NULL; 786 787 memCheck("solution"); 788 789 if (!pmSubtractionAnalysis(analysis, header, kernels, region, numCols, numRows)) { 790 psError(psErrorCodeLast(), false, "Unable to generate QA data"); 791 goto MATCH_ERROR; 792 } 793 memCheck("diag outputs"); 794 795 psTrace("psModules.imcombine", 2, "Convolving...\n"); 796 if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, stride, maskBad, maskPoor, poorFrac, 797 kernelError, covarFrac, region, kernels, true, useFFT)) { 798 psError(psErrorCodeLast(), false, "Unable to convolve image."); 799 goto MATCH_ERROR; 800 } 801 802 psFree(kernels); 803 kernels = NULL; 804 } 793 psTrace("psModules.imcombine", 3, "Calculating normalization...\n"); 794 if (!pmSubtractionCalculateNormalization(stamps, kernels->mode)) { 795 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 796 goto MATCH_ERROR; 797 } 798 799 // on each iteration, we start from scratch 800 psFree(bestMatch); 801 802 // choose the spatial order and subtraction direction (1, 2, dual) 803 // XXX need to make these respect recipe somewhat 804 for (int order = 0; order <= N_TEST_ORDER; order++) { 805 for (int j = 0; j < N_TEST_MODES; j++) { 806 if (!pmSubtractionMatchAttempt(&bestMatch, kernels, stamps, TestModes[j], order, false)) { 807 goto MATCH_ERROR; 808 } 809 } 810 } 811 812 // reject the deviant stamps based on the stats of the best match 813 psTrace("psModules.imcombine", 3, "Rejecting stamps...\n"); 814 numRejected = pmSubtractionRejectStamps(kernels, stamps, bestMatch, subMask, rej); 815 if (numRejected < 0) { 816 psError(psErrorCodeLast(), false, "Unable to reject stamps."); 817 goto MATCH_ERROR; 818 } 819 memCheck(" reject stamps"); 820 } 821 822 // apply the best fit so we are ready to roll 823 psLogMsg("psModules.imcombine", PS_LOG_INFO, "applying order: %d, mode: %d\n", bestMatch->spatialOrder, bestMatch->mode); 824 if (!pmSubtractionMatchAttempt(NULL, kernels, stamps, bestMatch->mode, bestMatch->spatialOrder, true)) { 825 goto MATCH_ERROR; 826 } 827 psFree(stamps); 828 psFree(bestMatch); 829 memCheck("solution"); 830 831 if (!pmSubtractionAnalysis(analysis, header, kernels, region, numCols, numRows)) { 832 psError(psErrorCodeLast(), false, "Unable to generate QA data"); 833 goto MATCH_ERROR; 834 } 835 memCheck("diag outputs"); 836 837 psTrace("psModules.imcombine", 2, "Convolving...\n"); 838 if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, stride, maskBad, maskPoor, poorFrac, 839 kernelError, covarFrac, region, kernels, true, useFFT)) { 840 psError(psErrorCodeLast(), false, "Unable to convolve image."); 841 goto MATCH_ERROR; 842 } 843 844 psFree(kernels); 845 kernels = NULL; 846 } 805 847 } 806 848 psFree(rng); … … 816 858 817 859 if (conv1 && !pmSubtractionBorder(conv1->image, conv1->variance, conv1->mask, size, maskBad)) { 818 psError(psErrorCodeLast(), false, "Unable to set border of convolved image.");819 goto MATCH_ERROR;860 psError(psErrorCodeLast(), false, "Unable to set border of convolved image."); 861 goto MATCH_ERROR; 820 862 } 821 863 if (conv2 && !pmSubtractionBorder(conv2->image, conv2->variance, conv2->mask, size, maskBad)) { 822 psError(psErrorCodeLast(), false, "Unable to set border of convolved image.");823 goto MATCH_ERROR;864 psError(psErrorCodeLast(), false, "Unable to set border of convolved image."); 865 goto MATCH_ERROR; 824 866 } 825 867 … … 832 874 #ifdef TESTING 833 875 { 834 if (subMode == PM_SUBTRACTION_MODE_1 || subMode == PM_SUBTRACTION_MODE_DUAL) {835 psFits *fits = psFitsOpen("convolved1.fits", "w");836 psFitsWriteImage(fits, NULL, conv1->image, 0, NULL);837 psFitsClose(fits);838 }839 840 if (subMode == PM_SUBTRACTION_MODE_2 || subMode == PM_SUBTRACTION_MODE_DUAL) {841 psFits *fits = psFitsOpen("convolved2.fits", "w");842 psFitsWriteImage(fits, NULL, conv2->image, 0, NULL);843 psFitsClose(fits);844 }876 if (subMode == PM_SUBTRACTION_MODE_1 || subMode == PM_SUBTRACTION_MODE_DUAL) { 877 psFits *fits = psFitsOpen("convolved1.fits", "w"); 878 psFitsWriteImage(fits, NULL, conv1->image, 0, NULL); 879 psFitsClose(fits); 880 } 881 882 if (subMode == PM_SUBTRACTION_MODE_2 || subMode == PM_SUBTRACTION_MODE_DUAL) { 883 psFits *fits = psFitsOpen("convolved2.fits", "w"); 884 psFitsWriteImage(fits, NULL, conv2->image, 0, NULL); 885 psFitsClose(fits); 886 } 845 887 } 846 888 #endif … … 858 900 psFree(variance); 859 901 psFree(rng); 902 psFree(bestMatch); 860 903 return false; 861 904 } … … 866 909 // increment). 867 910 static int subtractionOrderWidth(const psKernel *kernel, // Image 868 float bg, // Background in image869 int size, // Maximum size870 const psArray *models, // Buffer of models871 const psVector *modelSums // Buffer of model sums911 float bg, // Background in image 912 int size, // Maximum size 913 const psArray *models, // Buffer of models 914 const psVector *modelSums // Buffer of model sums 872 915 ) 873 916 { … … 882 925 psVector *chi2 = psVectorAlloc(size, PS_TYPE_F32); // chi^2 as a function of radius 883 926 for (int sigma = 0; sigma < size; sigma++) { 884 double sumFG = 0.0; // Sum for calculating the normalisation of the Gaussian885 psKernel *model = models->data[sigma]; // Model of interest886 for (int y = yMin; y <= yMax; y++) {887 for (int x = xMin; x <= xMax; x++) {888 sumFG += model->kernel[y][x] * (kernel->kernel[y][x] - bg);889 }890 }891 float norm = sumFG * modelSums->data.F64[sigma]; // Normalisation for Gaussian892 double sumDev2 = 0.0; // Sum of square deviations893 for (int y = yMin; y <= yMax; y++) {894 for (int x = xMin; x <= xMax; x++) {895 float dev = kernel->kernel[y][x] - bg - norm * model->kernel[y][x]; // Deviation896 sumDev2 += PS_SQR(dev);897 }898 }899 chi2->data.F32[sigma] = sumDev2;927 double sumFG = 0.0; // Sum for calculating the normalisation of the Gaussian 928 psKernel *model = models->data[sigma]; // Model of interest 929 for (int y = yMin; y <= yMax; y++) { 930 for (int x = xMin; x <= xMax; x++) { 931 sumFG += model->kernel[y][x] * (kernel->kernel[y][x] - bg); 932 } 933 } 934 float norm = sumFG * modelSums->data.F64[sigma]; // Normalisation for Gaussian 935 double sumDev2 = 0.0; // Sum of square deviations 936 for (int y = yMin; y <= yMax; y++) { 937 for (int x = xMin; x <= xMax; x++) { 938 float dev = kernel->kernel[y][x] - bg - norm * model->kernel[y][x]; // Deviation 939 sumDev2 += PS_SQR(dev); 940 } 941 } 942 chi2->data.F32[sigma] = sumDev2; 900 943 } 901 944 … … 904 947 float bestChi2 = INFINITY; // Best chi^2 905 948 for (int i = 0; i < size; i++) { 906 if (chi2->data.F32[i] < bestChi2) {907 bestChi2 = chi2->data.F32[i];908 bestIndex = i;909 }949 if (chi2->data.F32[i] < bestChi2) { 950 bestChi2 = chi2->data.F32[i]; 951 bestIndex = i; 952 } 910 953 } 911 954 psFree(chi2); … … 916 959 917 960 bool pmSubtractionOrderStamp(psVector *ratios, psVector *mask, const pmSubtractionStampList *stamps, 918 const psArray *models, const psVector *modelSums,919 int index, float bg1, float bg2)961 const psArray *models, const psVector *modelSums, 962 int index, float bg1, float bg2) 920 963 { 921 964 PS_ASSERT_VECTOR_NON_NULL(ratios, false); … … 931 974 pmSubtractionStamp *stamp = stamps->stamps->data[index]; // Stamp of interest 932 975 psAssert(stamp->status == PM_SUBTRACTION_STAMP_CALCULATE || stamp->status == PM_SUBTRACTION_STAMP_USED, 933 "We checked this earlier.");976 "We checked this earlier."); 934 977 935 978 // Widths of stars … … 938 981 939 982 if (width1 == 0 || width2 == 0) { 940 ratios->data.F32[index] = NAN;941 mask->data.PS_TYPE_VECTOR_MASK_DATA[index] = 0xff;983 ratios->data.F32[index] = NAN; 984 mask->data.PS_TYPE_VECTOR_MASK_DATA[index] = 0xff; 942 985 } else { 943 ratios->data.F32[index] = (float)width1 / (float)width2;944 mask->data.PS_TYPE_VECTOR_MASK_DATA[index] = 0;945 psTrace("psModules.imcombine", 3, "Stamp %d (%.1f,%.1f) widths: %d, %d --> %f\n",946 index, stamp->x, stamp->y, width1, width2, ratios->data.F32[index]);986 ratios->data.F32[index] = (float)width1 / (float)width2; 987 mask->data.PS_TYPE_VECTOR_MASK_DATA[index] = 0; 988 psTrace("psModules.imcombine", 3, "Stamp %d (%.1f,%.1f) widths: %d, %d --> %f\n", 989 index, stamp->x, stamp->y, width1, width2, ratios->data.F32[index]); 947 990 } 948 991 … … 978 1021 psVector *modelSums = psVectorAlloc(size, PS_TYPE_F64); // Gaussian model sums 979 1022 for (int sigma = 0; sigma < size; sigma++) { 980 psKernel *model = psKernelAlloc(-size, size, -size, size); // Gaussian model981 float invSigma2 = 1.0 / (float)PS_SQR(1 + sigma); // Inverse sigma squared982 double sumGG = 0.0; // Sum of square of Gaussian983 for (int y = -size; y <= size; y++) {984 int y2 = PS_SQR(y); // y squared985 for (int x = -size; x <= size; x++) {986 float rad2 = PS_SQR(x) + y2; // Radius squared987 float value = expf(-rad2 * invSigma2); // Model value988 model->kernel[y][x] = value;989 sumGG += PS_SQR(value);990 }991 }992 models->data[sigma] = model;993 modelSums->data.F64[sigma] = 1.0 / sumGG;1023 psKernel *model = psKernelAlloc(-size, size, -size, size); // Gaussian model 1024 float invSigma2 = 1.0 / (float)PS_SQR(1 + sigma); // Inverse sigma squared 1025 double sumGG = 0.0; // Sum of square of Gaussian 1026 for (int y = -size; y <= size; y++) { 1027 int y2 = PS_SQR(y); // y squared 1028 for (int x = -size; x <= size; x++) { 1029 float rad2 = PS_SQR(x) + y2; // Radius squared 1030 float value = expf(-rad2 * invSigma2); // Model value 1031 model->kernel[y][x] = value; 1032 sumGG += PS_SQR(value); 1033 } 1034 } 1035 models->data[sigma] = model; 1036 modelSums->data.F64[sigma] = 1.0 / sumGG; 994 1037 } 995 1038 996 1039 // Fit models to stamps 997 1040 for (int i = 0; i < stamps->num; i++) { 998 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest999 if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE && stamp->status != PM_SUBTRACTION_STAMP_USED) {1000 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xff;1001 continue;1002 }1003 1004 if (pmSubtractionThreaded()) {1005 psThreadJob *job = psThreadJobAlloc("PSMODULES_SUBTRACTION_ORDER");1006 psArrayAdd(job->args, 1, ratios);1007 psArrayAdd(job->args, 1, mask);1008 psArrayAdd(job->args, 1, stamps);1009 psArrayAdd(job->args, 1, models);1010 psArrayAdd(job->args, 1, modelSums);1011 PS_ARRAY_ADD_SCALAR(job->args, i, PS_TYPE_S32);1012 PS_ARRAY_ADD_SCALAR(job->args, bg1, PS_TYPE_F32);1013 PS_ARRAY_ADD_SCALAR(job->args, bg2, PS_TYPE_F32);1014 if (!psThreadJobAddPending(job)) {1015 return false;1016 }1017 } else {1018 if (!pmSubtractionOrderStamp(ratios, mask, stamps, models, modelSums, i, bg1, bg2)) {1019 psError(psErrorCodeLast(), false, "Unable to measure PSF width for stamp %d", i);1020 psFree(models);1021 psFree(modelSums);1022 psFree(ratios);1023 psFree(mask);1024 return false;1025 }1026 }1041 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 1042 if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE && stamp->status != PM_SUBTRACTION_STAMP_USED) { 1043 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xff; 1044 continue; 1045 } 1046 1047 if (pmSubtractionThreaded()) { 1048 psThreadJob *job = psThreadJobAlloc("PSMODULES_SUBTRACTION_ORDER"); 1049 psArrayAdd(job->args, 1, ratios); 1050 psArrayAdd(job->args, 1, mask); 1051 psArrayAdd(job->args, 1, stamps); 1052 psArrayAdd(job->args, 1, models); 1053 psArrayAdd(job->args, 1, modelSums); 1054 PS_ARRAY_ADD_SCALAR(job->args, i, PS_TYPE_S32); 1055 PS_ARRAY_ADD_SCALAR(job->args, bg1, PS_TYPE_F32); 1056 PS_ARRAY_ADD_SCALAR(job->args, bg2, PS_TYPE_F32); 1057 if (!psThreadJobAddPending(job)) { 1058 return false; 1059 } 1060 } else { 1061 if (!pmSubtractionOrderStamp(ratios, mask, stamps, models, modelSums, i, bg1, bg2)) { 1062 psError(psErrorCodeLast(), false, "Unable to measure PSF width for stamp %d", i); 1063 psFree(models); 1064 psFree(modelSums); 1065 psFree(ratios); 1066 psFree(mask); 1067 return false; 1068 } 1069 } 1027 1070 } 1028 1071 1029 1072 if (!psThreadPoolWait(true)) { 1030 psError(psErrorCodeLast(), false, "Error waiting for threads.");1031 psFree(models);1032 psFree(modelSums);1033 psFree(ratios);1034 psFree(mask);1035 return false;1073 psError(psErrorCodeLast(), false, "Error waiting for threads."); 1074 psFree(models); 1075 psFree(modelSums); 1076 psFree(ratios); 1077 psFree(mask); 1078 return false; 1036 1079 } 1037 1080 … … 1041 1084 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 1042 1085 if (!psVectorStats(stats, ratios, NULL, mask, 0xff)) { 1043 psError(psErrorCodeLast(), false, "Unable to calculate statistics for moments ratio.");1044 psFree(mask);1045 psFree(ratios);1046 psFree(stats);1047 return PM_SUBTRACTION_MODE_ERR;1086 psError(psErrorCodeLast(), false, "Unable to calculate statistics for moments ratio."); 1087 psFree(mask); 1088 psFree(ratios); 1089 psFree(stats); 1090 return PM_SUBTRACTION_MODE_ERR; 1048 1091 } 1049 1092 psFree(ratios); … … 1052 1095 // XXX raise an error here or not? 1053 1096 if (isnan(stats->robustMedian)) { 1054 psFree(stats);1055 return PM_SUBTRACTION_MODE_ERR;1097 psFree(stats); 1098 return PM_SUBTRACTION_MODE_ERR; 1056 1099 } 1057 1100 … … 1066 1109 // Test a subtraction mode by performing a single iteration 1067 1110 static bool subtractionModeTest(pmSubtractionStampList *stamps, // Stamps to use to find best mode 1068 pmSubtractionKernels *kernels, // Kernel description1069 const char *description, // Description for trace1070 psImage *subMask, // Subtraction mask1071 float rej // Rejection threshold1072 )1111 pmSubtractionKernels *kernels, // Kernel description 1112 const char *description, // Description for trace 1113 psImage *subMask, // Subtraction mask 1114 float rej // Rejection threshold 1115 ) 1073 1116 { 1074 1117 assert(stamps); 1075 1118 assert(kernels); 1076 1119 1120 psAbort("this function is not working"); 1121 # if (0) 1122 psTrace("psModules.imcombine", 3, "Convolving stamps as needed...\n"); 1123 if (!pmSubtractionConvolveStamps(stamps, kernels)) { 1124 psError(psErrorCodeLast(), false, "Unable to convolve stamps."); 1125 return false; 1126 } 1127 1077 1128 psTrace("psModules.imcombine", 3, "Calculating %s normalization equation...\n", description); 1078 if (!pmSubtractionCalculateEquation(stamps, kernels , SUBMODE)) {1079 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1080 return false;1129 if (!pmSubtractionCalculateEquation(stamps, kernels)) { 1130 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 1131 return false; 1081 1132 } 1082 1133 1083 1134 psTrace("psModules.imcombine", 3, "Solving %s normalization equation...\n", description); 1084 if (!pmSubtractionSolveEquation(kernels, stamps , SUBMODE)) {1085 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1086 return false;1135 if (!pmSubtractionSolveEquation(kernels, stamps)) { 1136 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 1137 return false; 1087 1138 } 1088 1139 … … 1090 1141 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 1091 1142 if (!deviations) { 1092 psError(psErrorCodeLast(), false, "Unable to calculate deviations."); 1093 return false; 1094 } 1095 1143 psError(psErrorCodeLast(), false, "Unable to calculate deviations."); 1144 return false; 1145 } 1146 1147 // XXX this needs to be made consistent with the modified 'reject stamps' function 1096 1148 psTrace("psModules.imcombine", 3, "Rejecting %s stamps...\n", description); 1097 1149 long numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, rej); 1098 1150 if (numRejected < 0) { 1099 psError(psErrorCodeLast(), false, "Unable to reject stamps.");1100 psFree(deviations);1101 return false;1151 psError(psErrorCodeLast(), false, "Unable to reject stamps."); 1152 psFree(deviations); 1153 return false; 1102 1154 } 1103 1155 psFree(deviations); 1104 1156 1105 1157 if (numRejected > 0) { 1106 // Allow re-fit with reduced stamps set1107 psTrace("psModules.imcombine", 3, "Calculating %s normalization equation...\n", description);1108 if (!pmSubtractionCalculateEquation(stamps, kernels, PM_SUBTRACTION_EQUATION_ALL)) {1109 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1110 return false;1111 }1112 1113 psTrace("psModules.imcombine", 3, "Resolving %s equation...\n", description);1114 if (!pmSubtractionSolveEquation(kernels, stamps, PM_SUBTRACTION_EQUATION_ALL)) {1115 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation.");1116 return false;1117 }1118 psTrace("psModules.imcombine", 3, "Recalculate %s deviations...\n", description);1119 1120 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations1121 if (!deviations) {1122 psError(psErrorCodeLast(), false, "Unable to calculate deviations.");1123 return false;1124 }1125 psTrace("psModules.imcombine", 3, "Measuring %s quality...\n", description);1126 long numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN);1127 if (numRejected < 0) {1128 psError(psErrorCodeLast(), false, "Unable to reject stamps.");1129 psFree(deviations);1130 return false;1131 }1132 psFree(deviations);1133 } 1134 1158 // Allow re-fit with reduced stamps set 1159 psTrace("psModules.imcombine", 3, "Calculating %s normalization equation...\n", description); 1160 if (!pmSubtractionCalculateEquation(stamps, kernels)) { 1161 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 1162 return false; 1163 } 1164 1165 psTrace("psModules.imcombine", 3, "Resolving %s equation...\n", description); 1166 if (!pmSubtractionSolveEquation(kernels, stamps)) { 1167 psError(psErrorCodeLast(), false, "Unable to calculate least-squares equation."); 1168 return false; 1169 } 1170 psTrace("psModules.imcombine", 3, "Recalculate %s deviations...\n", description); 1171 1172 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 1173 if (!deviations) { 1174 psError(psErrorCodeLast(), false, "Unable to calculate deviations."); 1175 return false; 1176 } 1177 psTrace("psModules.imcombine", 3, "Measuring %s quality...\n", description); 1178 long numRejected = pmSubtractionRejectStamps(kernels, stamps, deviations, subMask, NAN); 1179 if (numRejected < 0) { 1180 psError(psErrorCodeLast(), false, "Unable to reject stamps."); 1181 psFree(deviations); 1182 return false; 1183 } 1184 psFree(deviations); 1185 } 1186 # endif 1135 1187 return true; 1136 1188 } … … 1138 1190 1139 1191 pmSubtractionMode pmSubtractionBestMode(pmSubtractionStampList **stamps, pmSubtractionKernels **kernels, 1140 const psImage *subMask, float rej)1192 const psImage *subMask, float rej) 1141 1193 { 1142 1194 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(*stamps, PM_SUBTRACTION_MODE_ERR); … … 1150 1202 1151 1203 if (!subtractionModeTest(stamps1, kernels1, "convolve 1", subMask1, rej)) { 1152 psError(psErrorCodeLast(), false, "Unable to test subtraction with convolution of image 1");1153 psFree(stamps1);1154 psFree(kernels1);1155 psFree(subMask1);1156 return PM_SUBTRACTION_MODE_ERR;1204 psError(psErrorCodeLast(), false, "Unable to test subtraction with convolution of image 1"); 1205 psFree(stamps1); 1206 psFree(kernels1); 1207 psFree(subMask1); 1208 return PM_SUBTRACTION_MODE_ERR; 1157 1209 } 1158 1210 psFree(subMask1); … … 1165 1217 1166 1218 if (!subtractionModeTest(stamps2, kernels2, "convolve 2", subMask2, rej)) { 1167 psError(psErrorCodeLast(), false, "Unable to test subtraction with convolution of image 2");1168 psFree(stamps2);1169 psFree(kernels2);1170 psFree(subMask2);1171 psFree(stamps1);1172 psFree(kernels1);1173 return PM_SUBTRACTION_MODE_ERR;1219 psError(psErrorCodeLast(), false, "Unable to test subtraction with convolution of image 2"); 1220 psFree(stamps2); 1221 psFree(kernels2); 1222 psFree(subMask2); 1223 psFree(stamps1); 1224 psFree(kernels1); 1225 return PM_SUBTRACTION_MODE_ERR; 1174 1226 } 1175 1227 psFree(subMask2); … … 1179 1231 pmSubtractionKernels *bestKernels = NULL; // Best choice for kernels 1180 1232 psLogMsg("psModules.imcombine", PS_LOG_INFO, 1181 "Image 1: %f +/- %f from %d stamps\nImage 2: %f +/- %f from %d stamps\n",1182 kernels1->mean, kernels1->rms, kernels1->numStamps,1183 kernels2->mean, kernels2->rms, kernels2->numStamps);1233 "Image 1: %f +/- %f from %d stamps\nImage 2: %f +/- %f from %d stamps\n", 1234 kernels1->mean, kernels1->rms, kernels1->numStamps, 1235 kernels2->mean, kernels2->rms, kernels2->numStamps); 1184 1236 1185 1237 if (kernels1->mean < kernels2->mean) { 1186 bestStamps = stamps1;1187 bestKernels = kernels1;1238 bestStamps = stamps1; 1239 bestKernels = kernels1; 1188 1240 } else { 1189 bestStamps = stamps2;1190 bestKernels = kernels2;1241 bestStamps = stamps2; 1242 bestKernels = kernels2; 1191 1243 } 1192 1244 … … 1204 1256 } 1205 1257 1206 1207 bool pmSubtractionParamsScale(int *kernelSize, int *stampSize, psVector *widths, 1208 float scaleRef, float scaleMin, float scaleMax) 1258 static float scaleRefOption = NAN; 1259 static float scaleMinOption = NAN; 1260 static float scaleMaxOption = NAN; 1261 static bool scaleOption = false; 1262 1263 bool pmSubtractionParamScaleOptions(bool scale, float scaleRef, float scaleMin, float scaleMax) { 1264 1265 if (scale) { 1266 PS_ASSERT_FLOAT_LARGER_THAN(scaleRef, 0.0, false); 1267 PS_ASSERT_FLOAT_LARGER_THAN(scaleMin, 0.0, false); 1268 PS_ASSERT_FLOAT_LARGER_THAN(scaleMax, 0.0, false); 1269 PS_ASSERT_FLOAT_LARGER_THAN(scaleMax, scaleMin, false); 1270 } 1271 1272 scaleRefOption = scaleRef; 1273 scaleMinOption = scaleMin; 1274 scaleMaxOption = scaleMax; 1275 scaleOption = scale; 1276 1277 return true; 1278 } 1279 1280 bool pmSubtractionParamsScale(int *kernelSize, int *stampSize, psVector *widths, float fwhm1, float fwhm2) 1209 1281 { 1210 PS_ASSERT_PTR_NON_NULL(kernelSize, false);1211 PS_ASSERT_PTR_NON_NULL(stampSize, false);1282 // PS_ASSERT_PTR_NON_NULL(kernelSize, false); 1283 // PS_ASSERT_PTR_NON_NULL(stampSize, false); 1212 1284 PS_ASSERT_VECTOR_NON_NULL(widths, false); 1213 1285 PS_ASSERT_VECTOR_TYPE(widths, PS_TYPE_F32, false); 1214 PS_ASSERT_FLOAT_LARGER_THAN(scaleRef, 0.0, false); 1215 PS_ASSERT_FLOAT_LARGER_THAN(scaleMin, 0.0, false); 1216 PS_ASSERT_FLOAT_LARGER_THAN(scaleMax, 0.0, false); 1217 PS_ASSERT_FLOAT_LARGER_THAN(scaleMax, scaleMin, false); 1218 1219 float fwhm1; 1220 float fwhm2; 1221 1222 pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 1223 psAssert(isfinite(fwhm1), "fwhm 1 not set"); 1224 psAssert(isfinite(fwhm2), "fwhm 2 not set"); 1286 1287 if (!scaleOption) return true; 1288 1289 // pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 1290 // psAssert(isfinite(fwhm1), "fwhm 1 not set"); 1291 // psAssert(isfinite(fwhm2), "fwhm 2 not set"); 1225 1292 1226 1293 // float diff = sqrtf(PS_SQR(PS_MAX(fwhm1, fwhm2)) - PS_SQR(PS_MIN(fwhm1, fwhm2))); // Difference 1227 float scale = PS_MAX(fwhm1, fwhm2) / scaleRef ; // Scaling factor1228 1229 if (isfinite(scaleMin ) && scale < scaleMin) {1230 scale = scaleMin;1231 } 1232 if (isfinite(scaleMax ) && scale > scaleMax) {1233 scale = scaleMax;1294 float scale = PS_MAX(fwhm1, fwhm2) / scaleRefOption; // Scaling factor 1295 1296 if (isfinite(scaleMinOption) && scale < scaleMinOption) { 1297 scale = scaleMinOption; 1298 } 1299 if (isfinite(scaleMaxOption) && scale > scaleMaxOption) { 1300 scale = scaleMaxOption; 1234 1301 } 1235 1302 1236 1303 for (int i = 0; i < widths->n; i++) { 1237 widths->data.F32[i] *= scale; 1238 } 1239 *kernelSize = *kernelSize * scale + 0.5; 1240 *stampSize = *stampSize * scale + 0.5; 1241 1242 psLogMsg("psModules.imcombine", PS_LOG_INFO, 1243 "Scaling kernel parameters by %f: %d %d", scale, *kernelSize, *stampSize); 1304 widths->data.F32[i] *= scale; 1305 } 1306 if (kernelSize) { 1307 *kernelSize = *kernelSize * scale + 0.5; 1308 } 1309 if (stampSize) { 1310 *stampSize = *stampSize * scale + 0.5; 1311 } 1312 1313 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Scaling kernel parameters by %f", scale); 1314 if (kernelSize) psLogMsg("psModules.imcombine", PS_LOG_INFO, " modified kernel size %d", *kernelSize); 1315 if (stampSize) psLogMsg("psModules.imcombine", PS_LOG_INFO, " modified stamp size %d", *stampSize); 1244 1316 1245 1317 return true; -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionMatch.h
r29543 r30631 8 8 #include <pmSubtractionKernels.h> 9 9 #include <pmSubtractionStamps.h> 10 #include <pmSubtraction.h> 10 11 11 12 /// Match two images … … 26 27 int size, ///< Kernel half-size 27 28 int order, ///< Spatial polynomial order 28 constpsVector *widths, ///< ISIS Gaussian widths29 psVector *widths, ///< ISIS Gaussian widths 29 30 const psVector *orders, ///< ISIS Polynomial orders 30 31 int inner, ///< Inner radius for various kernel types … … 100 101 101 102 /// Scale subtraction parameters according to the FWHMs of the inputs 102 bool pmSubtractionParamsScale( 103 int *kernelSize, ///< Half-size of the kernel 104 int *stampSize, ///< Half-size of the stamp (footprint) 105 psVector *widths, ///< ISIS widths 106 float scaleRef, ///< Reference width for scaling 107 float scaleMin, ///< Minimum scaling ratio, or NAN 108 float scaleMax ///< Maximum scaling ratio, or NAN 103 // bool pmSubtractionParamsScale( 104 // int *kernelSize, ///< Half-size of the kernel 105 // int *stampSize, ///< Half-size of the stamp (footprint) 106 // psVector *widths, ///< ISIS widths 107 // float scaleRef, ///< Reference width for scaling 108 // float scaleMin, ///< Minimum scaling ratio, or NAN 109 // float scaleMax ///< Maximum scaling ratio, or NAN 110 // ); 111 112 bool pmSubtractionParamsScale(int *kernelSize, int *stampSize, psVector *widths, float fwhm1, float fwhm2); 113 114 bool pmSubtractionParamScaleOptions(bool scale, float scaleRef, float scaleMin, float scaleMax); 115 116 bool pmSubtractionMatchAttempt( 117 pmSubtractionQuality **bestMatch, 118 pmSubtractionKernels *kernels, 119 pmSubtractionStampList *stamps, 120 pmSubtractionMode mode, 121 int spatialOrder, 122 bool final 109 123 ); 110 124 -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionParams.c
r27086 r30631 9 9 10 10 #include "pmErrorCodes.h" 11 #include "pmFPA.h" 12 #include "pmSubtractionTypes.h" 13 #include "pmSubtraction.h" 11 14 #include "pmSubtractionStamps.h" 12 #include "pmSubtraction.h"13 15 #include "pmSubtractionParams.h" 14 16 … … 16 18 17 19 #if 0 20 // XXX this was moved to pmSubtraction.c in r15443 -- delete 18 21 // Convolve the reference stamp by the kernel 19 22 static psKernel *convolveStamp(const pmSubtractionStamp *stamp, // Stamp to be convolved -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionStamps.c
r29543 r30631 27 27 #include "pmSource.h" 28 28 29 #include "pmSubtractionTypes.h" 29 30 #include "pmSubtraction.h" 30 31 #include "pmSubtractionStamps.h" 32 #include "pmSubtractionVisual.h" 31 33 32 34 #define STAMP_LIST_BUFFER 20 // Number of stamps to add to list at a time … … 122 124 if ((image1 && image1->data.F32[y][x] < thresh1) || 123 125 (image2 && image2->data.F32[y][x] < thresh2)) { 126 // fprintf (stderr, "%f,%f : thresh\n", xRaw, yRaw); 124 127 continue; 125 128 } … … 366 369 } 367 370 368 369 pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, const psImage *image1, 370 const psImage *image2, const psImage *subMask, 371 const psRegion *region, float thresh1, float thresh2, 372 int size, int footprint, float spacing, float normFrac, 373 float sysErr, float skyErr, pmSubtractionMode mode) 371 bool pmSubtractionStampsSelect(pmSubtractionStampList **stamps, // Stamps to read 372 const pmReadout *ro1, // Readout 1 373 const pmReadout *ro2, // Readout 2 374 const psImage *subMask, // Mask for subtraction, or NULL 375 psImage *variance, // Variance map 376 const psRegion *region, // Region of interest 377 float thresh1, // Threshold for stamp finding on readout 1 378 float thresh2, // Threshold for stamp finding on readout 2 379 float stampSpacing, // Spacing between stamps 380 float normFrac, // Fraction of flux in window for normalisation window 381 float sysError, // Relative systematic error in images 382 float skyError, // Relative systematic error in images 383 int size, // Kernel half-size 384 int footprint, // Convolution footprint for stamps 385 pmSubtractionMode mode // Mode for subtraction 386 ) 387 { 388 PS_ASSERT_PTR_NON_NULL(stamps, false); 389 PM_ASSERT_READOUT_NON_NULL(ro1, false); 390 PM_ASSERT_READOUT_NON_NULL(ro2, false); 391 PS_ASSERT_IMAGE_NON_NULL(subMask, false); 392 PS_ASSERT_IMAGE_NON_NULL(variance, false); 393 PS_ASSERT_PTR_NON_NULL(region, false); 394 395 psTrace("psModules.imcombine", 3, "Finding stamps...\n"); 396 397 psImage *image1 = ro1 ? ro1->image : NULL, *image2 = ro2 ? ro2->image : NULL; // Images of interest 398 399 *stamps = pmSubtractionStampsFind(*stamps, image1, image2, subMask, region, thresh1, thresh2, 400 size, footprint, stampSpacing, normFrac, sysError, skyError, mode); 401 if (!*stamps) { 402 psError(psErrorCodeLast(), false, "Unable to find stamps."); 403 return false; 404 } 405 406 psTrace("psModules.imcombine", 3, "Extracting stamps...\n"); 407 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2->image, variance, size, *region)) { 408 psError(psErrorCodeLast(), false, "Unable to extract stamps."); 409 return false; 410 } 411 412 pmSubtractionVisualPlotStamps(*stamps, (pmReadout *) ro1); 413 return true; 414 } 415 416 pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, 417 const psImage *image1, 418 const psImage *image2, 419 const psImage *subMask, 420 const psRegion *region, 421 float thresh1, 422 float thresh2, 423 int size, 424 int footprint, 425 float spacing, 426 float normFrac, 427 float sysErr, 428 float skyErr, 429 pmSubtractionMode mode) 374 430 { 375 431 if (!image1 && !image2) { … … 429 485 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing, 430 486 normFrac, sysErr, skyErr); 487 } 488 489 // XXX TEST : dump all stars in the stamps here 490 if (0) { 491 FILE *f = fopen ("stamp.dat", "w"); 492 for (int i = 0; i < stamps->num; i++) { 493 psVector *xList = stamps->x->data[i]; 494 psVector *yList = stamps->y->data[i]; // Coordinate lists 495 psVector *fluxList = stamps->flux->data[i]; // List of stamp fluxes 496 497 for (int j = 0; j < xList->n; j++) { 498 fprintf (f, "%d %d %f %f %f\n", i, j, xList->data.F32[j], yList->data.F32[j], fluxList->data.F32[j]); 499 } 500 } 501 fclose (f); 431 502 } 432 503 … … 636 707 } 637 708 709 int nTotal = 0; 710 638 711 // Sort the list by flux, with the brightest last 639 712 for (int i = 0; i < numStamps; i++) { … … 662 735 stamps->y->data[i] = ySorted; 663 736 stamps->flux->data[i] = fluxSorted; 664 } 665 737 nTotal += num; 738 } 739 // fprintf (stderr, "nTotal %d\n", nTotal); 740 666 741 return stamps; 667 742 } 668 743 669 670 bool pmSubtractionStampsGetWindow(pmSubtractionStampList *stamps, int kernelSize) 744 // we are essentially using aperture photometry to determine the photometric match between the 745 // images. we need to choose an appropriate-sized aperture for this analysis. If it is too 746 // large, the measurement will be noisy (and possibly biased) due to the sky noise. If it is 747 // too small, or inconsistent, the measurement will be biased. We use Kron-mag like aperture 748 // scaled by the first radial moment. 749 bool pmSubtractionStampsGetWindow(bool *tryAgain, pmSubtractionStampList *stamps, int kernelSize) 671 750 { 672 751 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 673 752 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 674 753 754 // if we succeed, or fail with an unrecoverable error, do not try again 755 if (tryAgain) { 756 *tryAgain = false; 757 } 758 675 759 int size = stamps->footprint; // Size of postage stamps 676 760 761 // window for moments calculations downstream 762 psFree (stamps->window); 763 stamps->window = psKernelAlloc(-size, size, -size, size); 764 psImageInit(stamps->window->image, 0.0); 765 766 // window1 and window2 are mean stamp images used here to measure the 767 // first radial moment, and thus the normalization window 677 768 psFree (stamps->window1); 678 769 stamps->window1 = psKernelAlloc(-size, size, -size, size); … … 683 774 psImageInit(stamps->window2->image, 0.0); 684 775 685 // Generate a weighting window based on the fwhms (20% larger than the largest) 686 { 687 float fwhm1, fwhm2; 688 689 // XXX this is annoyingly hack-ish 690 pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 691 692 float sigma = 1.5 * PS_MAX(fwhm1, fwhm2) / 2.35; 693 694 psFree (stamps->window); 695 stamps->window = psKernelAlloc(-size, size, -size, size); 696 psImageInit(stamps->window->image, 0.0); 697 698 for (int y = -size; y <= size; y++) { 699 for (int x = -size; x <= size; x++) { 700 stamps->window->kernel[y][x] = exp(-0.5*(x*x + y*y)/(sigma*sigma)); 701 } 702 } 776 // Generate an initial weighting window based on the fwhms (50% larger than the largest) 777 float fwhm1, fwhm2; 778 779 // XXX this is annoyingly hack-ish 780 pmSubtractionGetFWHMs(&fwhm1, &fwhm2); 781 782 float sigma = 1.5 * PS_MAX(fwhm1, fwhm2) / 2.35; 783 784 for (int y = -size; y <= size; y++) { 785 for (int x = -size; x <= size; x++) { 786 stamps->window->kernel[y][x] = exp(-0.5*(x*x + y*y)/(sigma*sigma)); 787 } 703 788 } 704 789 … … 790 875 psTrace("psModules.imcombine", 3, "Window total (2): %f, threshold: %f\n", sum2, (1.0 - stamps->normFrac) * sum2); 791 876 792 # if (1) 793 // this block attempts to calculate the radius based on the first radial moment 877 // attempt to calculate the normalization window based on the first radial moment 794 878 double Sr1 = 0.0; 795 879 double Sr2 = 0.0; … … 809 893 float R2 = Sr2 / Sf2; 810 894 811 stamps->normWindow1 = 2.0*R1; 812 stamps->normWindow2 = 2.0*R2; 813 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii: %f for 1, %f for 2\n", stamps->normWindow1, stamps->normWindow2); 814 815 # else 816 // XXX : this block attempts to calculate the radius by looking at the curve of growth (or something vaguely equivalent). 817 // It did not do very well (though a true curve-of-growth analysis might be better...) 818 bool done1 = false; 819 bool done2 = false; 820 double prior1 = 0.0; 821 double prior2 = 0.0; 822 double delta1o = 1.0; 823 double delta2o = 1.0; 824 for (int radius = 1; radius <= size && !(done1 && done2); radius++) { 825 double within1 = 0.0; 826 double within2 = 0.0; 827 for (int y = -radius; y <= radius; y++) { 828 for (int x = -radius; x <= radius; x++) { 829 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) { 830 within1 += stamps->window1->kernel[y][x]; 831 } 832 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) { 833 within2 += stamps->window2->kernel[y][x]; 834 } 835 } 836 } 837 double delta1 = (within1 - prior1) / within1; 838 if (!done1 && (fabs(delta1) < stamps->normFrac)) { 839 // interpolate to the radius at which delta2 is normFrac: 840 stamps->normWindow1 = radius - (stamps->normFrac - delta1) / (delta1o - delta1); 841 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 1 (%f : %f)\n", stamps->normWindow1, radius, within1, delta1); 842 done1 = true; 843 } 844 double delta2 = (within2 - prior2) / within2; 845 if (!done2 && (fabs(delta2) < stamps->normFrac)) { 846 // interpolate to the radius at which delta2 is normFrac: 847 stamps->normWindow2 = radius - (stamps->normFrac - delta2) / (delta2o - delta2); 848 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "choosing %f (%d) for 2 (%f : %f)\n", stamps->normWindow2, radius, within2, delta2); 849 done2 = true; 850 } 851 psTrace("psModules.imcombine", 5, "Radius %d: %f (%f) and %f (%f)\n", radius, within1, delta1, within2, delta2); 852 853 prior1 = within1; 854 prior2 = within2; 855 delta1o = delta1; 856 delta2o = delta2; 857 858 // if (!done1 && (within1 > (1.0 - stamps->normFrac) * sum1)) { 859 // stamps->normWindow1 = radius; 860 // done1 = true; 861 // } 862 // if (!done2 && (within2 > (1.0 - stamps->normFrac) * sum2)) { 863 // stamps->normWindow2 = radius; 864 // done2 = true; 865 // } 866 867 } 868 # endif 869 870 psTrace("psModules.imcombine", 3, "Normalisation window radii set to %f and %f\n", stamps->normWindow1, stamps->normWindow2); 871 if (stamps->normWindow1 == 0 || stamps->normWindow1 >= size) { 895 // Compare the Kron Radii (R1 & R2) to above to the FWHMs : if they are too discrepant, we will need to rescale 896 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii vs FWHMs 1: fwhm: %f, kron %f\n", fwhm1, R1); 897 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii vs FWHMs 2: fwhm: %f, kron %f\n", fwhm2, R2); 898 899 // XXX CAREFUL : in pmSubtractionMatch.c:703, we rely on this factor of 2.75.. 900 stamps->normWindow1 = 2.75*R1; 901 stamps->normWindow2 = 2.75*R2; 902 psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Windows from Kron Radii: %f for 1, %f for 2\n", stamps->normWindow1, stamps->normWindow2); 903 904 // if the calculated normWindows are too large, we will fall off the stamps. In this case, we need to try again. 905 if ((stamps->normWindow1 > size) || (stamps->normWindow2 > size)) { 906 if (tryAgain) { 907 *tryAgain = true; 908 } 909 psFree (stats); 910 psFree (flux1); 911 psFree (flux2); 912 psFree (norm1); 913 psFree (norm2); 914 return false; 915 } 916 917 // this is an unrecoverable error : something really bogus in the data 918 if (stamps->normWindow1 == 0) { 872 919 psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (1)."); 920 psFree (stats); 921 psFree (flux1); 922 psFree (flux2); 923 psFree (norm1); 924 psFree (norm2); 873 925 return false; 874 926 } 875 if (stamps->normWindow2 == 0 || stamps->normWindow2 >= size) {927 if (stamps->normWindow2 == 0) { 876 928 psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (2)."); 929 psFree (stats); 930 psFree (flux1); 931 psFree (flux2); 932 psFree (norm1); 933 psFree (norm2); 877 934 return false; 935 } 936 937 // Generate a weighting window based on the kron radii 938 float radius = 2.0 * PS_MAX(R1, R2); 939 psImageInit(stamps->window->image, 0.0); 940 941 // we use a top-hat window for the moments analysis 942 for (int y = -size; y <= size; y++) { 943 for (int x = -size; x <= size; x++) { 944 if (hypot(x,y) > radius) continue; 945 stamps->window->kernel[y][x] = 1.0; 946 } 878 947 } 879 948 … … 890 959 } 891 960 } 892 893 #if 0894 {895 psFits *fits = NULL;896 fits = psFitsOpen ("window1.norm.fits", "w");897 psFitsWriteImage (fits, NULL, stamps->window1->image, 0, NULL);898 psFitsClose (fits);899 fits = psFitsOpen ("window2.norm.fits", "w");900 psFitsWriteImage (fits, NULL, stamps->window2->image, 0, NULL);901 psFitsClose (fits);902 }903 #endif904 961 905 962 psFree (stats); … … 1128 1185 continue; 1129 1186 } 1187 1188 // XXX this is somewhat arbitrary... 1189 if (source->errMag > 0.05) continue; 1190 if (fabs(source->psfMag - source->apMag) > 0.5) continue; 1191 1130 1192 if (source->modelPSF) { 1131 1193 x->data.F32[numOut] = source->modelPSF->params->data.F32[PM_PAR_XPOS]; … … 1135 1197 y->data.F32[numOut] = source->peak->yf; 1136 1198 } 1137 // fprintf (stderr, "stamp: %5.1f %5.1f\n", x->data.F32[numOut], y->data.F32[numOut]);1138 1199 numOut++; 1139 1200 } -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionStamps.h
r29543 r30631 1 1 #ifndef PM_SUBTRACTION_STAMPS_H 2 2 #define PM_SUBTRACTION_STAMPS_H 3 4 #include <pslib.h>5 6 #include "pmSubtractionKernels.h"7 8 /// Status of stamp9 typedef enum {10 PM_SUBTRACTION_STAMP_INIT, ///< Initial state11 PM_SUBTRACTION_STAMP_FOUND, ///< Found a suitable source for this stamp12 PM_SUBTRACTION_STAMP_CALCULATE, ///< Calculate matrix and vector values for this stamp13 PM_SUBTRACTION_STAMP_USED, ///< Use this stamp14 PM_SUBTRACTION_STAMP_REJECTED, ///< This stamp has been rejected15 PM_SUBTRACTION_STAMP_NONE ///< No stamp in this region16 } pmSubtractionStampStatus;17 18 /// A list of stamps19 typedef struct {20 long num; ///< Number of stamps21 psArray *stamps; ///< The stamps22 psArray *regions; ///< Regions for each stamp23 psArray *x, *y; ///< Coordinates for possible stamps (or NULL)24 psArray *flux; ///< Fluxes for possible stamps (or NULL)25 int footprint; ///< Half-size of stamps26 float normFrac; ///< Fraction of flux in window for normalisation window27 float normValue; ///< calculated normalization28 float normValue2; ///< calculated normalization29 psKernel *window1; ///< window function generated from ensemble of stamps (input 1)30 psKernel *window2; ///< window function generated from ensemble of stamps (input 2)31 psKernel *window; ///< weighting window function (sigma = 1.1 * MAX(fwhm))32 float normWindow1; ///< Size of window for measuring normalisation33 float normWindow2; ///< Size of window for measuring normalisation34 float sysErr; ///< Systematic error35 float skyErr; ///< increase effective readnoise36 } pmSubtractionStampList;37 3 38 4 /// Allocate a list of stamps … … 74 40 ); 75 41 76 77 /// A stamp for image subtraction78 typedef struct {79 float x, y; ///< Position80 float flux; ///< Flux81 float xNorm, yNorm; ///< Normalised position82 psKernel *image1; ///< Reference image postage stamp83 psKernel *image2; ///< Input image postage stamp84 psKernel *weight; ///< Weight image (1/variance) postage stamp, or NULL85 psArray *convolutions1; ///< Convolutions of image 1 for each kernel component, or NULL86 psArray *convolutions2; ///< Convolutions of image 2 for each kernel component, or NULL87 psImage *matrix; ///< Least-squares matrix, or NULL88 psVector *vector; ///< Least-squares vector, or NULL89 double norm; ///< Normalisation difference90 double normI1; ///< Sum(flux) for image 191 double normI2; ///< Sum(flux) for image 292 double normSquare1; ///< Sum(flux^2) for image 1 (used for penalty)93 double normSquare2; ///< Sum(flux^2) for image 2 (used for penalty)94 pmSubtractionStampStatus status; ///< Status of stamp95 psVector *MxxI1; ///< second moments of convolution images96 psVector *MyyI1; ///< second moments of convolution images97 psVector *MxxI2; ///< second moments of convolution images98 psVector *MyyI2; ///< second moments of convolution images99 double MxxI1raw;100 double MyyI1raw;101 double MxxI2raw;102 double MyyI2raw;103 } pmSubtractionStamp;104 105 42 /// Allocate a stamp 106 43 pmSubtractionStamp *pmSubtractionStampAlloc(void); 44 45 // find and extract the stamps 46 bool pmSubtractionStampsSelect(pmSubtractionStampList **stamps, // Stamps to read 47 const pmReadout *ro1, // Readout 1 48 const pmReadout *ro2, // Readout 2 49 const psImage *subMask, // Mask for subtraction, or NULL 50 psImage *variance, // Variance map 51 const psRegion *region, // Region of interest 52 float thresh1, // Threshold for stamp finding on readout 1 53 float thresh2, // Threshold for stamp finding on readout 2 54 float stampSpacing, // Spacing between stamps 55 float normFrac, // Fraction of flux in window for normalisation window 56 float sysError, // Relative systematic error in images 57 float skyError, // Relative systematic error in images 58 int size, // Kernel half-size 59 int footprint, // Convolution footprint for stamps 60 pmSubtractionMode mode // Mode for subtraction 61 ); 62 107 63 108 64 /// Find stamps on an image … … 172 128 /// Calculate the window and normalisation window from the stamps 173 129 bool pmSubtractionStampsGetWindow( 130 bool *tryAgain, ///< re-try with new stamp size? 174 131 pmSubtractionStampList *stamps, ///< List of stamps 175 132 int kernelSize ///< Half-size of kernel -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionThreads.c
r27365 r30631 6 6 #include <pslib.h> 7 7 8 #include "pmSubtractionTypes.h" 8 9 #include "pmSubtractionMatch.h" 9 10 #include "pmSubtractionEquation.h" … … 33 34 34 35 { 35 psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_CALCULATE_EQUATION", 4);36 psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_CALCULATE_EQUATION", 3); 36 37 task->function = &pmSubtractionCalculateEquationThread; 38 psThreadTaskAdd(task); 39 psFree(task); 40 } 41 42 { 43 psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_CONVOLVE_STAMP", 3); 44 task->function = &pmSubtractionConvolveStampThread; 37 45 psThreadTaskAdd(task); 38 46 psFree(task); -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionVisual.c
r29600 r30631 16 16 17 17 #include "pmKapaPlots.h" 18 #include "pmFPA.h" 19 #include "pmSubtractionTypes.h" 18 20 #include "pmSubtraction.h" 19 21 #include "pmSubtractionStamps.h" 20 22 #include "pmSubtractionEquation.h" 21 23 #include "pmSubtractionKernels.h" 24 #include "pmSubtractionVisual.h" 22 25 23 26 #include "pmVisual.h" … … 210 213 psImageOverlaySection(canvas, im, x0, y0, "="); 211 214 stampNum++; 215 216 // renormalize the section 217 float maxValue = 0; 218 for (int iy = 0; iy < im->numRows; iy++) { 219 for (int ix = 0; ix < im->numCols; ix++) { 220 maxValue = PS_MAX(maxValue, im->data.F64[iy][ix]); 221 } 222 } 223 if (maxValue == 0.0) continue; 224 for (int iy = 0; iy < im->numRows; iy++) { 225 for (int ix = 0; ix < im->numCols; ix++) { 226 canvas->data.F64[y0 + iy][x0 + ix] /= maxValue; 227 } 228 } 212 229 } 213 230 … … 231 248 } 232 249 250 /** Plot the least-squares matrix of each stamp */ 251 bool pmSubtractionVisualPlotLeastSquaresResid (const pmSubtractionStampList *stamps, psImage *matrixIn, int nUsed) { 252 253 if (!pmVisualTestLevel("ppsub.chisq", 1)) return true; 254 255 if (!plotLeastSquares) return true; 256 257 if (!pmVisualInitWindow (&kapa1, "PPSub:Images")) { 258 return false; 259 } 260 261 psImage *matrixNorm = psImageCopy(NULL, matrixIn, PS_TYPE_F64); 262 { 263 // renormalize the matrix 264 float maxValue = 0; 265 for (int iy = 0; iy < matrixNorm->numRows; iy++) { 266 for (int ix = 0; ix < matrixNorm->numCols; ix++) { 267 maxValue = PS_MAX(maxValue, matrixNorm->data.F64[iy][ix]); 268 } 269 } 270 for (int iy = 0; iy < matrixNorm->numRows; iy++) { 271 for (int ix = 0; ix < matrixNorm->numCols; ix++) { 272 matrixNorm->data.F64[iy][ix] /= maxValue; 273 } 274 } 275 } 276 277 // Find the stamp size 278 int imageMax = -1; 279 int numStamps = 0; 280 psElemType type = PS_TYPE_F64; 281 282 for(int i = 0; i < stamps->num; i++) { 283 pmSubtractionStamp *stamp = stamps->stamps->data[i]; 284 if (stamp == NULL) continue; 285 286 psImage *im = stamp->matrix; 287 if (im == NULL) continue; 288 289 imageMax = PS_MAX(imageMax, im->numCols); 290 imageMax = PS_MAX(imageMax, im->numRows); 291 numStamps++; 292 type = im->type.type; 293 } 294 if (imageMax == -1) return false; 295 296 int border = 15; 297 imageMax += border; 298 int tileRowCount = (int) ceil(sqrt(numStamps)); 299 int canvasX = tileRowCount * (imageMax); 300 int canvasY = tileRowCount * (imageMax); 301 psImage *canvas = psImageAlloc (canvasX, canvasY, type); 302 psImageInit (canvas, NAN); 303 304 // overlay the images 305 int stampNum = 0; 306 int stampListNum = 0; 307 while (stampNum < numStamps) { 308 int x0 = (imageMax) * (stampNum % tileRowCount); 309 int y0 = (imageMax) * (stampNum / tileRowCount); 310 311 pmSubtractionStamp *stamp = stamps->stamps->data[stampListNum++]; 312 if (stamp == NULL) continue; 313 314 psImage *im = stamp->matrix; 315 if (im == NULL) continue; 316 317 stampNum++; 318 319 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue; 320 321 // renormalize the section 322 float maxValue = 0; 323 for (int iy = 0; iy < im->numRows; iy++) { 324 for (int ix = 0; ix < im->numCols; ix++) { 325 maxValue = PS_MAX(maxValue, im->data.F64[iy][ix]); 326 } 327 } 328 if (maxValue == 0.0) continue; 329 for (int iy = 0; iy < im->numRows; iy++) { 330 for (int ix = 0; ix < im->numCols; ix++) { 331 canvas->data.F64[y0 + iy][x0 + ix] = (im->data.F64[iy][ix] / maxValue - matrixNorm->data.F64[iy][ix]) / matrixNorm->data.F64[iy][ix]; 332 } 333 } 334 } 335 336 psImage *canvas32 = pmVisualImageToFloat(canvas); 337 pmVisualRangeImage(kapa2, canvas32, "Least_Squares", 0, -100.0, 100.0); 338 339 if (0) { 340 static int count = 0; 341 char filename[64]; 342 sprintf (filename, "chisq.%02d.fits", count); 343 count ++; 344 psFits *fits = psFitsOpen (filename, "w"); 345 psFitsWriteImage (fits, NULL, canvas32, 0, NULL); 346 psFitsClose (fits); 347 } 348 349 pmVisualAskUser(&plotLeastSquares); 350 psFree(canvas); 351 psFree(canvas32); 352 return true; 353 } 354 233 355 bool pmSubtractionVisualShowSubtraction(psImage *image, psImage *ref, psImage *sub) { 234 356 … … 304 426 } 305 427 306 // XXX clear the overlay(s) (red at least!) 428 // clear the overlay (red at least!) 429 KiiEraseOverlay (kapa2, "red"); 307 430 308 431 // get the kernel sizes … … 337 460 int nKernels = 0; 338 461 462 // paste in the kernel images, scaled by sum2 339 463 if (maxStamp->convolutions1) { 340 464 // output image is a grid of NXsub by NYsub sub-images … … 359 483 int yPix = ySub * (2*footprint + 1 + 3) + footprint; 360 484 361 double sum = 0.0;362 485 double sum2 = 0.0; 363 486 for (int y = -footprint; y <= footprint; y++) { 364 487 for (int x = -footprint; x <= footprint; x++) { 365 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x];366 sum += kernel->kernel[y][x];367 488 sum2 += PS_SQR(kernel->kernel[y][x]); 368 489 } 369 490 } 370 // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2); 491 float scale = sqrt(sum2) / PS_SQR(2*footprint + 1); 492 for (int y = -footprint; y <= footprint; y++) { 493 for (int x = -footprint; x <= footprint; x++) { 494 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x] / scale; 495 } 496 } 371 497 } 372 498 pmVisualScaleImage(kapa2, output, "Image", 0, true); … … 401 527 int yPix = ySub * (2*footprint + 1 + 3) + footprint; 402 528 403 double sum = 0.0;404 529 double sum2 = 0.0; 405 530 for (int y = -footprint; y <= footprint; y++) { 406 531 for (int x = -footprint; x <= footprint; x++) { 407 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x];408 sum += kernel->kernel[y][x];409 532 sum2 += PS_SQR(kernel->kernel[y][x]); 410 533 } 411 534 } 412 // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2); 535 float scale = sqrt(sum2) / PS_SQR(2*footprint + 1); 536 for (int y = -footprint; y <= footprint; y++) { 537 for (int x = -footprint; x <= footprint; x++) { 538 output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x] / scale; 539 } 540 } 413 541 } 414 542 pmVisualScaleImage(kapa2, output, "Image", 1, true); … … 468 596 KiiLoadOverlay (kapa2, overlay, Noverlay, "red"); 469 597 FREE (overlay); 470 return true;471 }472 473 static int footprint = 0;474 static int NX = 0;475 static int NY = 0;476 static psImage *sourceImage = NULL;477 static psImage *targetImage = NULL;478 static psImage *residualImage = NULL;479 static psImage *fresidualImage = NULL;480 static psImage *differenceImage = NULL;481 static psImage *convolutionImage = NULL;482 483 bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps) {484 485 if (!pmVisualTestLevel("ppsub.fit", 1)) return true;486 487 // generate 4 storage images large enough to hold the N stamps:488 489 footprint = stamps->footprint;490 491 float NXf = sqrt(stamps->num);492 NX = (int) NXf == NXf ? NXf : NXf + 1.0;493 494 float NYf = stamps->num / NX;495 NY = (int) NYf == NY ? NYf : NYf + 1.0;496 497 int NXpix = (2*footprint + 1) * NX;498 NXpix += (NX > 1) ? 3 * NX : 0;499 500 int NYpix = (2*footprint + 1) * NY;501 NYpix += (NY > 1) ? 3 * NY : 0;502 503 sourceImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);504 targetImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);505 residualImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);506 fresidualImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);507 differenceImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);508 convolutionImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);509 510 psImageInit (sourceImage, 0.0);511 psImageInit (targetImage, 0.0);512 psImageInit (residualImage, 0.0);513 psImageInit (fresidualImage, 0.0);514 psImageInit (differenceImage, 0.0);515 psImageInit (convolutionImage, 0.0);516 517 return true;518 }519 520 bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index) {521 522 if (!pmVisualTestLevel("ppsub.stamp", 1)) return true;523 524 double sum;525 526 int NXoff = index % NX;527 int NYoff = index / NX;528 529 int NXpix = NXoff * (2*footprint + 1 + 3) + footprint;530 int NYpix = NYoff * (2*footprint + 1 + 3) + footprint;531 532 // insert the (target) kernel into the (target) image:533 sum = 0.0;534 for (int y = -footprint; y <= footprint; y++) {535 for (int x = -footprint; x <= footprint; x++) {536 targetImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x];537 sum += targetImage->data.F32[y + NYpix][x + NXpix];538 }539 }540 targetImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;541 542 // insert the (source) kernel into the (source) image:543 sum = 0.0;544 for (int y = -footprint; y <= footprint; y++) {545 for (int x = -footprint; x <= footprint; x++) {546 sourceImage->data.F32[y + NYpix][x + NXpix] = source->kernel[y][x];547 sum += sourceImage->data.F32[y + NYpix][x + NXpix];548 }549 }550 sourceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;551 552 // insert the (convolution) kernel into the (convolution) image:553 sum = 0.0;554 for (int y = -footprint; y <= footprint; y++) {555 for (int x = -footprint; x <= footprint; x++) {556 convolutionImage->data.F32[y + NYpix][x + NXpix] = convolution->kernel[y][x];557 sum += convolutionImage->data.F32[y + NYpix][x + NXpix];558 }559 }560 convolutionImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;561 562 // insert the (difference) kernel into the (difference) image:563 sum = 0.0;564 for (int y = -footprint; y <= footprint; y++) {565 for (int x = -footprint; x <= footprint; x++) {566 differenceImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm;567 sum += differenceImage->data.F32[y + NYpix][x + NXpix];568 }569 }570 differenceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;571 572 // insert the (residual) kernel into the (residual) image:573 sum = 0.0;574 for (int y = -footprint; y <= footprint; y++) {575 for (int x = -footprint; x <= footprint; x++) {576 residualImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm - convolution->kernel[y][x];577 sum += residualImage->data.F32[y + NYpix][x + NXpix];578 }579 }580 residualImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;581 582 // insert the (fresidual) kernel into the (fresidual) image:583 for (int y = -footprint; y <= footprint; y++) {584 for (int x = -footprint; x <= footprint; x++) {585 fresidualImage->data.F32[y + NYpix][x + NXpix] = residualImage->data.F32[y + NYpix][x + NXpix] / sqrt(PS_MAX(target->kernel[y][x], 100.0));586 }587 }588 598 return true; 589 599 } … … 611 621 } 612 622 613 bool pmSubtractionVisualShowFit(double norm) { 614 615 // for testing, dump the residual image and exit 616 if (0) { 617 psMetadata *header = psMetadataAlloc();618 psMetadataAddF32 (header, PS_LIST_TAIL, "NORM", 0, "Normalization", norm);619 psFits *fits = psFitsOpen("resid.fits", "w");620 psFitsWriteImage(fits, header, residualImage, 0, NULL);621 psFitsClose(fits);622 // exit (0); 623 } 623 static int footprint = 0; 624 static int NX = 0; 625 static int NY = 0; 626 static psImage *sourceImage = NULL; 627 static psImage *targetImage = NULL; 628 static psImage *residualImage = NULL; 629 static psImage *fresidualImage = NULL; 630 static psImage *differenceImage = NULL; 631 static psImage *convolutionImage = NULL; 632 633 bool pmSubtractionVisualShowFit(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels) { 624 634 625 635 if (!pmVisualTestLevel("ppsub.fit", 1)) return true; … … 627 637 if (!pmVisualInitWindow(&kapa1, "ppSub:Images")) return false; 628 638 if (!pmVisualInitWindow(&kapa2, "ppSub:Misc")) return false; 639 640 // set up holding images for the visualization 641 pmSubtractionVisualShowFitInit (stamps); 642 643 int numKernels = kernels->num; // Number of kernels 644 645 psImage *polyValues = NULL; // Polynomial values 646 psKernel *residual = psKernelAlloc(-stamps->footprint, stamps->footprint, -stamps->footprint, stamps->footprint); // Residual image 647 648 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 649 650 for (int i = 0; i < stamps->num; i++) { 651 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest 652 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { continue; } 653 654 // Calculate coefficients of the kernel basis functions 655 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 656 double background = p_pmSubtractionSolutionBackground(kernels, polyValues); // Difference in background 657 658 psImageInit(residual->image, 0.0); 659 660 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 661 psKernel *target; // Target postage stamp 662 psKernel *source; // Source postage stamp 663 psArray *convolutions; // Convolution postage stamps for each kernel basis function 664 switch (kernels->mode) { 665 case PM_SUBTRACTION_MODE_1: 666 target = stamp->image2; 667 source = stamp->image1; 668 convolutions = stamp->convolutions1; 669 break; 670 case PM_SUBTRACTION_MODE_2: 671 target = stamp->image1; 672 source = stamp->image2; 673 convolutions = stamp->convolutions2; 674 break; 675 default: 676 psAbort("Unsupported subtraction mode: %x", kernels->mode); 677 } 678 679 for (int j = 0; j < numKernels; j++) { 680 psKernel *convolution = convolutions->data[j]; // Convolution 681 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 682 for (int y = - footprint; y <= footprint; y++) { 683 for (int x = - footprint; x <= footprint; x++) { 684 residual->kernel[y][x] += convolution->kernel[y][x] * coefficient; 685 } 686 } 687 } 688 // visualize the target, source, convolution and residual 689 pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i); 690 } else { 691 // Dual convolution 692 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image 693 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image 694 psKernel *image1 = stamp->image1; // The first image 695 psKernel *image2 = stamp->image2; // The second image 696 697 for (int j = 0; j < numKernels; j++) { 698 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image 699 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image 700 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1 701 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2 702 703 for (int y = - footprint; y <= footprint; y++) { 704 for (int x = - footprint; x <= footprint; x++) { 705 residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1; 706 } 707 } 708 } 709 // visualize the target, source, convolution and residual 710 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i); 711 } 712 } 713 pmSubtractionVisualShowFitImage(norm); 714 715 return true; 716 } 717 718 // generate 4 storage images large enough to hold the stamps: 719 bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps) { 720 721 footprint = stamps->footprint; 722 723 float NXf = sqrt(stamps->num); 724 NX = (int) NXf == NXf ? NXf : NXf + 1.0; 725 726 float NYf = stamps->num / NX; 727 NY = (int) NYf == NY ? NYf : NYf + 1.0; 728 729 int NXpix = (2*footprint + 1) * NX; 730 NXpix += (NX > 1) ? 3 * NX : 0; 731 732 int NYpix = (2*footprint + 1) * NY; 733 NYpix += (NY > 1) ? 3 * NY : 0; 734 735 sourceImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 736 targetImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 737 residualImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 738 fresidualImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 739 differenceImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 740 convolutionImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32); 741 742 psImageInit (sourceImage, 0.0); 743 psImageInit (targetImage, 0.0); 744 psImageInit (residualImage, 0.0); 745 psImageInit (fresidualImage, 0.0); 746 psImageInit (differenceImage, 0.0); 747 psImageInit (convolutionImage, 0.0); 748 749 return true; 750 } 751 752 bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index) { 753 754 double sum; 755 756 int NXoff = index % NX; 757 int NYoff = index / NX; 758 759 int NXpix = NXoff * (2*footprint + 1 + 3) + footprint; 760 int NYpix = NYoff * (2*footprint + 1 + 3) + footprint; 761 762 // insert the (target) kernel into the (target) image: 763 sum = 0.0; 764 for (int y = -footprint; y <= footprint; y++) { 765 for (int x = -footprint; x <= footprint; x++) { 766 targetImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x]; 767 sum += targetImage->data.F32[y + NYpix][x + NXpix]; 768 } 769 } 770 targetImage->data.F32[footprint + 1 + NYpix][NXpix] = sum; 771 772 // insert the (source) kernel into the (source) image: 773 sum = 0.0; 774 for (int y = -footprint; y <= footprint; y++) { 775 for (int x = -footprint; x <= footprint; x++) { 776 sourceImage->data.F32[y + NYpix][x + NXpix] = source->kernel[y][x]; 777 sum += sourceImage->data.F32[y + NYpix][x + NXpix]; 778 } 779 } 780 sourceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum; 781 782 // insert the (convolution) kernel into the (convolution) image: 783 sum = 0.0; 784 for (int y = -footprint; y <= footprint; y++) { 785 for (int x = -footprint; x <= footprint; x++) { 786 convolutionImage->data.F32[y + NYpix][x + NXpix] = convolution->kernel[y][x]; 787 sum += convolutionImage->data.F32[y + NYpix][x + NXpix]; 788 } 789 } 790 convolutionImage->data.F32[footprint + 1 + NYpix][NXpix] = sum; 791 792 // insert the (difference) kernel into the (difference) image: 793 sum = 0.0; 794 for (int y = -footprint; y <= footprint; y++) { 795 for (int x = -footprint; x <= footprint; x++) { 796 differenceImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm; 797 sum += differenceImage->data.F32[y + NYpix][x + NXpix]; 798 } 799 } 800 differenceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum; 801 802 // insert the (residual) kernel into the (residual) image: 803 sum = 0.0; 804 for (int y = -footprint; y <= footprint; y++) { 805 for (int x = -footprint; x <= footprint; x++) { 806 residualImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm - convolution->kernel[y][x]; 807 sum += residualImage->data.F32[y + NYpix][x + NXpix]; 808 } 809 } 810 residualImage->data.F32[footprint + 1 + NYpix][NXpix] = sum; 811 812 // insert the (fresidual) kernel into the (fresidual) image: 813 for (int y = -footprint; y <= footprint; y++) { 814 for (int x = -footprint; x <= footprint; x++) { 815 fresidualImage->data.F32[y + NYpix][x + NXpix] = residualImage->data.F32[y + NYpix][x + NXpix] / sqrt(PS_MAX(target->kernel[y][x], 100.0)); 816 } 817 } 818 return true; 819 } 820 821 bool pmSubtractionVisualShowFitImage(double norm) { 629 822 630 823 KiiEraseOverlay (kapa1, "red"); … … 673 866 psVector *x = psVectorAllocEmpty (kernels->num, PS_TYPE_F32); 674 867 psVector *y = psVectorAllocEmpty (kernels->num, PS_TYPE_F32); 868 psVector *dy = psVectorAllocEmpty (kernels->num, PS_TYPE_F32); 675 869 676 870 graphdata.xmin = -1.0; … … 685 879 x->data.F32[i] = i; 686 880 y->data.F32[i] = p_pmSubtractionSolutionCoeff(kernels, polyValues, i, false); 881 dy->data.F32[i] = kernels->solution1err->data.F64[i]; 687 882 graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[i]); 688 883 graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[i]); 689 884 } 690 x->n = y->n = kernels->num;885 x->n = y->n = dy->n = kernels->num; 691 886 692 887 float range; … … 709 904 graphdata.size = 0.5; 710 905 graphdata.style = 2; 906 graphdata.etype |= 0x01; 711 907 712 908 KapaPrepPlot (kapa3, x->n, &graphdata); 713 909 KapaPlotVector (kapa3, x->n, x->data.F32, "x"); 714 910 KapaPlotVector (kapa3, x->n, y->data.F32, "y"); 911 KapaPlotVector (kapa3, x->n, dy->data.F32, "dym"); 912 KapaPlotVector (kapa3, x->n, dy->data.F32, "dyp"); 715 913 716 914 psFree (x); 717 915 psFree (y); 916 psFree (dy); 718 917 psFree (polyValues); 918 919 pmVisualAskUser(NULL); 920 return true; 921 } 922 923 // plot log(flux) vs log(chisq), log(flux) vs log(moments), log(chisq) vs log(moments) 924 bool pmSubtractionVisualPlotChisqAndMoments(psVector *fluxes, psVector *chisq, psVector *moments) { 925 926 Graphdata graphdata; 927 KapaSection section; 928 929 if (!pmVisualTestLevel("ppsub.fit", 1)) return true; 930 931 if (!pmVisualInitWindow(&kapa3, "ppSub:plots")) return false; 932 933 KapaClearSections (kapa3); 934 KapaInitGraph (&graphdata); 935 KiiResize(kapa3, 1500, 500); 936 937 psVector *lchi = psVectorAlloc (fluxes->n, PS_TYPE_F32); 938 psVector *lflx = psVectorAlloc (fluxes->n, PS_TYPE_F32); 939 psVector *lMxx = psVectorAlloc (fluxes->n, PS_TYPE_F32); 940 941 // construct the plot vectors 942 for (int i = 0; i < fluxes->n; i++) { 943 lchi->data.F32[i] = log10(chisq->data.F32[i]); 944 lflx->data.F32[i] = log10(fluxes->data.F32[i]); 945 lMxx->data.F32[i] = log10(moments->data.F32[i]); 946 } 947 948 section.bg = KapaColorByName ("none"); // XXX probably should be 'none' 949 950 // section 1: lflux vs lchi 951 section.dx = 0.33; 952 section.dy = 1.00; 953 section.x = 0.00; 954 section.y = 0.00; 955 section.name = psStringCopy ("flux.v.chi"); 956 KapaSetSection (kapa3, §ion); 957 psFree (section.name); 958 959 graphdata.color = KapaColorByName ("black"); 960 pmVisualScaleGraphdata(&graphdata, lflx, lchi, false); 961 KapaSetLimits (kapa3, &graphdata); 962 963 KapaSetFont (kapa3, "helvetica", 14); 964 KapaBox (kapa3, &graphdata); 965 KapaSendLabel (kapa3, "log(flux)", KAPA_LABEL_XM); 966 KapaSendLabel (kapa3, "log(chisq)", KAPA_LABEL_YM); 967 968 graphdata.color = KapaColorByName ("black"); 969 graphdata.ptype = 2; 970 graphdata.size = 0.5; 971 graphdata.style = 2; 972 973 KapaPrepPlot (kapa3, lflx->n, &graphdata); 974 KapaPlotVector (kapa3, lflx->n, lflx->data.F32, "x"); 975 KapaPlotVector (kapa3, lflx->n, lchi->data.F32, "y"); 976 977 // section 2: lflux vs lMxx 978 section.dx = 0.33; 979 section.dy = 1.00; 980 section.x = 0.33; 981 section.y = 0.00; 982 section.name = psStringCopy ("flux.v.mom"); 983 KapaSetSection (kapa3, §ion); 984 psFree (section.name); 985 986 graphdata.color = KapaColorByName ("black"); 987 pmVisualScaleGraphdata(&graphdata, lflx, lMxx, false); 988 KapaSetLimits (kapa3, &graphdata); 989 990 KapaSetFont (kapa3, "helvetica", 14); 991 KapaBox (kapa3, &graphdata); 992 KapaSendLabel (kapa3, "log(flux)", KAPA_LABEL_XM); 993 KapaSendLabel (kapa3, "log(moments)", KAPA_LABEL_YM); 994 995 graphdata.color = KapaColorByName ("black"); 996 graphdata.ptype = 2; 997 graphdata.size = 0.5; 998 graphdata.style = 2; 999 1000 KapaPrepPlot (kapa3, lflx->n, &graphdata); 1001 KapaPlotVector (kapa3, lflx->n, lflx->data.F32, "x"); 1002 KapaPlotVector (kapa3, lflx->n, lMxx->data.F32, "y"); 1003 1004 // section 1: lflux vs lchi 1005 section.dx = 0.33; 1006 section.dy = 1.00; 1007 section.x = 0.66; 1008 section.y = 0.00; 1009 section.name = psStringCopy ("chi.v.mom"); 1010 KapaSetSection (kapa3, §ion); 1011 psFree (section.name); 1012 1013 graphdata.color = KapaColorByName ("black"); 1014 pmVisualScaleGraphdata(&graphdata, lchi, lMxx, false); 1015 KapaSetLimits (kapa3, &graphdata); 1016 1017 KapaSetFont (kapa3, "helvetica", 14); 1018 KapaBox (kapa3, &graphdata); 1019 KapaSendLabel (kapa3, "log(chisq)", KAPA_LABEL_XM); 1020 KapaSendLabel (kapa3, "log(moments)", KAPA_LABEL_YM); 1021 1022 graphdata.color = KapaColorByName ("black"); 1023 graphdata.ptype = 2; 1024 graphdata.size = 0.5; 1025 graphdata.style = 2; 1026 1027 KapaPrepPlot (kapa3, lflx->n, &graphdata); 1028 KapaPlotVector (kapa3, lflx->n, lchi->data.F32, "x"); 1029 KapaPlotVector (kapa3, lflx->n, lMxx->data.F32, "y"); 719 1030 720 1031 pmVisualAskUser(NULL); -
branches/czw_branch/20101203/psModules/src/imcombine/pmSubtractionVisual.h
r29601 r30631 6 6 bool pmSubtractionVisualPlotStamps(pmSubtractionStampList *stamps, pmReadout *ro); 7 7 bool pmSubtractionVisualPlotLeastSquares(pmSubtractionStampList *stamps); 8 bool pmSubtractionVisualPlotLeastSquaresResid (const pmSubtractionStampList *stamps, psImage *matrixIn, int nUsed); 8 9 bool pmSubtractionVisualShowSubtraction(psImage *image, psImage *ref, psImage *sub); 10 11 bool pmSubtractionVisualShowFit(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels); 9 12 bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps); 10 13 bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index); 11 bool pmSubtractionVisualShowFit(double norm); 14 bool pmSubtractionVisualShowFitImage(double norm); 15 12 16 bool pmSubtractionVisualPlotFit(const pmSubtractionKernels *kernels); 13 17 bool pmSubtractionVisualShowKernels(pmSubtractionKernels *kernels); 14 18 bool pmSubtractionVisualShowBasis(pmSubtractionStampList *stamps); 19 bool pmSubtractionVisualPlotChisqAndMoments(psVector *fluxes, psVector *chisq, psVector *moments); 15 20 16 21 #endif -
branches/czw_branch/20101203/psModules/src/objects
- Property svn:mergeinfo deleted
-
branches/czw_branch/20101203/psModules/src/objects/pmFootprint.c
r29004 r30631 255 255 } 256 256 257 // create a new footprint with the same span set as the input footprint 258 pmFootprint *pmFootprintCopyData(pmFootprint *inFoot, psImage *image) { 259 260 pmFootprint *outFoot = pmFootprintAlloc(inFoot->nspans, image); 261 for (int i = 0; i < inFoot->nspans; i++) { 262 pmSpan *span = inFoot->spans->data[i]; 263 pmFootprintAddSpan(outFoot, span->y, span->x0, span->x1); 264 } 265 return outFoot; 266 } 267 257 268 /************************************************************************************************************/ -
branches/czw_branch/20101203/psModules/src/objects/pmFootprint.h
r29004 r30631 27 27 28 28 bool pmFootprintAllocEmptySpans (pmFootprint *footprint, int nSpans); 29 30 pmFootprint *pmFootprintCopyData(pmFootprint *inFoot, psImage *image); 29 31 30 32 pmFootprint *pmFootprintNormalize(pmFootprint *fp); -
branches/czw_branch/20101203/psModules/src/objects/pmFootprintAssignPeaks.c
r29004 r30631 24 24 /* 25 25 * Given a psArray of pmFootprints and another of pmPeaks, assign the peaks to the 26 * footprints in which th atfall; if they _don't_ fall in a footprint, add a suitable26 * footprints in which they fall; if they _don't_ fall in a footprint, add a suitable 27 27 * one to the list. 28 28 */ … … 83 83 84 84 // XXX are we allowed to have peak-less footprints?? 85 if (!fp->peaks->n) continue; 85 if (fp->peaks->n == 0) continue; 86 if (fp->peaks->n == 1) continue; 86 87 87 88 fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN); 88 89 90 // XXX check for an assert on duplicates (I don't think they can happen, but 91 // let's double check for now) 92 93 for (int j = 1; j < fp->peaks->n; j++) { 94 psAssert (fp->peaks->data[j] != fp->peaks->data[j-1], "duplicate peak!"); 95 } 96 continue; 97 98 // XXX WHY am I culling duplicates? how can there be duplicates? 89 99 // XXX EAM : the algorithm below should be much faster than using psArrayRemove if 90 100 // the number of peaks in the footprint is large, or if there are no duplicates. … … 93 103 94 104 // track the number of good peaks in the footprint 95 int nGood = 1;105 int lastGood = 0; 96 106 97 107 // check for duplicates … … 100 110 // (if sorted list has A, B, A, B ...) 101 111 for (int j = 1; j < fp->peaks->n; j++) { 102 if (fp->peaks->data[j] == fp->peaks->data[ nGood]) {112 if (fp->peaks->data[j] == fp->peaks->data[lastGood]) { 103 113 // everything on the array has its own mem reference; free and drop this one 104 114 psFree (fp->peaks->data[j]); 105 115 fp->peaks->data[j] = NULL; 106 116 } else { 107 nGood ++;117 lastGood ++; 108 118 } 109 119 } 120 int nGood = lastGood + 1; 110 121 111 122 // no deleted peaks, go to next footprint -
branches/czw_branch/20101203/psModules/src/objects/pmFootprintCullPeaks.c
r29004 r30631 28 28 * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently 29 29 * isolated. More precisely, for each peak find the highest coll that you'd have to traverse 30 * to reach a still higher peak --- and if that coll's more than nsigma DN below your30 * to reach a still higher peak --- and if that coll's more (less?) than nsigma DN below your 31 31 * starting point, discard the peak. 32 32 */ … … 99 99 float threshold = flux - nsigma_delta*stdev_pad; 100 100 101 if (isnan(threshold) || threshold < min_threshold) {101 if (isnan(threshold)) { 102 102 // min_threshold is assumed to be below the detection threshold, 103 103 // so all the peaks are pmFootprint, and this isn't the brightest … … 109 109 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; 110 110 } 111 112 if (threshold < min_threshold) { 113 threshold = min_threshold; 114 } 111 115 112 116 // init peakFootprint here? -
branches/czw_branch/20101203/psModules/src/objects/pmModel.c
r29004 r30631 70 70 tmp->fitRadius = 0; 71 71 tmp->flags = PM_MODEL_STATUS_NONE; 72 tmp->residuals = NULL; // XXX should the model own this memory? 72 tmp->residuals = NULL; // do not free: the model does not own this memory 73 tmp->isPCM = false; 73 74 74 75 psS32 Nparams = pmModelClassParameterCount(type); … … 108 109 pmModel *pmModelCopy (pmModel *model) 109 110 { 110 PS_ASSERT_PTR_NON_NULL(model, NULL); 111 111 if (model == NULL) { 112 return NULL; 113 } 112 114 pmModel *new = pmModelAlloc (model->type); 113 115 -
branches/czw_branch/20101203/psModules/src/objects/pmModel.h
r29004 r30631 43 43 float fitRadius; ///< fit radius actually used 44 44 pmResiduals *residuals; ///< normalized PSF residuals 45 bool isPCM; ///< is this model fitted with PSF-convolution? 45 46 46 47 // functions for this model which depend on the model class -
branches/czw_branch/20101203/psModules/src/objects/pmPCMdata.h
r29004 r30631 83 83 pmPCMdata *pcm); 84 84 85 psKernel *pmPCMkernelFromPSF (pmSource *source, int nPix); 86 85 87 bool pmSourceModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal); 86 88 -
branches/czw_branch/20101203/psModules/src/objects/pmPSFtry.c
r29004 r30631 84 84 85 85 for (int i = 0; i < sources->n; i++) { 86 test->sources->data[i] = pmSourceCopy (sources->data[i]); 86 pmSource *sourceOld = sources->data[i]; 87 pmSource *sourceNew = pmSourceCopy (sourceOld); 88 89 // save a reference so we can get back to the original 90 // this is specifically used in psphotChooosePSF to unflag the candidate PSF sources 91 // which were not actually used to generate a PSF model 92 sourceNew->parent = sourceOld; 93 94 test->sources->data[i] = sourceNew; 87 95 } 88 96 -
branches/czw_branch/20101203/psModules/src/objects/pmPSFtryFitEXT.c
r29004 r30631 65 65 if (!source->moments) { 66 66 psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_EXT_FAIL; 67 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : no moments\n", i, source->peak->x, source->peak->y); 67 68 continue; 68 69 } 69 70 if (!source->moments->nPixels) { 71 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : no pixels\n", i, source->peak->x, source->peak->y); 70 72 psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_EXT_FAIL; 71 73 continue; … … 74 76 source->modelEXT = pmSourceModelGuess (source, options->type); 75 77 if (source->modelEXT == NULL) { 78 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : failed to generate model guess\n", i, source->peak->x, source->peak->y); 76 79 psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_EXT_FAIL; 77 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : failed to generate model guess\n", i, source->peak->x, source->peak->y);78 80 continue; 79 81 } … … 91 93 // exclude the poor fits 92 94 if (!status) { 95 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : status is poor\n", i, source->peak->x, source->peak->y); 93 96 psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_EXT_FAIL; 94 psTrace ("psModules.objects", 4, "masking %d (%d,%d) : status is poor\n", i, source->peak->x, source->peak->y);95 97 continue; 96 98 } -
branches/czw_branch/20101203/psModules/src/objects/pmPSFtryFitPSF.c
r29004 r30631 81 81 if (source->modelPSF == NULL) { 82 82 psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_BAD_MODEL; 83 psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : bad PSF fit\n", i, source->peak->x, source->peak->y); 83 84 continue; 84 85 } -
branches/czw_branch/20101203/psModules/src/objects/pmPSFtryModel.c
r30118 r30631 52 52 // mask values indicate the reason the source was rejected: 53 53 54 // XXX some test code (delete eventually) 55 // bool countMaskedSources(pmPSFtry *try, char *msg) { 56 // 57 // int N1 = 0; 58 // int N2 = 0; 59 // for (int i = 0; i < try->sources->n; i++) { 60 // pmSource *source = try->sources->data[i]; 61 // // fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR)); 62 // if (source->mode & PM_SOURCE_MODE_PSFSTAR) { 63 // N1 ++; 64 // } 65 // if (try->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) { 66 // N2 ++; 67 // } 68 // } 69 // fprintf (stderr, "%s : masked: %d or %d of %ld\n", msg, N1, N2, try->sources->n); 70 // return true; 71 // } 72 54 73 // generate a pmPSFtry with a copy of the test PSF sources 55 74 pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psImageMaskType maskVal, psImageMaskType markVal) … … 203 222 chisq->data.F32[i] = 0.0; 204 223 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xff; 224 psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : no PSF model\n", i, source->peak->x, source->peak->y); 205 225 } else { 206 226 flux->data.F32[i] = source->modelPSF->params->data.F32[PM_PAR_I0]; -
branches/czw_branch/20101203/psModules/src/objects/pmSource.c
r30118 r30631 61 61 psFree(tmp->moments); 62 62 psFree(tmp->diffStats); 63 psFree(tmp->radial );63 psFree(tmp->radialAper); 64 64 psFree(tmp->blends); 65 65 psTrace("psModules.objects", 10, "---- end ----\n"); … … 126 126 source->extpars = NULL; 127 127 source->diffStats = NULL; 128 source->radial = NULL; 128 source->radialAper = NULL; 129 source->parent = NULL; 129 130 130 131 source->region = psRegionSet(NAN, NAN, NAN, NAN); … … 159 160 affecting the original. This Copy can be used to allow multiple fit attempts on the same 160 161 object. The pixels, variance, and mask arrays all point to the same original subarrays. The 161 peak and moments point at the original values. 162 peak and moments point at the original values. The models, blends, and XXX are NOT copied 162 163 *****************************************************************************/ 163 164 pmSource *pmSourceCopy(pmSource *in) … … 167 168 } 168 169 pmSource *source = pmSourceAlloc (); 169 170 // keep the original ID so we can find map back to the original171 P_PM_SOURCE_SET_ID(source, in->id);172 170 173 171 // peak has the same values as the original … … 203 201 } 204 202 205 /******************************************************************************206 pmSourceCopyData(): this creates a new, duplicate source with the same parameters as the207 original (but is actually a new source at the same location)208 *****************************************************************************/209 pmSource *pmSourceCopyData(pmSource *in)210 {211 if (in == NULL) {212 return(NULL);213 }214 // this copy is used to allow multiple fit attempts on the215 // same object. the pixels, variance, and mask arrays all point to216 // the same original subarrays. the peak and moments point at217 // the original values.218 pmSource *source = pmSourceAlloc ();219 220 // this is actually the same peak as the original, is this the correct way to handle this?221 if (in->peak != NULL) {222 source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);223 source->peak->xf = in->peak->xf;224 source->peak->yf = in->peak->yf;225 source->peak->flux = in->peak->flux;226 source->peak->SN = in->peak->SN;227 }228 229 // copy the values in the moments structure230 if (in->moments != NULL) {231 source->moments = pmMomentsAlloc();232 *source->moments = *in->moments;233 }234 235 // These images are all views to the parent.236 // We want a new view, but pointing at the same pixels.237 source->pixels = psImageCopyView(NULL, in->pixels);238 source->variance = psImageCopyView(NULL, in->variance);239 source->maskView = in->maskView ? psImageCopyView(NULL, in->maskView) : NULL;240 241 // the maskObj is a unique mask array; create a new mask image242 source->maskObj = in->maskObj ? psImageCopy (NULL, in->maskObj, PS_TYPE_IMAGE_MASK) : NULL;243 244 source->type = in->type;245 source->mode = in->mode;246 source->imageID = in->imageID;247 248 return(source);249 }250 251 203 // x,y are defined in the parent image coords of readout->image 252 204 bool pmSourceDefinePixels(pmSource *mySource, … … 300 252 newRegion = psRegionForImage (readout->image, newRegion); 301 253 254 // re-define if required by region or absence of pixels 302 255 extend = false; 303 256 extend |= (int)(newRegion.x0) < (int)(mySource->region.x0); … … 335 288 } 336 289 return extend; 290 } 291 292 bool pmSourceRedefinePixelsByRegion(pmSource *mySource, 293 const pmReadout *readout, 294 psRegion newRegion) 295 { 296 PS_ASSERT_PTR_NON_NULL(mySource, false); 297 PS_ASSERT_PTR_NON_NULL(readout, false); 298 PS_ASSERT_PTR_NON_NULL(readout->image, false); 299 300 // re-create the subimage 301 psFree (mySource->pixels); 302 psFree (mySource->variance); 303 psFree (mySource->maskView); 304 305 mySource->pixels = psImageSubset(readout->image, newRegion); 306 mySource->variance = psImageSubset(readout->variance, newRegion); 307 mySource->maskView = psImageSubset(readout->mask, newRegion); 308 mySource->region = newRegion; 309 310 // re-copy the main mask pixels. NOTE: the user will need to reset the object mask 311 // pixels (eg, with psImageKeepCircle) 312 mySource->maskObj = psImageCopy (mySource->maskObj, mySource->maskView, PS_TYPE_IMAGE_MASK); 313 314 // drop the old modelFlux pixels and force the user to re-create 315 psFree (mySource->modelFlux); 316 mySource->modelFlux = NULL; 317 318 // drop the old psfImage pixels and force the user to re-create 319 psFree (mySource->psfImage); 320 mySource->psfImage = NULL; 321 322 return true; 337 323 } 338 324 … … 675 661 if ((source->moments->SN > PSF_SN_LIM) && (radius < PSF_CLUMP_NSIGMA)) { 676 662 source->type = PM_SOURCE_TYPE_STAR; 677 source-> mode |= PM_SOURCE_MODE_PSFSTAR;663 source->tmpFlags |= PM_SOURCE_TMPF_CANDIDATE_PSFSTAR; 678 664 Npsf ++; 679 665 continue; … … 934 920 } 935 921 936 // construct a realization of the source model 937 // XXX this function should optionally save an existing psf image from modelFlux 922 // construct a realization of the PSF model at the location of this source 938 923 bool pmSourceCachePSF (pmSource *source, psImageMaskType maskVal) { 939 924 PS_ASSERT_PTR_NON_NULL(source, false); … … 1020 1005 } 1021 1006 1022 if (!addNoise) { 1023 if (add) { 1024 status = pmModelAddWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy); 1025 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED; 1026 } else { 1027 status = pmModelSubWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy); 1028 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 1029 } 1007 if (add) { 1008 status = pmModelAddWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy); 1009 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED; 1010 } else { 1011 status = pmModelSubWithOffset (target, source->maskObj, model, PM_MODEL_OP_FULL, maskVal, dx, dy); 1012 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 1030 1013 } 1031 1014 -
branches/czw_branch/20101203/psModules/src/objects/pmSource.h
r29546 r30631 35 35 PM_SOURCE_TMPF_SIZE_CR_CANDIDATE = 0x0008, 36 36 PM_SOURCE_TMPF_MOMENTS_MEASURED = 0x0010, 37 PM_SOURCE_TMPF_CANDIDATE_PSFSTAR = 0x0020, 37 38 } pmSourceTmpF; 38 39 … … 42 43 * simplest measurement of a source is the location and flux of the peak pixel 43 44 * associated with the source: 45 * 46 * a pmSource is the information about a (possible) blob of flux in a specific image. A source 47 * may represent an insignificant or undetected source. There may be multiple representations 48 * of an image (eg, alternate smoothed copies); sources on alternate images may have a pointer 49 * to the version on the primary image (source->parent). A set of sources on different, but 50 * related images (eg, multiple exposures or different filters) which (may) represent the same 51 * astronomical object are grouped together with the pmPhotObj type (set pmPhotObj.h). 52 * 53 * A single source may be fitted with multiple models (not at the same time!). The PSF model 54 * fit is a fit of the position (optionally) and the flux to the PSF model at the location of 55 * the source. Alternate model fits are extended source models. The best model fit is used to 56 * subtract the object from the image. 44 57 * 45 58 * XXX do I have to re-organize this (again!) to allow an arbitrary set of extended model fits?? … … 54 67 pmPeak *peak; ///< Description of peak pixel. 55 68 psImage *pixels; ///< Rectangular region including object pixels. 56 psImage *variance; ///< Image variance.69 psImage *variance; ///< Image variance. 57 70 psImage *maskObj; ///< unique mask for this object which marks included pixels associated with objects. 58 71 psImage *maskView; ///< view into global image mask for this object region 59 72 psImage *modelFlux; ///< cached copy of the best model for this source 60 psImage *psfImage; ///< cached copy of the psf model for this source73 psImage *psfImage; ///< cached copy of the psf model for this source 61 74 pmMoments *moments; ///< Basic moments measured for the object. 62 75 pmModel *modelPSF; ///< PSF Model fit (parameters and type) … … 89 102 pmSourceExtendedPars *extpars; ///< extended source parameters 90 103 pmSourceDiffStats *diffStats; ///< extra parameters for difference detections 91 pmSourceRadialApertures *radial; ///< radial flux in circular apertures 104 psArray *radialAper; ///< radial flux in circular apertures 105 pmSource *parent; ///< reference to the master source from which this is derived 92 106 int imageID; 93 107 }; … … 162 176 ); 163 177 178 bool pmSourceRedefinePixelsByRegion ( 179 pmSource *mySource, ///< source to be re-defined 180 const pmReadout *readout, ///< base the source on this readout 181 psRegion newRegion ///< region for source pixel definition 182 ); 183 164 184 /** pmSourcePSFClump() 165 185 * -
branches/czw_branch/20101203/psModules/src/objects/pmSourceExtendedPars.c
r28013 r30631 17 17 #endif 18 18 19 // #include <stdio.h>20 // #include <math.h>21 // #include <string.h>22 19 #include <pslib.h> 23 // #include "pmHDU.h"24 // #include "pmFPA.h"25 // #include "pmFPAMaskWeight.h"26 // #include "pmSpan.h"27 // #include "pmFootprint.h"28 // #include "pmPeaks.h"29 // #include "pmMoments.h"30 // #include "pmResiduals.h"31 // #include "pmGrowthCurve.h"32 // #include "pmTrend2D.h"33 // #include "pmPSF.h"34 // #include "pmModel.h"35 // #include "pmSource.h"36 20 #include "pmSourceExtendedPars.h" 37 21 -
branches/czw_branch/20101203/psModules/src/objects/pmSourceFitPCM.c
r29004 r30631 89 89 if (!fitStatus) pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE; 90 90 91 // once we have fitted a model, we need to record that this model is a PCM model: 92 pcm->modelConv->isPCM = true; 93 91 94 // models can go insane: reject these 92 95 bool onPic = true; -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO.c
r29546 r30631 59 59 60 60 // lookup the EXTNAME values used for table data and image header segments 61 static bool sourceExtensions(psString *headname, // Extension name for header 62 psString *dataname, // Extension name for data 63 psString *deteffname, // Extension name for detection efficiency 64 psString *xsrcname, // Extension name for extended sources 65 psString *xfitname, // Extension name for extended fits 66 const pmFPAfile *file, // File of interest 67 const pmFPAview *view // View to level of interest 68 ) 61 bool pmSourceIOextnames(psString *headname, // Extension name for image header 62 psString *dataname, // Extension name for PSF table data 63 psString *deteffname, // Extension name for detection efficiency 64 psString *xsrcname, // Extension name for extended non-parametric measurements 65 psString *xfitname, // Extension name for extended fitted measurements 66 psString *xradname, // Extension name for radial apertures 67 const pmFPAfile *file, // File of interest 68 const pmFPAview *view // View to level of interest 69 ) 69 70 { 70 71 bool status; // Status of MD lookup … … 87 88 } 88 89 89 // EXTNAME for table data90 // EXTNAME for PSF table data 90 91 if (dataname) { 91 92 const char *rule = psMetadataLookupStr(&status, menu, "CMF.DATA"); … … 107 108 } 108 109 109 // EXTNAME for extended source data table110 // EXTNAME for extended source non-parametric measurements 110 111 if (xsrcname) { 111 112 const char *rule = psMetadataLookupStr(&status, menu, "CMF.XSRC"); … … 117 118 } 118 119 120 // EXTNAME for extended source fitted measurements 119 121 if (xfitname) { 120 // EXTNAME for extended source data table121 122 const char *rule = psMetadataLookupStr(&status, menu, "CMF.XFIT"); 122 123 if (!rule) { … … 125 126 } 126 127 *xfitname = pmFPAfileNameFromRule (rule, file, view); 128 } 129 130 // EXTNAME for radial apertures 131 if (xradname) { 132 const char *rule = psMetadataLookupStr(&status, menu, "CMF.XRAD"); 133 if (!rule) { 134 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XRAD in EXTNAME.RULES in camera.config"); 135 return false; 136 } 137 *xradname = pmFPAfileNameFromRule (rule, file, view); 127 138 } 128 139 … … 344 355 status &= pmSourcesWrite_##TYPE##_XFIT (file->fits, readout, sources, file->header, xfitname); \ 345 356 } \ 357 if (xradname) { \ 358 status &= pmSourcesWrite_##TYPE##_XRAD (file->fits, readout, sources, file->header, xradname, recipe); \ 359 } \ 346 360 } 347 361 … … 449 463 bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS"); 450 464 bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS"); 465 bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES"); 451 466 452 467 // define the EXTNAME values for the different data segments: … … 456 471 psString xsrcname = NULL; 457 472 psString xfitname = NULL; 458 if (!sourceExtensions(&headname, &dataname, &deteffname, 459 XSRC_OUTPUT ? &xsrcname : NULL, 460 XFIT_OUTPUT ? &xfitname : NULL, 461 file, view)) { 473 psString xradname = NULL; 474 if (!pmSourceIOextnames(&headname, &dataname, &deteffname, 475 XSRC_OUTPUT ? &xsrcname : NULL, 476 XFIT_OUTPUT ? &xfitname : NULL, 477 XRAD_OUTPUT ? &xradname : NULL, 478 file, view)) { 462 479 return false; 463 480 } … … 539 556 psMetadataAddStr (outhead, PS_LIST_TAIL, "XFITNAME", PS_META_REPLACE, "name of XFIT table extension", xfitname); 540 557 } 541 558 if (xradname) { 559 psMetadataAddStr (outhead, PS_LIST_TAIL, "XRADNAME", PS_META_REPLACE, "name of XRAD table extension", xradname); 560 } 542 561 543 562 // these are case-sensitive since the EXTYPE is case-sensitive … … 563 582 } 564 583 565 566 584 // write out the detection efficiency TABLE segments 567 585 if (deteffname) { … … 583 601 psFree (xsrcname); 584 602 psFree (xfitname); 603 psFree (xradname); 585 604 psFree (deteffname); 586 605 … … 593 612 psFree (xsrcname); 594 613 psFree (xfitname); 614 psFree (xradname); 595 615 psFree (deteffname); 596 616 return false; … … 939 959 psString dataname = NULL; 940 960 psString deteffname = NULL; 941 if (! sourceExtensions(&headname, &dataname, &deteffname, NULL, NULL, file, view)) {961 if (!pmSourceIOextnames(&headname, &dataname, &deteffname, NULL, NULL, NULL, file, view)) { 942 962 return false; 943 963 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO.h
r29546 r30631 30 30 bool pmSourcesWrite_SMPDATA_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 31 31 bool pmSourcesWrite_SMPDATA_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 32 bool pmSourcesWrite_SMPDATA_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 32 33 33 34 bool pmSourcesWrite_PS1_DEV_0(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 34 35 bool pmSourcesWrite_PS1_DEV_0_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 35 36 bool pmSourcesWrite_PS1_DEV_0_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 37 bool pmSourcesWrite_PS1_DEV_0_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 36 38 37 39 bool pmSourcesWrite_PS1_DEV_1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 38 40 bool pmSourcesWrite_PS1_DEV_1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 39 41 bool pmSourcesWrite_PS1_DEV_1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 42 bool pmSourcesWrite_PS1_DEV_1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 40 43 41 44 bool pmSourcesWrite_PS1_CAL_0(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 42 45 bool pmSourcesWrite_PS1_CAL_0_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 43 46 bool pmSourcesWrite_PS1_CAL_0_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 47 bool pmSourcesWrite_PS1_CAL_0_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 44 48 45 49 bool pmSourcesWrite_CMF_PS1_V1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 46 50 bool pmSourcesWrite_CMF_PS1_V1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 47 51 bool pmSourcesWrite_CMF_PS1_V1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 52 bool pmSourcesWrite_CMF_PS1_V1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 48 53 49 54 bool pmSourcesWrite_CMF_PS1_V2(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 50 55 bool pmSourcesWrite_CMF_PS1_V2_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 51 56 bool pmSourcesWrite_CMF_PS1_V2_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 57 bool pmSourcesWrite_CMF_PS1_V2_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 52 58 53 59 bool pmSourcesWrite_CMF_PS1_V3(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 54 60 bool pmSourcesWrite_CMF_PS1_V3_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 55 61 bool pmSourcesWrite_CMF_PS1_V3_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 62 bool pmSourcesWrite_CMF_PS1_V3_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 56 63 57 64 bool pmSourcesWrite_CMF_PS1_SV1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 58 65 bool pmSourcesWrite_CMF_PS1_SV1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 59 66 bool pmSourcesWrite_CMF_PS1_SV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 67 bool pmSourcesWrite_CMF_PS1_SV1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 60 68 61 69 bool pmSourcesWrite_CMF_PS1_DV1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 62 70 bool pmSourcesWrite_CMF_PS1_DV1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 63 71 bool pmSourcesWrite_CMF_PS1_DV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 72 bool pmSourcesWrite_CMF_PS1_DV1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 64 73 65 74 bool pmSourcesWrite_CMF_PS1_DV2(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe); 66 75 bool pmSourcesWrite_CMF_PS1_DV2_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 67 76 bool pmSourcesWrite_CMF_PS1_DV2_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); 77 bool pmSourcesWrite_CMF_PS1_DV2_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); 68 78 69 79 psArray *pmSourcesReadCMP (char *filename, psMetadata *header); -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c
r29004 r30631 676 676 return true; 677 677 } 678 679 bool pmSourcesWrite_CMF_PS1_DV1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 680 { 681 return true; 682 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c
r29620 r30631 737 737 return true; 738 738 } 739 740 bool pmSourcesWrite_CMF_PS1_DV2_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 741 { 742 return true; 743 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c
r29019 r30631 20 20 21 21 #include "pmConfig.h" 22 #include "pmErrorCodes.h" 22 23 #include "pmDetrendDB.h" 23 24 … … 71 72 psF32 errMag, chisq, apRadius; 72 73 psS32 nPix, nDOF; 73 char keyword1[80], keyword2[80];74 74 75 75 pmChip *chip = readout->parent->parent; … … 103 103 table = psArrayAllocEmpty (sources->n); 104 104 105 # if (0) 105 106 // we use this just to define the output vectors (which must be present for all objects) 106 107 bool status = false; … … 118 119 psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword2, PS_META_REPLACE, "min radius for SB profile", radMax->data.F32[i]); 119 120 } 120 121 # endif 121 122 122 123 // we write out PSF-fits for all sources, regardless of quality. the source flags tell us the state … … 258 259 psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2", PS_DATA_U32, "psphot analysis flags", source->mode2); 259 260 261 # if (0) 262 // XXX if we have raw radial apertures, write them out here 260 263 psVector *radFlux = psVectorAlloc(radMax->n, PS_TYPE_F32); 261 264 psVector *radFluxErr = psVectorAlloc(radMax->n, PS_TYPE_F32); … … 284 287 psFree (radFluxErr); 285 288 psFree (radFill); 289 # endif 286 290 287 291 // XXX not sure how to get this : need to load Nimages with weight? … … 781 785 return true; 782 786 } 787 788 // **** write out the radial flux values for the sources for a given matched-PSF image 789 // **** how do we distinguish the matched-PSF images from the non-matched version 790 bool pmSourcesWrite_CMF_PS1_SV1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 791 { 792 793 psArray *table; 794 psMetadata *row; 795 psF32 xPos, yPos; 796 char keyword1[80], keyword2[80]; 797 798 // create a header to hold the output data 799 psMetadata *outhead = psMetadataAlloc (); 800 801 // write the links to the image header 802 psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "radial flux table extension", extname); 803 804 // we use this just to define the output vectors (which must be present for all objects) 805 bool status = false; 806 psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER"); 807 psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER"); 808 psAssert (radMax, "this must have been defined and tested earlier!"); 809 psAssert (radMax->n, "this must have been defined and tested earlier!"); 810 psAssert (radMin->n == radMax->n, "inconsistent annular bins"); 811 812 // write the radial profile apertures to header 813 for (int i = 0; i < radMax->n; i++) { 814 sprintf (keyword1, "RMIN_%02d", i); 815 sprintf (keyword2, "RMAX_%02d", i); 816 psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword1, PS_META_REPLACE, "min radius for SB profile", radMin->data.F32[i]); 817 psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword2, PS_META_REPLACE, "min radius for SB profile", radMax->data.F32[i]); 818 } 819 820 psVector *fwhmValues = psMetadataLookupVector(&status, readout->analysis, "STACK.PSF.FWHM.VALUES"); 821 if (!fwhmValues) { 822 psError (PM_ERR_CONFIG, true, "convolved or measured FWHM is not defined for this readout"); 823 return false; 824 } 825 826 // let's write these out in S/N order 827 sources = psArraySort (sources, pmSourceSortBySN); 828 829 table = psArrayAllocEmpty (sources->n); 830 831 // we write out all sources, regardless of quality. the source flags tell us the state 832 for (int i = 0; i < sources->n; i++) { 833 834 pmSource *source = sources->data[i]; 835 836 // skip sources without radial aper measurements (or insufficient) 837 if (source->radialAper == NULL) continue; 838 psAssert (source->radialAper->n == fwhmValues->n, "inconsistent radial aperture set"); 839 840 for (int entry = 0; entry < fwhmValues->n; entry++) { 841 842 // choose the convolved EXT model, if available, otherwise the simple one 843 pmSourceRadialApertures *radialAper = source->radialAper->data[entry]; 844 assert (radialAper); 845 846 bool useMoments = true; 847 useMoments = (useMoments && source->moments); // can't if there are no moments 848 useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured 849 useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed... 850 851 if (useMoments) { 852 xPos = source->moments->Mx; 853 yPos = source->moments->My; 854 } else { 855 xPos = source->peak->xf; 856 yPos = source->peak->yf; 857 } 858 859 row = psMetadataAlloc (); 860 861 // XXX we are not writing out the mode (flags) or the type (psf, ext, etc) 862 psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET", 0, "IPP detection identifier index", source->seq); 863 psMetadataAddF32 (row, PS_LIST_TAIL, "X_APER", 0, "Center of aperture measurements", xPos); 864 psMetadataAddF32 (row, PS_LIST_TAIL, "Y_APER", 0, "Center of aperture measurements", yPos); 865 psMetadataAddF32 (row, PS_LIST_TAIL, "PSF_FWHM", 0, "FWHM of matched PSF", fwhmValues->data.F32[entry]); 866 867 // XXX if we have raw radial apertures, write them out here 868 psVector *radFlux = psVectorAlloc(radMax->n, PS_TYPE_F32); 869 psVector *radFluxErr = psVectorAlloc(radMax->n, PS_TYPE_F32); 870 psVector *radFill = psVectorAlloc(radMax->n, PS_TYPE_F32); 871 psVectorInit (radFlux, NAN); 872 psVectorInit (radFluxErr, NAN); 873 psVectorInit (radFill, NAN); 874 if (!radialAper->flux) goto write_annuli; 875 if (!radialAper->fill) goto write_annuli; 876 psAssert (radialAper->flux->n <= radFlux->n, "inconsistent vector lengths"); 877 psAssert (radialAper->fill->n <= radFlux->n, "inconsistent vector lengths"); 878 879 // copy the data from fluxVal (which is not guaranteed to be the full length) to radFlux 880 for (int j = 0; j < radialAper->flux->n; j++) { 881 radFlux->data.F32[j] = radialAper->flux->data.F32[j]; 882 radFluxErr->data.F32[j] = radialAper->fluxErr->data.F32[j]; 883 radFill->data.F32[j] = radialAper->fill->data.F32[j]; 884 } 885 886 write_annuli: 887 psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX", PS_DATA_VECTOR, "flux within annuli", radFlux); 888 psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR", PS_DATA_VECTOR, "flux error in annuli", radFluxErr); 889 psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL", PS_DATA_VECTOR, "fill factor of annuli", radFill); 890 psFree (radFlux); 891 psFree (radFluxErr); 892 psFree (radFill); 893 894 psArrayAdd (table, 100, row); 895 psFree (row); 896 } 897 } 898 899 if (table->n == 0) { 900 if (!psFitsWriteBlank (fits, outhead, extname)) { 901 psError(psErrorCodeLast(), false, "Unable to write empty sources file."); 902 psFree(outhead); 903 psFree(table); 904 return false; 905 } 906 psFree (outhead); 907 psFree (table); 908 return true; 909 } 910 911 psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname); 912 if (!psFitsWriteTable (fits, outhead, table, extname)) { 913 psError(psErrorCodeLast(), false, "writing ext data %s\n", extname); 914 psFree (outhead); 915 psFree(table); 916 return false; 917 } 918 psFree (outhead); 919 psFree (table); 920 return true; 921 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c
r29004 r30631 721 721 return false; 722 722 } 723 724 bool pmSourcesWrite_CMF_PS1_V1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 725 { 726 return true; 727 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_V2.c
r29004 r30631 724 724 return true; 725 725 } 726 727 bool pmSourcesWrite_CMF_PS1_V2_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 728 { 729 return true; 730 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_CMF_PS1_V3.c
r29620 r30631 762 762 return true; 763 763 } 764 765 bool pmSourcesWrite_CMF_PS1_V3_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 766 { 767 return true; 768 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_PS1_CAL_0.c
r29004 r30631 702 702 return true; 703 703 } 704 705 bool pmSourcesWrite_PS1_CAL_0_XRAD (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 706 { 707 return true; 708 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_PS1_DEV_0.c
r29004 r30631 248 248 return true; 249 249 } 250 251 bool pmSourcesWrite_PS1_DEV_0_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 252 { 253 return true; 254 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_PS1_DEV_1.c
r29004 r30631 588 588 return true; 589 589 } 590 591 bool pmSourcesWrite_PS1_DEV_1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 592 { 593 return true; 594 } -
branches/czw_branch/20101203/psModules/src/objects/pmSourceIO_SMPDATA.c
r29004 r30631 222 222 return true; 223 223 } 224 225 bool pmSourcesWrite_SMPDATA_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe) 226 { 227 return true; 228 } -
branches/czw_branch/20101203/psModules/src/psmodules.h
r29388 r30631 98 98 // the following headers are from psModule:imcombine 99 99 #include <pmStack.h> 100 #include <pmSubtractionTypes.h> 100 101 #include <pmStackReject.h> 101 102 #include <pmSubtraction.h>
Note:
See TracChangeset
for help on using the changeset viewer.
