00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020
00021 #include <kdebug.h>
00022 #include <klocale.h>
00023 #include <kprogress.h>
00024 #include <kapplication.h>
00025
00026 #include <qimage.h>
00027
00028 #include "fitsprocess.h"
00029 #include "fitsviewer.h"
00030 #include "fitsimage.h"
00031
00032 #define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; }
00033
00034 FITSProcess::FITSProcess(FITSViewer *parent, QStringList darkFiles, QStringList flatFiles, QStringList darkflatFiles, int darkMode, int flatMode, int darkflatMode)
00035 {
00036 float * buffer = NULL;
00037 darkCombineMode = darkMode;
00038 flatCombineMode = flatMode;
00039 darkflatCombineMode = darkflatMode;
00040 viewer = parent;
00041 finalDark = NULL;
00042 finalFlat = NULL;
00043 finalDarkFlat = NULL;
00044 npix = viewer->image->width * viewer->image->height;
00045
00046 darkFrames.setAutoDelete(true);
00047 flatFrames.setAutoDelete(true);
00048 darkflatFrames.setAutoDelete(true);
00049
00050 KProgressDialog reduceProgress(0, 0, i18n("FITS Viewer"), i18n("Image Loading Process..."));
00051 reduceProgress.progressBar()->setTotalSteps(darkFiles.size() + flatFiles.size() + darkflatFiles.size());
00052 reduceProgress.setMinimumWidth(300);
00053 reduceProgress.show();
00054
00055 int nprogress = 0;
00056
00057
00058 for (unsigned int i=0; i < darkFiles.size(); i++)
00059 {
00060 if ( (buffer = viewer->loadData(darkFiles[i].ascii(), buffer)) == NULL)
00061 {
00062 kdDebug() << "Error loading dark file " << darkFiles[i] << endl;
00063 break;
00064 }
00065
00066 reduceProgress.progressBar()->setProgress(++nprogress);
00067 kapp->processEvents();
00068 darkFrames.append(buffer);
00069 }
00070
00071
00072 for (unsigned int i=0; i < flatFiles.size(); i++)
00073 {
00074 if ( (buffer = viewer->loadData(flatFiles[i].ascii(), buffer)) == NULL)
00075 {
00076 kdDebug() << "Error loading flat file " << flatFiles[i] << endl;
00077 break;
00078 }
00079
00080 reduceProgress.progressBar()->setProgress(++nprogress);
00081 kapp->processEvents();
00082 flatFrames.append(buffer);
00083 }
00084
00085
00086 for (unsigned int i=0; i < darkflatFiles.size(); i++)
00087 {
00088 if ( (buffer = viewer->loadData(darkflatFiles[i].ascii(), buffer)) == NULL)
00089 {
00090 kdDebug() << "Error loading dark flat file " << darkflatFiles[i] << endl;
00091 break;
00092 }
00093
00094 reduceProgress.progressBar()->setProgress(++nprogress);
00095 kapp->processEvents();
00096 darkflatFrames.append(buffer);
00097 }
00098
00099 }
00100
00101
00102 FITSProcess::~FITSProcess() {}
00103
00104 float * FITSProcess::combine(QPtrList<float> & frames, int mode)
00105 {
00106 int nframes = frames.count();
00107 float *dest;
00108 float *narray;
00109
00110 if (nframes == 0)
00111 {
00112 dest = NULL;
00113 return dest;
00114 }
00115 else if (nframes == 1)
00116 {
00117 dest = frames.at(0);
00118 return dest;
00119 }
00120
00121 dest = frames.at(0);
00122 narray = (float *) malloc (nframes * sizeof(float));
00123
00124 switch (mode)
00125 {
00126
00127 case 0:
00128 for (int i=0; i < npix; i++)
00129 {
00130 for (int j=0; j < nframes; j++)
00131 narray[j] = *((frames.at(j)) + i);
00132 dest[i] = average(narray, nframes);
00133
00134 }
00135 break;
00136
00137 case 1:
00138 for (int i=0; i < npix; i++)
00139 {
00140 for (int j=0; j < nframes; j++)
00141 narray[j] = *((frames.at(j)) + i);
00142 dest[i] = quick_select(narray, nframes);
00143 }
00144 break;
00145 }
00146
00147 free(narray);
00148 return dest;
00149 }
00150
00151
00152
00153
00154
00155
00156 float FITSProcess::quick_select(float * arr, int n)
00157 {
00158 int low, high ;
00159 int median;
00160 int middle, ll, hh;
00161
00162 low = 0 ; high = n-1 ; median = (low + high) / 2;
00163 for (;;) {
00164 if (high <= low)
00165 return arr[median] ;
00166
00167 if (high == low + 1) {
00168 if (arr[low] > arr[high])
00169 ELEM_SWAP(arr[low], arr[high]) ;
00170 return arr[median] ;
00171 }
00172
00173
00174 middle = (low + high) / 2;
00175 if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ;
00176 if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ;
00177 if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ;
00178
00179
00180 ELEM_SWAP(arr[middle], arr[low+1]) ;
00181
00182
00183 ll = low + 1;
00184 hh = high;
00185 for (;;) {
00186 do ll++; while (arr[low] > arr[ll]) ;
00187 do hh--; while (arr[hh] > arr[low]) ;
00188
00189 if (hh < ll)
00190 break;
00191
00192 ELEM_SWAP(arr[ll], arr[hh]) ;
00193 }
00194
00195
00196 ELEM_SWAP(arr[low], arr[hh]) ;
00197
00198
00199 if (hh <= median)
00200 low = ll;
00201 if (hh >= median)
00202 high = hh - 1;
00203 }
00204 }
00205
00206 float FITSProcess::average(float * array, int n)
00207 {
00208 double total=0;
00209 for (int i=0; i < n; i++)
00210 total += array[i];
00211
00212 return (total / n);
00213 }
00214
00215
00216 void FITSProcess::subtract(float * img1, float * img2)
00217 {
00218 for (int i=0; i < npix; i++)
00219 if (img1[i] < img2[i])
00220 img1[i] = 0;
00221 else img1[i] -= img2[i];
00222
00223 }
00224
00225 void FITSProcess::divide(float * img1, float * img2)
00226 {
00227 for (int i=0; i < npix; i++)
00228 {
00229 if (img2[i] == 0)
00230 img1[i] = 0;
00231 else
00232 img1[i] = img1[i] / img2[i];
00233 }
00234
00235 }
00236
00237 void FITSProcess::normalize(float *buf)
00238 {
00239
00240 float avg = average(buf, npix);
00241 if (!avg) return;
00242
00243 if (avg < 0)
00244 avg += abs((int) min(buf));
00245
00246 for (int i=0; i < npix; i++)
00247 buf[i] = buf[i] / avg;
00248
00249 }
00250
00251 float FITSProcess::min(float *buf)
00252 {
00253 float lmin= buf[0];
00254
00255 for (int i=1; i < npix; i++)
00256 if (buf[i] < lmin) lmin = buf[i];
00257
00258 return lmin;
00259 }
00260
00261 void FITSProcess::reduce()
00262 {
00263 KProgressDialog reduceProgress(0, 0, i18n("FITS Viewer"), i18n("Image Reduction Process..."));
00264 reduceProgress.progressBar()->setTotalSteps(20);
00265 reduceProgress.setMinimumWidth(300);
00266 reduceProgress.show();
00267
00268 reduceProgress.progressBar()->setProgress(1);
00269 kapp->processEvents();
00270
00271
00272 finalDark = combine(darkFrames, darkCombineMode);
00273
00274 reduceProgress.progressBar()->setProgress(5);
00275 kapp->processEvents();
00276
00277
00278 finalFlat = combine(flatFrames, flatCombineMode);
00279 reduceProgress.progressBar()->setProgress(10);
00280 kapp->processEvents();
00281
00282
00283 finalDarkFlat = combine(darkflatFrames, darkflatCombineMode);
00284 reduceProgress.progressBar()->setProgress(12);
00285 kapp->processEvents();
00286
00287
00288 if (finalDark)
00289 subtract( viewer->imgBuffer, finalDark);
00290 reduceProgress.progressBar()->setProgress(14);
00291 kapp->processEvents();
00292
00293
00294
00295 if (finalFlat)
00296 {
00297 if (finalDarkFlat)
00298 subtract( finalFlat, finalDarkFlat);
00299 reduceProgress.progressBar()->setProgress(16);
00300 kapp->processEvents();
00301
00302 normalize(finalFlat);
00303 reduceProgress.progressBar()->setProgress(18);
00304 kapp->processEvents();
00305
00306 divide(viewer->imgBuffer, finalFlat);
00307 }
00308
00309 reduceProgress.progressBar()->setProgress(20);
00310 kapp->processEvents();
00311
00312 }
00313
00314 FITSProcessCommand::FITSProcessCommand(FITSViewer *parent)
00315 {
00316
00317 viewer = parent;
00318 oldImage = new QImage();
00319
00320 buffer = (float *) malloc (viewer->image->width * viewer->image->height * sizeof(float));
00321 memcpy(buffer, viewer->imgBuffer, viewer->image->width * viewer->image->height * sizeof(float));
00322
00323 }
00324
00325 FITSProcessCommand::~FITSProcessCommand()
00326 {
00327 free (buffer);
00328 delete (oldImage);
00329 }
00330
00331 void FITSProcessCommand::execute()
00332 {
00333 memcpy(viewer->imgBuffer, buffer, viewer->image->width * viewer->image->height * sizeof(float));
00334 *oldImage = viewer->image->displayImage->copy();
00335 }
00336
00337 void FITSProcessCommand::unexecute()
00338 {
00339
00340 memcpy( viewer->imgBuffer, buffer, viewer->image->width * viewer->image->height * sizeof(float));
00341 viewer->calculateStats();
00342 *viewer->image->displayImage = oldImage->copy();
00343 viewer->image->zoomToCurrent();
00344
00345 }
00346
00347 QString FITSProcessCommand::name() const
00348 {
00349 return i18n("Image Reduction");
00350 }
00351
00352