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, "mean") == 0) {
00178 sm->method = MEAN;
00179 }
00180 else if (strcmp(sm->method_name, "wmean") == 0) {
00181 sm->method = WMEAN;
00182 }
00183 else if (strcmp(sm->method_name, "median") == 0) {
00184 sm->method = MEDIAN;
00185 }
00186 else if (strcmp(sm->method_name, "minmax") == 0) {
00187
00188
00189
00190 sm->method = MINMAX;
00191 }
00192 else if (strcmp(sm->method_name, "ksigma") == 0) {
00193 sm->method = KSIGMA;
00194 }
00195 else {
00196 assure( false, return NULL, "Unknown stack method '%s'", sm->method_name);
00197 }
00198
00199 switch (sm->method) {
00200 case AVERAGE: break;
00201 case MEAN: break;
00202 case WMEAN: break;
00203 case MEDIAN: break;
00204 case MINMAX:
00205
00206 cpl_msg_indent_more();
00207 cpl_msg_indent_more();
00208 name = cpl_sprintf("%s.%s", context, "minrejection");
00209 sm->pars.minmax.min_reject = dfs_get_parameter_int_const(parameters,
00210 name);
00211 cpl_free((void *)name); name = NULL;
00212 cpl_msg_indent_less();
00213 cpl_msg_indent_less();
00214 assure( !cpl_error_get_code(), return NULL, NULL );
00215
00216 cpl_msg_indent_more();
00217 cpl_msg_indent_more();
00218 name = cpl_sprintf("%s.%s", context, "maxrejection");
00219 sm->pars.minmax.max_reject = dfs_get_parameter_int_const(parameters,
00220 name);
00221 cpl_free((void *)name); name = NULL;
00222 cpl_msg_indent_less();
00223 cpl_msg_indent_less();
00224 assure( !cpl_error_get_code(), return NULL, NULL );
00225
00226 break;
00227 case KSIGMA:
00228 cpl_msg_indent_more();
00229 cpl_msg_indent_more();
00230 name = cpl_sprintf("%s.%s", context, "klow");
00231 sm->pars.ksigma.klow = dfs_get_parameter_double_const(parameters,
00232 name);
00233 cpl_free((void *)name); name = NULL;
00234 cpl_msg_indent_less();
00235 cpl_msg_indent_less();
00236 assure( !cpl_error_get_code(), return NULL, NULL );
00237
00238 cpl_msg_indent_more();
00239 cpl_msg_indent_more();
00240 name = cpl_sprintf("%s.%s", context, "khigh");
00241 sm->pars.ksigma.khigh = dfs_get_parameter_double_const(parameters,
00242 name);
00243 cpl_free((void *)name); name = NULL;
00244 cpl_msg_indent_less();
00245 cpl_msg_indent_less();
00246 assure( !cpl_error_get_code(), return NULL, NULL );
00247
00248 cpl_msg_indent_more();
00249 cpl_msg_indent_more();
00250 name = cpl_sprintf("%s.%s", context, "kiter");
00251 sm->pars.ksigma.kiter = dfs_get_parameter_int_const(parameters,
00252 name);
00253 cpl_free((void *)name); name = NULL;
00254 cpl_msg_indent_less();
00255 cpl_msg_indent_less();
00256 assure( !cpl_error_get_code(), return NULL, NULL );
00257
00258 break;
00259 default:
00260 passure( false, return NULL );
00261 break;
00262 }
00263
00264 cleanup;
00265 return sm;
00266 }
00267
00272 void
00273 fors_stack_method_delete(stack_method **sm)
00274 {
00275 if (sm && *sm) {
00276 cpl_free(*sm); *sm = NULL;
00277 }
00278 return;
00279 }
00280
00281 #undef cleanup
00282 #define cleanup
00283
00288 const char *fors_stack_method_get_string(const stack_method *sm)
00289 {
00290 assure( sm != NULL, return "Null", NULL );
00291
00292 return sm->method_name;
00293 }
00294
00295 #undef cleanup
00296 #define cleanup \
00297 do { \
00298 } while (0)
00299
00305 fors_image *
00306 fors_stack_const(const fors_image_list *images, const stack_method *sm)
00307 {
00308 fors_image *master = NULL;
00309
00310 assure( images != NULL, return master, NULL );
00311 assure( fors_image_list_size(images) > 0, return master,
00312 "No images to collapse");
00313
00314 cpl_msg_info(cpl_func, "Stacking images (method = %s)",
00315 fors_stack_method_get_string(sm));
00316
00317 switch (sm->method) {
00318 case AVERAGE:
00319 master = fors_image_collapse_create(images);
00320 break;
00321 case MEDIAN:
00322 master = fors_image_collapse_median_create(images);
00323 break;
00324 case MINMAX:
00325 master = fors_image_collapse_minmax_create(images,
00326 sm->pars.minmax.min_reject,
00327 sm->pars.minmax.max_reject);
00328 break;
00329 case KSIGMA:
00330
00331
00332
00333
00334 master = fors_image_collapse_ksigma_create(images,
00335 sm->pars.ksigma.klow,
00336 sm->pars.ksigma.khigh,
00337 sm->pars.ksigma.kiter);
00338 break;
00339 default:
00340 assure( false, return NULL, "Unknown stack method '%s' (%d)",
00341 fors_stack_method_get_string(sm), sm->method);
00342 break;
00343 }
00344
00345 return master;
00346 }
00347
00351 fors_image *
00352 fors_stack(fors_image_list *images, const stack_method *sm)
00353 {
00354 return fors_stack_const((const fors_image_list *)images, sm);
00355 }
00356
00357