mirror of
https://github.com/eddyem/apogee_control.git
synced 2025-12-06 02:35:16 +03:00
Add global settings & simple WCS given by user
This commit is contained in:
parent
a910538d33
commit
21b870159d
@ -14,7 +14,7 @@ message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||
if(NOT DEFINED LOCALEDIR)
|
||||
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
|
||||
endif()
|
||||
set(SOURCES takepic.c usage.c camtools.c am.c macros.c)
|
||||
set(SOURCES defhdrs.c takepic.c usage.c camtools.c am.c macros.c)
|
||||
if(NOT DEFINED NOBTA)
|
||||
set(SOURCES ${SOURCES} bta_print.c)
|
||||
add_definitions(-DUSE_BTA)
|
||||
@ -28,6 +28,9 @@ endif()
|
||||
if(DEFINED TELLAT)
|
||||
add_definitions(-DTELLAT=${TELLAT})
|
||||
endif()
|
||||
if(DEFINED TELFOCUS)
|
||||
add_definitions(-DTELFOCUS=${TELFOCUS})
|
||||
endif()
|
||||
if(NOT DEFINED PROCESSOR_COUNT)
|
||||
set(PROCESSOR_COUNT 2) # by default 2 cores
|
||||
set(cpuinfo_file "/proc/cpuinfo")
|
||||
|
||||
12
README
12
README
@ -3,7 +3,7 @@ This utilite depends on library libapogee & C-wrapper over it
|
||||
First, you should install a latest version of libapogee from directory "libapogee"
|
||||
or from original site: http://www.randomfactory.com/downloads/
|
||||
If you will meet a bug in link stage ("can't find -lboost_regex-mt") cd to directory
|
||||
libapogee-[version]/apogee and run
|
||||
libapogee-[version]/apogee and run
|
||||
$ sed -i 's/boost_regex-mt/boost_regex/g' Makefile
|
||||
after this small fix cd .. and run make again.
|
||||
|
||||
@ -34,4 +34,14 @@ By default observatory location is SAO RAS, to change coordinates define:
|
||||
* -DTELLAT=lattitude in degr
|
||||
* -DTELLONG=longitude in degr
|
||||
* -DTELALT=altitude in m
|
||||
* -DTELFOCUS=focal ratio of telescope in metres
|
||||
|
||||
|
||||
|
||||
user can store default headers in ~/apogee_hdrs.fits
|
||||
user can give additional keys as command line parameters
|
||||
to calculate simplest CDx_x coefficients user can give parameter ROT0:
|
||||
- for left-handed system it shoud be less than 0 (-360..0)
|
||||
CROTA2 = -ROT0 + PARANGLE - VAL_P
|
||||
- for right-handed > 0 (0..360)
|
||||
CROTA2 = ROT0 - PARANGLE + VAL_P
|
||||
|
||||
51
TODO
Normal file
51
TODO
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
Правильно писать шапку:
|
||||
DATA - дата записи файла формата dd/mm/yy (UTC)
|
||||
DATE-OBS - дата считывания данных с матрицы (начало, середина или конец - указывать в комментарии), dd/mm/yy, UTC
|
||||
ORIGIN - место записи (SAO RAS, правильно)
|
||||
INSTRUME - название прибора
|
||||
CREATOR - название ПО, записавшего файл
|
||||
EQUINOX - эпоха системы координат, используемой в файле (правильно)
|
||||
EPOCH - Deprecated
|
||||
|
||||
Комментарии, помимо COMMENT, могут просто начинаться с 9 столбца, оставляя первые 8 пустыми
|
||||
Аналогично для HISTORY
|
||||
(во всех трех случаях в столбце 9 не должно быть =)
|
||||
|
||||
|
||||
Если данные непонятно в чем (особенно это касается таблиц), нужно использовать ключи:
|
||||
BUNIT - binary unit (как для изображения, так и для таблиц)
|
||||
TUNITn - единицы n-го столбца таблицы
|
||||
см. http://www.lsw.uni-heidelberg.de/iau/units.html
|
||||
|
||||
BITPIX:
|
||||
8 - uint8_t
|
||||
16 - int16_t (BZERO=32768 для uint16_t)
|
||||
32 - int32_t (BZERO=2147483648 для uint32_t)
|
||||
-32 - float
|
||||
-64 - double
|
||||
|
||||
|
||||
EXTEND = T
|
||||
этот параметр не обязательно означает наличие "расширений", но если его нет, это гарантирует
|
||||
отсутствие расширений
|
||||
|
||||
Все расширения (изображения, таблицы и т.п.) должны начинаться со слова
|
||||
XTENSION = [тип] - тип расширения (например, XTENSION= 'TABLE'
|
||||
далее обязательны BITPIX, NAXIS и NAXIS1, NAXIS2 ...
|
||||
Если данные отсутствуют, пишем NAXIS1 = 0
|
||||
Расширению можно дать имя (скажем, таблице):
|
||||
EXTNAME = 'название'
|
||||
их можно версионировать (EXTVER) и разделять по иерархии (EXTLEVEL)
|
||||
|
||||
|
||||
ТАБЛИЦЫ: XTENSION='TABLE'
|
||||
BITPIX=8 (ASCII)
|
||||
NAXIS=2 (двумерная таблица)
|
||||
NAXIS1= количество символов в строке таблицы (все столбцы)
|
||||
NAXIS2= количество строк
|
||||
PCOUNT=0 (ASCII)
|
||||
GCOUNT=1
|
||||
TFIELDS= количество столбцов
|
||||
|
||||
|
||||
32
bta_print.c
32
bta_print.c
@ -33,6 +33,8 @@
|
||||
#include "camtools.h"
|
||||
#include "bta_print.h"
|
||||
#include "macros.h"
|
||||
#include "usage.h" // command line parameters
|
||||
#include "defhdrs.h"
|
||||
#include <slamac.h> // SLA macros
|
||||
|
||||
extern void sla_amp(double*, double*, double*, double*, double*, double*);
|
||||
@ -51,7 +53,7 @@ void calc_mean(double appRA, double appDecl, double *r, double *d){
|
||||
double ra, dec;
|
||||
appRA *= DS2R;
|
||||
appDecl *= DAS2R;
|
||||
DBG("appRa: %g, appDecl: %g", appRA, appDecl);
|
||||
//DBG("appRa: %g, appDecl: %g", appRA, appDecl);
|
||||
double mjd = JDate - jd0;
|
||||
slaamp(appRA, appDecl, mjd, 2000.0, &ra, &dec);
|
||||
ra *= DR2S;
|
||||
@ -60,10 +62,9 @@ void calc_mean(double appRA, double appDecl, double *r, double *d){
|
||||
if(d) *d = dec;
|
||||
}
|
||||
|
||||
#define CMNTSZ 79
|
||||
char comment[CMNTSZ + 1];
|
||||
#define CMNT(...) snprintf(comment, CMNTSZ, __VA_ARGS__)
|
||||
#define FTKEY(...) WRITEKEY(fp, __VA_ARGS__, comment)
|
||||
char comment[FLEN_CARD];
|
||||
#define CMNT(...) snprintf(comment, FLEN_CARD, __VA_ARGS__)
|
||||
#define FTKEY(...) WRITEKEY(__VA_ARGS__, comment)
|
||||
#define WRITEHIST(fp) \
|
||||
do{ if(test_headers){printf("HISTORY: %s\n", comment);}else{ \
|
||||
int status = 0; \
|
||||
@ -140,6 +141,7 @@ BTA_Queue *bta_queue = NULL;
|
||||
void write_bta_data(fitsfile *fp){
|
||||
char *val;
|
||||
double dtmp;
|
||||
//char buf[FLEN_CARD];
|
||||
time_t t_now = time(NULL);
|
||||
struct tm *tm_ut, *tm_loc;
|
||||
tm_ut = gmtime(&t_now);
|
||||
@ -215,29 +217,33 @@ void write_bta_data(fitsfile *fp){
|
||||
double a2000, d2000;
|
||||
calc_mean(InpAlpha, InpDelta, &a2000, &d2000);
|
||||
CMNT("R.A. given by user (for J2000): %s", time_asc(a2000));
|
||||
FTKEY(TDOUBLE, "INPRA0", &a2000);
|
||||
dtmp = a2000 / 3600.;
|
||||
FTKEY(TDOUBLE, "INPRA0", &dtmp);
|
||||
CMNT("Decl. given by user (for J2000): %s", angle_asc(d2000));
|
||||
FTKEY(TDOUBLE, "INPDEC0", &d2000);
|
||||
dtmp = d2000 / 3600;
|
||||
FTKEY(TDOUBLE, "INPDEC0", &dtmp);
|
||||
calc_mean(CurAlpha, CurDelta, &a2000, &d2000);
|
||||
CMNT("Current R.A. (for J2000): %s", time_asc(a2000));
|
||||
FTKEY(TDOUBLE, "CURRA0", &a2000);
|
||||
dtmp = a2000 / 3600.;
|
||||
FTKEY(TDOUBLE, "CURRA0", &dtmp);
|
||||
CMNT("Current Decl. (for J2000): %s", angle_asc(d2000));
|
||||
FTKEY(TDOUBLE, "CURDEC0", &d2000);
|
||||
dtmp = d2000 / 3600;
|
||||
FTKEY(TDOUBLE, "CURDEC0", &dtmp);
|
||||
// A / Azimuth
|
||||
CMNT("Current object Azimuth: %s", angle_asc(tag_A));
|
||||
dtmp = tag_A / 3600.; FTKEY(TDOUBLE, "A", &dtmp);
|
||||
// Z / Zenith distance
|
||||
CMNT("Current object Zenith: %s", angle_asc(tag_Z));
|
||||
dtmp = tag_Z / 3600.; FTKEY(TDOUBLE, "Z", &dtmp);
|
||||
// ROTANGLE / Field rotation angle
|
||||
CMNT("Field rotation angle: %s", angle_asc(tag_P));
|
||||
dtmp = tag_P / 3600.;FTKEY(TDOUBLE, "ROTANGLE", &dtmp);
|
||||
// PARANGLE / Parallactic angle
|
||||
CMNT("Parallactic angle: %s", angle_asc(tag_P));
|
||||
dtmp = tag_P / 3600.;FTKEY(TDOUBLE, "PARANGLE", &dtmp);
|
||||
|
||||
CMNT("Telescope A: %s", angle_asc(val_A));
|
||||
dtmp = val_A / 3600.; FTKEY(TDOUBLE, "VAL_A", &dtmp);
|
||||
CMNT("Telescope Z: %s", angle_asc(val_Z));
|
||||
dtmp = val_Z / 3600.; FTKEY(TDOUBLE, "VAL_Z", &dtmp);
|
||||
CMNT("Current P: %s", angle_asc(val_P));
|
||||
CMNT("Current P2 value: %s", angle_asc(val_P));
|
||||
dtmp = val_P / 3600.; FTKEY(TDOUBLE, "VAL_P", &dtmp);
|
||||
|
||||
CMNT("Dome A: %s", angle_asc(val_D));
|
||||
|
||||
120
camtools.c
120
camtools.c
@ -23,6 +23,7 @@
|
||||
#include "camtools.h"
|
||||
#include "usage.h"
|
||||
#include "macros.h"
|
||||
#include "defhdrs.h"
|
||||
|
||||
#ifdef USE_BTA
|
||||
#include "bta_print.h"
|
||||
@ -31,60 +32,6 @@
|
||||
unsigned short max=0, min=65535; // extremums of current image
|
||||
double avr, std; // average value and standard deviation
|
||||
|
||||
/*
|
||||
* Fake util to show FITS keys in stdout
|
||||
* when test_headers == 1
|
||||
*/
|
||||
void print_fits_header(fitsfile *fptr __attribute((unused)), int datatype,
|
||||
char *keyname, void *value, char *comment){
|
||||
void _ub(char* r, void* p){snprintf(r, 80, "%hhu", *(unsigned char*)p);}
|
||||
void _b(char* r, void* p){snprintf(r, 80, "%hhd", *(char*)p);}
|
||||
void _us(char* r, void* p){snprintf(r, 80, "%hu", *(unsigned short*)p);}
|
||||
void _ui(char* r, void* p){snprintf(r, 80, "%u", *(unsigned int*)p);}
|
||||
void _ul(char* r, void* p){snprintf(r, 80, "%lu", *(unsigned long*)p);}
|
||||
void _s(char* r, void* p){snprintf(r, 80, "%hd", *(short*)p);}
|
||||
void _i(char* r, void* p){snprintf(r, 80, "%d", *(int*)p);}
|
||||
void _l(char* r, void* p){snprintf(r, 80, "%ld", *(long*)p);}
|
||||
void _ll(char* r, void* p){snprintf(r, 80, "%lld", *(long long*)p);}
|
||||
void _f(char* r, void* p){snprintf(r, 80, "%g", *(float*)p);}
|
||||
void _d(char* r, void* p){snprintf(r, 80, "%g", *(double*)p);}
|
||||
void _fc(char* r, void* p){snprintf(r, 80, "(%.8g, %.8g)",
|
||||
((float*)p)[0], ((float*)p)[1]);}
|
||||
void _dc(char* r, void* p){snprintf(r, 80, "(%.8g, %.8g)",
|
||||
((double*)p)[0], ((double*)p)[1]);}
|
||||
void _log(char* r, void* p){snprintf(r, 80, "'%s'", (int*)p ? "true" : "false");}
|
||||
void _str(char* r, void* p){snprintf(r, 80, "'%s'", (char*)p);}
|
||||
void _unk(char* r, void* p __attribute((unused))){sprintf(r, "unknown datatype");}
|
||||
char tmp[81], res[81];
|
||||
void (*__)(char*, void*);
|
||||
switch(datatype){
|
||||
case TBIT:
|
||||
case TBYTE: __ = _ub; break;
|
||||
case TSBYTE: __ = _b; break;
|
||||
case TUSHORT: __ = _us; break;
|
||||
case TUINT: __ = _ui; break;
|
||||
case TULONG: __ = _ul; break;
|
||||
case TSHORT: __ = _s; break;
|
||||
case TINT: __ = _i; break;
|
||||
case TLONG: __ = _l; break;
|
||||
case TLONGLONG: __ = _ll; break;
|
||||
case TFLOAT: __ = _f; break;
|
||||
case TDOUBLE: __ = _d; break;
|
||||
case TCOMPLEX: __ = _fc; break;
|
||||
case TDBLCOMPLEX: __ = _dc; break;
|
||||
case TLOGICAL: __ = _log; break;
|
||||
case TSTRING: __ = _str; break;
|
||||
default: __ = _unk;
|
||||
}
|
||||
__(res, value);
|
||||
if(strlen(res) < 20)
|
||||
snprintf(tmp, 80, "%-8s = %-20s", keyname, res);
|
||||
else
|
||||
snprintf(tmp, 80, "%-8s = %s", keyname, res);
|
||||
snprintf(res, 80, "%s / %s", tmp, comment);
|
||||
printf("%s\n", res);
|
||||
}
|
||||
|
||||
/*
|
||||
* set fun speed
|
||||
* if user set option fan-speed=F, then speed would be set to F
|
||||
@ -225,63 +172,60 @@ int writefits(char *filename, int width, int height, void *data){
|
||||
TRYFITS(fits_create_file, &fp, filename);
|
||||
TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
|
||||
// FILE / Input file original name
|
||||
WRITEKEY(fp, TSTRING, "FILE", filename, "Input file original name");
|
||||
WRITEKEY(TSTRING, "FILE", filename, "Input file original name");
|
||||
/*
|
||||
* Detector parameters
|
||||
*/
|
||||
// DETECTOR / detector
|
||||
if(camera){
|
||||
WRITEKEY(fp, TSTRING, "DETECTOR", camera, "Detector model");
|
||||
WRITEKEY(TSTRING, "DETECTOR", camera, "Detector model");
|
||||
}
|
||||
// SENSOR / sensor
|
||||
if(sensor){
|
||||
WRITEKEY(fp, TSTRING, "SENSOR", sensor, "Camera sensor model");
|
||||
WRITEKEY(TSTRING, "SENSOR", sensor, "Camera sensor model");
|
||||
}
|
||||
// INSTRUME / Instrument
|
||||
if(instrument){
|
||||
WRITEKEY(fp, TSTRING, "INSTRUME", instrument, "Instrument");
|
||||
WRITEKEY(TSTRING, "INSTRUME", instrument, "Instrument");
|
||||
}else
|
||||
WRITEKEY(fp, TSTRING, "INSTRUME", "direct imaging", "Instrument");
|
||||
WRITEKEY(TSTRING, "INSTRUME", "direct imaging", "Instrument");
|
||||
snprintf(buf, 79, "%.g x %.g", pixX, pixY);
|
||||
// PXSIZE / pixel size
|
||||
WRITEKEY(fp, TSTRING, "PXSIZE", buf, "Pixel size in mkm");
|
||||
WRITEKEY(TSTRING, "PXSIZE", buf, "Pixel size in mkm");
|
||||
// XPIXELSZ, YPIXELSZ -- the same
|
||||
WRITEKEY(fp, TDOUBLE, "XPIXELSZ", &pixX, "X pixel size in mkm");
|
||||
WRITEKEY(fp, TDOUBLE, "YPIXELSZ", &pixY, "Y pixel size in mkm");
|
||||
WRITEKEY(fp, TSTRING, "VIEW_FIELD", viewfield, "Camera field of view");
|
||||
// CRVAL1, CRVAL2 / Offset in X, Y
|
||||
if(X0) WRITEKEY(fp, TINT, "CRVAL1", &X0, "Offset in X");
|
||||
if(Y0) WRITEKEY(fp, TINT, "CRVAL2", &Y0, "Offset in Y");
|
||||
WRITEKEY(TDOUBLE, "XPIXELSZ", &pixX, "X pixel size in mkm");
|
||||
WRITEKEY(TDOUBLE, "YPIXELSZ", &pixY, "Y pixel size in mkm");
|
||||
WRITEKEY(TSTRING, "VIEWFLD", viewfield, "Camera field of view");
|
||||
if(exptime == 0) sprintf(buf, "bias");
|
||||
else if(shutter == 0) sprintf(buf, "dark");
|
||||
else if(objtype) strncpy(buf, objtype, 79);
|
||||
else sprintf(buf, "object");
|
||||
// IMAGETYP / object, flat, dark, bias, scan, eta, neon, push
|
||||
WRITEKEY(fp, TSTRING, "IMAGETYP", buf, "Image type");
|
||||
WRITEKEY(TSTRING, "IMAGETYP", buf, "Image type");
|
||||
// DATAMAX, DATAMIN / Max,min pixel value
|
||||
ustmp = ((twelveBit) ? 4095 : 65535);
|
||||
WRITEKEY(fp, TUSHORT, "DATAMAX", &ustmp, "Max pixel value");
|
||||
WRITEKEY(TUSHORT, "DATAMAX", &ustmp, "Max pixel value");
|
||||
ustmp = 0;
|
||||
WRITEKEY(fp, TUSHORT, "DATAMIN", &ustmp, "Min pixel value");
|
||||
WRITEKEY(TUSHORT, "DATAMIN", &ustmp, "Min pixel value");
|
||||
// Some Statistics
|
||||
WRITEKEY(fp, TUSHORT, "STATMAX", &max, "Max data value");
|
||||
WRITEKEY(fp, TUSHORT, "STATMIN", &min, "Min data value");
|
||||
WRITEKEY(fp, TDOUBLE, "STATAVR", &avr, "Average data value");
|
||||
WRITEKEY(fp, TDOUBLE, "STATSTD", &std, "Standart deviation of data value");
|
||||
WRITEKEY(TUSHORT, "STATMAX", &max, "Max data value");
|
||||
WRITEKEY(TUSHORT, "STATMIN", &min, "Min data value");
|
||||
WRITEKEY(TDOUBLE, "STATAVR", &avr, "Average data value");
|
||||
WRITEKEY(TDOUBLE, "STATSTD", &std, "Standart deviation of data value");
|
||||
// Temperatures
|
||||
WRITEKEY(fp, TDOUBLE, "TEMP0", &temperature, "Camera temperature at exp. start (degr C)");
|
||||
WRITEKEY(fp, TDOUBLE, "TEMP1", &t_int, "Camera temperature at exp. end (degr C)");
|
||||
WRITEKEY(TDOUBLE, "TEMP0", &temperature, "Camera temperature at exp. start (degr C)");
|
||||
WRITEKEY(TDOUBLE, "TEMP1", &t_int, "Camera temperature at exp. end (degr C)");
|
||||
if(t_ext > -30.) // there's a hot temp sensor
|
||||
WRITEKEY(fp, TDOUBLE, "TEMPBODY", &t_ext, "Camera body temperature at exp. end (degr C)");
|
||||
WRITEKEY(TDOUBLE, "TEMPBODY", &t_ext, "Camera body temperature at exp. end (degr C)");
|
||||
tmp = (temperature + t_int) / 2. + 273.15;
|
||||
// CAMTEMP / Camera temperature (K)
|
||||
WRITEKEY(fp, TDOUBLE, "CAMTEMP", &tmp, "Camera temperature (K)");
|
||||
WRITEKEY(TDOUBLE, "CAMTEMP", &tmp, "Camera temperature (K)");
|
||||
tmp = (double)exptime / 1000.;
|
||||
// EXPTIME / actual exposition time (sec)
|
||||
WRITEKEY(fp, TDOUBLE, "EXPTIME", &tmp, "actual exposition time (sec)");
|
||||
WRITEKEY(TDOUBLE, "EXPTIME", &tmp, "actual exposition time (sec)");
|
||||
// DATE / Creation date (YYYY-MM-DDThh:mm:ss, UTC)
|
||||
strftime(buf, 79, "%Y-%m-%dT%H:%M:%S", gmtime(&savetime));
|
||||
WRITEKEY(fp, TSTRING, "DATE", buf, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
|
||||
WRITEKEY(TSTRING, "DATE", buf, "Creation date (YYYY-MM-DDThh:mm:ss, UTC)");
|
||||
tm_starttime = localtime(&expStartsAt);
|
||||
/*
|
||||
* startTime = (long)expStartsAt;
|
||||
@ -290,7 +234,7 @@ int writefits(char *filename, int width, int height, void *data){
|
||||
*/
|
||||
strftime(buf, 79, "%Y-%m-%dT%H:%M:%S", tm_starttime);
|
||||
// DATE-OBS / DATE OF OBS.
|
||||
WRITEKEY(fp, TSTRING, "DATE-OBS", buf, "DATE OF OBS. (YYYY-MM-DDThh:mm:ss, local)");
|
||||
WRITEKEY(TSTRING, "DATE-OBS", buf, "DATE OF OBS. (YYYY-MM-DDThh:mm:ss, local)");
|
||||
/*
|
||||
* // START / Measurement start time (local) (hh:mm:ss)
|
||||
* strftime(buf, 79, "%H:%M:%S", tm_starttime);
|
||||
@ -298,30 +242,32 @@ int writefits(char *filename, int width, int height, void *data){
|
||||
*/
|
||||
// OBJECT / Object name
|
||||
if(objname){
|
||||
WRITEKEY(fp, TSTRING, "OBJECT", objname, "Object name");
|
||||
WRITEKEY(TSTRING, "OBJECT", objname, "Object name");
|
||||
}
|
||||
// BINNING / Binning
|
||||
if(hbin != 1 || vbin != 1){
|
||||
snprintf(buf, 79, "%d x %d", hbin, vbin);
|
||||
WRITEKEY(fp, TSTRING, "BINNING", buf, "Binning (hbin x vbin)");
|
||||
WRITEKEY(TSTRING, "BINNING", buf, "Binning (hbin x vbin)");
|
||||
}
|
||||
WRITEKEY(fp, TINT, "XBIN", &hbin, "Horizontal binning");
|
||||
WRITEKEY(fp, TINT, "YBIN", &vbin, "Vertical binning");
|
||||
WRITEKEY(TINT, "XBIN", &hbin, "Horizontal binning");
|
||||
WRITEKEY(TINT, "YBIN", &vbin, "Vertical binning");
|
||||
// OBSERVER / Observers
|
||||
if(observers){
|
||||
WRITEKEY(fp, TSTRING, "OBSERVER", observers, "Observers");
|
||||
WRITEKEY(TSTRING, "OBSERVER", observers, "Observers");
|
||||
}
|
||||
// PROG-ID / Observation program identifier
|
||||
if(prog_id){
|
||||
WRITEKEY(fp, TSTRING, "PROG-ID", prog_id, "Observation program identifier");
|
||||
WRITEKEY(TSTRING, "PROG-ID", prog_id, "Observation program identifier");
|
||||
}
|
||||
// AUTHOR / Author of the program
|
||||
if(author){
|
||||
WRITEKEY(fp, TSTRING, "AUTHOR", author, "Author of the program");
|
||||
WRITEKEY(TSTRING, "AUTHOR", author, "Author of the program");
|
||||
}
|
||||
#ifdef USE_BTA
|
||||
write_bta_data(fp);
|
||||
#endif
|
||||
check_wcs();
|
||||
write_list(fp);
|
||||
TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data);
|
||||
TRYFITS(fits_close_file, fp);
|
||||
return 0;
|
||||
|
||||
@ -30,13 +30,7 @@ do{if(!test_headers){ int status = 0; \
|
||||
fits_report_error(stderr, status); \
|
||||
return -1;} \
|
||||
}}while(0)
|
||||
#define WRITEKEY(...) \
|
||||
do{ if(test_headers){ \
|
||||
print_fits_header(__VA_ARGS__); \
|
||||
}else{ int status = 0; \
|
||||
fits_write_key(__VA_ARGS__, &status); \
|
||||
if(status) fits_report_error(stderr, status);\
|
||||
}}while(0)
|
||||
#define WRITEKEY(...) do{add_fits_header(__VA_ARGS__);}while(0)
|
||||
|
||||
void print_fits_header(fitsfile *fptr, int datatype, char *keyname,
|
||||
void *value, char *comment);
|
||||
|
||||
435
defhdrs.c
Normal file
435
defhdrs.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* defhdrs.c - read default headers from user file
|
||||
*
|
||||
* Copyright 2016 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* Only these parameters are recognized:
|
||||
SUBNET (instead of -E)
|
||||
CAMMSGID (instead of -M)
|
||||
INSTRUME
|
||||
OBSERVER
|
||||
PROG-ID
|
||||
AUTHOR
|
||||
|
||||
XPIXELSZ
|
||||
YPIXELSZ
|
||||
IMSCALE
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <fitsio.h>
|
||||
|
||||
|
||||
#include "defhdrs.h"
|
||||
#include "usage.h"
|
||||
#include "macros.h"
|
||||
#include "camtools.h"
|
||||
|
||||
// global keylist
|
||||
static KeyList *FITS_keys = NULL;
|
||||
double crval1 = -5e5, crval2 = -5e5, crpix1 = -5e5, crpix2 = -5e5;
|
||||
double CD[2][2] = {{0.,0.}, {0.,0.}};
|
||||
|
||||
void get_defhdrs(char *fname){
|
||||
mmapbuf *mmb = NULL;
|
||||
if(!fname){ // find in default file: ~/$DEFCONF
|
||||
const char *homedir;
|
||||
if ((homedir = getenv("HOME")) == NULL){
|
||||
homedir = getpwuid(getuid())->pw_dir;
|
||||
}
|
||||
size_t L = strlen(homedir) + strlen(DEFCONF) + 2;
|
||||
fname = malloc(L);
|
||||
snprintf(fname, L, "%s/%s", homedir, DEFCONF);
|
||||
mmb = My_mmap(fname);
|
||||
FREE(fname);
|
||||
}else mmb = My_mmap(fname);
|
||||
if(!mmb) return;
|
||||
char *hdrs = strdup(mmb->data);
|
||||
My_munmap(mmb);
|
||||
char *nl = NULL;
|
||||
while((nl = strchr(hdrs, '\n'))){
|
||||
*nl = 0;
|
||||
list_add_record(&FITS_keys, hdrs, 1);
|
||||
hdrs = nl + 1;
|
||||
}
|
||||
if(*hdrs){ // last line in file didn't have newline
|
||||
list_add_record(&FITS_keys, hdrs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add headers from command line parameters
|
||||
* something like `apogee_control <parameters> filename "KEY1 = VAL1 / comment" "KEYn = VALn / comment"
|
||||
*/
|
||||
void add_morehdrs(int argc, char **argv){
|
||||
int i;
|
||||
char buf[FLEN_CARD];
|
||||
for(i = 0; i < argc; ++i){ // we should override parameters from default configuration file
|
||||
char *dup = strdup(argv[i]);
|
||||
char *eq = strchr(dup, '=');
|
||||
if(eq){
|
||||
*(eq++) = 0;
|
||||
KeyList *found = list_find_key(FITS_keys, dup);
|
||||
if(found) list_modify_key(FITS_keys, dup, eq, 2); // comments (if exists in new header) will be override too
|
||||
else{
|
||||
snprintf(buf, FLEN_CARD, "%-8s= %s", dup, eq);
|
||||
list_add_record(&FITS_keys, buf, 2);
|
||||
}
|
||||
}else{ // comment or something else
|
||||
list_add_record(&FITS_keys, dup, 2);
|
||||
}
|
||||
FREE(dup);
|
||||
}
|
||||
}
|
||||
|
||||
KeyList *list_get_end(KeyList *list){
|
||||
if(!list) return NULL;
|
||||
KeyList *first = list;
|
||||
if(list->last) return list->last;
|
||||
while(list->next) list = list->next;
|
||||
first->last = list;
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* add record to keylist
|
||||
* @param list (io) - pointer to root of list or NULL
|
||||
* if *root == NULL, just created node will be placed there
|
||||
* @param rec - data inserted
|
||||
* @return pointer to created node
|
||||
*/
|
||||
KeyList *list_add_record(KeyList **list, char *rec, int immutable){
|
||||
KeyList *node, *last;
|
||||
if((node = (KeyList*) MALLOC(KeyList, 1)) == 0) return NULL; // allocation error
|
||||
node->record = strdup(rec); // insert data
|
||||
node->immutable = immutable;
|
||||
DBG("add record %s", rec);
|
||||
if(!node->record){
|
||||
/// "Не могу скопировать данные"
|
||||
WARNX(_("Can't copy data"));
|
||||
return NULL;
|
||||
}
|
||||
if(list){
|
||||
if(*list){ // there was root node - search last
|
||||
last = list_get_end(*list);
|
||||
last->next = node; // insert pointer to new node into last element in list
|
||||
(*list)->last = node;
|
||||
// DBG("last node %s", (*list)->last->record);
|
||||
}else *list = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// compare keywords from `list` and `keyname`
|
||||
int compare_keyw(KeyList *list, char *keyname){
|
||||
if(!list || !keyname || !list->record) return 0;
|
||||
size_t L = strlen(keyname);
|
||||
if(strncmp(list->record, keyname, L) == 0){ // key found
|
||||
char *ltr = list->record + L;
|
||||
while(*ltr == ' ') ++ltr; // omit spaces
|
||||
if(*ltr == '=') return 1; // only if there's equal sign after keyname!
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* return record with given key or NULL
|
||||
*/
|
||||
KeyList *list_find_key(KeyList *list, char *keyname){
|
||||
if(!list || !keyname) return NULL;
|
||||
do{
|
||||
if(compare_keyw(list, keyname)) return list;
|
||||
list = list->next;
|
||||
}while(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* find value of key
|
||||
* @return NULL if not found or strdup`ed value
|
||||
*/
|
||||
char *list_find_keyval(KeyList *l, char *key){
|
||||
KeyList *list = list_find_key(l, key);
|
||||
if(!list) return NULL;
|
||||
char *rec = strdup(list->record);
|
||||
char *val = strchr(rec, '=');
|
||||
*val++ = 0;
|
||||
char *com = strchr(val, '/');
|
||||
if(com) *com = 0;
|
||||
char *retval = strdup(val);
|
||||
FREE(rec);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int getdoubleval(double *val, KeyList *list, char *key){
|
||||
char *v = list_find_keyval(list, key);
|
||||
if(!v) return 0;
|
||||
*val = strtod(v, NULL);
|
||||
FREE(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* modify key value
|
||||
* return NULL if given key is absent
|
||||
*/
|
||||
KeyList *list_modify_key(KeyList *list, char *key, char *newval, int immutable){
|
||||
char buf[FLEN_CARD];
|
||||
KeyList *rec = list_find_key(list, key);
|
||||
if(!rec) return NULL;
|
||||
if(rec->immutable > immutable) return NULL; // not modify immutable records
|
||||
rec->immutable = immutable;
|
||||
newval = strdup(newval);
|
||||
char *comnt = strchr(newval, '/');
|
||||
if(comnt){
|
||||
*(comnt++) = 0;
|
||||
}else{
|
||||
comnt = strchr(rec->record, '/');
|
||||
if(comnt) ++comnt;
|
||||
}
|
||||
if(comnt){
|
||||
snprintf(buf, FLEN_CARD, "%-8s= %-21s/%s", key, newval, comnt);
|
||||
}else{
|
||||
snprintf(buf, FLEN_CARD, "%-8s= %s", key, newval);
|
||||
}
|
||||
FREE(rec->record);
|
||||
FREE(newval);
|
||||
DBG("modify record %s", buf);
|
||||
rec->record = strdup(buf);
|
||||
return rec;
|
||||
}
|
||||
|
||||
void add_fits_header(int datatype, char *keyname, void *value, char *comment){
|
||||
void _ub(char* r, void* p){snprintf(r, FLEN_CARD, "%20hhu", *(unsigned char*)p);}
|
||||
void _b(char* r, void* p){snprintf(r, FLEN_CARD, "%20hhd", *(char*)p);}
|
||||
void _us(char* r, void* p){snprintf(r, FLEN_CARD, "%20hu", *(unsigned short*)p);}
|
||||
void _ui(char* r, void* p){snprintf(r, FLEN_CARD, "%20u", *(unsigned int*)p);}
|
||||
void _ul(char* r, void* p){snprintf(r, FLEN_CARD, "%20lu", *(unsigned long*)p);}
|
||||
void _s(char* r, void* p){snprintf(r, FLEN_CARD, "%20hd", *(short*)p);}
|
||||
void _i(char* r, void* p){snprintf(r, FLEN_CARD, "%20d", *(int*)p);}
|
||||
void _l(char* r, void* p){snprintf(r, FLEN_CARD, "%20ld", *(long*)p);}
|
||||
void _ll(char* r, void* p){snprintf(r, FLEN_CARD, "%20lld", *(long long*)p);}
|
||||
void _f(char* r, void* p){snprintf(r, FLEN_CARD, "%20.8f", *(float*)p);}
|
||||
void _d(char* r, void* p){snprintf(r, FLEN_CARD, "%20.8f", *(double*)p);}
|
||||
void _fc(char* r, void* p){snprintf(r, FLEN_CARD, "(%.8f, %.8f)",
|
||||
((float*)p)[0], ((float*)p)[1]);}
|
||||
void _dc(char* r, void* p){snprintf(r, FLEN_CARD, "(%.8f, %.8f)",
|
||||
((double*)p)[0], ((double*)p)[1]);}
|
||||
void _log(char* r, void* p){snprintf(r, FLEN_CARD, "'%s'", (int*)p ? "true" : "false");}
|
||||
void _str(char* r, void* p){snprintf(r, FLEN_CARD, "'%s'", (char*)p);}
|
||||
void _unk(char* r, void* p __attribute((unused))){sprintf(r, "unknown datatype");}
|
||||
char tmp[FLEN_CARD], res[FLEN_CARD];
|
||||
void (*__)(char*, void*);
|
||||
switch(datatype){
|
||||
case TBIT:
|
||||
case TBYTE: __ = _ub; break;
|
||||
case TSBYTE: __ = _b; break;
|
||||
case TUSHORT: __ = _us; break;
|
||||
case TUINT: __ = _ui; break;
|
||||
case TULONG: __ = _ul; break;
|
||||
case TSHORT: __ = _s; break;
|
||||
case TINT: __ = _i; break;
|
||||
case TLONG: __ = _l; break;
|
||||
case TLONGLONG: __ = _ll; break;
|
||||
case TFLOAT: __ = _f; break;
|
||||
case TDOUBLE: __ = _d; break;
|
||||
case TCOMPLEX: __ = _fc; break;
|
||||
case TDBLCOMPLEX: __ = _dc; break;
|
||||
case TLOGICAL: __ = _log; break;
|
||||
case TSTRING: __ = _str; break;
|
||||
default: __ = _unk;
|
||||
}
|
||||
__(res, value);
|
||||
KeyList *rec = list_find_key(FITS_keys, keyname);
|
||||
if(rec){
|
||||
if(comment){
|
||||
if(strlen(res) < 21)
|
||||
snprintf(tmp, FLEN_CARD, "%-21s / %s", res, comment);
|
||||
else
|
||||
snprintf(tmp, FLEN_CARD, "%s / %s", res, comment);
|
||||
}else snprintf(tmp, FLEN_CARD, "%s", res);
|
||||
list_modify_key(FITS_keys, keyname, tmp, 0);
|
||||
}else{
|
||||
if(strlen(res) < 21)
|
||||
snprintf(tmp, FLEN_CARD, "%-8s= %-20s", keyname, res);
|
||||
else
|
||||
snprintf(tmp, FLEN_CARD, "%-8s=%s", keyname, res);
|
||||
snprintf(res, FLEN_CARD, "%s / %s", tmp, comment);
|
||||
list_add_record(&FITS_keys, res, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* free list memory & set it to NULL
|
||||
*/
|
||||
void list_free(KeyList **list){
|
||||
KeyList *node = *list, *next;
|
||||
if(!list || !*list) return;
|
||||
do{
|
||||
next = node->next;
|
||||
FREE(node->record);
|
||||
free(node);
|
||||
node = next;
|
||||
}while(node);
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
void free_fits_list(){ list_free(&FITS_keys); }
|
||||
/*
|
||||
void list_print(KeyList *list){
|
||||
while(list){
|
||||
printf("%s\n", list->record);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
void show_list(){
|
||||
list_print(FITS_keys);
|
||||
}
|
||||
*/
|
||||
|
||||
void write_list(fitsfile *fp){
|
||||
if(FITS_keys){ // there's keys
|
||||
KeyList *records = FITS_keys;
|
||||
while(records){
|
||||
char *rec = records->record;
|
||||
records = records->next;
|
||||
if(strncmp(rec, "SIMPLE", 6) == 0 || strncmp(rec, "EXTEND", 6) == 0) // key "file does conform ..."
|
||||
continue;
|
||||
// comment of obligatory key in FITS head
|
||||
else if(strncmp(rec, "COMMENT FITS", 14) == 0 || strncmp(rec, "COMMENT and Astrophysics", 26) == 0)
|
||||
continue;
|
||||
else if(strncmp(rec, "NAXIS", 5) == 0 || strncmp(rec, "BITPIX", 6) == 0) // NAXIS, NAXISxxx, BITPIX
|
||||
continue;
|
||||
if(!test_headers){
|
||||
int status = 0;
|
||||
fits_write_record(fp, rec, &status);
|
||||
if(status) fits_report_error(stderr, status);
|
||||
}else
|
||||
printf("%s\n", rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user tell some information about WCS and add it into headers
|
||||
*/
|
||||
void check_wcs(){
|
||||
double cd = -5e5, crot = -5e5, rot0 = -5e5;
|
||||
char buf[FLEN_CARD];
|
||||
// first correct scale: user value SCALE will fix parameter imscale
|
||||
if(imscale < 0.) getdoubleval(&imscale, FITS_keys, "SCALE");
|
||||
if(imscale < 0.){
|
||||
imscale = 180.*3600./M_PI / TELFOCUS / 1000000. * sqrt(pixX*pixY); // default system value
|
||||
}
|
||||
snprintf(buf, FLEN_CARD, "%.4f x %.4f", imscale * hbin, imscale * vbin);
|
||||
WRITEKEY(TSTRING, "IMSCALE", buf, "image scale (''/Pix x ''/Pix)");
|
||||
|
||||
int cnt = getdoubleval(&crval1, FITS_keys, "CRVAL1");
|
||||
cnt += getdoubleval(&crval2, FITS_keys, "CRVAL1");
|
||||
cnt += getdoubleval(&crpix1, FITS_keys, "CRPIX1");
|
||||
cnt += getdoubleval(&crpix2, FITS_keys, "CRPIX2");
|
||||
cnt += getdoubleval(&cd, FITS_keys, "CD1_1");
|
||||
cnt += getdoubleval(&crot, FITS_keys, "CROTA2");
|
||||
cnt += getdoubleval(&rot0, FITS_keys, "ROT0");
|
||||
DBG("cnt = %d", cnt);
|
||||
if(!cnt) return;
|
||||
int wcs = 2;
|
||||
WRITEKEY(TINT, "WCSAXIS", &wcs, "Number of WCS axes");
|
||||
WRITEKEY(TSTRING, "CTYPE1", "RA---TAN", "RA-Gnomic projection");
|
||||
WRITEKEY(TSTRING, "CUNIT1", "deg", "RA units - degrees");
|
||||
WRITEKEY(TSTRING, "CTYPE2", "DEC---TAN", "Decl-Gnomic projection");
|
||||
WRITEKEY(TSTRING, "CUNIT2", "deg", "Decl units - degrees");
|
||||
// CRVAL1 = / RA of reference pixel
|
||||
if(crval1 > -4e-5)
|
||||
WRITEKEY(TDOUBLE, "CRVAL1", &crval1, "RA of reference pixel");
|
||||
else crval1 = 0;
|
||||
// CRVAL2 = / Decl of reference pixel
|
||||
if(crval2 > -4e-5)
|
||||
WRITEKEY(TDOUBLE, "CRVAL2", &crval2, "Decl of reference pixel");
|
||||
else crval2 = 0;
|
||||
//CRPIX1 = / X reference pixel
|
||||
if(crpix1 > -4e-5)
|
||||
WRITEKEY(TDOUBLE, "CRPIX1", &crpix1, "X reference pixel");
|
||||
else crpix1 = 0;
|
||||
//CRPIX2 = / Y reference pixel
|
||||
if(crpix2 > -4e-5)
|
||||
WRITEKEY(TDOUBLE, "CRPIX2", &crpix2, "Y reference pixel");
|
||||
else crpix2 = 0;
|
||||
cnt = 0;
|
||||
if(cd > -4e5){
|
||||
++cnt;
|
||||
WRITEKEY(TDOUBLE, "CD1_1", &cd, "rotation matrix coefficient [1,1]");
|
||||
CD[0][0] = cd;
|
||||
}
|
||||
if(getdoubleval(&cd, FITS_keys, "CD1_2")){
|
||||
++cnt;
|
||||
WRITEKEY(TDOUBLE, "CD1_2", &cd, "rotation matrix coefficient [1,2]");
|
||||
CD[0][1] = cd;
|
||||
}
|
||||
if(getdoubleval(&cd, FITS_keys, "CD2_1")){
|
||||
++cnt;
|
||||
WRITEKEY(TDOUBLE, "CD2_1", &cd, "rotation matrix coefficient [2,1]");
|
||||
CD[1][0] = cd;
|
||||
}
|
||||
if(getdoubleval(&cd, FITS_keys, "CD2_2")){
|
||||
++cnt;
|
||||
WRITEKEY(TDOUBLE, "CD2_2", &cd, "rotation matrix coefficient [2,2]");
|
||||
CD[1][1] = cd;
|
||||
}
|
||||
if(cnt == 4) return;
|
||||
// no coefficients - use CROTA & CDELT
|
||||
cnt = 0;
|
||||
if(crot > -4e5){
|
||||
++cnt;
|
||||
DBG("crot: %g", crot);
|
||||
WRITEKEY(TDOUBLE, "CROTA2", &crot, "North rotation angle");
|
||||
}
|
||||
if(getdoubleval(&crot, FITS_keys, "CDELT1")){
|
||||
++cnt;
|
||||
WRITEKEY(TDOUBLE, "CDELT1", &crot, "X axis scale");
|
||||
getdoubleval(&crot, FITS_keys, "CDELT2");
|
||||
WRITEKEY(TDOUBLE, "CDELT2", &crot, "Y axis scale"); // use CDELT1 if user omits CDELT2
|
||||
}
|
||||
if(cnt == 2) return;
|
||||
// still no coefficients - try to calculate CDx_x by user data
|
||||
double parangle, rotangle;
|
||||
if(rot0 < -4e5) return; // no values
|
||||
if(!getdoubleval(¶ngle, FITS_keys, "PARANGLE")) return;
|
||||
if(!getdoubleval(&rotangle, FITS_keys, "VAL_P")) return;
|
||||
double s, c, scx = imscale / 3600. * hbin, scy = imscale / 3600. * vbin;
|
||||
if(rot0 < 0){ // left-handed
|
||||
crot = (-rot0 + parangle - rotangle)*M_PI/180;
|
||||
DBG("crot = %g", crot*180/M_PI);
|
||||
sincos(crot, &s, &c);
|
||||
CD[0][0] = -scx * c; CD[0][1] = scy * s;
|
||||
CD[1][0] = scx * s; CD[1][1] = scy * c;
|
||||
}else{ // right-handed
|
||||
crot = (rot0 - parangle + rotangle)*M_PI/180;
|
||||
sincos(crot, &s, &c);
|
||||
CD[0][0] = scx * c; CD[0][1] = -scy * s;
|
||||
CD[1][0] = scx * s; CD[1][1] = scy * c;
|
||||
}
|
||||
WRITEKEY(TDOUBLE, "CD1_1", &CD[0][0], "rotation matrix coefficient [1,1]");
|
||||
WRITEKEY(TDOUBLE, "CD1_2", &CD[0][1], "rotation matrix coefficient [1,2]");
|
||||
WRITEKEY(TDOUBLE, "CD2_1", &CD[1][0], "rotation matrix coefficient [2,1]");
|
||||
WRITEKEY(TDOUBLE, "CD2_2", &CD[1][1], "rotation matrix coefficient [2,2]");
|
||||
}
|
||||
52
defhdrs.h
Normal file
52
defhdrs.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* defhdrs.h
|
||||
*
|
||||
* Copyright 2016 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef __DEFHDRS_H__
|
||||
#define __DEFHDRS_H__
|
||||
|
||||
extern double crval1, crval2, crpix1, crpix2, CD[2][2]; // global coefficients for WCS
|
||||
|
||||
typedef struct klist_{
|
||||
char *record;
|
||||
int immutable; // not modify record if old value of `immutable` > new value
|
||||
struct klist_ *next;
|
||||
struct klist_ *last;
|
||||
} KeyList;
|
||||
|
||||
void list_free(KeyList **list);
|
||||
void free_fits_list();
|
||||
KeyList *list_add_record(KeyList **list, char *rec, int immutable);
|
||||
KeyList *list_find_key(KeyList *list, char *key);
|
||||
KeyList *list_modify_key(KeyList *list, char *key, char *newval, int immutable);
|
||||
KeyList *list_get_end(KeyList *list);
|
||||
/*
|
||||
void list_print(KeyList *list);
|
||||
void show_list();
|
||||
*/
|
||||
void add_fits_header(int datatype, char *keyname, void *value, char *comment);
|
||||
|
||||
void write_list(fitsfile *fp);
|
||||
void get_defhdrs(char *fname);
|
||||
void add_morehdrs(int argc, char **argv);
|
||||
|
||||
void check_wcs();
|
||||
|
||||
#endif // __DEFHDRS_H__
|
||||
13
macros.c
13
macros.c
@ -172,15 +172,16 @@ mmapbuf *My_mmap(char *filename){
|
||||
char *ptr;
|
||||
size_t Mlen;
|
||||
struct stat statbuf;
|
||||
if(!filename) ERRX(_("No filename given!"));
|
||||
DBG("Try to mmap %s", filename);
|
||||
if(!filename) return NULL;
|
||||
if((fd = open(filename, O_RDONLY)) < 0)
|
||||
ERR(_("Can't open %s for reading"), filename);
|
||||
return NULL;
|
||||
if(fstat (fd, &statbuf) < 0)
|
||||
ERR(_("Can't stat %s"), filename);
|
||||
return NULL;
|
||||
Mlen = statbuf.st_size;
|
||||
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
|
||||
ERR(_("Mmap error for input"));
|
||||
if(close(fd)) ERR(_("Can't close mmap'ed file"));
|
||||
return NULL;
|
||||
if(close(fd)) return NULL;
|
||||
mmapbuf *ret = MALLOC(mmapbuf, 1);
|
||||
ret->data = ptr;
|
||||
ret->len = Mlen;
|
||||
@ -189,7 +190,7 @@ mmapbuf *My_mmap(char *filename){
|
||||
|
||||
void My_munmap(mmapbuf *b){
|
||||
if(munmap(b->data, b->len))
|
||||
ERR(_("Can't munmap"));
|
||||
WARN(_("Can't munmap"));
|
||||
FREE(b);
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
|
||||
#include "defhdrs.h"
|
||||
#include "usage.h"
|
||||
#include "camtools.h"
|
||||
#ifdef USE_BTA
|
||||
@ -44,7 +45,7 @@
|
||||
|
||||
#define TMBUFSIZ 40 // time string buffer length
|
||||
|
||||
char *pidfilename = "/tmp/takepic.pid"; // pidfile
|
||||
char *pidfilename = "/tmp/apogee_control.pid"; // pidfile
|
||||
|
||||
char tm_buf[TMBUFSIZ]; // time string buffer
|
||||
|
||||
@ -692,6 +693,7 @@ returning:
|
||||
restore_signals();
|
||||
DBG("free buffers & close files");
|
||||
free(buf);
|
||||
free_fits_list();
|
||||
if(f_tlog) fclose(f_tlog);
|
||||
if(f_statlog) fclose(f_statlog);
|
||||
#ifdef IMAGEVIEW
|
||||
|
||||
50
takepic.h
50
takepic.h
@ -21,7 +21,9 @@
|
||||
#pragma once
|
||||
#ifndef __TAKEPIC_H__
|
||||
#define __TAKEPIC_H__
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 501
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
@ -56,40 +58,24 @@
|
||||
* SAO longitude 41 26 29.175
|
||||
* SAO latitude 43 39 12.7
|
||||
* SAO altitude 2070
|
||||
* BTA focal ratio 24.024 m
|
||||
*/
|
||||
#ifndef TELLAT
|
||||
#define TELLAT 43.6535278
|
||||
#define TELLAT (43.6535278)
|
||||
#endif
|
||||
#ifndef TELLONG
|
||||
#define TELLONG 41.44143375
|
||||
#define TELLONG (41.44143375)
|
||||
#endif
|
||||
#ifndef TELALT
|
||||
#define TELALT 2070.0
|
||||
#define TELALT (2070.0)
|
||||
#endif
|
||||
#ifndef TELFOCUS
|
||||
#define TELFOCUS (24.024)
|
||||
#endif
|
||||
// filename for default headers (in ~)
|
||||
#ifndef DEFCONF
|
||||
#define DEFCONF "apogee_hdrs.fits"
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define _(String) gettext(String)
|
||||
#define gettext_noop(String) String
|
||||
#define N_(String) gettext_noop(String)
|
||||
// ÒÅÖÉÍ ÏÔÌÁÄËÉ, -DEBUG
|
||||
#ifdef EBUG
|
||||
#define RED "\033[1;32;41m"
|
||||
#define GREEN "\033[5;30;42m"
|
||||
#define OLDCOLOR "\033[0;0;0m"
|
||||
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
|
||||
#define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n");} while(0)
|
||||
#define ERR(...) DBG(__VA_ARGS__)
|
||||
#else
|
||||
#define FNAME() do{}while(0)
|
||||
#define DBG(...) do{}while(0)
|
||||
#define ERR(...) do{fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n");} while(0)
|
||||
#endif //EBUG
|
||||
|
||||
*/
|
||||
|
||||
extern int test_headers;
|
||||
|
||||
extern const char *__progname;
|
||||
@ -98,14 +84,4 @@ extern const char *__progname;
|
||||
printf(format, ## args); \
|
||||
printf("\n");}while(0)
|
||||
|
||||
/*
|
||||
#define warnc(c, format, args...) \
|
||||
warnx(format ": %s", ## args, strerror(c))
|
||||
long r;
|
||||
#define TRYFUNC(f, ...) \
|
||||
do{ if((r = f(__VA_ARGS__))) \
|
||||
warnc(-r, #f "() failed"); \
|
||||
}while(0)
|
||||
*/
|
||||
|
||||
#endif // __TAKEPIC_H__
|
||||
|
||||
56
usage.c
56
usage.c
@ -21,6 +21,7 @@
|
||||
|
||||
#include "usage.h"
|
||||
#include "macros.h"
|
||||
#include "defhdrs.h"
|
||||
|
||||
Apn_Filter Tturret = Apn_Filter_FW50_7S; // turrer type
|
||||
int
|
||||
@ -43,6 +44,7 @@ char
|
||||
,*author = NULL // author of program
|
||||
,*subnet = NULL // subnet for ethernet camera discovery
|
||||
,*cammsgid = NULL // MSG-ID of camera
|
||||
,*defhdr_filename = NULL // name of file with default headers
|
||||
;
|
||||
int
|
||||
exptime = -1 // exposition time (in ms), -1 means no exposition
|
||||
@ -65,7 +67,11 @@ int
|
||||
,flipY = 0 // flip image around Y axe (horizontal flip)
|
||||
,histry = 0 // write history at expositions
|
||||
;
|
||||
double temperature = -25.; // setpoint of temperature
|
||||
double
|
||||
temperature = -25. // setpoint of temperature
|
||||
,imscale = -1. // image scale (''/pix) given by user
|
||||
;
|
||||
|
||||
|
||||
int shutter = 1; // object frame == 1, dark frame == 0
|
||||
|
||||
@ -125,31 +131,37 @@ void usage(char *fmt, ...){
|
||||
}
|
||||
va_end(ap);
|
||||
// "éÓÐÏÌØÚÏ×ÁÎÉÅ:\t%s [ÏÐÃÉÉ] [ÐÒÅÆÉËÓ ×ÙÈÏÄÎÙÈ ÆÁÊÌÏ×]\n"
|
||||
printf(_("Usage:\t%s [options] [output files prefix]\n"),
|
||||
printf(_("Usage:\t%s [options] [output files prefix] [additional headers]\n"),
|
||||
__progname);
|
||||
// "\tïÐÃÉÉ:\n"
|
||||
printf(_("\tOptions:\n"));
|
||||
printf("\t-A,\t--author=author\t\t%s\n",
|
||||
// "Á×ÔÏÒ ÐÒÏÇÒÁÍÍÙ"
|
||||
_("program author"));
|
||||
printf("\t-b,\t--defhdr=filename\t%s\n",
|
||||
// "ÉÍÑ ÆÁÊÌÁ Ó ÚÁÇÏÌÏ×ËÁÍÉ ÐÏ ÕÍÏÌÞÁÎÉÀ"
|
||||
_("file with default headers"));
|
||||
printf("\t-c,\t--cooler-off\t\t%s\n",
|
||||
// "ÏÔËÌÀÞÉÔØ ÈÏÌÏÄÉÌØÎÉË"
|
||||
_("Set cooler off"));
|
||||
_("set cooler off"));
|
||||
printf("\t-C,\t--imscale\t\t%s\n",
|
||||
// "ÍÁÓÛÔÁÂ ÉÚÏÂÒÁÖÅÎÉÑ ÂÅÚ ÂÉÎÎÉÎÇÁ"
|
||||
_("image scale without binning"));
|
||||
printf("\t-d,\t--dark\t\t\t%s\n",
|
||||
// "ÎÅ ÏÔËÒÙ×ÁÔØ ÚÁÔ×ÏÒ ÐÒÉ ÜËÓÐÏÚÉÃÉÉ (\"ÔÅÍÎÏ×ÙÅ\")"
|
||||
_("not open shutter when exposing (\"dark frames\")"));
|
||||
printf("\t-D,\t--display-image\t\t%s\n",
|
||||
// "ïÔÏÂÒÁÚÉÔØ ÎÁ ÜËÒÁÎÅ ÐÏÌÕÞÅÎÎÏÅ ÉÚÏÂÒÁÖÅÎÉÅ"
|
||||
_("Display last image"));
|
||||
_("display last image"));
|
||||
printf("\t-E,\t--ether-subnet\t\t%s\n",
|
||||
// "ðÏÄÓÅÔØ ÄÌÑ ÐÏÉÓËÁ ethernet-ËÁÍÅÒÙ"
|
||||
_("Subnet fot ethernet camera discovery"));
|
||||
_("subnet fot ethernet camera discovery"));
|
||||
printf("\t-f,\t--no-flash\t\t%s\n",
|
||||
// "ÎÅ ÚÁÓ×ÅÞÉ×ÁÔØ ÍÁÔÒÉÃÕ ÐÅÒÅÄ ÜËÓÐÏÚÉÃÉÅÊ"
|
||||
_("Don't flash CCD chip before expose"));
|
||||
_("don't flash CCD chip before expose"));
|
||||
printf("\t-F,\t--fan-speed=F\t\t%s\n",
|
||||
// "õÓÔÁÎÏ×ÉÔØ ÓËÏÒÏÓÔØ ×ÅÎÔÉÌÑÔÏÒÏ× × F (0..3)"
|
||||
_("Set fan speed to F (0..3)"));
|
||||
_("set fan speed to F (0..3)"));
|
||||
printf("\t-g,\t--wheel-get\t\t%s\n",
|
||||
// ÐÏÌÕÞÉÔØ Ó×ÅÄÅÎÉÑ Ï ÔÕÒÅÌÉ
|
||||
_("get turret's parameters"));
|
||||
@ -265,7 +277,7 @@ void usage(char *fmt, ...){
|
||||
void parse_args(int argc, char **argv){
|
||||
FNAME();
|
||||
int i;
|
||||
char short_options[] = "A:cdDE:fF:gG:H:h:I:i:LlM:N:n:O:o:P:p:Rr:SsTt:v:Ww:x:X:Y:";
|
||||
char short_options[] = "A:b:cC:dDE:fF:gG:H:h:I:i:LlM:N:n:O:o:P:p:Rr:SsTt:v:Ww:x:X:Y:";
|
||||
struct option long_options[] = {
|
||||
/* { name, has_arg, flag, val }, ÇÄÅ:
|
||||
* name - name of long parameter
|
||||
@ -276,10 +288,12 @@ void parse_args(int argc, char **argv){
|
||||
* !!! last string - for zeros !!!
|
||||
*/
|
||||
{"author", 1, 0, 'A'},
|
||||
{"defhdr", 1, 0, 'b'},
|
||||
{"cooler-off", 0, 0, 'c'},
|
||||
{"imscale", 1, 0, 'C'},
|
||||
{"dark", 0, 0, 'd'},
|
||||
{"display-image",0, 0, 'D'},
|
||||
{"--ether-subnet",1,0, 'E'},
|
||||
{"ether-subnet",1, 0, 'E'},
|
||||
{"no-flash", 0, 0, 'f'},
|
||||
{"fan-speed", 1, 0, 'F'},
|
||||
{"wheel-get", 0, 0, 'g'},
|
||||
@ -337,6 +351,9 @@ void parse_args(int argc, char **argv){
|
||||
// "á×ÔÏÒ ÐÒÏÇÒÁÍÍÙ: %s"
|
||||
info(_("Program author: %s"), author);
|
||||
break;
|
||||
case 'b':
|
||||
defhdr_filename = strdup(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
only_turret = FALSE;
|
||||
set_T = TRUE;
|
||||
@ -344,6 +361,13 @@ void parse_args(int argc, char **argv){
|
||||
info(_("Set cooler off"));
|
||||
cooler_off = TRUE;
|
||||
break;
|
||||
case 'C':
|
||||
imscale = atof(optarg);
|
||||
if(imscale < 0.){
|
||||
// "IMSCALE ÄÏÌÖÎÏ ÂÙÔØ ÂÏÌØÛÅ ÎÕÌÑ"
|
||||
usage(_("IMSCALE should be greater than zero"));
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
shutter = 0;
|
||||
// "óßÅÍËÁ ÔÅÍÎÏ×ÙÈ"
|
||||
@ -427,7 +451,7 @@ void parse_args(int argc, char **argv){
|
||||
break;
|
||||
case 'M':
|
||||
cammsgid = strdup(optarg);
|
||||
info("MSG_ID: %s", cammsgid);
|
||||
info("CAMMSGID: %s", cammsgid);
|
||||
break;
|
||||
case 'N':
|
||||
only_turret = FALSE;
|
||||
@ -559,16 +583,18 @@ void parse_args(int argc, char **argv){
|
||||
if(argc == 0){
|
||||
save_image = FALSE;
|
||||
}
|
||||
else{
|
||||
else if(!strchr(argv[0], '=') && !strchr(argv[0], ' ')){ // argv[0] is a filename
|
||||
outfile = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if(argc > 0){
|
||||
// "éÇÎÏÒÉÒÕÀ ÁÒÇÕÍÅÎÔ[Ù]:\n"
|
||||
printf(_("Ignore argument[s]:\n"));
|
||||
get_defhdrs(defhdr_filename);
|
||||
if(argc > 0){ // additional headers
|
||||
// "äÏÐÏÌÎÉÔÅÌØÎÙÅ ÚÁÇÏÌÏ×ËÉ:\n"
|
||||
info(_("Additional headers"));
|
||||
for (i = 0; i < argc; i++)
|
||||
warnx("%s ", argv[i]);
|
||||
info("%s ", argv[i]);
|
||||
}
|
||||
add_morehdrs(argc, argv);
|
||||
if(Shtr != -1) only_turret = FALSE;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user