00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <fors_stack.h>
00033
00034 #include <fors_dfs.h>
00035 #include <fors_utils.h>
00036
00037 #include <cpl.h>
00038
00039 #include <string.h>
00040 #include <stdbool.h>
00041
00055 void fors_stack_define_parameters(cpl_parameterlist *parameters,
00056 const char *context,
00057 const char *default_method)
00058 {
00059 cpl_parameter *p;
00060 const char *full_name = NULL;
00061 const char *name;
00062
00063 name = "stack_method";
00064 full_name = cpl_sprintf("%s.%s", context, name);
00065 p = cpl_parameter_new_enum(full_name,
00066 CPL_TYPE_STRING,
00067 "Frames combination method",
00068 context,
00069 default_method, 4,
00070 "average", "median", "minmax", "ksigma");
00071 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00072 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00073 cpl_parameterlist_append(parameters, p);
00074 cpl_free((void *)full_name);
00075
00076
00077
00078 name = "minrejection";
00079 full_name = cpl_sprintf("%s.%s", context, name);
00080 p = cpl_parameter_new_value(full_name,
00081 CPL_TYPE_INT,
00082 "Number of lowest values to be rejected",
00083 context,
00084 1);
00085 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00086 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00087 cpl_parameterlist_append(parameters, p);
00088 cpl_free((void *)full_name);
00089
00090 name = "maxrejection";
00091 full_name = cpl_sprintf("%s.%s", context, name);
00092 p = cpl_parameter_new_value(full_name,
00093 CPL_TYPE_INT,
00094 "Number of highest values to be rejected",
00095 context,
00096 1);
00097 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00098 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00099 cpl_parameterlist_append(parameters, p);
00100 cpl_free((void *)full_name);
00101
00102
00103 name = "klow";
00104 full_name = cpl_sprintf("%s.%s", context, name);
00105 p = cpl_parameter_new_value(full_name,
00106 CPL_TYPE_DOUBLE,
00107 "Low threshold in ksigma method",
00108 context,
00109 3.0);
00110 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00111 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00112 cpl_parameterlist_append(parameters, p);
00113 cpl_free((void *)full_name);
00114
00115 name = "khigh";
00116 full_name = cpl_sprintf("%s.%s", context, name);
00117 p = cpl_parameter_new_value(full_name,
00118 CPL_TYPE_DOUBLE,
00119 "High threshold in ksigma method",
00120 context,
00121 3.0);
00122 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00123 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00124 cpl_parameterlist_append(parameters, p);
00125 cpl_free((void *)full_name);
00126
00127 name = "kiter";
00128 full_name = cpl_sprintf("%s.%s", context, name);
00129 p = cpl_parameter_new_value(full_name,
00130 CPL_TYPE_INT,
00131 "Max number of iterations in ksigma method",
00132 context,
00133 999);
00134 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00135 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00136 cpl_parameterlist_append(parameters, p);
00137 cpl_free((void *)full_name);
00138
00139 return;
00140 }
00141
00142 #undef cleanup
00143 #define cleanup \
00144 do { \
00145 cpl_free((void *)name); \
00146 } while (0)
00147
00156 stack_method *
00157 fors_stack_method_new(const cpl_parameterlist *parameters, const char *context)
00158 {
00159 stack_method *sm = cpl_malloc(sizeof(stack_method));
00160 const char *name = NULL;
00161
00162 cpl_msg_info(cpl_func, "Stack method parameters:");
00163
00164 cpl_msg_indent_more();
00165 name = cpl_sprintf("%s.%s", context, "stack_method");
00166 sm->method_name = dfs_get_parameter_string_const(parameters,
00167 name);
00168 cpl_free((void *)name); name = NULL;
00169 cpl_msg_indent_less();
00170
00171 assure( !cpl_error_get_code(), return NULL, NULL );
00172 assure( sm->method_name != NULL, return NULL, NULL );
00173
00174 if (strcmp(sm->method_name, "average") == 0) {
00175 sm->method = AVERAGE;
00176 }
00177 else if (strcmp(sm->method_name, "median") == 0) {
00178 sm->method = MEDIAN;
00179 }
00180 else if (strcmp(sm->method_name, "minmax") == 0) {
00181
00182
00183
00184 sm->method = MINMAX;
00185 }
00186 else if (strcmp(sm->method_name, "ksigma") == 0) {
00187 sm->method = KSIGMA;
00188 }
00189 else {
00190 assure( false, return NULL, "Unknown stack method '%s'", sm->method_name);
00191 }
00192
00193 switch (sm->method) {
00194 case AVERAGE: break;
00195 case MEDIAN: break;
00196 case MINMAX:
00197
00198 cpl_msg_indent_more();
00199 cpl_msg_indent_more();
00200 name = cpl_sprintf("%s.%s", context, "minrejection");
00201 sm->pars.minmax.min_reject = dfs_get_parameter_int_const(parameters,
00202 name);
00203 cpl_free((void *)name); name = NULL;
00204 cpl_msg_indent_less();
00205 cpl_msg_indent_less();
00206 assure( !cpl_error_get_code(), return NULL, NULL );
00207
00208 cpl_msg_indent_more();
00209 cpl_msg_indent_more();
00210 name = cpl_sprintf("%s.%s", context, "maxrejection");
00211 sm->pars.minmax.max_reject = dfs_get_parameter_int_const(parameters,
00212 name);
00213 cpl_free((void *)name); name = NULL;
00214 cpl_msg_indent_less();
00215 cpl_msg_indent_less();
00216 assure( !cpl_error_get_code(), return NULL, NULL );
00217
00218 break;
00219 case KSIGMA:
00220 cpl_msg_indent_more();
00221 cpl_msg_indent_more();
00222 name = cpl_sprintf("%s.%s", context, "klow");
00223 sm->pars.ksigma.klow = dfs_get_parameter_double_const(parameters,
00224 name);
00225 cpl_free((void *)name); name = NULL;
00226 cpl_msg_indent_less();
00227 cpl_msg_indent_less();
00228 assure( !cpl_error_get_code(), return NULL, NULL );
00229
00230 cpl_msg_indent_more();
00231 cpl_msg_indent_more();
00232 name = cpl_sprintf("%s.%s", context, "khigh");
00233 sm->pars.ksigma.khigh = dfs_get_parameter_double_const(parameters,
00234 name);
00235 cpl_free((void *)name); name = NULL;
00236 cpl_msg_indent_less();
00237 cpl_msg_indent_less();
00238 assure( !cpl_error_get_code(), return NULL, NULL );
00239
00240 cpl_msg_indent_more();
00241 cpl_msg_indent_more();
00242 name = cpl_sprintf("%s.%s", context, "kiter");
00243 sm->pars.ksigma.kiter = dfs_get_parameter_int_const(parameters,
00244 name);
00245 cpl_free((void *)name); name = NULL;
00246 cpl_msg_indent_less();
00247 cpl_msg_indent_less();
00248 assure( !cpl_error_get_code(), return NULL, NULL );
00249
00250 break;
00251 default:
00252 passure( false, return NULL );
00253 break;
00254 }
00255
00256 cleanup;
00257 return sm;
00258 }
00259
00264 void
00265 fors_stack_method_delete(stack_method **sm)
00266 {
00267 if (sm && *sm) {
00268 cpl_free(*sm); *sm = NULL;
00269 }
00270 return;
00271 }
00272
00273 #undef cleanup
00274 #define cleanup
00275
00280 static const char *fors_stack_method_get_string(const stack_method *sm)
00281 {
00282 assure( sm != NULL, return "Null", NULL );
00283
00284 return sm->method_name;
00285 }
00286
00287 #undef cleanup
00288 #define cleanup \
00289 do { \
00290 } while (0)
00291
00297 fors_image *
00298 fors_stack_const(const fors_image_list *images, const stack_method *sm)
00299 {
00300 fors_image *master = NULL;
00301
00302 assure( images != NULL, return master, NULL );
00303 assure( fors_image_list_size(images) > 0, return master,
00304 "No images to collapse");
00305
00306 cpl_msg_info(cpl_func, "Stacking images (method = %s)",
00307 fors_stack_method_get_string(sm));
00308
00309 switch (sm->method) {
00310 case AVERAGE:
00311 master = fors_image_collapse_create(images);
00312 break;
00313 case MEDIAN:
00314 master = fors_image_collapse_median_create(images);
00315 break;
00316 case MINMAX:
00317 master = fors_image_collapse_minmax_create(images,
00318 sm->pars.minmax.min_reject,
00319 sm->pars.minmax.max_reject);
00320 break;
00321 case KSIGMA:
00322
00323
00324
00325
00326 master = fors_image_collapse_ksigma_create(images,
00327 sm->pars.ksigma.klow,
00328 sm->pars.ksigma.khigh,
00329 sm->pars.ksigma.kiter);
00330 break;
00331 default:
00332 assure( false, return NULL, "Unknown stack method '%s' (%d)",
00333 fors_stack_method_get_string(sm), sm->method);
00334 break;
00335 }
00336
00337 return master;
00338 }
00339
00343 fors_image *
00344 fors_stack(fors_image_list *images, const stack_method *sm)
00345 {
00346 return fors_stack_const((const fors_image_list *)images, sm);
00347 }
00348
00349