mirror of
https://github.com/eddyem/apogee_control.git
synced 2025-12-06 02:35:16 +03:00
350 lines
10 KiB
C
350 lines
10 KiB
C
/*
|
|
* bta_print.c
|
|
*
|
|
* Copyright 2015 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.
|
|
*/
|
|
|
|
/* Print some BTA NewACS data (or write to file)
|
|
* Usage:
|
|
* bta_print [time_step] [file_name]
|
|
* Where:
|
|
* time_step - writing period in sec., >=1.0
|
|
* <1.0 - once and exit (default)
|
|
* file_name - name of file to write to,
|
|
* "-" - stdout (default)
|
|
*/
|
|
#include "bta_shdata.h"
|
|
#include "takepic.h"
|
|
#include "camtools.h"
|
|
#include "bta_print.h"
|
|
#include "macros.h"
|
|
#include <slamac.h> // SLA macros
|
|
|
|
extern void sla_amp(double*, double*, double*, double*, double*, double*);
|
|
|
|
void slaamp(double ra, double da, double date, double eq, double *rm, double *dm ){
|
|
double r = ra, d = da, mjd = date, equi = eq;
|
|
sla_amp(&r, &d, &mjd, &equi, rm, dm);
|
|
}
|
|
const double jd0 = 2400000.5; // JD for MJD==0
|
|
/**
|
|
* convert apparent coordinates (nowadays) to mean (JD2000)
|
|
* appRA, appDecl in seconds
|
|
* r, d in seconds
|
|
*/
|
|
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);
|
|
double mjd = JDate - jd0;
|
|
slaamp(appRA, appDecl, mjd, 2000.0, &ra, &dec);
|
|
ra *= DR2S;
|
|
dec *= DR2AS;
|
|
if(r) *r = ra;
|
|
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)
|
|
#define WRITEHIST(fp) \
|
|
do{ if(test_headers){printf("HISTORY: %s\n", comment);}else{ \
|
|
int status = 0; \
|
|
fits_write_history(fp, comment, &status); \
|
|
if(status) fits_report_error(stderr, status);\
|
|
}}while(0)
|
|
|
|
int shm_ready = FALSE; // BTA shm_get
|
|
|
|
// calculate airmass
|
|
extern void calc_airmass(
|
|
// in
|
|
double daynum, // Day number from beginning of year, 0 = midnight Jan 1
|
|
double relhumid,// Relative humidity in percent
|
|
double p0, // local pressure in mmHg
|
|
double t0, // temperature in kelvins
|
|
double z, // zenith distance in degr
|
|
// out
|
|
double *am, // AIRMASS
|
|
double *acd, // column density
|
|
double *wcd, // water vapor column density
|
|
double *wam // water vapor airmass
|
|
);
|
|
|
|
static char buf[1024];
|
|
char *time_asc(double t){
|
|
int h, m;
|
|
double s;
|
|
h = (int)(t/3600.);
|
|
m = (int)((t - (double)h*3600.)/60.);
|
|
s = t - (double)h*3600. - (double)m*60.;
|
|
h %= 24;
|
|
if(s>59) s=59;
|
|
sprintf(buf, "%dh:%02dm:%04.1fs", h,m,s);
|
|
return buf;
|
|
}
|
|
|
|
char *angle_asc(double a){
|
|
char s;
|
|
int d, min;
|
|
double sec;
|
|
if (a >= 0.)
|
|
s = '+';
|
|
else{
|
|
s = '-'; a = -a;
|
|
}
|
|
d = (int)(a/3600.);
|
|
min = (int)((a - (double)d*3600.)/60.);
|
|
sec = a - (double)d*3600. - (double)min*60.;
|
|
d %= 360;
|
|
if(sec>59.9) sec=59.9;
|
|
sprintf(buf, "%c%d:%02d':%04.1f''", s,d,min,sec);
|
|
return buf;
|
|
}
|
|
|
|
typedef struct{
|
|
double JD; // JDate
|
|
double Azimuth; // val_A
|
|
double Zenith; // val_Z
|
|
double P2; // val_P
|
|
double Wind; // val_Wnd
|
|
//double Tmir; //
|
|
} BTA_PARAMS;
|
|
|
|
typedef struct _BTA_Que{
|
|
BTA_PARAMS *data;
|
|
struct _BTA_Que *next;
|
|
struct _BTA_Que *last;
|
|
} BTA_Queue;
|
|
|
|
void write_bta_queue(fitsfile *fp);
|
|
BTA_Queue *bta_queue = NULL;
|
|
|
|
void write_bta_data(fitsfile *fp){
|
|
char *val;
|
|
double dtmp;
|
|
time_t t_now = time(NULL);
|
|
struct tm *tm_ut, *tm_loc;
|
|
tm_ut = gmtime(&t_now);
|
|
tm_loc = localtime(&t_now);
|
|
if(!shm_ready){
|
|
if(!get_shm_block(&sdat, ClientSide)) return;
|
|
else shm_ready = TRUE;
|
|
}
|
|
if(!check_shm_block(&sdat)) return;
|
|
/*
|
|
* Observatory parameters
|
|
*/
|
|
// TELESCOP / Telescope name
|
|
CMNT("Telescope name");
|
|
FTKEY(TSTRING, "TELESCOP", "BTA 6m telescope");
|
|
// ORIGIN / organization responsible for the data
|
|
CMNT("organization responsible for the data");
|
|
FTKEY(TSTRING, "ORIGIN", "SAO RAS");
|
|
// OBSERVAT / Observatory name
|
|
CMNT("Observatory name");
|
|
FTKEY(TSTRING, "OBSERVAT", "Special Astrophysical Observatory, Russia");
|
|
// placement
|
|
CMNT("Observatory altitude, m");
|
|
dtmp = TELALT; FTKEY(TDOUBLE, "ALT_OBS", &dtmp);
|
|
CMNT("Observatory longitude, degr");
|
|
dtmp = TELLONG; FTKEY(TDOUBLE, "LONG_OBS", &dtmp);
|
|
CMNT("Observatory lattitude, degr");
|
|
dtmp = TELLAT; FTKEY(TDOUBLE, "LAT_OBS", &dtmp);
|
|
/*
|
|
* Times
|
|
*/
|
|
dtmp = S_time-EE_time;
|
|
// ST / sidereal time (hh:mm:ss.ms)
|
|
CMNT("Sidereal time: %s", time_asc(dtmp));
|
|
FTKEY(TDOUBLE, "ST", &dtmp);
|
|
// UT / universal time (hh:mm:ss.ms)
|
|
CMNT("Universal time: %s", time_asc(M_time));
|
|
FTKEY(TDOUBLE, "UT", &M_time);
|
|
CMNT("Julian date");
|
|
FTKEY(TDOUBLE, "JD", &JDate);
|
|
/*
|
|
* Telescope parameters
|
|
*/
|
|
switch(Tel_Focus){
|
|
case Nasmyth1 : val = "Nasmyth1"; break;
|
|
case Nasmyth2 : val = "Nasmyth2"; break;
|
|
default : val = "Prime"; break;
|
|
}
|
|
// FOCUS / Focus of telescope (mm)
|
|
CMNT("Observation focus");
|
|
FTKEY(TSTRING, "FOCUS", val);
|
|
// VAL_F / focus value
|
|
CMNT("Focus value (mm)");
|
|
FTKEY(TDOUBLE, "VAL_F", &val_F);
|
|
// EQUINOX / Epoch of RA & DEC
|
|
dtmp = 1900 + tm_ut->tm_year + tm_ut->tm_yday / 365.2422;
|
|
CMNT("Epoch of RA & DEC");
|
|
FTKEY(TDOUBLE, "EQUINOX", &dtmp);
|
|
CMNT("Current object R.A.: %s", time_asc(CurAlpha));
|
|
// RA / Right ascention (H.H)
|
|
dtmp = CurAlpha / 3600.; FTKEY(TDOUBLE, "RA", &dtmp);
|
|
// DEC / Declination (D.D)
|
|
CMNT("Current object Decl.: %s", angle_asc(CurDelta));
|
|
dtmp = CurDelta / 3600.; FTKEY(TDOUBLE, "DEC", &dtmp);
|
|
CMNT("Source R.A.: %s", time_asc(SrcAlpha));
|
|
dtmp = SrcAlpha / 3600.; FTKEY(TDOUBLE, "S_RA", &dtmp);
|
|
CMNT("Source Decl.: %s", angle_asc(SrcDelta));
|
|
dtmp = SrcDelta / 3600.; FTKEY(TDOUBLE, "S_DEC", &dtmp);
|
|
CMNT("Telescope R.A: %s", time_asc(val_Alp));
|
|
dtmp = val_Alp / 3600.; FTKEY(TDOUBLE, "T_RA", &dtmp);
|
|
CMNT("Telescope Decl.: %s", angle_asc(val_Del));
|
|
dtmp = val_Del / 3600.; FTKEY(TDOUBLE, "T_DEC", &dtmp);
|
|
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);
|
|
CMNT("Decl. given by user (for J2000): %s", angle_asc(d2000));
|
|
FTKEY(TDOUBLE, "INPDEC0", &d2000);
|
|
calc_mean(CurAlpha, CurDelta, &a2000, &d2000);
|
|
CMNT("Current R.A. (for J2000): %s", time_asc(a2000));
|
|
FTKEY(TDOUBLE, "CURRA0", &a2000);
|
|
CMNT("Current Decl. (for J2000): %s", angle_asc(d2000));
|
|
FTKEY(TDOUBLE, "CURDEC0", &d2000);
|
|
// 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);
|
|
|
|
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));
|
|
dtmp = val_P / 3600.; FTKEY(TDOUBLE, "VAL_P", &dtmp);
|
|
|
|
CMNT("Dome A: %s", angle_asc(val_D));
|
|
dtmp = val_D / 3600.; FTKEY(TDOUBLE, "VAL_D", &dtmp);
|
|
// OUTTEMP / Out temperature (C)
|
|
CMNT("Outern temperature, degC");
|
|
FTKEY(TDOUBLE, "OUTTEMP", &val_T1);
|
|
// DOMETEMP / Dome temperature (C)
|
|
CMNT("In-dome temperature, degC");
|
|
FTKEY(TDOUBLE, "DOMETEMP", &val_T2);
|
|
// MIRRTEMP / Mirror temperature (C)
|
|
CMNT("Mirror temperature, degC");
|
|
FTKEY(TDOUBLE, "MIRRTEMP", &val_T3);
|
|
// PRESSURE / Pressure (mmHg)
|
|
CMNT("Pressure, mmHg");
|
|
FTKEY(TDOUBLE, "PRESSURE", &val_B);
|
|
// WIND / Wind speed (m/s)
|
|
CMNT("Wind speed, m/s");
|
|
FTKEY(TDOUBLE, "WIND", &val_Wnd);
|
|
CMNT("Humidity, %%");
|
|
FTKEY(TDOUBLE, "HUM", &val_Hmd);
|
|
/*
|
|
* Airmass calculation
|
|
* by Reed D. Meyer
|
|
*/
|
|
double am, acd, wcd, wam;
|
|
dtmp = tm_loc->tm_yday; // current day of year
|
|
calc_airmass(dtmp, val_Hmd, val_B, val_T1+273.15, val_Z/3600., &am, &acd, &wcd, &wam);
|
|
//printf("am=%g, acd=%g, wcd=%g, wam=%g\n", am,acd,wcd,wam);
|
|
CMNT("Air mass by Reed D. Meyer");
|
|
FTKEY(TDOUBLE, "AIRMASS", &am);
|
|
CMNT("Water vapour air mass by Reed D. Meyer");
|
|
FTKEY(TDOUBLE, "WVAM", &wam);
|
|
CMNT("Atm. column density by Reed D. Meyer, g/cm^2");
|
|
FTKEY(TDOUBLE, "ATMDENS", &acd);
|
|
CMNT("WV column density by Reed D. Meyer, g/cm^2");
|
|
FTKEY(TDOUBLE, "WVDENS", &wcd);
|
|
// if bta_queue nonempty write its data to HISTORY section
|
|
if(bta_queue) write_bta_queue(fp);
|
|
}
|
|
|
|
// get parameters
|
|
int get_params(BTA_PARAMS *P){
|
|
if(!shm_ready){
|
|
if(!get_shm_block(&sdat, ClientSide)) return -1;
|
|
else shm_ready = TRUE;
|
|
}
|
|
if(!check_shm_block(&sdat)) return -1;
|
|
P->JD = JDate;
|
|
P->Azimuth = val_A;
|
|
P->Zenith = val_Z;
|
|
P->P2 = val_P;
|
|
P->Wind = val_Wnd;
|
|
return 0;
|
|
}
|
|
|
|
int push_param(){
|
|
DBG("Try to push parameter");
|
|
if(!shm_ready){
|
|
if(!get_shm_block(&sdat, ClientSide)) return -4;
|
|
else shm_ready = TRUE;
|
|
}
|
|
if(!check_shm_block(&sdat)) return -3;
|
|
BTA_PARAMS *Par = calloc(1, sizeof(BTA_PARAMS));
|
|
BTA_Queue *qcur = calloc(1, sizeof(BTA_Queue));
|
|
if(!Par || !qcur){
|
|
free(Par);
|
|
free(qcur);
|
|
return -2; // malloc error
|
|
}
|
|
if(get_params(Par)){
|
|
free(Par);
|
|
free(qcur);
|
|
return -1; // error getting parameters
|
|
}
|
|
qcur->data = Par;
|
|
qcur->next = NULL;
|
|
qcur->last = qcur;
|
|
if(!bta_queue){ // initialisation of que
|
|
bta_queue = qcur;
|
|
}else{ // variable que initialized previously
|
|
bta_queue->last->next = qcur;
|
|
bta_queue->last = qcur;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void write_bta_queue(fitsfile *fp){
|
|
#define HISTRY(...) do{CMNT(__VA_ARGS__); WRITEHIST(fp);}while(0)
|
|
if(!bta_queue) return;
|
|
BTA_Queue *cur = bta_queue, *ptr;
|
|
BTA_PARAMS *P;
|
|
int i = 0;
|
|
do{
|
|
P = cur->data;
|
|
ptr = cur;
|
|
HISTRY("Data record # %d", i);
|
|
HISTRY("JD = %.8f / Julian date", P->JD);
|
|
HISTRY("T_AZ = %.8f / Telescope Az: %s", P->Azimuth / 3600., angle_asc(P->Azimuth));
|
|
HISTRY("T_ZD = %.8f / Telescope ZD: %s", P->Zenith / 3600., angle_asc(P->Zenith));
|
|
HISTRY("T_P2 = %.8f / Current P: %s", P->P2 / 3600., angle_asc(P->P2));
|
|
HISTRY("WIND = %.2f / Wind speed, m/s", P->Wind);
|
|
i++;
|
|
cur = cur->next;
|
|
free(P);
|
|
free(ptr);
|
|
bta_queue = cur;
|
|
}while(cur);
|
|
}
|