• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
  • fitsviewer
fitsimage.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  FITSImage.cpp - FITS Image
3  -------------------
4  begin : Thu Jan 22 2004
5  copyright : (C) 2004 by Jasem Mutlaq
6  email : mutlaqja@ikarustech.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  * Some code fragments were adapted from Peter Kirchgessner's FITS plugin*
17  * See http://members.aol.com/pkirchg for more details. *
18  ***************************************************************************/
19 
20 #include <config-kstars.h>
21 
22 #include "fitsimage.h"
23 
24 #include <cmath>
25 #include <cstdlib>
26 
27 #include <QApplication>
28 #include <QFile>
29 #include <QProgressDialog>
30 #include <KMessageBox>
31 
32 #ifdef HAVE_WCSLIB
33 #include <wcshdr.h>
34 #include <wcsfix.h>
35 #include <wcs.h>
36 #include <getwcstab.h>
37 #endif
38 
39 #include "ksutils.h"
40 
41 #define ZOOM_DEFAULT 100.0
42 #define ZOOM_MIN 10
43 #define ZOOM_MAX 400
44 #define ZOOM_LOW_INCR 10
45 #define ZOOM_HIGH_INCR 50
46 
47 const int MINIMUM_ROWS_PER_CENTER=3;
48 
49 #define JM_LOWER_LIMIT 5
50 #define JM_UPPER_LIMIT 400
51 
52 #define LOW_EDGE_CUTOFF_1 50
53 #define LOW_EDGE_CUTOFF_2 10
54 
55 //#define FITS_DEBUG
56 
57 bool greaterThan(Edge *s1, Edge *s2)
58 {
59  return s1->width > s2->width;
60 }
61 
62 
63 
64 FITSImage::FITSImage(FITSMode fitsMode)
65 {
66  image_buffer = NULL;
67  wcs_coord = NULL;
68  fptr = NULL;
69  tempFile = false;
70  starsSearched = false;
71  HasWCS = false;
72  mode = fitsMode;
73 }
74 
75 FITSImage::~FITSImage()
76 {
77  int status=0;
78 
79  delete(image_buffer);
80 
81  if (starCenters.count() > 0)
82  qDeleteAll(starCenters);
83 
84  delete (wcs_coord);
85 
86  if (fptr)
87  {
88  fits_close_file(fptr, &status);
89 
90  if (tempFile)
91  QFile::remove(filename);
92 
93  }
94 }
95 
96 bool FITSImage::loadFITS ( const QString &inFilename, QProgressDialog *progress )
97 {
98  int status=0, nulval=0, anynull=0;
99  long fpixel[2], nelements, naxes[2];
100  char error_status[512];
101 
102  qDeleteAll(starCenters);
103  starCenters.clear();
104 
105  if (mode == FITS_NORMAL && progress)
106  {
107  progress->setLabelText(i18n("Please hold while loading FITS file..."));
108  progress->setWindowTitle(i18n("Loading FITS"));
109  }
110 
111  if (mode == FITS_NORMAL && progress)
112  progress->setValue(30);
113 
114  if (fptr)
115  {
116 
117  fits_close_file(fptr, &status);
118 
119  if (tempFile)
120  QFile::remove(filename);
121  }
122 
123  filename = inFilename;
124 
125  if (filename.contains("/tmp/"))
126  tempFile = true;
127  else
128  tempFile = false;
129 
130  filename.remove("file://");
131 
132 
133  if (fits_open_image(&fptr, filename.toAscii(), READONLY, &status))
134  {
135  fits_report_error(stderr, status);
136  fits_get_errstatus(status, error_status);
137  if (progress)
138  KMessageBox::error(0, i18n("Could not open file %1 (fits_get_img_param). Error %2", filename, QString::fromUtf8(error_status)), i18n("FITS Open"));
139  return false;
140  }
141 
142  if (mode == FITS_NORMAL && progress)
143  if (progress->wasCanceled())
144  return false;
145 
146  if (mode == FITS_NORMAL && progress)
147  progress->setValue(40);
148 
149 
150  if (fits_get_img_param(fptr, 2, &(stats.bitpix), &(stats.ndim), naxes, &status))
151  {
152  fits_report_error(stderr, status);
153  fits_get_errstatus(status, error_status);
154 
155  if (progress)
156  KMessageBox::error(0, i18n("FITS file open error (fits_get_img_param): %1", QString::fromUtf8(error_status)), i18n("FITS Open"));
157  return false;
158  }
159 
160  if (stats.ndim < 2)
161  {
162  if (progress)
163  KMessageBox::error(0, i18n("1D FITS images are not supported in KStars."), i18n("FITS Open"));
164  return false;
165  }
166 
167 
168  if (fits_get_img_type(fptr, &data_type, &status))
169  {
170  fits_report_error(stderr, status);
171  fits_get_errstatus(status, error_status);
172 
173  if (progress)
174  KMessageBox::error(0, i18n("FITS file open error (fits_get_img_type): %1", QString::fromUtf8(error_status)), i18n("FITS Open"));
175  return false;
176  }
177 
178  if (mode == FITS_NORMAL && progress)
179  if (progress->wasCanceled())
180  return false;
181 
182  if (mode == FITS_NORMAL && progress)
183  progress->setValue(60);
184 
185  stats.dim[0] = naxes[0];
186  stats.dim[1] = naxes[1];
187 
188  delete (image_buffer);
189  image_buffer = NULL;
190 
191  image_buffer = new float[stats.dim[0] * stats.dim[1]];
192 
193  if (image_buffer == NULL)
194  {
195  qDebug() << "Not enough memory for image_buffer";
196  return false;
197  }
198  if (mode == FITS_NORMAL && progress)
199  {
200  if (progress->wasCanceled())
201  {
202  delete (image_buffer);
203  return false;
204  }
205  }
206 
207  if (mode == FITS_NORMAL && progress)
208  progress->setValue(70);
209 
210  nelements = stats.dim[0] * stats.dim[1];
211  fpixel[0] = 1;
212  fpixel[1] = 1;
213 
214  qApp->processEvents();
215 
216  if (fits_read_2d_flt(fptr, 0, nulval, naxes[0], naxes[0], naxes[1], image_buffer, &anynull, &status))
217  {
218  fprintf(stderr, "fits_read_pix error\n");
219  fits_report_error(stderr, status);
220  return false;
221  }
222 
223  if (mode == FITS_NORMAL && progress)
224  {
225  if (progress->wasCanceled())
226  {
227  delete (image_buffer);
228  return false;
229  }
230  }
231 
232  calculateStats();
233 
234  if (mode == FITS_NORMAL && progress)
235  progress->setValue(80);
236 
237  //currentWidth = stats.dim[0];
238  // currentHeight = stats.dim[1];
239 
240  qApp->processEvents();
241 
242  if (mode == FITS_NORMAL)
243  {
244  checkWCS();
245 
246  if (progress)
247  progress->setValue(90);
248  }
249 
250  if (mode == FITS_NORMAL && progress)
251  {
252  if (progress->wasCanceled())
253  {
254  delete (image_buffer);
255  return false;
256  }
257  }
258 
259  if (mode == FITS_NORMAL && progress)
260  progress->setValue(100);
261 
262  starsSearched = false;
263 
264  return true;
265 
266 }
267 
268 int FITSImage::saveFITS( const QString &newFilename )
269 {
270  int status=0;
271  long fpixel[2], nelements;
272  fitsfile *new_fptr;
273 
274  nelements = stats.dim[0] * stats.dim[1];
275  fpixel[0] = 1;
276  fpixel[1] = 1;
277 
278 
279  /* Create a new File, overwriting existing*/
280  if (fits_create_file(&new_fptr, newFilename.toAscii(), &status))
281  {
282  fits_report_error(stderr, status);
283  return status;
284  }
285 
286  /* Copy ALL contents */
287  if (fits_copy_file(fptr, new_fptr, 1, 1, 1, &status))
288  {
289  fits_report_error(stderr, status);
290  return status;
291  }
292 
293  /* close current file */
294  if (fits_close_file(fptr, &status))
295  {
296  fits_report_error(stderr, status);
297  return status;
298  }
299 
300  if (tempFile)
301  {
302  QFile::remove(filename);
303  tempFile = false;
304  }
305 
306  filename = newFilename;
307 
308  fptr = new_fptr;
309 
310  /* Write Data */
311  if (fits_write_pix(fptr, TFLOAT, fpixel, nelements, image_buffer, &status))
312  {
313  fits_report_error(stderr, status);
314  return status;
315  }
316 
317  /* Write keywords */
318 
319  // Minimum
320  if (fits_update_key(fptr, TDOUBLE, "DATAMIN", &(stats.min), "Minimum value", &status))
321  {
322  fits_report_error(stderr, status);
323  return status;
324  }
325 
326  // Maximum
327  if (fits_update_key(fptr, TDOUBLE, "DATAMAX", &(stats.max), "Maximum value", &status))
328  {
329  fits_report_error(stderr, status);
330  return status;
331  }
332 
333  // ISO Date
334  if (fits_write_date(fptr, &status))
335  {
336  fits_report_error(stderr, status);
337  return status;
338  }
339 
340  QString history = QString("Modified by KStars on %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss"));
341  // History
342  if (fits_write_history(fptr, history.toAscii(), &status))
343  {
344  fits_report_error(stderr, status);
345  return status;
346  }
347 
348  return status;
349 }
350 
351 
352 int FITSImage::calculateMinMax(bool refresh)
353 {
354  int status, nfound=0;
355  long npixels;
356 
357  status = 0;
358 
359  if (refresh == false)
360  {
361  if (fits_read_key_dbl(fptr, "DATAMIN", &(stats.min), NULL, &status) ==0)
362  nfound++;
363 
364  if (fits_read_key_dbl(fptr, "DATAMAX", &(stats.max), NULL, &status) == 0)
365  nfound++;
366 
367  // If we found both keywords, no need to calculate them
368  if (nfound == 2)
369  return 0;
370  }
371 
372  npixels = stats.dim[0] * stats.dim[1]; /* number of pixels in the image */
373  stats.min= 1.0E30;
374  stats.max= -1.0E30;
375 
376  for (int i=0; i < npixels; i++)
377  {
378  if (image_buffer[i] < stats.min) stats.min = image_buffer[i];
379  else if (image_buffer[i] > stats.max) stats.max = image_buffer[i];
380  }
381 
382  //qDebug() << "DATAMIN: " << stats.min << " - DATAMAX: " << stats.max;
383  return 0;
384 }
385 
386 
387 void FITSImage::calculateStats(bool refresh)
388 {
389  calculateMinMax(refresh);
390  // #1 call average, average is used in std deviation
391  stats.average = average();
392  // #2 call std deviation
393  stats.stddev = stddev();
394 
395  if (refresh && markStars)
396  // Let's try to find star positions again after transformation
397  starsSearched = false;
398 
399 }
400 
401 double FITSImage::average()
402 {
403  double sum=0;
404  int row=0;
405  int width = stats.dim[0];
406  int height = stats.dim[1];
407 
408  if (!image_buffer) return -1;
409 
410  for (int i= 0 ; i < height; i++)
411  {
412  row = (i * width);
413  for (int j= 0; j < width; j++)
414  sum += image_buffer[row+j];
415  }
416 
417  return (sum / (width * height ));
418 
419 }
420 
421 double FITSImage::stddev()
422 {
423 
424  int row=0;
425  double lsum=0;
426  int width = stats.dim[0];
427  int height = stats.dim[1];
428 
429  if (!image_buffer) return -1;
430 
431  for (int i= 0 ; i < height; i++)
432  {
433  row = (i * width);
434  for (int j= 0; j < width; j++)
435  {
436  lsum += (image_buffer[row + j] - stats.average) * (image_buffer[row+j] - stats.average);
437  }
438  }
439 
440  return (sqrt(lsum/(width * height - 1)));
441 
442 
443 }
444 
445 void FITSImage::setFITSMinMax(double newMin, double newMax)
446 {
447  stats.min = newMin;
448  stats.max = newMax;
449 }
450 
451 int FITSImage::getFITSRecord(QString &recordList, int &nkeys)
452 {
453  char *header;
454  int status=0;
455 
456  if (fits_hdr2str(fptr, 0, NULL, 0, &header, &nkeys, &status))
457  {
458  fits_report_error(stderr, status);
459  free(header);
460  return -1;
461  }
462 
463  recordList = QString(header);
464 
465  free(header);
466 
467  return 0;
468 }
469 
470 bool FITSImage::checkCollision(Edge* s1, Edge*s2)
471 {
472  int dis; //distance
473 
474  int diff_x=s1->x - s2->x;
475  int diff_y=s1->y - s2->y;
476 
477  dis = abs( sqrt( diff_x*diff_x + diff_y*diff_y));
478  dis -= s1->width/2;
479  dis -= s2->width/2;
480 
481  if (dis<=0) //collision
482  return true;
483 
484  //no collision
485  return false;
486 }
487 
488 
489 /*** Find center of stars and calculate Half Flux Radius */
490 void FITSImage::findCentroid(int initStdDev, int minEdgeWidth)
491 {
492  double threshold=0;
493  double avg = 0;
494  double sum=0;
495  int pixelRadius =0;
496  int pixVal=0;
497  int badPix=0;
498 
499  QList<Edge*> edges;
500 
501  while (initStdDev >= 1)
502  {
503  threshold = stats.stddev* initStdDev;
504 
505  #ifdef FITS_DEBUG
506  qDebug() << "The threshold level is " << threshold << endl;
507  #endif
508 
509  // Detect "edges" that are above threshold
510  for (int i=0; i < stats.dim[1]; i++)
511  {
512  pixelRadius = 0;
513 
514  for(int j=0; j < stats.dim[0]; j++)
515  {
516  pixVal = image_buffer[j+(i*stats.dim[0])] - stats.min;
517 
518 
519  // If pixel value > threshold, let's get its weighted average
520  if ( pixVal >= threshold || (sum > 0 && badPix <= 2))
521  {
522  if (pixVal < threshold)
523  badPix++;
524  else
525  badPix=0;
526 
527  avg += j * pixVal;
528  sum += pixVal;
529  pixelRadius++;
530 
531  }
532  // Value < threshold but avg exists
533  else if (sum > 0)
534  {
535 
536  // We found a potential centroid edge
537  if (pixelRadius >= (minEdgeWidth - (MINIMUM_STDVAR - initStdDev)))
538  {
539  //int center = round(avg/sum);
540 
541  float center = avg/sum;
542 
543 
544  if (center > 0)
545  {
546  int i_center = round(center);
547 
548  Edge *newEdge = new Edge();
549 
550  newEdge->x = center;
551  newEdge->y = i;
552  newEdge->scanned = 0;
553  newEdge->val = image_buffer[i_center+(i*stats.dim[0])] - stats.min;
554  newEdge->width = pixelRadius;
555  newEdge->HFR = 0;
556  newEdge->sum = sum;
557 
558  edges.append(newEdge);
559  }
560 
561  }
562 
563  // Reset
564  badPix = 0;
565  avg=0;
566  sum=0;
567  pixelRadius=0;
568 
569 
570  }
571  }
572 
573 
574  }
575 
576  #ifdef FITS_DEBUG
577  qDebug() << "Total number of edges found is: " << edges.count() << endl;
578  #endif
579 
580  if (edges.count() >= MINIMUM_STDVAR)
581  break;
582 
583  qDeleteAll(edges);
584  edges.clear();
585  initStdDev--;
586  }
587 
588  int cen_count=0;
589  int cen_x=0;
590  int cen_y=0;
591  int cen_v=0;
592  int cen_w=0;
593  int width_sum=0;
594 
595  // Let's sort edges, starting with widest
596  qSort(edges.begin(), edges.end(), greaterThan);
597 
598  // Now, let's scan the edges and find the maximum centroid vertically
599  for (int i=0; i < edges.count(); i++)
600  {
601  #ifdef FITS_DEBUG
602  qDebug() << "# " << i << " Edge at (" << edges[i]->x << "," << edges[i]->y << ") With a value of " << edges[i]->val << " and width of "
603  << edges[i]->width << " pixels. with sum " << edges[i]->sum << endl;
604  #endif
605 
606  // If edge scanned already, skip
607  if (edges[i]->scanned == 1)
608  {
609  #ifdef FITS_DEBUG
610  qDebug() << "Skipping check for center " << i << " because it was already counted" << endl;
611  #endif
612  continue;
613  }
614 
615  #ifdef FITS_DEBUG
616  qDebug() << "Invetigating edge # " << i << " now ..." << endl;
617  #endif
618 
619  // Get X, Y, and Val of edge
620  cen_x = edges[i]->x;
621  cen_y = edges[i]->y;
622  cen_v = edges[i]->sum;
623  cen_w = edges[i]->width;
624 
625  float avg_x = 0;
626  float avg_y = 0;
627 
628  sum = 0;
629  cen_count=0;
630 
631  // Now let's compare to other edges until we hit a maxima
632  for (int j=0; j < edges.count();j++)
633  {
634  if (edges[j]->scanned)
635  continue;
636 
637  if (checkCollision(edges[j], edges[i]))
638  {
639  if (edges[j]->sum >= cen_v)
640  {
641  cen_v = edges[j]->sum;
642  cen_w = edges[j]->width;
643  }
644 
645  edges[j]->scanned = 1;
646  cen_count++;
647 
648  avg_x += edges[j]->x * edges[j]->val;
649  avg_y += edges[j]->y * edges[j]->val;
650  sum += edges[j]->val;
651 
652  continue;
653  }
654 
655  }
656 
657  int cen_limit = (MINIMUM_ROWS_PER_CENTER - (MINIMUM_STDVAR - initStdDev));
658 
659  if (edges.count() < LOW_EDGE_CUTOFF_1)
660  {
661  if (edges.count() < LOW_EDGE_CUTOFF_2)
662  cen_limit = 1;
663  else
664  cen_limit = 2;
665  }
666 
667  #ifdef FITS_DEBUG
668  qDebug() << "center_count: " << cen_count << " and initstdDev= " << initStdDev << " and limit is "
669  << cen_limit << endl;
670  #endif
671 
672  if (cen_limit < 1 || (cen_w > (0.2 * stats.dim[0])))
673  continue;
674 
675  // If centroid count is within acceptable range
676  //if (cen_limit >= 2 && cen_count >= cen_limit)
677  if (cen_count >= cen_limit)
678  {
679  // We detected a centroid, let's init it
680  Edge *rCenter = new Edge();
681 
682  //rCenter->x = edges[rc_index]->x;
683  rCenter->x = avg_x/sum;
684  rCenter->y = avg_y/sum;
685 
686  width_sum += rCenter->width;
687 
688  //rCenter->y = edges[rc_index]->y;
689 
690 
691  rCenter->width = cen_w;
692 
693  #ifdef FITS_DEBUG
694  qDebug() << "Found a real center with number " << rc_index << "with (" << rCenter->x << "," << rCenter->y << ")" << endl;
695 
696  qDebug() << "Profile for this center is:" << endl;
697  for (int i=edges[rc_index]->width/2; i >= -(edges[rc_index]->width/2) ; i--)
698  qDebug() << "#" << i << " , " << image_buffer[(int) round(rCenter->x-i+(rCenter->y*stats.dim[0]))] - stats.min << endl;
699 
700  #endif
701 
702  // Calculate Total Flux From Center, Half Flux, Full Summation
703  double TF=0;
704  double HF=0;
705  double FSum=0;
706 
707  cen_x = (int) round(rCenter->x);
708  cen_y = (int) round(rCenter->y);
709 
710  if (cen_x < 0 || cen_x > stats.dim[0] || cen_y < 0 || cen_y > stats.dim[1])
711  continue;
712 
713 
714  // Complete sum along the radius
715  //for (int k=0; k < rCenter->width; k++)
716  for (int k=rCenter->width/2; k >= -(rCenter->width/2) ; k--)
717  FSum += image_buffer[cen_x-k+(cen_y*stats.dim[0])] - stats.min;
718 
719  // Half flux
720  HF = FSum / 2.0;
721 
722  // Total flux starting from center
723  TF = image_buffer[cen_y * stats.dim[0] + cen_x] - stats.min;
724 
725  int pixelCounter = 1;
726 
727  // Integrate flux along radius axis until we reach half flux
728  for (int k=1; k < rCenter->width/2; k++)
729  {
730  TF += image_buffer[cen_y * stats.dim[0] + cen_x + k] - stats.min;
731  TF += image_buffer[cen_y * stats.dim[0] + cen_x - k] - stats.min;
732 
733  if (TF >= HF)
734  {
735  #ifdef FITS_DEBUG
736  qDebug() << "Stopping at TF " << TF << " after #" << k << " pixels." << endl;
737  #endif
738  break;
739  }
740 
741  pixelCounter++;
742  }
743 
744  // Calculate weighted Half Flux Radius
745  rCenter->HFR = pixelCounter * (HF / TF);
746  // Store full flux
747  rCenter->val = FSum;
748 
749  #ifdef FITS_DEBUG
750  qDebug() << "HFR for this center is " << rCenter->HFR << " pixels and the total flux is " << FSum << endl;
751  #endif
752  starCenters.append(rCenter);
753 
754  }
755  }
756 
757  if (starCenters.count() > 1 && mode != FITS_FOCUS)
758  {
759  float width_avg = width_sum / starCenters.count();
760 
761  float lsum =0, sdev=0;
762 
763  foreach(Edge *center, starCenters)
764  lsum += (center->width - width_avg) * (center->width - width_avg);
765 
766  sdev = (sqrt(lsum/(starCenters.count() - 1))) * 4;
767 
768  // Reject stars > 4 * stddev
769  foreach(Edge *center, starCenters)
770  if (center->width > sdev)
771  starCenters.removeOne(center);
772 
773  //foreach(Edge *center, starCenters)
774  //qDebug() << center->x << "," << center->y << "," << center->width << "," << center->val << endl;
775 
776  }
777 
778  // Release memory
779  qDeleteAll(edges);
780 }
781 
782 double FITSImage::getHFR(HFRType type)
783 {
784  // This method is less susceptible to noise
785  // Get HFR for the brightest star only, instead of averaging all stars
786  // It is more consistent.
787  // TODO: Try to test this under using a real CCD.
788 
789  if (starCenters.size() == 0)
790  return -1;
791 
792  if (type == HFR_MAX)
793  {
794  int maxVal=0;
795  int maxIndex=0;
796  for (int i=0; i < starCenters.count() ; i++)
797  {
798  if (starCenters[i]->val > maxVal)
799  {
800  maxIndex=i;
801  maxVal = starCenters[i]->val;
802 
803  }
804  }
805 
806  return starCenters[maxIndex]->HFR;
807  }
808 
809  double FSum=0;
810  double avgHFR=0;
811 
812  // Weighted average HFR
813  for (int i=0; i < starCenters.count() ; i++)
814  {
815  avgHFR += starCenters[i]->val * starCenters[i]->HFR;
816  FSum += starCenters[i]->val;
817  }
818 
819  if (FSum != 0)
820  {
821  //qDebug() << "Average HFR is " << avgHFR / FSum << endl;
822  return (avgHFR / FSum);
823  }
824  else
825  return -1;
826 
827 }
828 
829 void FITSImage::applyFilter(FITSScale type, float *image, int min, int max)
830 {
831  if (type == FITS_NONE || histogram == NULL)
832  return;
833 
834  double coeff=0;
835  float val=0,bufferVal =0;
836 
837  if (image == NULL)
838  image = image_buffer;
839 
840  int width = stats.dim[0];
841  int height = stats.dim[1];
842 
843  if (min == -1)
844  min = stats.min;
845  if (max == -1)
846  max = stats.max;
847 
848  switch (type)
849  {
850  case FITS_AUTO:
851  case FITS_LINEAR:
852  for (int i=0; i < height; i++)
853  for (int j=0; j < width; j++)
854  {
855  bufferVal = image[i * width + j];
856  if (bufferVal < min) bufferVal = min;
857  else if (bufferVal > max) bufferVal = max;
858  image[i * width + j] = bufferVal;
859 
860  }
861  break;
862 
863  case FITS_LOG:
864  coeff = max / log(1 + max);
865 
866  for (int i=0; i < height; i++)
867  for (int j=0; j < width; j++)
868  {
869  bufferVal = image[i * width + j];
870  if (bufferVal < min) bufferVal = min;
871  else if (bufferVal > max) bufferVal = max;
872  val = (coeff * log(1 + bufferVal));
873  if (val < min) val = min;
874  else if (val > max) val = max;
875  image[i * width + j] = val;
876  }
877  break;
878 
879  case FITS_SQRT:
880  coeff = max / sqrt(max);
881 
882  for (int i=0; i < height; i++)
883  for (int j=0; j < width; j++)
884  {
885  bufferVal = (int) image[i * width + j];
886  if (bufferVal < min) bufferVal = min;
887  else if (bufferVal > max) bufferVal = max;
888  val = (int) (coeff * sqrt(bufferVal));
889  image[i * width + j] = val;
890  }
891  break;
892 
893  case FITS_AUTO_STRETCH:
894  {
895  min = stats.average - stats.stddev;
896  if (min < 0)
897  min =0;
898  //max = histogram->getMeanStdDev()*3 / histogram->getBinWidth() + min;
899  max = stats.average + stats.stddev * 3;
900 
901  for (int i=0; i < height; i++)
902  for (int j=0; j < width; j++)
903  {
904  bufferVal = image[i * width + j];
905  if (bufferVal < min) bufferVal = min;
906  else if (bufferVal > max) bufferVal = max;
907  image[i * width + j] = bufferVal;
908  }
909  }
910  break;
911 
912  case FITS_HIGH_CONTRAST:
913  {
914  //min = stats.average - stats.stddev;
915  min = stats.average + stats.stddev;
916  if (min < 0)
917  min =0;
918  //max = histogram->getMeanStdDev()*3 / histogram->getBinWidth() + min;
919  max = stats.average + stats.stddev * 3;
920 
921  for (int i=0; i < height; i++)
922  for (int j=0; j < width; j++)
923  {
924  bufferVal = image[i * width + j];
925  if (bufferVal < min) bufferVal = min;
926  else if (bufferVal > max) bufferVal = max;
927  image[i * width + j] = bufferVal;
928  }
929  }
930  break;
931 
932  case FITS_EQUALIZE:
933  {
934  QVarLengthArray<int, INITIAL_MAXIMUM_WIDTH> cumulativeFreq = histogram->getCumulativeFreq();
935  coeff = 255.0 / (height * width);
936 
937  for (int i=0; i < height; i++)
938  for (int j=0; j < width; j++)
939  {
940  bufferVal = (int) (image[i * width + j] - min) * histogram->getBinWidth();
941 
942  if (bufferVal >= cumulativeFreq.size())
943  bufferVal = cumulativeFreq.size()-1;
944 
945  val = (int) (coeff * cumulativeFreq[bufferVal]);
946 
947  image[i * width + j] = val;
948  }
949  }
950  break;
951 
952  case FITS_HIGH_PASS:
953  min = stats.average;
954  for (int i=0; i < height; i++)
955  for (int j=0; j < width; j++)
956  {
957  bufferVal = image[i * width + j];
958  if (bufferVal < min) bufferVal = min;
959  else if (bufferVal > max) bufferVal = max;
960  image[i * width + j] = bufferVal;
961  }
962  break;
963 
964 
965  default:
966  return;
967  break;
968  }
969 
970  calculateStats(true);
971 }
972 
973 void FITSImage::subtract(float *dark_buffer)
974 {
975  for (int i=0; i < stats.dim[0]*stats.dim[1]; i++)
976  {
977  image_buffer[i] -= dark_buffer[i];
978  if (image_buffer[i] < 0)
979  image_buffer[i] = 0;
980  }
981 
982  calculateStats(true);
983 }
984 
985 int FITSImage::findStars()
986 {
987  if (histogram == NULL)
988  return -1;
989 
990  if (starsSearched == false)
991  {
992  qDeleteAll(starCenters);
993  starCenters.clear();
994 
995  if (histogram->getJMIndex() > JM_LOWER_LIMIT && histogram->getJMIndex() < JM_UPPER_LIMIT)
996  {
997  findCentroid();
998  getHFR();
999  }
1000  }
1001 
1002  starsSearched = true;
1003 
1004  return starCenters.count();
1005 
1006 }
1007 
1008 void FITSImage::getCenterSelection(int *x, int *y)
1009 {
1010  if (starCenters.count() == 0)
1011  return;
1012 
1013  Edge *pEdge = new Edge();
1014  pEdge->x = *x;
1015  pEdge->y = *y;
1016  pEdge->width = 1;
1017 
1018  foreach(Edge *center, starCenters)
1019  if (checkCollision(pEdge, center))
1020  {
1021  *x = center->x;
1022  *y = center->y;
1023  break;
1024  }
1025 
1026  delete (pEdge);
1027 }
1028 
1029 void FITSImage::checkWCS()
1030 {
1031 #ifdef HAVE_WCSLIB
1032 
1033  int status=0;
1034  char *header;
1035  int nkeyrec, nreject, nwcs, stat[2];
1036  double imgcrd[2], phi, pixcrd[2], theta, world[2];
1037  struct wcsprm *wcs=0;
1038  int width=getWidth();
1039  int height=getHeight();
1040 
1041  if (fits_hdr2str(fptr, 1, NULL, 0, &header, &nkeyrec, &status))
1042  {
1043  fits_report_error(stderr, status);
1044  return;
1045  }
1046 
1047  if ((status = wcspih(header, nkeyrec, WCSHDR_all, -3, &nreject, &nwcs, &wcs)))
1048  {
1049  fprintf(stderr, "wcspih ERROR %d: %s.\n", status, wcshdr_errmsg[status]);
1050  return;
1051  }
1052 
1053  free(header);
1054 
1055  if (wcs == 0)
1056  {
1057  //fprintf(stderr, "No world coordinate systems found.\n");
1058  return;
1059  }
1060 
1061  // FIXME: Call above goes through EVEN if no WCS is present, so we're adding this to return for now.
1062  if (wcs->crpix[0] == 0)
1063  return;
1064 
1065  HasWCS = true;
1066 
1067  if ((status = wcsset(wcs)))
1068  {
1069  fprintf(stderr, "wcsset ERROR %d: %s.\n", status, wcs_errmsg[status]);
1070  return;
1071  }
1072 
1073  delete (wcs_coord);
1074 
1075  wcs_coord = new wcs_point[width*height];
1076 
1077  wcs_point *p = wcs_coord;
1078 
1079  for (int i=0; i < height; i++)
1080  {
1081  for (int j=0; j < width; j++)
1082  {
1083  pixcrd[0]=j;
1084  pixcrd[1]=i;
1085 
1086  if ((status = wcsp2s(wcs, 1, 2, &pixcrd[0], &imgcrd[0], &phi, &theta, &world[0], &stat[0])))
1087  {
1088  fprintf(stderr, "wcsp2s ERROR %d: %s.\n", status,
1089  wcs_errmsg[status]);
1090  }
1091  else
1092  {
1093  p->ra = world[0];
1094  p->dec = world[1];
1095 
1096  p++;
1097  }
1098  }
1099  }
1100 #endif
1101 
1102 }
LOW_EDGE_CUTOFF_1
#define LOW_EDGE_CUTOFF_1
Definition: fitsimage.cpp:52
fitsimage.h
JM_UPPER_LIMIT
#define JM_UPPER_LIMIT
Definition: fitsimage.cpp:50
Edge::sum
float sum
Definition: fitsimage.h:70
greaterThan
bool greaterThan(Edge *s1, Edge *s2)
Definition: fitsimage.cpp:57
wcs_point::ra
double ra
Definition: fitsimage.h:57
FITSImage::findStars
int findStars()
Definition: fitsimage.cpp:985
FITS_AUTO
Definition: fitscommon.h:22
FITS_HIGH_CONTRAST
Definition: fitscommon.h:22
FITS_HIGH_PASS
Definition: fitscommon.h:22
Edge::width
float width
Definition: fitsimage.h:68
wcs_point::dec
double dec
Definition: fitsimage.h:58
FITSHistogram::getJMIndex
double getJMIndex()
Definition: fitshistogram.h:63
FITSImage::getFITSRecord
int getFITSRecord(QString &recordList, int &nkeys)
Definition: fitsimage.cpp:451
FITS_NORMAL
Definition: fitscommon.h:20
FITSHistogram::getBinWidth
double getBinWidth()
Definition: fitshistogram.h:62
Edge::x
float x
Definition: fitsimage.h:64
FITSImage::findCentroid
void findCentroid(int initStdDev=MINIMUM_STDVAR, int minEdgeWidth=MINIMUM_PIXEL_RANGE)
Definition: fitsimage.cpp:490
FITS_SQRT
Definition: fitscommon.h:22
Edge
Definition: fitsimage.h:61
FITSImage::saveFITS
int saveFITS(const QString &filename)
Definition: fitsimage.cpp:268
FITSImage::getHeight
long getHeight()
Definition: fitsimage.h:99
FITSImage::min
double min
Definition: fitsimage.h:128
Edge::y
float y
Definition: fitsimage.h:65
FITSImage::stats
struct FITSImage::@1 stats
FITS_AUTO_STRETCH
Definition: fitscommon.h:22
FITSImage::max
double max
Definition: fitsimage.h:128
FITS_EQUALIZE
Definition: fitscommon.h:22
FITSImage::applyFilter
void applyFilter(FITSScale type, float *image=NULL, int min=-1, int max=-1)
Definition: fitsimage.cpp:829
FITSScale
FITSScale
Definition: fitscommon.h:22
MINIMUM_STDVAR
#define MINIMUM_STDVAR
Definition: fitsimage.h:51
HFRType
HFRType
Definition: fitscommon.h:24
Edge::scanned
int scanned
Definition: fitsimage.h:67
JM_LOWER_LIMIT
#define JM_LOWER_LIMIT
Definition: fitsimage.cpp:49
HFR_MAX
Definition: fitscommon.h:24
FITS_LINEAR
Definition: fitscommon.h:22
FITS_FOCUS
Definition: fitscommon.h:20
FITSImage::stddev
double stddev
Definition: fitsimage.h:130
FITSImage::average
double average
Definition: fitsimage.h:129
FITS_LOG
Definition: fitscommon.h:22
FITSImage::getWidth
long getWidth()
Definition: fitsimage.h:98
FITSImage::getCenterSelection
void getCenterSelection(int *x, int *y)
Definition: fitsimage.cpp:1008
Edge::HFR
float HFR
Definition: fitsimage.h:69
FITSImage::FITSImage
FITSImage(FITSMode mode=FITS_NORMAL)
Definition: fitsimage.cpp:64
FITSImage::getHFR
double getHFR(HFRType type=HFR_AVERAGE)
Definition: fitsimage.cpp:782
FITSImage::~FITSImage
~FITSImage()
Definition: fitsimage.cpp:75
LOW_EDGE_CUTOFF_2
#define LOW_EDGE_CUTOFF_2
Definition: fitsimage.cpp:53
FITS_NONE
Definition: fitscommon.h:22
FITSImage::subtract
void subtract(float *darkFrame)
Definition: fitsimage.cpp:973
Edge::val
int val
Definition: fitsimage.h:66
ksutils.h
FITSImage::loadFITS
bool loadFITS(const QString &filename, QProgressDialog *progress=NULL)
Definition: fitsimage.cpp:96
FITSImage::setFITSMinMax
void setFITSMinMax(double newMin, double newMax)
Definition: fitsimage.cpp:445
FITSImage::calculateStats
void calculateStats(bool refresh=false)
Definition: fitsimage.cpp:387
wcs_point
Definition: fitsimage.h:55
FITSMode
FITSMode
Definition: fitscommon.h:20
QList
FITSHistogram::getCumulativeFreq
QVarLengthArray< int, INITIAL_MAXIMUM_WIDTH > getCumulativeFreq()
Definition: fitshistogram.h:65
MINIMUM_ROWS_PER_CENTER
const int MINIMUM_ROWS_PER_CENTER
Definition: fitsimage.cpp:47
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal