Image2D TestSetGenerator::MakeGaussianData(unsigned width, unsigned height) { Image2D image = Image2D::MakeUnsetImage(width, height); for(unsigned y=0;y<height;++y) { for(unsigned x=0;x<width;++x) { image.SetValue(x, y, RNG::Gaussian()); } } return image; }
Image2D TestSetGenerator::sampleRFIDistribution(unsigned width, unsigned height, double ig_over_rsq) { Image2D image = Image2D::MakeUnsetImage(width, height); const double sigma = 1.0; for(size_t f=0; f<height;++f) { for(size_t t=0; t<width;++t) { image.SetValue(t, f, Rand(Gaussian)*sigma + ig_over_rsq / RNG::Uniform()); } } return image; }
void ImageTile::SetValueAt(Image2D &dest, unsigned frequencyIndex, unsigned scanIndex, long double newValue) { return dest.SetValue(_scanOffset + scanIndex, _channelOffset + frequencyIndex, newValue); }
Image2D TestSetGenerator::MakeTestSet(int number, Mask2D& rfi, unsigned width, unsigned height, int gaussianNoise) { Image2D image; switch(number) { case 0: // Image of all zero's return Image2D::MakeZeroImage(width, height); case 1: // Image of all ones image = Image2D::MakeUnsetImage(width, height); image.SetAll(1.0); break; case 2: // Noise return MakeNoise(width, height, gaussianNoise); case 3: { // Several broadband lines image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 1.0); } break; case 4: { // Several broadband lines image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 0.5); } break; case 5: { // Several broadband lines of random length image = MakeNoise(width, height, gaussianNoise); AddVarBroadbandToTestSet(image, rfi); } break; case 6: { // Different broadband lines + low freq background image = MakeNoise(width, height, gaussianNoise); AddVarBroadbandToTestSet(image, rfi); for(unsigned y=0;y<image.Height();++y) { for(unsigned x=0;x<image.Width();++x) { image.AddValue(x, y, sinn(num_t(x)*M_PIn*5.0 / image.Width()) + 0.1); } } } break; case 7: { // Different broadband lines + high freq background image = MakeNoise(width, height, gaussianNoise); for(unsigned y=0;y<image.Height();++y) { for(unsigned x=0;x<image.Width();++x) { image.AddValue(x, y, sinn((long double) (x+y*0.1)*M_PIn*5.0L / image.Width() + 0.1)); image.AddValue(x, y, sinn((long double) (x+pown(y, 1.1))*M_PIn*50.0L / image.Width() + 0.1)); } } AddVarBroadbandToTestSet(image, rfi); for(unsigned y=0;y<image.Height();++y) { for(unsigned x=0;x<image.Width();++x) { image.AddValue(x, y, 1.0); } } } break; case 8: { // Different droadband lines + smoothed&subtracted high freq background image = MakeNoise(width, height, gaussianNoise); for(unsigned y=0;y<image.Height();++y) { for(unsigned x=0;x<image.Width();++x) { image.AddValue(x, y, sinn((num_t) (x+y*0.1)*M_PIn*5.0 / image.Width() + 0.1)); image.AddValue(x, y, sinn((num_t) (x+pown(y, 1.1))*M_PIn*50.0 / image.Width() + 0.1)); } } SubtractBackground(image); AddVarBroadbandToTestSet(image, rfi); } break; case 9: { //FFT of 7 image = MakeTestSet(7, rfi, width, height); Image2D copy(image); FFTTools::CreateHorizontalFFTImage(image, copy, false); for(unsigned y=0;y<rfi.Height();++y) { for(unsigned x=0;x<rfi.Width();++x) { image.SetValue(x, y, image.Value(x, y) / sqrtn(image.Width())); } } } break; case 10: { // Identity matrix image = Image2D::MakeZeroImage(width, height); unsigned min = width < height ? width : height; for(unsigned i=0;i<min;++i) { image.SetValue(i, i, 1.0); rfi.SetValue(i, i, true); } } break; case 11: { // FFT of identity matrix image = MakeTestSet(10, rfi, width, height); Image2D copy(image); FFTTools::CreateHorizontalFFTImage(image, copy, false); for(unsigned y=0;y<rfi.Height();++y) { for(unsigned x=0;x<rfi.Width();++x) { image.SetValue(x, y, image.Value(x, y) / sqrtn(width)); } } } break; case 12: { // Broadband contaminating all channels image = MakeNoise(width, height, gaussianNoise); for(unsigned y=0;y<image.Height();++y) { for(unsigned x=0;x<image.Width();++x) { image.AddValue(x, y, sinn((num_t) (x+y*0.1)*M_PIn*5.0 / image.Width() + 0.1)); image.AddValue(x, y, sinn((num_t) (x+powl(y, 1.1))*M_PIn*50.0 / image.Width() + 0.1)); } } AddBroadbandToTestSet(image, rfi, 1.0); } break; case 13: { // Model of three point sources with broadband RFI SetModelData(image, rfi, 3); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; AddBroadbandToTestSet(image, rfi, 1.0); } break; case 14: { // Model of five point sources with broadband RFI SetModelData(image, rfi, 5); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; AddBroadbandToTestSet(image, rfi, 1.0); } break; case 15: { // Model of five point sources with partial broadband RFI SetModelData(image, rfi, 5); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; AddBroadbandToTestSet(image, rfi, 0.5); } break; case 16: { // Model of five point sources with random broadband RFI SetModelData(image, rfi, 5); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; AddVarBroadbandToTestSet(image, rfi); } break; case 17: { // Background-fitted model of five point sources with random broadband RFI SetModelData(image, rfi, 5); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; SubtractBackground(image); AddVarBroadbandToTestSet(image, rfi); } break; case 18: { // Model of three point sources with random RFI SetModelData(image, rfi, 3); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; AddVarBroadbandToTestSet(image, rfi); } break; case 19: { // Model of three point sources with noise SetModelData(image, rfi, 3); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; } break; case 20: { // Model of five point sources with noise SetModelData(image, rfi, 5); Image2D noise = MakeNoise(image.Width(), image.Height(), gaussianNoise); image += noise; } break; case 21: { // Model of three point sources SetModelData(image, rfi, 3); } break; case 22: { // Model of five point sources image = Image2D::MakeZeroImage(width, height); SetModelData(image, rfi, 5); } break; case 23: image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 0.5, 0.1, true); break; case 24: image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 0.5, 10.0, true); break; case 25: image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 0.5, 1.0, true); break; case 26: { // Several Gaussian broadband lines image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 1.0, 1.0, false, GaussianShape); } break; case 27: { // Several Sinusoidal broadband lines image = MakeNoise(width, height, gaussianNoise); AddBroadbandToTestSet(image, rfi, 1.0, 1.0, false, SinusoidalShape); } break; case 28: { // Several slewed Gaussian broadband lines image = MakeNoise(width, height, gaussianNoise); AddSlewedBroadbandToTestSet(image, rfi, 1.0); } break; case 29: { // Several bursty broadband lines image = MakeNoise(width, height, gaussianNoise); AddBurstBroadbandToTestSet(image, rfi); } break; case 30: { // noise + RFI ^-2 distribution image = sampleRFIDistribution(width, height, 1.0); rfi.SetAll<true>(); } break; case 31: { // noise + RFI ^-2 distribution image = sampleRFIDistribution(width, height, 0.1); rfi.SetAll<true>(); } break; case 32: { // noise + RFI ^-2 distribution image = sampleRFIDistribution(width, height, 0.01); rfi.SetAll<true>(); } break; } return image; }
int main(int argc, char *argv[]) { int pindex = 1; // parameters bool useSpectrum = true; bool colormap = false; int removeNoiseImages = 0; bool fft = false; enum ScaleMethod { MaximumContrast, Constant } scaleMethod = MaximumContrast; long double scaleValue = 1.0; std::string subtractFile, outputFitsFile, outputPngFile; bool subtract = false, redblue = false, rms = false, individualMaximization = false, displayMax = false, singleImage = false; bool window = false, cutWindow = false, saveFits = false, savePng = false; size_t windowX = 0, windowY = 0, windowWidth = 0, windowHeight = 0; size_t cutWindowX = 0, cutWindowY = 0, cutWindowWidth = 0, cutWindowHeight = 0; size_t singleImageIndex = 0; while(pindex < argc && argv[pindex][0] == '-') { string parameter = argv[pindex]+1; if(parameter == "s") { useSpectrum = true; } else if(parameter == "c") { useSpectrum = false; } else if(parameter == "d") { ++pindex; subtractFile = argv[pindex]; subtract=true; } else if(parameter == "fft") { fft = true; } else if(parameter == "fi") { individualMaximization = true; } else if(parameter == "fits") { saveFits = true; ++pindex; outputFitsFile = argv[pindex]; } else if(parameter == "fm") { scaleMethod = MaximumContrast; } else if(parameter == "fv") { scaleMethod = Constant; ++pindex; scaleValue = atof(argv[pindex]); } else if(parameter == "m") { colormap = true; } else if(parameter == "max") { displayMax=true; } else if(parameter == "png") { savePng = true; ++pindex; outputPngFile = argv[pindex]; } else if(parameter == "r") { ++pindex; removeNoiseImages = atoi(argv[pindex]); } else if(parameter == "rb") { redblue=true; } else if(parameter == "rms") { rms=true; } else if(parameter == "si") { singleImage = true; ++pindex; singleImageIndex = atoi(argv[pindex]); } else if(parameter == "w") { window = true; ++pindex; windowX = atoi(argv[pindex]); ++pindex; windowY = atoi(argv[pindex]); ++pindex; windowWidth = atoi(argv[pindex]); ++pindex; windowHeight = atoi(argv[pindex]); } else if(parameter == "wc") { cutWindow = true; ++pindex; cutWindowX = atoi(argv[pindex]); ++pindex; cutWindowY = atoi(argv[pindex]); ++pindex; cutWindowWidth = atoi(argv[pindex]); ++pindex; cutWindowHeight = atoi(argv[pindex]); } else { cerr << "Unknown parameter: -" << parameter << endl; return -1; } ++pindex; } if(argc-pindex < 1) { cerr << "Usage: \n\t" << argv[0] << " [options] <input fits file>\n" "\toptions:\n" "\t-d <fitsfile> subtract the file from the image\n" "\t-fft perform fft before combining\n" "\t-fi maximize each individual image before summing\n" "\t-fits <file> store in fits file (does not preserve the headers)\n" "\t-fm scale colors for maximum contrast, upper 0.02% of the data will be oversaturated (default)\n" "\t-fv <value> scale so that <value> flux is full brightness\n" "\t-m add colormap to image\n" "\t-max display maximum of each image\n" "\t-png <file> save as png file\n" "\t-rb don't use frequency colored, but use red/blue map for positive/negative values\n" "\t-rms calculate and show the rms of the upperleft 10% data\n" "\t-s use spectrum (default)\n" "\t-si <index> select single image from each fits file\n" "\t-c use color circle\n" "\t-w <x> <y> <width> <height> select a window of each frame only\n" "\t-wc <x> <y> <width> <height> cut a window in each frame\n"; return -1; } Image2D *red = 0; Image2D *green = 0; Image2D *blue = 0; Image2D *mono = 0; long double totalRed = 0.0, totalGreen = 0.0, totalBlue = 0.0; unsigned addedCount = 0; size_t inputCount = argc-pindex; for(unsigned inputIndex=pindex;inputIndex<(unsigned) argc;++inputIndex) { cout << "Opening " << argv[inputIndex] << "..." << endl; FitsFile fitsfile(argv[inputIndex]); fitsfile.Open(FitsFile::ReadOnlyMode); fitsfile.MoveToHDU(1); unsigned images = Image2D::GetImageCountInHUD(fitsfile); FitsFile *subtractFits = 0; if(subtract) { cout << "Opening " << subtractFile << "..." << endl; subtractFits = new FitsFile(subtractFile); subtractFits->Open(FitsFile::ReadOnlyMode); subtractFits->MoveToHDU(1); unsigned sImages = Image2D::GetImageCountInHUD(fitsfile); if(sImages < images) images = sImages; } std::vector<ImageInfo> variances; if(removeNoiseImages > 0) { cout << "Sorting images on noise level..." << endl; for(unsigned i=0;i<images;++i) { if(i % 8 == 0) { unsigned upper = i+9; if(upper > images) upper = images; cout << "Measuring noise level in images " << (i+1) << " - " << upper << "..." << endl; } Image2D *image = Image2D::CreateFromFits(fitsfile, i); struct ImageInfo imageInfo; imageInfo.variance = image->GetRMS(); imageInfo.index = i; variances.push_back(imageInfo); delete image; } sort(variances.begin(), variances.end()); cout << "The following images are removed because of too many noise: " << variances.front().index; for(std::vector<ImageInfo>::const_iterator i=variances.begin()+1;i<variances.begin()+removeNoiseImages;++i) { cout << ", " << i->index; } cout << endl; } unsigned lowI, highI; if(singleImage) { lowI = singleImageIndex; highI = singleImageIndex+1; } else { lowI = 0; highI = images; } for(unsigned i=lowI;i<highI;++i) { if(i % 8 == 0) { unsigned upper = i+9; if(upper > images) upper = images; cout << "Adding image " << (i+1) << " - " << upper << "..." << endl; } bool skip = false; if(removeNoiseImages > 0) { for(std::vector<ImageInfo>::const_iterator j=variances.begin();j<variances.begin()+removeNoiseImages;++j) { if(j->index == i) { skip = true; break; } } } if(!skip) { long double wavelengthRatio; if(images*inputCount > 1) wavelengthRatio = (1.0 - (long double) (i+((int) inputIndex-(int) pindex)*images) / (images*inputCount-1.0)); else wavelengthRatio = 0.5; std::cout << "ratio=" << wavelengthRatio << '\n'; Image2D *image = Image2D::CreateFromFits(fitsfile, i); if(subtract) { Image2D *imageB = Image2D::CreateFromFits(*subtractFits, i); Image2D *AminB = Image2D::CreateFromDiff(*image, *imageB); delete image; image = AminB; delete imageB; } if(window) { Image2D *empty = Image2D::CreateZeroImage(image->Width(), image->Height()); for(unsigned y=image->Height()-windowY-windowHeight;y<image->Height()-windowY;++y) { for(unsigned x=windowX;x<windowX+windowWidth;++x) empty->SetValue(x, y, image->Value(x, y)); } delete image; image = empty; } if(cutWindow) { for(unsigned y=image->Height()-cutWindowY-cutWindowHeight;y<image->Height()-cutWindowY;++y) { for(unsigned x=cutWindowX;x<cutWindowX+cutWindowWidth;++x) image->SetValue(x, y, 0.0); } } if(fft) { Image2D *fft = FFTTools::CreateFFTImage(*image, FFTTools::Absolute); Image2D *fullfft = FFTTools::CreateFullImageFromFFT(*fft); delete image; delete fft; image = fullfft; } long double max; if(individualMaximization) { max = image->GetMaximum(); if(max <= 0.0) max = 1.0; } else { max = 1.0; } if(displayMax) cout << "max=" << image->GetMinimum() << ":" << image->GetMaximum() << endl; if(rms) ReportRMS(image); long double r=0.0,g=0.0,b=0.0; if(redblue) { r = 1.0; b = 1.0; } else if(useSpectrum) ScaledWLtoRGB(wavelengthRatio, r, g, b); else HLStoRGB(wavelengthRatio, 0.5, 1.0, r, g, b); totalRed += r; totalGreen += g; totalBlue += b; if(red == 0) { red = Image2D::CreateUnsetImage(image->Width(), image->Height()); green = Image2D::CreateUnsetImage(image->Width(), image->Height()); blue = Image2D::CreateUnsetImage(image->Width(), image->Height()); mono = Image2D::CreateUnsetImage(image->Width(), image->Height()); } size_t minY = image->Height(), minX = image->Width(); if(red->Height() < minY) minY = red->Height(); if(red->Width() < minX) minX = red->Width(); for(unsigned y=0;y<minY;++y) { for(unsigned x=0;x<minX;++x) { long double value = image->Value(x, y); mono->AddValue(x, y, value); if(redblue) { if(value > 0) red->AddValue(x, y, value/max); else blue->AddValue(x, y, value/(-max)); } else { if(value < 0.0) value = 0.0; value /= max; if(colormap && (y < 96 && y >= 32 && x < images*8)) { if(x >= i*8 && x < i*8+8) { red->SetValue(x, y, r * images); green->SetValue(x, y, g * images); blue->SetValue(x, y, b * images); } } else { red->AddValue(x, y, r * value); green->AddValue(x, y, g * value); blue->AddValue(x, y, b * value); } } } } ++addedCount; delete image; } } if(subtract) { subtractFits->Close(); delete subtractFits; } } cout << "Scaling to ordinary units..." << endl; for(unsigned y=0;y<red->Height();++y) { for(unsigned x=0;x<red->Width();++x) { red->SetValue(x, y, red->Value(x, y) / addedCount); blue->SetValue(x, y, blue->Value(x, y) / addedCount); green->SetValue(x, y, green->Value(x, y) / addedCount); mono->SetValue(x, y, mono->Value(x, y) / addedCount); } } if(rms) { ReportRMS(mono); } if(saveFits) { cout << "Saving fits file..." << endl; mono->SaveToFitsFile(outputFitsFile); } if(savePng) { cout << "Normalizing..." << endl; long double maxRed, maxGreen, maxBlue; switch(scaleMethod) { default: case MaximumContrast: maxRed = red->GetTresholdForCountAbove(red->Width() * red->Height() / 5000); maxGreen = green->GetTresholdForCountAbove(green->Width() * green->Height() / 5000); maxBlue = blue->GetTresholdForCountAbove(blue->Width() * blue->Height() / 5000); break; case Constant: maxRed = scaleValue; maxGreen = scaleValue * totalGreen / totalRed; maxBlue = scaleValue * totalBlue / totalRed; break; } if(maxRed <= 0.0) maxRed = 1.0; if(maxGreen <= 0.0) maxGreen = 1.0; if(maxBlue <= 0.0) maxBlue = 1.0; cout << "Contrast stretch value for red: " << maxRed << endl; PngFile file(outputPngFile, red->Width(), red->Height()); file.BeginWrite(); cout << "Writing " << outputPngFile << "..." << endl; for(unsigned y=0;y<red->Height();++y) { for(unsigned x=0;x<red->Width();++x) { unsigned r = (unsigned) ((red->Value(x, y) / maxRed) * 255.0), g = (unsigned) ((green->Value(x, y) / maxGreen) * 255.0), b = (unsigned) ((blue->Value(x, y) / maxBlue) * 255.0); if(r > 255) r = 255; if(g > 255) g = 255; if(b > 255) b = 255; file.PlotDatapoint(x, red->Height() - 1 - y, r, g, b, 255); } } file.Close(); } delete red; delete green; delete blue; delete mono; return EXIT_SUCCESS; }