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 assure( false, return NULL, "Unsupported stack method %s", sm->method_name);
00188 sm->method = KSIGMA;
00189 }
00190 else {
00191 assure( false, return NULL, "Unknown stack method '%s'", sm->method_name);
00192 }
00193
00194 switch (sm->method) {
00195 case AVERAGE: break;
00196 case MEDIAN: break;
00197 case MINMAX:
00198
00199 cpl_msg_indent_more();
00200 cpl_msg_indent_more();
00201 name = cpl_sprintf("%s.%s", context, "minrejection");
00202 sm->pars.minmax.min_reject = dfs_get_parameter_int_const(parameters,
00203 name);
00204 cpl_free((void *)name); name = NULL;
00205 cpl_msg_indent_less();
00206 cpl_msg_indent_less();
00207 assure( !cpl_error_get_code(), return NULL, NULL );
00208
00209 cpl_msg_indent_more();
00210 cpl_msg_indent_more();
00211 name = cpl_sprintf("%s.%s", context, "maxrejection");
00212 sm->pars.minmax.max_reject = dfs_get_parameter_int_const(parameters,
00213 name);
00214 cpl_free((void *)name); name = NULL;
00215 cpl_msg_indent_less();
00216 cpl_msg_indent_less();
00217 assure( !cpl_error_get_code(), return NULL, NULL );
00218
00219 break;
00220 case KSIGMA:
00221 cpl_msg_indent_more();
00222 cpl_msg_indent_more();
00223 name = cpl_sprintf("%s.%s", context, "klow");
00224 sm->pars.ksigma.klow = dfs_get_parameter_double_const(parameters,
00225 name);
00226 cpl_free((void *)name); name = NULL;
00227 cpl_msg_indent_less();
00228 cpl_msg_indent_less();
00229 assure( !cpl_error_get_code(), return NULL, NULL );
00230
00231 cpl_msg_indent_more();
00232 cpl_msg_indent_more();
00233 name = cpl_sprintf("%s.%s", context, "khigh");
00234 sm->pars.ksigma.khigh = dfs_get_parameter_double_const(parameters,
00235 name);
00236 cpl_free((void *)name); name = NULL;
00237 cpl_msg_indent_less();
00238 cpl_msg_indent_less();
00239 assure( !cpl_error_get_code(), return NULL, NULL );
00240
00241 cpl_msg_indent_more();
00242 cpl_msg_indent_more();
00243 name = cpl_sprintf("%s.%s", context, "kiter");
00244 sm->pars.ksigma.kiter = dfs_get_parameter_int_const(parameters,
00245 name);
00246 cpl_free((void *)name); name = NULL;
00247 cpl_msg_indent_less();
00248 cpl_msg_indent_less();
00249 assure( !cpl_error_get_code(), return NULL, NULL );
00250
00251 break;
00252 default:
00253 passure( false, return NULL );
00254 break;
00255 }
00256
00257 cleanup;
00258 return sm;
00259 }
00260
00265 void
00266 fors_stack_method_delete(stack_method **sm)
00267 {
00268 if (sm && *sm) {
00269 cpl_free(*sm); *sm = NULL;
00270 }
00271 return;
00272 }
00273
00274 #undef cleanup
00275 #define cleanup
00276
00281 static const char *fors_stack_method_get_string(const stack_method *sm)
00282 {
00283 assure( sm != NULL, return "Null", NULL );
00284
00285 return sm->method_name;
00286 }
00287
00288 #undef cleanup
00289 #define cleanup \
00290 do { \
00291 } while (0)
00292
00298 fors_image *
00299 fors_stack_const(const fors_image_list *images, const stack_method *sm)
00300 {
00301 fors_image *master = NULL;
00302
00303 assure( images != NULL, return master, NULL );
00304 assure( fors_image_list_size(images) > 0, return master,
00305 "No images to collapse");
00306
00307 cpl_msg_info(cpl_func, "Stacking images (method = %s)",
00308 fors_stack_method_get_string(sm));
00309
00310 switch (sm->method) {
00311 case AVERAGE:
00312 master = fors_image_collapse_create(images);
00313 break;
00314 case MEDIAN:
00315 master = fors_image_collapse_median_create(images);
00316 break;
00317 case MINMAX:
00318
00319
00320
00321
00322
00323
00324 master = fors_image_collapse_minmax_create(images,
00325 sm->pars.minmax.min_reject,
00326 sm->pars.minmax.max_reject);
00327 break;
00328 case KSIGMA:
00329 assure( false, return NULL, "Unsupported stack method %s",
00330 fors_stack_method_get_string(sm));
00331 break;
00332 default:
00333 assure( false, return NULL, "Unknown stack method '%s' (%d)",
00334 fors_stack_method_get_string(sm), sm->method);
00335 break;
00336 }
00337
00338 return master;
00339 }
00340
00344 fors_image *
00345 fors_stack(fors_image_list *images, const stack_method *sm)
00346 {
00347 return fors_stack_const((const fors_image_list *)images, sm);
00348 }
00349
00350