some little fixes + readme update

This commit is contained in:
Edward Emelianov 2024-02-21 17:26:04 +03:00
parent 2f33d6773c
commit eb8f497b0b
5 changed files with 190 additions and 52 deletions

View File

@ -56,14 +56,17 @@ static uint8_t bitpix = 16; // bit depth: 8 or 16
static il_Image *imagemask = NULL, *imagebg; // mask & background
static char *maskfilename = NULL, *bgfilename = NULL; // filenames
// local counters of `mag`, `x` and `y` setters
static int magctr = 0, xctr = 0, yctr = 0;
typedef struct{
int Nstars; // amount of stars
int x0, y0; // center of field in array coordinates
double rotan0; // starting rotation angle
int xs[MAX_STARS], ys[MAX_STARS]; // center of star field in array coordinates
double xs[MAX_STARS], ys[MAX_STARS]; // center of star field in array coordinates
double fwhm; // stars min FWHM, arcsec
double beta; // Moffat `beta` parameter
double theta; // start theta, arcsec
//double theta; // Moffat `theta`, arcsec
double scale; // CCD scale: arcsec/pix
double mag[MAX_STARS]; // star magnitude: 0m is 0xffff/0xff ADUs per second
double vX; // X axe drift speed (arcsec/s)
@ -90,7 +93,7 @@ static int Xc = 0, Yc = 0; // current pixel coordinates of "sky" center (due to
static double Tstart = -1.; // global acquisition start
static double Xfluct = 0., Yfluct = 0.; // fluctuation additions in arcsec
static il_Image *star = NULL; // template of star 0m
static double FWHM0 = 0., scale0 = 0.; // template fwhm/scale
static double FWHM0 = 0., scale0 = 0., BETA0 = 0.; // template fwhm/scale
static int templ_wh = 0; // template width/height in pixels
static double noicelambdamin = 1.;
@ -98,19 +101,21 @@ static double noicelambdamin = 1.;
* @brief test_template - test star template and recalculate new if need
*/
static void test_template(){
if(star && FWHM0 == settings.fwhm && scale0 == settings.scale) return;
if(star && FWHM0 == settings.fwhm && scale0 == settings.scale && BETA0 == settings.beta) return;
templ_wh = (1 + 6*settings.fwhm/settings.scale); // +1 for center
FWHM0 = settings.fwhm;
scale0 = settings.scale;
BETA0 = settings.beta;
il_Image_free(&star);
DBG("MAKE STAR, wh=%d, beta=%g", templ_wh, settings.beta);
star = il_Image_star(IMTYPE_D, templ_wh, templ_wh, settings.fwhm, settings.beta);
il_Image_minmax(star);
DBG("STAR: %dx%d, max=%g, min=%g, %d bytes per pix, type %d; templ_wh=%d", star->height, star->width, star->maxval, star->minval, star->pixbytes, star->type, templ_wh);
if(!star) ERRX(_("Can't generate star template"));
//il_Image_minmax(star);
//DBG("STAR: %dx%d, max=%g, min=%g, %d bytes per pix, type %d; templ_wh=%d", star->height, star->width, star->maxval, star->minval, star->pixbytes, star->type, templ_wh);
double sum = 0., *ptr = (double*)star->data;
int l = templ_wh * templ_wh;
for(int i = 0; i < l; ++i) sum += ptr[i];
green("sum=%g\n", sum);
//green("sum=%g\n", sum);
OMP_FOR()
for(int i = 0; i < l; ++i) ptr[i] /= sum;
}
@ -281,6 +286,7 @@ static int camcapt(cc_IMG *ima){
ima->h = camera.geometry.h;
ima->bytelen = ima->w*ima->h*cc_getNbytes(ima);
bzero(ima->data, ima->h*ima->w*cc_getNbytes(ima));
if(!star) ERRX(_("No star template - die"));
if(bitpix == 16) gen16(ima);
else gen8(ima);
DBG("Time of capture: %g", dtime() - t0);
@ -446,26 +452,31 @@ static int whlgetnam(char *n, int l){
}
static cc_hresult setXYs(const char *str, cc_charbuff *ans){
static int xctr = 0, yctr = 0; // counters of X and Y (by default MAG[x] = 0)
char buf[256], *bptr = buf;
strncpy(buf, str, 255);
char *val = cc_get_keyval(&bptr);
int ival = atoi(val);
if(!val){ // getter
for(int i = 0; i < settings.Nstars; ++i){
snprintf(buf, 255, "x[%d]=%g, y[%d]=%g\n", i, settings.xs[i], i, settings.ys[i]);
cc_charbufaddline(ans, buf);
}
return RESULT_SILENCE;
}
double dval = atof(val);
if(strcmp(bptr, "x") == 0){
if(xctr >= MAX_STARS){
cc_charbufaddline(ans, "MAX: " STR(MAX_STARS) "stars");
return RESULT_FAIL;
}
DBG("x[%d]=%d", xctr, ival);
settings.xs[xctr++] = ival;
}
else if(strcmp(bptr, "y") == 0){
DBG("x[%d]=%g", xctr, dval);
settings.xs[xctr++] = dval;
} else if(strcmp(bptr, "y") == 0){
if(yctr >= MAX_STARS){
cc_charbufaddline(ans, "MAX: " STR(MAX_STARS) "stars");
return RESULT_FAIL;
}
DBG("y[%d]=%d", yctr, ival);
settings.ys[yctr++] = ival;
DBG("y[%d]=%g", yctr, dval);
settings.ys[yctr++] = dval;
}
else{ return RESULT_BADKEY;} // unreachable
settings.Nstars = (xctr < yctr) ? xctr : yctr;
@ -474,10 +485,16 @@ static cc_hresult setXYs(const char *str, cc_charbuff *ans){
}
static cc_hresult setmag(const char *str, cc_charbuff *ans){
static int magctr = 0;
char buf[256], *bptr = buf;
strncpy(buf, str, 255);
char *val = cc_get_keyval(&bptr);
if(!val){ // getter
for(int i = 0; i < settings.Nstars; ++i){
snprintf(buf, 255, "mag[%d]=%g", i, settings.mag[i]);
cc_charbufaddline(ans, buf);
}
return RESULT_SILENCE;
}
double dval = atof(val);
if(strcmp(bptr, "mag") != 0) return RESULT_BADKEY;
if(dval > magmax || dval < magmin){
@ -540,22 +557,22 @@ static cc_hresult loadbg(const char *str, cc_charbuff *ans){
// cmd, help, handler, ptr, min, max, type
static cc_parhandler_t handlers[] = {
{"xc", "x center of field in array coordinates", NULL, (void*)&settings.x0, NULL, NULL, CC_PAR_INT},
{"yc", "y center of field in array coordinates", NULL, (void*)&settings.y0, NULL, NULL, CC_PAR_INT},
{"x", "X coordinate of next star (arcsec, in field coordinate system)", setXYs, NULL, NULL, NULL, CC_PAR_INT},
{"y", "Y coordinate of next star (arcsec, in field coordinate system)", setXYs, NULL, NULL, NULL, CC_PAR_INT},
{"beta", "Moffat `beta` parameter", NULL, (void*)&settings.beta, (void*)&betamin, NULL, CC_PAR_DOUBLE},
{"bkg", "load background image", loadbg, (void*)&bgfilename, NULL, NULL, CC_PAR_STRING},
{"fluct", "stars position fluctuations (arcsec per sec)", NULL, (void*)&settings.fluct, (void*)&fluctmin, (void*)&fluctmax, CC_PAR_DOUBLE},
{"fwhm", "stars min FWHM, arcsec", NULL, (void*)&settings.fwhm, (void*)&fwhmmin, (void*)&fwhmmax, CC_PAR_DOUBLE},
{"scale", "CCD scale: arcsec/pix", NULL, (void*)&settings.scale, (void*)&scalemin, (void*)&scalemax, CC_PAR_DOUBLE},
{"lambda", "Poisson noice lambda value (>1)", NULL, (void*)&settings.noiselambda, (void*)&noicelambdamin, NULL, CC_PAR_DOUBLE},
{"mag", "Next star magnitude: 0m is 0xffff/0xff (16/8 bit) ADUs per second", setmag, NULL, (void*)&magmin, (void*)&magmax, CC_PAR_DOUBLE},
{"mask", "load mask image (binary, ANDed)", loadmask, (void*)&maskfilename, NULL, NULL, CC_PAR_STRING},
{"bkg", "load background image", loadbg, (void*)&bgfilename, NULL, NULL, CC_PAR_STRING},
{"rotangle", "Starting rotation angle (arcsec)", NULL, (void*)&settings.rotan0, (void*)&rotanmin, (void*)&rotanmax, CC_PAR_DOUBLE},
{"scale", "CCD scale: arcsec/pix", NULL, (void*)&settings.scale, (void*)&scalemin, (void*)&scalemax, CC_PAR_DOUBLE},
{"vr", "rotation speed (arcsec/s)", NULL, (void*)&settings.vR, (void*)&vrotmin, (void*)&vrotmax, CC_PAR_DOUBLE},
{"vx", "X axe drift speed (arcsec/s)", NULL, (void*)&settings.vX, (void*)&vmin, (void*)&vmax, CC_PAR_DOUBLE},
{"vy", "Y axe drift speed (arcsec/s)", NULL, (void*)&settings.vY, (void*)&vmin, (void*)&vmax, CC_PAR_DOUBLE},
{"vr", "rotation speed (arcsec/s)", NULL, (void*)&settings.vR, (void*)&vrotmin, (void*)&vrotmax, CC_PAR_DOUBLE},
{"fluct", "stars position fluctuations (arcsec per sec)", NULL, (void*)&settings.fluct, (void*)&fluctmin, (void*)&fluctmax, CC_PAR_DOUBLE},
{"beta", "Moffat `beta` parameter", NULL, (void*)&settings.beta, (void*)&betamin, NULL, CC_PAR_DOUBLE},
{"lambda", "Poisson noice lambda value (>1)", NULL, (void*)&settings.noiselambda, (void*)&noicelambdamin, NULL, CC_PAR_DOUBLE},
{"rotangle", "Starting rotation angle (arcsec)", NULL, (void*)&settings.rotan0, (void*)&rotanmin, (void*)&rotanmax, CC_PAR_DOUBLE},
{"x", "X coordinate of next star (arcsec, in field coordinate system)", setXYs, NULL, NULL, NULL, CC_PAR_DOUBLE},
{"y", "Y coordinate of next star (arcsec, in field coordinate system)", setXYs, NULL, NULL, NULL, CC_PAR_DOUBLE},
{"xc", "x center of field in array coordinates", NULL, (void*)&settings.x0, NULL, NULL, CC_PAR_INT},
{"yc", "y center of field in array coordinates", NULL, (void*)&settings.y0, NULL, NULL, CC_PAR_INT},
//{"", "", NULL, (void*)&settings., (void*)&, (void*)&, CC_PAR_DOUBLE},
CC_PARHANDLER_END
};

137
Readme.md
View File

@ -4,9 +4,17 @@ CCD/CMOS imaging server
Supports FLI cameras/focusers/wheels and cameras: ZWO, Basler, HikRobot, PointGrey, Apogee.
Allows to run as standalone application or imaging server/client.
To restart server (e.g. if hardware was off) kill it with SIGUSR1
To restart server (e.g. if hardware was off) kill it with SIGUSR1 or send command `restartTheServer`.
## Compile
The tool itself depends on [usefull_macros](https://github.com/eddyem/snippets_library) librariy.
"Artifical star" plugin depends on my [improclib](https://github.com/eddyem/improclib).
Image viewer depends on OpenGL and GLUT libraries (also depending on X11).
All other plugins (excluding "dummy camera") depends on third-party libraries. Apogee plugin also
depends on [apogee C wrapper](https://github.com/eddyem/apogee_control/tree/master/apogee_C_wrapper).
I will try later to combine all third-party libraries in this repository.
cmake options:
@ -112,11 +120,106 @@ Mouse functions:
- Wheel up - scroll up, or scroll left (with Shift), or zoom+ (with Ctrl).
- Wheel down - scroll down, or scroll right (with Shift), or zoom- (with Ctrl).
## Server
When you run the server you need at least to point:
- camera plugin (`-C libdev….so`);
- command socket: it could be local INET socket (then by default image socket will have next number),
just point `--port=port`, or UNIX socket, then point `--path=path` (for unnamed sockets use "\0" as first
path letter);
- image socket (optionally): `--imageport=port` - to have ability to transmit image to other PCs by
network INET socket (default value: 12345 if no command socket port used, or cmdport+1);
- shared memory key for fast local image transmission, `-k=key` (default value: 7777777).
To send commands to server you can use client, open `netcat` session, use my [tty_term](https://github.com/eddyem/tty_term)
or any other tools. Server have text protocol (send `help\n` to see full list):
- 8bit - run in 8 bit mode instead of 16 bit
- author - FITS 'AUTHOR' field
- brightness - camera brightness
- camdevno - camera device number
- camlist - list all connected cameras
- ccdfanspeed - fan speed of camera
- confio - camera IO configuration
- dark - don't open shutter @ exposure
- expstate - get exposition state
- exptime - exposition time
- fastspeed - fast readout speed
- filename - save file with this name, like file.fits
- filenameprefix - prefix of files, like ex (will be saved as exXXXX.fits)
- focdevno - focuser device number
- foclist - list all connected focusers
- focpos - focuser position
- format - camera frame format (X0,Y0,X1,Y1)
- gain - camera gain
- getheaders - get last file FITS headers
- hbin - horizontal binning
- headerfiles - add FITS records from these files (comma-separated list)
- help - show this help
- imheight - last image height
- imwidth - last image width
- info - connected devices state
- infty - an infinity loop taking images until there's connected clients
- instrument - FITS 'INSTRUME' field
- io - get/set camera IO
- lastfilename - path to last saved file
- maxformat - camera maximal available format
- nflushes - camera number of preflushes
- object - FITS 'OBJECT' field
- objtype - FITS 'IMAGETYP' field
- observer - FITS 'OBSERVER' field
- plugincmd - custom camera plugin command
- program - FITS 'PROG-ID' field
- restartTheServer - restart server
- rewrite - rewrite file (if give `filename`, not `filenameprefix`)
- shmemkey - get shared memory key
- shutter - camera shutter's operations
- tcold - camera chip temperature
- tremain - time (in seconds) of exposition remained
- vbin - vertical binning
- wdevno - wheel device number
- wlist - list all connected wheels
- wpos - wheel position
Send `expstate=1` to start capture. As only the frame is ready server will send `expstate=4` to all
clients connected.
When you send a command to server you will receive:
- one of answers - "OK" (all OK), "BUSY" (can't run setter because camera is busy), "FAIL" (some error
occured), "BADKEY" (wrong key name) or "BADVAL" (wrong key's value) - for procedures and setters
(instead of "OK" you will give "parameter=value" for setter if all OK);
- "parameter=value" for getters.
Command `info` equivalent to sequential commands `camlist`, `hbin`, `vbin`, `tcold`, `tbody`, `thot`,
`exptime`, `lastfilename`, `expstate` and `camflags`.
Command `getheaders` returns base FITS-header of last file.
## Client
To run client you should point `--client` and same ports' options like for server (command socket and
image SHM key or socket).
Use `--forceimsock` to forse getting image through INET socket even if run on the same PC as server.
Client have no options to connect to server on other host, so you need to make proxy with ssh or other
tool. Maybe later I will add `--host` option for these purposes (but for security you will still have
to use ssh-proxy for command socket).
Using client as pure viewer (using `--viewer` option) you can't run expositions - just can view last
files done by command from other clients. But if you will send to server `infty=1`, it will run in
infinity mode, making frame by frame while at least one client connected. To turn this off send
`infty=0`.
Without image view options (`--viewer` or `-D`) client just send given options to server and shuts down,
but you can wait until image done with option `--wait` (be careful: when reading process takes too long
time taking server in busy state, client can decide to shut down by timeout).
## Plugins custom commands
Since version 1.2.0 introduced custom camera plugin commands system. Commonly to read help just
type `-_help`. You can point as much custom commands in one commandline as you need. They can be a
procedures/flags (like `-_cmd`) or a setters/getters (like `-_key` and `-_key=value`).
To transmit these custom commands to server use `plugincmd=key[=value]`.
### Dummy camera plugin custom commands
This plugin simply emulates image aqcuisition process where images are 2-D sinusoide with given periods.
Each next frame will be shifted by one pixel.
@ -130,26 +233,34 @@ Commands:
### Artifical star plugin custom commands
This plugin lets you to emulate star field with up to 32 stars. You can shift center of field emulating
telescope correction, also you can rotate field emulating derotation.
All stars (Moffat) have the same FWHM and scale parameters. Their coordinates are given by arrays `x`
All stars (Moffat) have the same FWHM and scale parameters. Their coordinates (arcsec) are given by arrays `x`
and `y` with a hardware magnitude `mag`. You can emulate image drift and rotation. Also you can add
a little image position (full frame position) fluctuations. To emulate poisson noice just point its `lambda`
value (`lambda==1` means no noise).
Two additional commands - `mask` and `bkg` allows you to load binary mask and background.
The background image (8-bit monochrome) will be added to generated star field. After that if you
pointed an mask image it will be AND-ed with result: all non-zero pixels on mask remains the same
pixels of resulting image, but zeros will clean them emulating holes or screens.
And at last Poisson noice will be added to full frame.
Commands:
- xc = (int) - x center of field in array coordinates
- yc = (int) - y center of field in array coordinates
- x - X coordinate of next star
- y - Y coordinate of next star
- beta = (double) [0.5, inf] - Moffat `beta` parameter
- bkg = (string) - load background image
- fluct = (double) [0, 3] - stars position fluctuations (arcsec per sec)
- fwhm = (double) [0.1, 10] - stars min FWHM, arcsec
- lambda = (double) [1, inf] - Poisson noice lambda value (>1)
- mag = (double) [-30, 30] - Next star magnitude: 0m is 0xffff/0xff (16/8 bit) ADUs per second
- mask = (string) - load mask image (binary, ANDed)
- rotangle = (double) [0, 1.296e+06] - Starting rotation angle (arcsec)
- scale = (double) [0.001, 3600] - CCD scale: arcsec/pix
- mag - Next star magnitude: 0m is 0xffff/0xff (16/8 bit) ADUs per second
- mask - load mask image (binary, ANDed)
- vr = (double) [-36000, 36000] - rotation speed (arcsec/s)
- vx = (double) [-20, 20] - X axe drift speed (arcsec/s)
- vy = (double) [-20, 20] - Y axe drift speed (arcsec/s)
- vr = (double) [-36000, 36000] - rotation speed (arcsec/s)
- fluct = (double) [0, 3] - stars position fluctuations (arcsec per sec)
- beta = (double) [0.5, inf] - Moffat `beta` parameter
- lambda = (double) [1, inf] - Poisson noice lambda value (>1)
- rotangle = (double) [0, 1.296e+06] - Starting rotation angle (arcsec)
- x = (int) - X coordinate of next star (arcsec, in field coordinate system)
- y = (int) - Y coordinate of next star (arcsec, in field coordinate system)
- xc = (int) - x center of field in array coordinates
- yc = (int) - y center of field in array coordinates

View File

@ -126,6 +126,16 @@ DBG("1 msg-> %s, ans -> %s", msg, ans);
* @brief processData - process here some actions and make messages for server
*/
static void send_headers(int sock){
if(GP->plugincmd){
char **p = GP->plugincmd;
green("Send custom plugin commands\n");
while(p && *p){
printf("\t%s\n", *p);
SENDMSGW(CC_CMD_PLUGINCMD, "=%s", *p);
++p;
}
while(getans(sock, NULL));
}
if(GP->exptime > -DBL_EPSILON) SENDMSGW(CC_CMD_EXPOSITION, "=%g", GP->exptime);
DBG("infty=%d", GP->infty);
if(GP->infty > -1) SENDMSGW(CC_CMD_INFTY, "=%d", GP->infty);

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-21 11:24+0300\n"
"POT-Creation-Date: 2024-02-21 16:53+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -568,7 +568,7 @@ msgstr ""
msgid "Can't grab image"
msgstr ""
#: ccdfunc.c:793 client.c:270
#: ccdfunc.c:793 client.c:280
#, c-format
msgid "%d seconds till pause ends\n"
msgstr ""
@ -581,11 +581,11 @@ msgstr ""
msgid "No camera device"
msgstr ""
#: client.c:256
#: client.c:266
msgid "Can't make exposition"
msgstr ""
#: client.c:286
#: client.c:296
msgid "Server timeout"
msgstr ""

View File

@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-20 16:30+0300\n"
"POT-Creation-Date: 2024-02-21 16:53+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -21,7 +21,7 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
msgid "%.1f seconds till exposition ends"
msgstr "%.1f ÓÅËÕÎÄ ÄÏ ÏËÏÎÞÁÎÉÑ ÜËÓÐÏÚÉÃÉÉ"
#: ccdfunc.c:793 client.c:270
#: ccdfunc.c:793 client.c:280
#, c-format
msgid "%d seconds till pause ends\n"
msgstr "%d ÓÅËÕÎÄ ÄÏ ÏËÏÎÞÁÎÉÑ ÐÁÕÚÙ\n"
@ -134,7 +134,7 @@ msgstr "
msgid "Can't init mutex!"
msgstr "îÅ ÍÏÇÕ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÍØÀÔÅËÓ!"
#: client.c:256
#: client.c:266
msgid "Can't make exposition"
msgstr "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ ÜËÓÐÏÚÉÃÉÀ"
@ -342,7 +342,7 @@ msgstr "
msgid "Readout mode: %s"
msgstr "òÅÖÉÍ ÓÞÉÔÙ×ÁÎÉÑ: %s"
#: client.c:286
#: client.c:296
msgid "Server timeout"
msgstr "ôÁÊÍÁÕÔ ÓÅÒ×ÅÒÁ"