Changeset 13870
- Timestamp:
- Jun 18, 2007, 5:40:48 PM (19 years ago)
- Location:
- trunk/psModules/src/detrend
- Files:
-
- 2 edited
-
pmShutterCorrection.c (modified) (5 diffs)
-
pmShutterCorrection.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/detrend/pmShutterCorrection.c
r13700 r13870 13 13 #include "psVectorBracket.h" 14 14 #include "pmConceptsAverage.h" 15 #include "pmReadoutStack.h" 15 16 16 17 #include "pmShutterCorrection.h" … … 58 59 59 60 61 #define MEASURE_SAMPLES 4 // Number of samples to make over the image. This should only be 62 // changed with great caution, since assumptions on its value are in 63 // the code (see pmShutterCorrectionDataAlloc). 64 65 60 66 static void pmShutterCorrectionFree(pmShutterCorrection *pars) 61 67 { … … 346 352 347 353 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 348 349 #define MEASURE_SAMPLES 4350 354 351 355 bool pmShutterCorrectionMeasure(pmReadout *output, const psArray *readouts, int size, psStatsOptions meanStat, … … 680 684 681 685 if (exptime <= 0.0) { 682 // In the extreme case that we have exptime <= 0.0, we correct the image to 683 // counts-per-second, rather than counts in the nominal exposure time684 for (int y = 0; y < image->numRows; y++) {685 for (int x = 0; x < image->numCols; x++) {686 image->data.F32[y][x] *= 1.0 / (exptime + shutterImage->data.F32[y][x]);687 }688 }689 psMetadataAddF32 (cell->concepts, PS_LIST_TAIL, "CELL.EXPOSURE", PS_META_REPLACE, "exposure time re-normalized to 1.0", 1.0); // Exposure time690 psString line = NULL;691 psStringAppend (&line, "extreme exposure time %f, re-normalized to 1.0", exptime);692 psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, line, "");693 psFree (line);686 // In the extreme case that we have exptime <= 0.0, we correct the image to 687 // counts-per-second, rather than counts in the nominal exposure time 688 for (int y = 0; y < image->numRows; y++) { 689 for (int x = 0; x < image->numCols; x++) { 690 image->data.F32[y][x] *= 1.0 / (exptime + shutterImage->data.F32[y][x]); 691 } 692 } 693 psMetadataAddF32 (cell->concepts, PS_LIST_TAIL, "CELL.EXPOSURE", PS_META_REPLACE, "exposure time re-normalized to 1.0", 1.0); // Exposure time 694 psString line = NULL; 695 psStringAppend (&line, "extreme exposure time %f, re-normalized to 1.0", exptime); 696 psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, line, ""); 697 psFree (line); 694 698 } else { 695 for (int y = 0; y < image->numRows; y++) {696 for (int x = 0; x < image->numCols; x++) {697 image->data.F32[y][x] *= exptime / (exptime + shutterImage->data.F32[y][x]);698 }699 }699 for (int y = 0; y < image->numRows; y++) { 700 for (int x = 0; x < image->numCols; x++) { 701 image->data.F32[y][x] *= exptime / (exptime + shutterImage->data.F32[y][x]); 702 } 703 } 700 704 } 701 705 psFree(shutterImage); … … 712 716 return true; 713 717 } 718 719 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 720 721 722 #define IMAGES_BUFFER 10 // Allocate space for this many images at a time 723 724 static void shutterCorrectionDataFree(pmShutterCorrectionData *data) 725 { 726 psFree(data->regions); 727 psFree(data->mean); 728 psFree(data->stdev); 729 730 psFree(data->exptimes); 731 psFree(data->refs); 732 733 return; 734 } 735 736 pmShutterCorrectionData *pmShutterCorrectionDataAlloc(int numCols, int numRows, int size) 737 { 738 pmShutterCorrectionData *data = psAlloc(sizeof(pmShutterCorrectionData)); 739 psMemSetDeallocator(data, (psFreeFunc)shutterCorrectionDataFree); 740 741 data->num = 0; 742 data->numCols = 0; 743 data->numRows = 0; 744 745 data->regions = psArrayAlloc(MEASURE_SAMPLES); 746 for (int j = 0; j < MEASURE_SAMPLES; j++) { 747 int x = (j % 2) ? size : numCols - size - 1; 748 int y = (j > 1) ? size : numRows - size - 1; 749 psRegion region = psRegionForSquare(x, y, size); 750 data->regions->data[j] = psRegionAlloc(region.x0, region.x1, region.y0, region.y1); 751 } 752 753 data->mean = psArrayAlloc(MEASURE_SAMPLES); 754 data->stdev = psArrayAlloc(MEASURE_SAMPLES); 755 for (int i = 0; i < MEASURE_SAMPLES; i++) { 756 data->mean->data[i] = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32); 757 data->stdev->data[i] = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32); 758 } 759 760 data->exptimes = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32); 761 data->refs = psVectorAllocEmpty(IMAGES_BUFFER, PS_TYPE_F32); 762 763 return data; 764 } 765 766 bool pmShutterCorrectionAddReadout(pmShutterCorrectionData *data, 767 const pmReadout *readout, ///< Readout to add 768 psStatsOptions meanStat, ///< Statistic to use for mean 769 psStatsOptions stdevStat, ///< Statistic to use for stdev 770 psMaskType maskVal, ///< Mask value 771 psRandom *rng ///< Random number generator 772 ) 773 { 774 PS_ASSERT_PTR_NON_NULL(data, NULL); 775 PS_ASSERT_PTR_NON_NULL(readout, NULL); 776 PS_ASSERT_IMAGE_NON_NULL(readout->image, NULL); 777 PS_ASSERT_IMAGE_TYPE(readout->image, PS_TYPE_F32, NULL); 778 if (data->num == 0) { 779 data->numCols = readout->image->numCols; 780 data->numRows = readout->image->numRows; 781 } else { 782 PS_ASSERT_IMAGE_SIZE(readout->image, data->numCols, data->numRows, NULL); 783 } 784 if (readout->mask) { 785 PS_ASSERT_IMAGE_NON_NULL(readout->mask, NULL); 786 PS_ASSERT_IMAGE_TYPE(readout->mask, PS_TYPE_MASK, NULL); 787 PS_ASSERT_IMAGE_SIZE(readout->mask, data->numCols, data->numRows, NULL); 788 } 789 if (readout->weight) { 790 PS_ASSERT_IMAGE_NON_NULL(readout->weight, NULL); 791 PS_ASSERT_IMAGE_TYPE(readout->weight, PS_TYPE_F32, NULL); 792 PS_ASSERT_IMAGE_SIZE(readout->weight, data->numCols, data->numRows, NULL); 793 } 794 795 // Add the exposure time 796 float exptime = psMetadataLookupF32(NULL, readout->parent->concepts, "CELL.EXPOSURE"); // Exp. time 797 if (!isfinite(exptime)) { 798 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Exposure time is not set."); 799 return false; 800 } 801 data->exptimes->data.F32[data->exptimes->n] = exptime; 802 data->exptimes = psVectorExtend(data->exptimes, IMAGES_BUFFER, 1); 803 804 // Add the statistics 805 806 // Add the reference value 807 psStats *stats = psStatsAlloc(meanStat | stdevStat); // Statistics to apply 808 if (!rng) { 809 rng = psRandomAlloc(PS_RANDOM_TAUS, 0); 810 } else { 811 psMemIncrRefCounter(rng); 812 } 813 if (!psImageBackground(stats, readout->image, readout->mask, maskVal, rng)) { 814 psError(PS_ERR_UNKNOWN, false, "Unable to measure reference statistics.\n"); 815 psFree(stats); 816 psFree(rng); 817 return false; 818 } 819 psFree(rng); 820 float refValue = psStatsGetValue(stats, meanStat); // Reference value 821 psTrace("psModules.detrend", 3, "Reference value for shutter image = %f\n", refValue); 822 if (refValue <= 0.0) { 823 psError(PS_ERR_UNKNOWN, true, "Measured non-positive reference value.\n"); 824 psFree(stats); 825 return false; 826 } 827 refValue = 1.0 / refValue; 828 data->refs->data.F32[data->refs->n] = refValue; 829 data->refs = psVectorExtend(data->refs, IMAGES_BUFFER, 1); 830 831 // Add the region statistics 832 for (int j = 0; j < MEASURE_SAMPLES; j++) { 833 psRegion *region = data->regions->data[j]; // Region of interest 834 psImage *subImage = psImageSubset(readout->image, *region); // Sub-image 835 psImage *subMask = NULL; // Sub-image of mask 836 if (readout->mask) { 837 subMask = psImageSubset(readout->mask, *region); 838 } 839 if (!psImageStats(stats, subImage, subMask, maskVal)) { 840 psString regionString = psRegionToString(*region); 841 psWarning("Unable to measure sample statistics at %s in image.\n", 842 regionString); 843 psFree(regionString); 844 } 845 psFree(subImage); 846 psFree(subMask); 847 848 psVector *mean = data->mean->data[j]; // Vector of means for this region 849 psVector *stdev = data->stdev->data[j]; // Vector of standard deviations for this region 850 851 mean->data.F32[mean->n] = psStatsGetValue(stats, meanStat) * refValue; 852 stdev->data.F32[stdev->n] = psStatsGetValue(stats, stdevStat) * refValue; 853 data->mean->data[j] = psVectorExtend(mean, IMAGES_BUFFER, 1); 854 data->stdev->data[j] = psVectorExtend(stdev, IMAGES_BUFFER, 1); 855 } 856 857 data->num++; 858 859 return true; 860 } 861 862 float pmShutterCorrectionReference(const pmShutterCorrectionData *data) 863 { 864 PS_ASSERT_PTR_NON_NULL(data, NAN); 865 PS_ASSERT_INT_POSITIVE(data->num, NAN); 866 867 float meanRef = 0.0; // Mean reference offset 868 int numGood = 0; // Number of good measurements 869 for (int i = 0; i < MEASURE_SAMPLES; i++) { 870 psVector *counts = data->mean->data[i]; // Mean for each image 871 psVector *errors = data->stdev->data[i]; // Stdev for each image 872 pmShutterCorrection *guess = pmShutterCorrectionGuess(data->exptimes, counts); // Guess at correction 873 pmShutterCorrection *corr = pmShutterCorrectionFullFit(data->exptimes, counts, 874 errors, guess); // The actual correction 875 psFree(guess); 876 if (corr && isfinite(corr->offref)) { 877 psTrace("psModules.detrend", 5, "Sample reference value: %f\n", corr->offref); 878 meanRef += corr->offref; 879 numGood++; 880 } 881 psFree(corr); 882 } 883 884 if (numGood == 0) { 885 psError(PS_ERR_UNKNOWN, true, "Unable to measure mean reference offset.\n"); 886 return false; 887 } 888 meanRef /= (float)numGood; 889 psTrace("psModules.detrend", 3, "Mean reference value: %f\n", meanRef); 890 return meanRef; 891 } 892 893 bool pmShutterCorrectionGenerate(pmReadout *shutter, pmReadout *pattern, const psArray *inputs, 894 float reference, const pmShutterCorrectionData *data, 895 int nIter, float rej, psMaskType maskVal) 896 { 897 PS_ASSERT_PTR_NON_NULL(shutter, false); 898 PS_ASSERT_ARRAY_NON_NULL(inputs, false); 899 PS_ASSERT_INT_EQUAL(data->num, inputs->n, false); 900 901 int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine 902 int xSize, ySize; // Size of the output image 903 if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize, 904 inputs)) { 905 psError(PS_ERR_UNKNOWN, false, "No valid input readouts."); 906 return false; 907 } 908 909 pmReadoutUpdateSize(shutter, minInputCols, minInputRows, xSize, ySize, false); 910 if (pattern) { 911 pmReadoutUpdateSize(pattern, minInputCols, minInputRows, xSize, ySize, false); 912 } 913 914 psImage *shutterImage = shutter->image; // Shutter correction image 915 psImage *patternImage; // Illumination pattern 916 if (pattern) { 917 patternImage = psMemIncrRefCounter(pattern->image); 918 } else { 919 patternImage = psImageAlloc(xSize, ySize, PS_TYPE_F32); 920 } 921 922 int num = data->num; // Number of images 923 psVector *counts = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image 924 psVector *errors = psVectorAlloc(num, PS_TYPE_F32); // Counts in each image 925 psVector *mask = psVectorAlloc(num, PS_TYPE_MASK); // Mask for each image 926 psTrace("psModules.detrend", 2, "Performing linear fit on individual pixels...\n"); 927 for (int i = minInputRows; i < maxInputRows; i++) { 928 int yOut = i - shutter->row0; // y position on output readout 929 for (int j = minInputCols; j < maxInputCols; j++) { 930 int xOut = j - shutter->col0; // x position on output readout 931 932 psVectorInit(mask, 0); 933 for (int r = 0; r < num; r++) { 934 pmReadout *readout = inputs->data[r]; // Readout of interest 935 int yIn = i - readout->row0; // y position on input readout 936 int xIn = j - readout->col0; // x position on input readout 937 psImage *image = readout->image; // Image of interest 938 float ref = data->refs->data.F32[r]; // (Inverse) reference value 939 counts->data.F32[r] = image->data.F32[yIn][xIn] * ref; 940 if (readout->mask) { 941 mask->data.PS_TYPE_MASK_DATA[r] = readout->mask->data.PS_TYPE_MASK_DATA[yIn][xIn]; 942 } 943 if (readout->weight) { 944 errors->data.F32[r] = sqrtf(readout->weight->data.F32[yIn][xIn]) * ref; 945 } else { 946 errors->data.F32[r] = sqrtf(image->data.F32[yIn][xIn]) * ref; 947 } 948 } 949 950 pmShutterCorrection *corr = pmShutterCorrectionLinFit(data->exptimes, counts, errors, mask, 951 reference, nIter, rej, maskVal); 952 shutterImage->data.F32[yOut][xOut] = corr->offset; 953 patternImage->data.F32[yOut][xOut] = corr->scale; 954 psFree(corr); 955 } 956 } 957 psFree(mask); 958 psFree(errors); 959 psFree(counts); 960 961 // Update the "concepts" 962 psList *inputCells = psListAlloc(NULL); // List of cells 963 for (long i = 0; i < inputs->n; i++) { 964 pmReadout *readout = inputs->data[i]; // Readout of interest 965 psListAdd(inputCells, PS_LIST_TAIL, readout->parent); 966 } 967 bool success = pmConceptsAverageCells(shutter->parent, inputCells, NULL, NULL, true); 968 psFree(inputCells); 969 970 // Correct the exposure times --- they don't make sense any more. 971 psMetadataItem *item = psMetadataLookup(shutter->parent->concepts, "CELL.EXPOSURE"); 972 item->data.F32 = NAN; 973 item = psMetadataLookup(shutter->parent->concepts, "CELL.DARKTIME"); 974 item->data.F32 = NAN; 975 976 shutter->data_exists = true; 977 shutter->parent->data_exists = true; 978 shutter->parent->parent->data_exists = true; 979 980 if (pattern) { 981 pattern->data_exists = true; 982 pattern->parent->data_exists = true; 983 pattern->parent->parent->data_exists = true; 984 } 985 986 return success; 987 } -
trunk/psModules/src/detrend/pmShutterCorrection.h
r12988 r13870 5 5 * @author Paul Price, IfA 6 6 * 7 * @version $Revision: 1.1 3$ $Name: not supported by cvs2svn $8 * @date $Date: 2007-0 4-24 21:17:19$7 * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2007-06-19 03:40:48 $ 9 9 * Copyright 2006 Institute for Astronomy, University of Hawaii 10 10 */ … … 128 128 ); 129 129 130 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 131 132 // Functions for doing the shutter correction piece-meal (don't have to read entire image stack into memory at 133 // once). A single read run through the stack is required, calling pmShutterCorrectionAddReadout on each. 134 // Then pmShutterCorrectionReference provides the required reference shutter time, so that 135 // pmShutterCorrectionGenerate can generate a shutter correction piece by piece as overlapping pixels from 136 // each input are read in. 137 138 139 /// Data for measuring the shutter correction 140 typedef struct { 141 int num; ///< Number of images 142 int numCols, numRows; ///< Size of images 143 psArray *regions; ///< Regions at which to measure statistics 144 psArray *mean; ///< Vector of means at each region 145 psArray *stdev; ///< Vector of standard deviations at each region 146 psVector *exptimes; ///< Exposure times for each image 147 psVector *refs; ///< Reference fluxes 148 } pmShutterCorrectionData; 149 150 /// Allocator for pmShutterCorrectionData 151 pmShutterCorrectionData *pmShutterCorrectionDataAlloc(int numCols, int numRows, ///< Size of images 152 int size ///< Size of regions 153 ); 154 155 /// Add a readout to the correction data 156 /// 157 /// Performs statistics on the readout, recording the data 158 bool pmShutterCorrectionAddReadout(pmShutterCorrectionData *data, ///< Correction data 159 const pmReadout *readout, ///< Readout to add 160 psStatsOptions meanStat, ///< Statistic to use for mean 161 psStatsOptions stdevStat, ///< Statistic to use for stdev 162 psMaskType maskVal, ///< Mask value 163 psRandom *rng ///< Random number generator 164 ); 165 166 /// Calculate the reference shutter time from the correction data 167 float pmShutterCorrectionReference(const pmShutterCorrectionData *data ///< Correction data 168 ); 169 170 /// Generate a shutter correction 171 /// 172 /// Performs the linear fit to each pixel in the stack. 173 bool pmShutterCorrectionGenerate(pmReadout *shutter, ///< Shutter correction 174 pmReadout *pattern, ///< Background pattern (or NULL) 175 const psArray *inputs, ///< Stack of input pmReadouts 176 float reference, ///< Reference shutter time (from pmShutterCorrectionRef) 177 const pmShutterCorrectionData *data, ///< Correction data 178 int nIter, ///< Number of iterations 179 float rej, ///< Rejection threshold (sigma) 180 psMaskType maskVal ///< Mask value 181 ); 182 183 184 130 185 /// @} 131 186 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
