From c01fc88b312c3e377b593e6764aa0c3efe423479 Mon Sep 17 00:00:00 2001 From: karpov-sv Date: Fri, 21 Sep 2018 13:12:10 +0200 Subject: [PATCH 1/3] Quoted strings support in 'exe' script command argument. Now it is possible to pass it a command with command line parameters, which will be correctly passed to the executable. Parameters in turn may also contain quoted strings, if you use proper quote type (as both ' and " quotations are supported). --- lib/rts2/connfork.cpp | 58 ++++++++++++++++++++++++++++++++++++--- lib/rts2script/script.cpp | 21 ++++++++++---- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/lib/rts2/connfork.cpp b/lib/rts2/connfork.cpp index ff49847ff..0845c874f 100644 --- a/lib/rts2/connfork.cpp +++ b/lib/rts2/connfork.cpp @@ -1,4 +1,4 @@ -/* +/* * Forking connection handling. * Copyright (C) 2003-2007 Petr Kubanek * @@ -35,8 +35,58 @@ ConnFork::ConnFork (rts2core::Block *_master, const char *_exe, bool _fillConnEn else sockwrite = -1; - exePath = new char[strlen (_exe) + 1]; - strcpy (exePath, _exe); + // Parse command string into executable proper and arguments + char *pos = (char *)_exe; + bool finished = false; + int count = 0; + + while (!finished) + { + char *start = pos; // Start of token + char endChar = 0; + + while (isspace(*pos) && *pos) + { + pos++; + start++; + } + + if (*pos == '"' || *pos == '\'') + { + // Quoted string started + endChar = *pos; + pos++; + start++; + } + + while (((endChar == 0 && !isspace(*pos)) || + (endChar && *pos != endChar)) && *pos) + pos++; + + if (!*pos) + finished = true; + else + { + *pos = '\0'; + pos++; + } + + if (pos > start) + { + // Non-empty token + if (count == 0) + { + exePath = new char[pos - start]; + strcpy (exePath, start); + } + else + { + addArg (start); + } + } + + count ++; + } connDebug = false; @@ -79,7 +129,7 @@ int ConnFork::writeToProcess (const char *msg) logStream (MESSAGE_DEBUG) << "wrote to process " << getExePath () << ":" << completeMessage.substr (0, ret) << sendLog; } setInput (completeMessage.substr (ret)); - return 0; + return 0; } int ConnFork::writeToProcessInt (int msg) diff --git a/lib/rts2script/script.cpp b/lib/rts2script/script.cpp index 1e132e58f..9addb57a6 100644 --- a/lib/rts2script/script.cpp +++ b/lib/rts2script/script.cpp @@ -65,10 +65,21 @@ bool Script::isNext (const char *element) char *Script::nextElement () { char *elementStart; + char endChar = 0; + while (isspace (*cmdBufTop)) cmdBufTop++; + + if (*cmdBufTop == '"' || *cmdBufTop == '\'') + { + // Quoted string started, we will select until matching end character; + endChar = *cmdBufTop; + cmdBufTop++; + } + elementStart = cmdBufTop; - while (!isspace (*cmdBufTop) && *cmdBufTop) + while (((endChar == 0 && !isspace (*cmdBufTop)) || + (endChar && *cmdBufTop != endChar)) && *cmdBufTop) cmdBufTop++; if (*cmdBufTop) { @@ -238,14 +249,14 @@ int Script::setTarget (const char *cam_name, Rts2Target * target) target->getPosition (&target_pos); strcpy (defaultDevice, cam_name); - + // set device specific values Configuration *config = Configuration::instance (); config->getFloat (cam_name, "readout_time", fullReadoutTime, fullReadoutTime); config->getFloat (cam_name, "filter_movement", filterMovement, filterMovement); config->getFloat ("observatory", "telescope_settle_time", telescopeSettleTime, telescopeSettleTime); config->getFloat ("observatory", "telescope_speed", telescopeSpeed, telescopeSpeed); - + commentNumber = 1; wholeScript = std::string (""); @@ -802,7 +813,7 @@ rts2operands::Operand * Script::parseOperand (Rts2Target *target, rts2operands:: { cmp = rts2operands::CMP_GREAT; } - else + else { throw ParsingError ("In conditions, only == is allowed"); } @@ -998,7 +1009,7 @@ double rts2script::getMaximalScriptDuration (Rts2Target *tar, rts2db::CamList &c script.setTarget (cam->c_str (), tar); double d = script.getExpectedDuration (tel, runnum); if (d > md) - md = d; + md = d; } return md; } From 7e10dd468b6a646299c424d5f64515f30ab1ed6c Mon Sep 17 00:00:00 2001 From: karpov-sv Date: Fri, 21 Sep 2018 14:45:19 +0200 Subject: [PATCH 2/3] Mention latest 'exe' command change in the manual --- man/rts2.script.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/man/rts2.script.txt b/man/rts2.script.txt index a7a46024b..58496faf1 100644 --- a/man/rts2.script.txt +++ b/man/rts2.script.txt @@ -27,12 +27,14 @@ cmd {command}[({arg{,arg2..}})]:: can be specified in round bracket, separated with comma, without any space between command and ending bracket. -exe {executable filename}:: +exe {executable}:: Execute external script. The script communicates with executor through standard input and outputs - both normal and error output. For documentation of the protocol, as well as available Python class for handling of this communication, - please see bellow. + please see bellow. The executable may be either a filename or a + quoted string containing filename and command-line parameters to + be passed to it. SEQUENCE {filter} {repeat} {exposure_time}:: Performs exposure sequence. First set a filter, described as @@ -77,7 +79,7 @@ I {exposure_time}:: offsets,..) must be coma "," separated and enclosed in round brackets "(", ")". This is valid syntax for increase of the telescope offset by 10 degrees in RA and 5 degrees in DEC: - + * T0.OFFS+=(10,5) {device name}.!{value name}operation{new value}:: @@ -240,7 +242,7 @@ exposure:: others current settings will be used. When exposure is finished, controlling script receives notification - on standard input with *exposure_end* string. + on standard input with *exposure_end* string. When the image is written to disk, controlling script receives image name on standard input, preceeded by *image* string. Script is responsible to @@ -279,7 +281,7 @@ rename {image name} {expression}:: echo exposure read exposure_end # is notified of exposure end read image imagename # $image will hold "image" string -echo rename $imagename /foo/bar/%f # renames acquired image to /foo/bar/{standard image pattern} +echo rename $imagename /foo/bar/%f # renames acquired image to /foo/bar/{standard image pattern} read new_name # reads new image name to $new_name ``` @@ -357,7 +359,7 @@ value {value name} {operator} {operand1 [operand2..]}:: ``` bash echo value exposure += 1 -echo value WINDOW = 0 0 10 10 +echo value WINDOW = 0 0 10 10 ``` device_by_type {device_type}:: @@ -424,7 +426,7 @@ waitidle {device name} {timeout}:: This function is equvivalent to calling *S* command, compare status and return 1 if device properly reached idle, 0 if it timeouts. - +w C {device name} {command..}:: Executes an arbitary command on device. Please see device drivers source code for allowed commands - they are called from commandAuthorize call. @@ -655,7 +657,7 @@ focpos-=50 for 10 { E 5 focpos+=10 } This script test how various SPL_MODE affect resulting image. Sequence of 1, 5 and 10 seconds exposures is taken, then SPL_MODE variable is increased by 1. - + ``` for 3 { E 1 E 5 E 10 SPL_MODE+=1 } ``` @@ -721,4 +723,3 @@ AUTHOR ------ Petr Kubanek - From a9876e444e488086c289a839721ef9634b927286 Mon Sep 17 00:00:00 2001 From: karpov-sv Date: Sat, 22 Sep 2018 22:56:03 +0200 Subject: [PATCH 3/3] Better defocusing simulation (ring-shaped profile). Expose some parameters of stellar field simulation (Moffat beta, slope of intensity distribution, defocusing scale) as writable variables. --- src/camd/dummy.cpp | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/camd/dummy.cpp b/src/camd/dummy.cpp index 96eb59456..354a74417 100644 --- a/src/camd/dummy.cpp +++ b/src/camd/dummy.cpp @@ -92,6 +92,15 @@ class Dummy:public Camera createValue (aamp, "astar_amp", "[adu] artificial star amplitude", false, RTS2_VALUE_WRITABLE); aamp->setValueInteger (200000); + createValue (moffat_beta, "moffat_beta", "artificial star Moffat beta", false, RTS2_VALUE_WRITABLE); + moffat_beta->setValueInteger (2.5); + + createValue (defocus_scale, "defoc_scale", "scale of defocusing", false, RTS2_VALUE_WRITABLE); + defocus_scale->setValueInteger (100); + + createValue (mag_slope, "mag_slope", "slope of brightness distribution of stars", false, RTS2_VALUE_WRITABLE); + mag_slope->setValueInteger (1); + createValue (noiseBias, "noise_bias", "[ADU] noise base level", false, RTS2_VALUE_WRITABLE); noiseBias->setValueDouble (400); @@ -323,6 +332,10 @@ class Dummy:public Camera rts2core::ValueDouble *aamp; + rts2core::ValueDouble *moffat_beta; + rts2core::ValueDouble *defocus_scale; + rts2core::ValueDouble *mag_slope; + rts2core::ValueBool *fitsTransfer; int width; @@ -596,6 +609,11 @@ void Dummy::generateImage (size_t pixelsize, int chan) } } +inline double moffat (double r, double r0, double sigma2, double beta) +{ + return pow (1 + (r - r0)*(r - r0) / sigma2, -beta); +} + template void Dummy::generateData (dt *data, size_t pixelSize) { double sx = astarX->getValueDouble () / binningHorizontal (); @@ -607,21 +625,33 @@ template void Dummy::generateData (dt *data, size_t pixelSize) sy *= sy; int focPos = getFocPos (); - double beta = 1.5; // Moffat profile beta + double beta = moffat_beta->getValueDouble (); // Moffat profile beta + double r0; // Moffat off-center parameter for defocusing + double deFocScale = defocus_scale->getValueDouble (); // Defocusing scale, focuser shift causing large effect + double magSlope = mag_slope->getValueDouble (); // Slope of brightness distribution in stellar field if (focPos != -1 && genType->getValueInteger () == 6) { // Simulate de-focusing for stellar field. // Optimal focus is at -1, to match absence of focuser - sx *= (1.0 + fabs (focPos + 1) / 100); - sy *= (1.0 + fabs (focPos + 1) / 100); + sx *= (1.0 + fabs (focPos + 1) / deFocScale); + sy *= (1.0 + fabs (focPos + 1) / deFocScale); - xmax *= fmin (3.0, (1.0 + fabs (focPos + 1) / 100)); - ymax *= fmin (3.0, (1.0 + fabs (focPos + 1) / 100)); + xmax *= fmin (3.0, (1.0 + fabs (focPos + 1) / deFocScale)); + ymax *= fmin (3.0, (1.0 + fabs (focPos + 1) / deFocScale)); - beta = fmax (1.02, 1.5 - 0.03 * fabs (focPos + 1) / 100); + beta = fmax (1.02, 2.5 - 0.03 * fabs (focPos + 1) / deFocScale); + + r0 = 0.1*xmax*fmax (0.3, 0.3*fabs (focPos + 1) / deFocScale); } + // Normalization for (ring-shaped) Moffat can't be done analytically, so ... + double moffat_norm = 0; + + for(int x = -xmax; x < xmax; x++) + for(int y = -ymax; y < ymax; y++) + moffat_norm += moffat (hypot (x, y), r0, sx, beta); + for (size_t i = 0; i < pixelSize; i++, data++) { double n; @@ -695,15 +725,12 @@ template void Dummy::generateData (dt *data, size_t pixelSize) double aax = x - (*astar_Xp)[j]; double aay = y - (*astar_Yp)[j]; - double flux = pow (1.0 + j, -1.0); // Distribution of relative fluxes + double r = hypot (aax, aay); + double flux = pow (1.0 + j, -magSlope); // Distribution of relative fluxes - if (hypot (aax, aay) < xmax) + if (r < xmax) { - aax *= aax; - aay *= aay; - - *data += flux * aamp->getValueDouble () * - (beta - 1) / M_PI / sqrt (sx) * pow (1 + (aax + aay) / sx, -beta); + *data += 3.0 * flux * aamp->getValueDouble () * moffat (r, r0, sx, beta) / moffat_norm; } } }