diff --git a/Astar_cameras/artifical_star.c b/Astar_cameras/artifical_star.c index ee3cb99..c70ba69 100644 --- a/Astar_cameras/artifical_star.c +++ b/Astar_cameras/artifical_star.c @@ -36,6 +36,14 @@ extern cc_Wheel wheel; // array size #define ARRAYH (1050) #define ARRAYW (1050) +// amount of stars +#define MAX_STARS (32) +#ifndef _STR +#define _STR(x) #x +#endif +#ifndef STR +#define STR(x) _STR(x) +#endif static const int filtermax = 5; static const float focmaxpos = 10.; @@ -45,23 +53,29 @@ static float camtemp = -30., exptime = 0.1; static cc_capture_status capstat = CAPTURE_NO; static double texpstart = 0.; static uint8_t bitpix = 16; // bit depth: 8 or 16 +static il_Image *imagemask = NULL; // mask typedef struct{ - int x0; int y0; // center of star field in array coordinates + int Nstars; // amount of stars + int x0, y0; // center of field in array coordinates + int 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 scale; // CCD scale: arcsec/pix - double mag; // star magnitude: 0m is 0xffff/0xff ADUs per second + double mag[MAX_STARS]; // star magnitude: 0m is 0xffff/0xff ADUs per second double vX; // X axe drift speed (arcsec/s) double vY; // Y -//- double fluct; // stars position fluctuations (arcsec/sec) + double noiselambda; // poisson noice lambda value } settings_t; static settings_t settings = { + .Nstars = 1, .x0 = 512, .y0 = 512, - .fwhm = 1.5, .beta = 1., .scale = 0.03, .mag = 0., - .fluct = 0.5 + .xs = {0}, .ys = {0}, + .fwhm = 1.5, .beta = 1., .scale = 0.03, .mag = {0.}, + .fluct = 1., .noiselambda = 3., }; // min/max for parameters static const double fwhmmin = 0.1, fwhmmax = 10., scalemin = 0.001, scalemax = 3600., magmin = -30., magmax = 30.; @@ -73,6 +87,7 @@ 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 int templ_wh = 0; // template width/height in pixels +static double noicelambdamin = 1.; /** * @brief test_template - test star template and recalculate new if need @@ -108,53 +123,71 @@ static void test_template(){ * 5. Add background and noice. */ +#define GEN(ima, type, maxval) \ + register int w = ima->w;\ + int h = ima->h, tw2 = templ_wh/2, X0,Y0, X1,Y1, x0,y0;\ + for(int N = 0; N < settings.Nstars; ++N){\ + int Xstar = Xc + settings.xs[N] - camera.geometry.xoff, Ystar = Yc + settings.ys[N] - camera.geometry.yoff;\ + if(Xstar - tw2 < 0){\ + X0 = tw2 - Xstar + 1;\ + x0 = 0;\ + }else{\ + X0 = 1; x0 = Xstar - tw2;\ + }\ + if(Ystar - tw2 < 0){\ + Y0 = tw2 - Ystar + 1;\ + y0 = 0;\ + }else{\ + Y0 = 1; y0 = Ystar - tw2;\ + }\ + if(Xstar + tw2 > w-1){\ + /* templ_wh - (Xc + tw2 - (w - 1))*/ \ + X1 = templ_wh - Xstar - tw2 + w - 1; \ + }else X1 = templ_wh;\ + if(Ystar + tw2 > h-1){\ + Y1 = templ_wh - Ystar - tw2 + h - 1;\ + }else Y1 = templ_wh;\ + double mul = exptime * maxval * pow(10, -0.4*settings.mag[N]); /* multiplier due to "star" magnitude */ \ + /* check if the 'star' out of frame */ \ + DBG("X0=%d, X1=%d, Y0=%d, Y1=%d, x0=%d, y0=%d, mul=%g", X0,X1,Y0,Y1,x0,y0, mul);\ + if(X0 < 0 || X0 > templ_wh - 1 || Y0 < 0 || Y0 > templ_wh - 1) continue;\ + if(x0 < 0 || x0 > w-1 || y0 < 0 || y0 > h-1) continue;\ + if(X1 < 0 || X1 > templ_wh || Y1 < 0 || Y1 > templ_wh) continue;\ + if(X0 > X1 || Y0 > Y1) return;\ + OMP_FOR()\ + for(int y = Y0; y < Y1; ++y){\ + type *out = &((type*)ima->data)[(y-Y0+y0)*w + x0];\ + double *in = &((double*)star->data)[y*templ_wh + X0];\ + for(int x = X0; x < X1; ++x, ++in, ++out){\ + double val = *out + *in * mul;\ + *out = (val > maxval) ? maxval : (type)val;\ + }\ + }\ + }\ + if(imagemask){ /* apply mask */ \ + X0 = camera.geometry.xoff; Y0 = camera.geometry.yoff; \ + X1 = imagemask->width; Y1 = imagemask->height; \ + if(X1-X0 > w) X1 = X0 + w;\ + if(Y1-Y0 > h) Y1 = Y0 + h; \ + OMP_FOR()\ + for(int y = Y0; y < Y1; ++y){\ + type *out = &((type*)ima->data)[(y-Y0)*w];\ + uint8_t *in = &((uint8_t*)imagemask->data)[y*imagemask->width + X0];\ + for(int x = X0; x < X1; ++x, ++in, ++out){\ + type p = il_Poisson(settings.noiselambda); \ + /*type p = fabs(il_Normal(0., 3.)); */\ + if(*in == 0) *out = p; else *out = (*out+p > maxval) ? maxval : *out + p; \ + }\ + } \ + } + static void gen16(cc_IMG *ima){ - static int n = 0; - register int w = ima->w; - int h = ima->h, tw2 = templ_wh/2, X0,Y0, X1,Y1, x0,y0; - if(Xc - tw2 < 0){ - X0 = tw2 - Xc; - x0 = 0; - }else{ - X0 = 0; x0 = Xc - tw2; - } - if(Yc - tw2 < 0){ - Y0 = tw2 - Yc; - y0 = 0; - }else{ - Y0 = 0; y0 = Yc - tw2; - } - if(Xc + tw2 > w-1){ - X1 = templ_wh - Xc + tw2 - w - 1; // templ_wh - (Xc + tw2 - (w - 1)) - }else X1 = templ_wh; - if(Yc + tw2 > h-1){ - Y1 = templ_wh - Yc + tw2 - h - 1; - }else Y1 = templ_wh; - double mul = exptime * 0xffff * pow(10, -0.4*settings.mag); // multiplier due to "star" magnitude - // check if the 'star' out of frame - DBG("X0=%d, X1=%d, Y0=%d, Y1=%d, x0=%d, y0=%d, mul=%g", X0,X1,Y0,Y1,x0,y0, mul); - if(X0 < 0 || X0 > templ_wh - 1 || Y0 < 0 || Y0 > templ_wh - 1) return; - if(x0 < 0 || x0 > w-1 || y0 < 0 || y0 > h-1) return; - if(X1 < 0 || X1 > templ_wh || Y1 < 0 || Y1 > templ_wh) return; - if(X0 > X1 || Y0 > Y1) return; - OMP_FOR() - for(int y = Y0; y < Y1; ++y){ - uint16_t *out = &((uint16_t*)ima->data)[(y+y0)*w + x0]; - double *in = &((double*)star->data)[y*templ_wh + X0]; - for(int x = X0; x < X1; ++x, ++in, ++out){ - double val = *in * mul; - *out = (val > 0xffff) ? 0xffff : (uint16_t)val; - } - } - ++n; + GEN(ima, uint16_t, 0xffff); } -/* + static void gen8(cc_IMG *ima){ - static int n = 0; - OMP_FOR() - ; - ++n; -}*/ + GEN(ima, uint8_t, 0xff); +} static int campoll(cc_capture_status *st, float *remain){ if(capstat != CAPTURE_PROCESS){ @@ -214,7 +247,7 @@ static int camcapt(cc_IMG *ima){ ima->bytelen = ima->w*ima->h*cc_getNbytes(ima); bzero(ima->data, ima->h*ima->w*cc_getNbytes(ima)); if(bitpix == 16) gen16(ima); - // else gen8(ima); + else gen8(ima); DBG("Time of capture: %g", dtime() - t0); return TRUE; } @@ -377,17 +410,90 @@ static int whlgetnam(char *n, int l){ return TRUE; } +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(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){ + 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; + } + else{ return RESULT_BADKEY;} // unreachable + settings.Nstars = (xctr < yctr) ? xctr : yctr; + DBG("Nstars=%d", settings.Nstars); + return RESULT_SILENCE; +} + +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); + double dval = atof(val); + if(strcmp(bptr, "mag") != 0) return RESULT_BADKEY; + if(dval > magmax || dval < magmin){ + snprintf(buf, 255, "%g < mag < %g", magmin, magmax); + cc_charbufaddline(ans, buf); + return RESULT_BADVAL; + } + if(magctr >= MAX_STARS){ + cc_charbufaddline(ans, "MAX: " STR(MAX_STARS) "stars"); + return RESULT_FAIL; + } + DBG("mag[%d]=%g", magctr, dval); + settings.mag[magctr++] = dval; + return RESULT_SILENCE; +} + +static cc_hresult loadmask(const char *str, cc_charbuff *ans){ + char buf[FILENAME_MAX+32], *bptr = buf; + strncpy(buf, str, FILENAME_MAX+31); + char *val = cc_get_keyval(&bptr); + if(strcmp(bptr, "mask") != 0) return RESULT_BADKEY; + if(imagemask) il_Image_free(&imagemask); + imagemask = il_Image_read(val); + char *nm = strdup (val); + cc_hresult res = RESULT_OK; + if(!imagemask){ + snprintf(buf, FILENAME_MAX, "Can't read image '%s'", nm); + res = RESULT_FAIL; + }else{ + snprintf(buf, FILENAME_MAX, "Got image '%s'; w=%d, h=%d, type=%d (impix=%d)", nm, imagemask->width, imagemask->height, imagemask->type, imagemask->pixbytes); + } + cc_charbufaddline(ans, buf); + FREE(nm); + return res; +} + // 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", setXYs, NULL, NULL, NULL, 0}, + {"y", "Y coordinate of next star", setXYs, NULL, NULL, NULL, 0}, {"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}, - {"mag", "star magnitude: 0m is 0xffff/0xff (16/8 bit) ADUs per second", NULL, (void*)&settings.mag, (void*)&magmin, (void*)&magmax, CC_PAR_DOUBLE}, + {"mag", "Next star magnitude: 0m is 0xffff/0xff (16/8 bit) ADUs per second", setmag, NULL, NULL, NULL, 0}, + {"mask", "load mask image (binary, ANDed)", loadmask, NULL, NULL, NULL, 0}, {"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}, {"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}, //{"", "", NULL, (void*)&settings., (void*)&, (void*)&, CC_PAR_DOUBLE}, CC_PARHANDLER_END }; diff --git a/ccdcapture.c b/ccdcapture.c index 5dbf298..5dd39d8 100644 --- a/ccdcapture.c +++ b/ccdcapture.c @@ -209,19 +209,19 @@ cc_hresult cc_str2hresult(const char *str){ * @param keyval (io) - pair `key = val`, return `key` * @return `val` */ -char *cc_get_keyval(char *keyval){ - DBG("Got string %s", keyval); +char *cc_get_keyval(char **keyval){ + DBG("Got string %s", *keyval); // remove starting spaces in key - while(isspace(*keyval)) ++keyval; - char *val = strchr(keyval, '='); + while(isspace(**keyval)) ++(*keyval); + char *val = strchr(*keyval, '='); if(val){ // got value: remove starting spaces in val *val++ = 0; while(isspace(*val)) ++val; } DBG("val = %s (%zd bytes)", val, (val)?strlen(val):0); // remove trailing spaces in key - char *e = keyval + strlen(keyval) - 1; // last key symbol - while(isspace(*e) && e > keyval) --e; + char *e = *keyval + strlen(*keyval) - 1; // last key symbol + while(isspace(*e) && e > *keyval) --e; e[1] = 0; // now we have key (`str`) and val (or NULL) //DBG("key=%s, val=%s", keyval, val); @@ -537,8 +537,8 @@ double cc_getAnsTmout(){return answer_timeout;} */ static cc_hresult ask4cmd(int fd, cc_strbuff *buf, const char *cmdwargs){ DBG("ask for command %s", cmdwargs); - char *key = strdup(cmdwargs); - cc_get_keyval(key); // pick out key from `cmdwargs` + char *keyptr = strdup(cmdwargs), *key = keyptr; + cc_get_keyval(&key); // pick out key from `cmdwargs` int l = strlen(key); cc_hresult ret = RESULT_FAIL; for(int i = 0; i < ntries; ++i){ @@ -579,7 +579,7 @@ static cc_hresult ask4cmd(int fd, cc_strbuff *buf, const char *cmdwargs){ } rtn: DBG("returned with `%s`", cc_hresult2str(ret)); - FREE(key); + FREE(keyptr); return ret; } @@ -605,7 +605,8 @@ cc_hresult cc_getint(int fd, cc_strbuff *cbuf, const char *cmd, int *val){ snprintf(buf, BBUFS, "%s\n", cmd); cc_hresult r = ask4cmd(fd, cbuf, buf); if(r == RESULT_OK){ - char *sv = cc_get_keyval(cbuf->string); + char *p = cbuf->string; + char *sv = cc_get_keyval(&p); if(!sv) return RESULT_FAIL; char *ep; long L = strtol(sv, &ep, 0); @@ -635,7 +636,8 @@ cc_hresult cc_getfloat(int fd, cc_strbuff *cbuf, const char *cmd, float *val){ snprintf(buf, BBUFS, "%s\n", cmd); cc_hresult r = ask4cmd(fd, cbuf, buf); if(r == RESULT_OK){ - char *sv = cc_get_keyval(cbuf->string); + char *p = cbuf->string; + char *sv = cc_get_keyval(&p); if(!sv) return RESULT_FAIL; char *ep; double d = strtod(sv, &ep); @@ -759,16 +761,16 @@ static size_t print_val(cc_partype_t t, void *val, char *buf, size_t bufl){ */ cc_hresult cc_plugin_customcmd(const char *str, cc_parhandler_t *handlers, cc_charbuff *ans){ if(!str || !handlers) return RESULT_FAIL; - char key[256]; + char key[256], *kptr = key; snprintf(key, 255, "%s", str); - char *val = cc_get_keyval(key); + char *val = cc_get_keyval(&kptr); cc_parhandler_t *phptr = handlers; cc_hresult result = RESULT_BADKEY; char buf[512]; #define ADDL(...) do{if(ans){size_t l = snprintf(bptr, L, __VA_ARGS__); bptr += l; L -= l;}}while(0) #define PRINTVAL(v) do{if(ans){size_t l = print_val(phptr->type, phptr->v, bptr, L); bptr += l; L -= l;}}while(0) while(phptr->cmd){ - if(0 == strcmp(key, phptr->cmd)){ + if(0 == strcmp(kptr, phptr->cmd)){ char *bptr = buf; size_t L = 511; result = RESULT_OK; if(phptr->checker) result = phptr->checker(str, ans); diff --git a/ccdcapture.h b/ccdcapture.h index 0cc71c3..116c79b 100644 --- a/ccdcapture.h +++ b/ccdcapture.h @@ -323,7 +323,7 @@ int cc_open_socket(int isserver, char *path, int isnet); int cc_senddata(int fd, void *data, size_t l); int cc_sendmessage(int fd, const char *msg, int l); int cc_sendstrmessage(int fd, const char *msg); -char *cc_get_keyval(char *keyval); +char *cc_get_keyval(char **keyval); cc_IMG *cc_getshm(key_t key, size_t imsize); int cc_canberead(int fd); cc_hresult cc_setint(int fd, cc_strbuff *cbuf, const char *cmd, int val); diff --git a/client.c b/client.c index 0c6054a..5fafe1c 100644 --- a/client.c +++ b/client.c @@ -81,7 +81,7 @@ static int parseans(char *ans){ } if(0 == strcmp(cc_hresult2str(RESULT_FAIL), ans)) return TRUE; if(0 == strcmp(cc_hresult2str(RESULT_OK), ans)) return TRUE; - char *val = cc_get_keyval(ans); // now `ans` is a key and `val` its value + char *val = cc_get_keyval(&ans); // now `ans` is a key and `val` its value if(0 == strcmp(CC_CMD_EXPSTATE, ans)){ expstate = atoi(val); DBG("Exposition state: %d", expstate); diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 61fb09a..4f37b79 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-15 16:32+0300\n" +"POT-Creation-Date: 2024-02-19 11:54+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/server.c b/server.c index 28afd5f..2336378 100644 --- a/server.c +++ b/server.c @@ -1274,7 +1274,7 @@ char *makeabspath(const char *path, int shouldbe){ // @return FALSE if client closed (nothing to read) static int parsestring(int fd, cc_handleritem *handlers, char *str){ if(fd < 1 || !handlers || !handlers->key || !str || !*str) return FALSE; - char *val = cc_get_keyval(str); + char *val = cc_get_keyval(&str); if(val){ DBG("RECEIVE '%s=%s'", str, val); LOGDBG("RECEIVE '%s=%s'", str, val);