Commit 5eb3fc02 authored by Jasem Mutlaq's avatar Jasem Mutlaq
Browse files

WCS support for KStars

Adding initial World Coordinate Systems (WCS) support to KStars. Now the
FITSviewer can read FITS files encoded with WCS and present pixel to
world transformations if available. For this, wcslib is now an
_optional_ dependency. WCS will have numerous uses within the FITSViewer
and especially Ekos.
parent 18ed4964
......@@ -24,6 +24,10 @@ macro_bool_to_01(INDI_FOUND HAVE_INDI_H)
macro_log_feature(INDI_FOUND "libindi" "Support for controlling astronomical devices with KStars." "http://www.indilib.org" FALSE "0.9.5" "")
ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
macro_optional_find_package(WCSLIB)
macro_bool_to_01(WCSLIB_FOUND HAVE_WCSLIB)
macro_log_feature(WCSLIB_FOUND "WCSLib" "Support for World Coordinate System in KStars." "http://www.atnf.csiro.au/people/mcalabre/WCS/" FALSE "" "WCS enables KStars to read and process world coordinate systems in FITS header.")
check_include_files(linux/videodev2.h HAVE_LINUX_VIDEODEV2_H)
check_include_files(termios.h TERMIOS_FOUND)
macro_bool_to_01(TERMIOS_FOUND HAVE_TERMIOS_H)
......@@ -45,6 +49,7 @@ if (EIGEN2_FOUND)
add_subdirectory( kstars )
endif (EIGEN2_FOUND)
if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
macro_display_feature_log()
endif (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
# - Try to find WCSLIB
# Once done this will define
#
# WCSLIB_FOUND - system has WCSLIB
# WCSLIB_INCLUDE_DIR - the WCSLIB include directory
# WCSLIB_LIBRARIES - Link these to use WCSLIB
# Copyright (c) 2006, Jasem Mutlaq <mutlaqja@ikarustech.com>
# Based on FindLibfacile by Carsten Niehaus, <cniehaus@gmx.de>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
# in cache already
set(WCSLIB_FOUND TRUE)
message(STATUS "Found WCSLIB: ${WCSLIB_LIBRARIES}, ${WCSLIB_INCLUDE_DIR}")
else (WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
if (NOT WIN32)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(PC_WCSLIB wcslib)
endif (PKG_CONFIG_FOUND)
endif (NOT WIN32)
find_path(WCSLIB_INCLUDE_DIR wcs.h
PATH_SUFFIXES wcslib
${PC_WCSLIB_INCLUDE_DIRS}
${_obIncDir}
${GNUWIN32_DIR}/include
)
find_library(WCSLIB_LIBRARIES NAMES wcs
PATHS
${PC_WCSLIB_LIBRARY_DIRS}
${_obLinkDir}
${GNUWIN32_DIR}/lib
)
if(WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
set(WCSLIB_FOUND TRUE)
else (WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
set(WCSLIB_FOUND FALSE)
endif(WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
if (WCSLIB_FOUND)
if (NOT WCSLIB_FIND_QUIETLY)
message(STATUS "Found WCSLIB: ${WCSLIB_LIBRARIES}, ${WCSLIB_INCLUDE_DIR}")
endif (NOT WCSLIB_FIND_QUIETLY)
else (WCSLIB_FOUND)
if (WCSLIB_FIND_REQUIRED)
message(FATAL_ERROR "WCSLIB not found. Please install wcslib and try again.")
endif (WCSLIB_FIND_REQUIRED)
endif (WCSLIB_FOUND)
mark_as_advanced(WCSLIB_INCLUDE_DIR WCSLIB_LIBRARIES)
endif (WCSLIB_INCLUDE_DIR AND WCSLIB_LIBRARIES)
......@@ -15,3 +15,6 @@
/* Define if you have xplanet */
#cmakedefine HAVE_XPLANET 1
/* Define if you have wcslibt */
#cmakedefine HAVE_WCSLIB 1
......@@ -80,6 +80,10 @@ if (INDI_FOUND)
include_directories(${INDI_INCLUDE_DIR})
endif(INDI_FOUND)
if (WCSLIB_FOUND)
include_directories( ${WCSLIB_INCLUDE_DIR} )
endif (WCSLIB_FOUND)
if ( XPLANET_FOUND )
set (xplanet_SRCS
xplanet/opsxplanet.cpp
......@@ -97,9 +101,6 @@ if ( OPENGL_FOUND )
add_definitions(-DHAVE_OPENGL)
endif( OPENGL_FOUND )
include_directories(
${kstars_SOURCE_DIR}/kstars/tools
${kstars_SOURCE_DIR}/kstars/skyobjects
......@@ -468,6 +469,9 @@ endif (CFITSIO_FOUND)
if (INDI_FOUND)
target_link_libraries(kstars ${INDI_LIBRARIES} ${INDI_CLIENT_LIBRARIES} z)
endif (INDI_FOUND)
if (WCSLIB_FOUND)
target_link_libraries(kstars ${WCSLIB_LIBRARIES})
endif (WCSLIB_FOUND)
if( OPENGL_FOUND )
target_link_libraries(kstars
......
......@@ -18,7 +18,7 @@
#define FITSCOMMON_H
typedef enum { FITS_NORMAL, FITS_FOCUS, FITS_GUIDE, FITS_CALIBRATE } FITSMode;
typedef enum { FITS_POSITION, FITS_VALUE, FITS_RESOLUTION, FITS_ZOOM, FITS_MESSAGE } FITSBar;
typedef enum { FITS_POSITION, FITS_VALUE, FITS_RESOLUTION, FITS_ZOOM, FITS_WCS, FITS_MESSAGE } FITSBar;
typedef enum { FITS_NONE, FITS_AUTO_STRETCH, FITS_HIGH_CONTRAST, FITS_EQUALIZE, FITS_HIGH_PASS, FITS_AUTO , FITS_LINEAR, FITS_LOG, FITS_SQRT, FITS_CUSTOM } FITSScale;
typedef enum { ZOOM_FIT_WINDOW, ZOOM_KEEP_LEVEL, ZOOM_FULL } FITSZoom;
typedef enum { HFR_AVERAGE, HFR_MAX } HFRType;
......
......@@ -17,6 +17,8 @@
* See http://members.aol.com/pkirchg for more details. *
***************************************************************************/
#include <config-kstars.h>
#include "fitsimage.h"
#include <math.h>
......@@ -41,6 +43,13 @@
#include <KMessageBox>
#include <KFileDialog>
#ifdef HAVE_WCSLIB
#include <wcshdr.h>
#include <wcsfix.h>
#include <wcs.h>
#include <getwcstab.h>
#endif
#include "ksutils.h"
#define ZOOM_DEFAULT 100.0
......@@ -95,6 +104,21 @@ void FITSLabel::mouseMoveEvent(QMouseEvent *e)
emit newStatus(KGlobal::locale()->formatNumber( buffer[(int) (y * width + x)]), FITS_VALUE);
if (image->hasWCS)
{
int index = x + y * height;
if (index > image->wcs_coord.count())
return;
wcs_point *p = image->wcs_coord.at(index);
ra.setD(p->ra);
dec.setD(p->dec);
emit newStatus(QString("%1 , %2").arg( ra.toHMSString()).arg(dec.toDMSString()), FITS_WCS);
}
setCursor(Qt::CrossCursor);
e->accept();
......@@ -128,6 +152,7 @@ FITSImage::FITSImage(QWidget * parent, FITSMode fitsMode) : QScrollArea(parent)
firstLoad = true;
tempFile = false;
starsSearched = false;
hasWCS = false;
mode = fitsMode;
......@@ -159,6 +184,8 @@ FITSImage::~FITSImage()
if (starCenters.count() > 0)
qDeleteAll(starCenters);
qDeleteAll(wcs_coord);
if (fptr)
{
fits_close_file(fptr, &status);
......@@ -224,8 +251,8 @@ bool FITSImage::loadFITS ( const QString &inFilename )
return false;
if (mode == FITS_NORMAL)
fitsProg.setValue(50);
//qApp->processEvents(QEventLoop::ExcludeSocketNotifiers);
fitsProg.setValue(40);
if (fits_get_img_param(fptr, 2, &(stats.bitpix), &(stats.ndim), naxes, &status))
{
......@@ -327,6 +354,10 @@ bool FITSImage::loadFITS ( const QString &inFilename )
currentWidth = stats.dim[0];
currentHeight = stats.dim[1];
checkWCS();
if (mode == FITS_NORMAL)
fitsProg.setValue(90);
// Rescale to fits window
if (firstLoad)
{
......@@ -1021,7 +1052,6 @@ void FITSImage::findCentroid(int initStdDev, int minEdgeWidth)
starCenters.append(rCenter);
}
}
if (starCenters.count() > 1 && mode != FITS_FOCUS)
......@@ -1113,13 +1143,11 @@ double FITSImage::getHFR(HFRType type)
maxVal = starCenters[i]->val;
}
}
return starCenters[maxIndex]->HFR;
}
double FSum=0;
double avgHFR=0;
......@@ -1376,4 +1404,86 @@ void FITSImage::processPointSelection(int x, int y)
delete (pEdge);
}
void FITSImage::checkWCS()
{
#ifdef HAVE_WCSLIB
int status=0;
char *header;
int nkeyrec, nreject, nwcs, stat[2];
//double *imgcrd, phi, *pixcrd, theta, *world;
double imgcrd[2], phi, pixcrd[2], theta, world[2];
struct wcsprm *wcs=0;
int width=getWidth();
int height=getHeight();
if (fits_hdr2str(fptr, 1, NULL, 0, &header, &nkeyrec, &status))
{
fits_report_error(stderr, status);
return;
}
if ((status = wcspih(header, nkeyrec, WCSHDR_all, -3, &nreject, &nwcs, &wcs)))
{
fprintf(stderr, "wcspih ERROR %d: %s.\n", status, wcshdr_errmsg[status]);
return;
}
free(header);
if (wcs == 0)
{
//fprintf(stderr, "No world coordinate systems found.\n");
return;
}
// FIXME: Call above goes through EVEN if no WCS is present, so we're adding this to return for now.
if (wcs->crpix[0] == 0)
return;
hasWCS = true;
if ((status = wcsset(wcs)))
{
fprintf(stderr, "wcsset ERROR %d: %s.\n", status, wcs_errmsg[status]);
return;
}
/*world = malloc(2 * sizeof(double));
imgcrd = malloc(2 * sizeof(double));
pixcrd = malloc(2 * sizeof(double));
stat = malloc(2 * sizeof(int));/*/
for (int i=0; i < height; i++)
//for (int i=0; i < 10; i++)
{
for (int j=0; j < width; j++)
//for (int j=0; j < 10; j++)
{
pixcrd[0]=j;
pixcrd[1]=i;
if ((status = wcsp2s(wcs, 1, 2, &pixcrd[0], &imgcrd[0], &phi, &theta, &world[0], &stat[0])))
{
fprintf(stderr, "wcsp2s ERROR %d: %s.\n", status,
wcs_errmsg[status]);
}
else
{
wcs_point * p = new wcs_point;
p->ra = world[0];
p->dec = world[1];
//qDebug() << "For pixel (" << j << "," << i << ")" << " we got RA: " << p->ra << " DEC: " << p->dec << endl;
wcs_coord.append(p);
//qDebug() << "and index of " << wcs_coord.count() << endl;
}
}
}
#endif
}
#include "fitsimage.moc"
......@@ -41,6 +41,8 @@
#include "fitshistogram.h"
#include "fitscommon.h"
#include "dms.h"
#define INITIAL_W 640
#define INITIAL_H 480
......@@ -49,6 +51,12 @@
class FITSImage;
typedef struct
{
double ra;
double dec;
} wcs_point;
class FITSLabel : public QLabel
{
Q_OBJECT
......@@ -62,10 +70,14 @@ protected:
private:
FITSImage *image;
dms ra;
dms dec;
signals:
void newStatus(const QString &msg, FITSBar id);
void pointSelected(int x, int y);
};
class Edge
......@@ -147,7 +159,6 @@ public:
long dim[2];
} stats;
public slots:
void ZoomIn();
void ZoomOut();
......@@ -162,6 +173,7 @@ private:
double average();
double stddev();
int calculateMinMax(bool refresh=false);
void checkWCS();
bool markStars;
FITSLabel *image_frame;
......@@ -177,18 +189,20 @@ private:
bool firstLoad;
bool tempFile;
bool starsSearched;
bool hasWCS;
QString filename;
FITSMode mode;
QList<wcs_point *> wcs_coord;
QList<Edge*> starCenters;
signals:
void newStatus(const QString &msg, FITSBar id);
void actionUpdated(const QString &name, bool enable);
void guideStarSelected(int x, int y);
friend class FITSLabel;
};
......
......@@ -32,7 +32,6 @@
FITSTab::FITSTab(FITSViewer *parent) : QWidget()
{
image = NULL;
histogram = NULL;
viewer = parent;
......@@ -42,7 +41,6 @@ FITSTab::FITSTab(FITSViewer *parent) : QWidget()
undoStack->setUndoLimit(10);
undoStack->clear();
connect(undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(modifyFITSState(bool)));
}
FITSTab::~FITSTab()
......@@ -219,7 +217,6 @@ void FITSTab::headerFITS()
void FITSTab::saveFile()
{
int err_status;
char err_text[FLEN_STATUS];
......@@ -306,5 +303,3 @@ void FITSTab::tabPositionUpdated()
emit newStatus(QString("%1%").arg(image->getCurrentZoom()), FITS_ZOOM);
emit newStatus(QString("%1x%2").arg(image->getWidth()).arg(image->getHeight()), FITS_RESOLUTION);
}
......@@ -97,6 +97,8 @@ FITSViewer::FITSViewer (QWidget *parent)
statusBar()->setItemFixed(FITS_RESOLUTION, 100);
statusBar()->insertItem(QString(), FITS_ZOOM);
statusBar()->setItemFixed(FITS_ZOOM, 50);
statusBar()->insertItem(QString(), FITS_WCS);
statusBar()->setItemFixed(FITS_WCS, 200);
statusBar()->insertPermanentItem(i18n("Welcome to KStars FITS Viewer"), FITS_MESSAGE, 1);
statusBar()->setItemAlignment(FITS_MESSAGE , Qt::AlignLeft);
......@@ -276,6 +278,8 @@ void FITSViewer::tabFocusUpdated(int currentIndex)
else
updateStatusBar("", FITS_MESSAGE);
updateStatusBar("", FITS_WCS);
}
void FITSViewer::slotClose()
......
......@@ -100,6 +100,6 @@ INDI_P * INDI_G::getProperty(const QString & propName)
return pp;
}
return false;
return NULL;
}
......@@ -204,6 +204,7 @@ void ServerManager::connectionSuccess()
void ServerManager::processServerError(QProcess::ProcessError err)
{
INDI_UNUSED(err);
emit serverFailure(this);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment