36 #include "visir_recipe.h"
38 #include "visir_spc_distortion.h"
39 #include "visir_cpl_compat.h"
40 #include "visir_utils.h"
50 #define RECIPE_STRING "visir_util_undistort"
57 #define cpl_plugin_get_info visir_util_undistort_get_info
59 cpl_recipe_define(visir_util_undistort, VISIR_BINARY_VERSION,
60 "Lars Lundin", PACKAGE_BUGREPORT,
"2011",
61 "Correct the distortion in spectral data",
62 "The files listed in the Set Of Frames (sof-file) "
64 "VISIR-chopnod-corrected-file.fits " VISIR_UTIL_UNDISTORT_RAW
65 "\nOptionally, a bad pixel map may be provided:\n"
66 "VISIR-bpm-file.fits " VISIR_CALIB_STATIC_MASK
"\n"
67 "\nThe product(s) will have a FITS card\n"
68 "'HIERARCH ESO PRO CATG' with a value of:\n"
69 VISIR_UTIL_UNDISTORT_PROCATG
"\n"
70 #ifdef VISIR_UTIL_UNDISTORT_AUTO_REJECT
71 #
if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 4, 0)
72 "If no bad pixel map is provided, the recipe will "
73 "automatically flag input intensities greater than or equal "
77 "The recipe default values for the transformation are only "
78 "valid for spectral data taken in Low resolution mode");
100 static cpl_error_code
101 visir_util_undistort_fill_parameterlist(cpl_parameterlist *
self)
104 const char * context = PACKAGE
"." RECIPE_STRING;
107 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
108 "bkgcorrect", CPL_TRUE, NULL, context,
109 "Cho-nod correct the data");
110 cpl_ensure_code(!err, err);
113 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
114 "xl", 117, NULL, context,
115 "Coordinate in spatial direction. "
116 "Together with yl it defines the "
117 "lower point of a rectangle containing "
118 "only skylines for the "
119 "wavelength shift detection");
120 cpl_ensure_code(!err, err);
123 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
124 "yl", 110, NULL, context,
125 "Coordinate in wavelength direction. "
127 cpl_ensure_code(!err, err);
130 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
131 "xh", 125, NULL, context,
132 "Coordinate in spatial direction. "
133 "Together with yl it defines the "
134 "higher point of a rectangle containing "
135 "only skylines for the "
136 "wavelength shift detection");
137 cpl_ensure_code(!err, err);
140 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
141 "yh", 150, NULL, context,
142 "Coordinate in wavelength direction. "
144 cpl_ensure_code(!err, err);
147 VISIR_PARAM_SPECSKEW | VISIR_PARAM_VERTARC |
149 ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
164 shift_data(
double * out,
const double * in,
size_t n,
double shift)
169 for (
size_t i = 1; i < n; i++)
170 out[i] = (in[i] - in[i - 1]) * shift + in[i];
173 out[n - 1] = in[n - 1];
174 for (
size_t i = 0; i < n - 1; i++)
175 out[i] = (in[i + 1] - in[i]) * shift + in[i];
203 get_grating_shift(
const cpl_image * a,
const cpl_image * b,
204 cpl_size xl, cpl_size yl, cpl_size xh, cpl_size yh)
206 cpl_image * aslice = cpl_image_extract(a, xl, yl, xh, yh);
207 cpl_image * bslice = cpl_image_extract(b, xl, yl, xh, yh);
208 const size_t n = yh - yl;
213 double minsum = DBL_MAX;
214 double best_shift = 0;
215 const int step = 5000;
217 const double range = 1;
220 for (
size_t i = 0; i < n; i++) {
221 va = cpl_vector_new_from_image_row(aslice, i + 1);
222 vb = cpl_vector_new_from_image_row(bslice, i + 1);
223 adata[i] = cpl_vector_get_median(va);
224 bdata[i] = cpl_vector_get_median(vb);
225 cpl_vector_delete(va);
226 cpl_vector_delete(vb);
228 va = cpl_vector_wrap(n, adata);
229 vb = cpl_vector_wrap(n, bdata);
231 cpl_vector_subtract_scalar(va, cpl_vector_get_median_const(va));
232 cpl_vector_subtract_scalar(vb, cpl_vector_get_median_const(vb));
235 cpl_vector_subtract(vb, va);
239 for (
int i = 0; i < step; i++) {
240 const double shift = (double)(i - (step / 2)) / step * range * 2;
244 shift_data(ashifted, adata, n, shift);
247 for (
size_t j = 0; j < n; j++) {
248 const double tmp = (ashifted[j] - adata[j]) - bdata[j];
258 cpl_vector_unwrap(va);
259 cpl_vector_unwrap(vb);
260 cpl_image_delete(aslice);
261 cpl_image_delete(bslice);
263 cpl_msg_info(cpl_func,
"Grating shift: %.3f", best_shift);
271 for (cpl_size i = 0; i < visir_imglist_get_size(b); i++) {
272 visir_imglist_append(a, visir_imglist_get_img(b, i),
273 visir_imglist_get_data(b, i));
275 visir_imglist_unwrap(b, NULL);
279 load_images(cpl_frame * frame,
const cpl_mask * bpm)
281 const int next = cpl_frame_get_nextensions(frame);
282 const char * filename = cpl_frame_get_filename(frame);
283 cpl_image * img = NULL;
286 for (
int iext = 0; iext < next + 1; iext++) {
287 cpl_errorstate prestate = cpl_errorstate_get();
289 img = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, iext);
291 cpl_msg_debug(cpl_func,
"No image-data in extension %d", iext);
292 cpl_errorstate_set(prestate);
297 skip_if(cpl_image_reject_from_mask(img, bpm));
298 visir_interpolate_rejected(img, NULL, NULL);
301 visir_imglist_append(res, img, NULL);
319 static cpl_error_code
320 overscan_correct(cpl_image * img)
322 const cpl_size nx = cpl_image_get_size_x(img);
323 const cpl_size ny = cpl_image_get_size_y(img);
324 for (cpl_size x = 1; x < nx + 1; x++) {
326 cpl_image * top = cpl_image_extract(img, 1, ny - 7, nx, ny);
327 cpl_image * bot = cpl_image_extract(img, 1, 7, nx, 13);
328 cpl_vector * t = cpl_vector_new_from_image_column(top, x);
329 cpl_vector * b = cpl_vector_new_from_image_column(bot, x);
330 double topmed = cpl_vector_get_median(t);
331 double botmed = cpl_vector_get_median(b);
332 for (cpl_size y = 1; y < ny / 2 + 1; y++) {
334 cpl_image_set(img, x, y, cpl_image_get(img, x, y, &d) - botmed);
336 for (cpl_size y = ny / 2 + 1; y < ny + 1; y++) {
338 cpl_image_set(img, x, y, cpl_image_get(img, x, y, &d) - topmed);
340 cpl_vector_delete(t);
341 cpl_vector_delete(b);
342 cpl_image_delete(top);
343 cpl_image_delete(bot);
346 return cpl_error_get_code();
350 static cpl_error_code
352 cpl_size xl, cpl_size yl, cpl_size xh, cpl_size yh,
353 double phi,
double ksi,
double eps,
double delta,
354 const visir_data_type dtype)
356 const cpl_size n = visir_imglist_get_size(list);
357 const cpl_size nx = cpl_image_get_size_x(visir_imglist_get_img(list, 0));
358 const cpl_size ny = cpl_image_get_size_y(visir_imglist_get_img(list, 0));
359 error_if(xh > nx || yh > ny, CPL_ERROR_ILLEGAL_INPUT,
360 "Sky region %d/%d larger than image %d/%d", (
int)xh, (
int)yh,
364 #pragma omp parallel for
366 for (cpl_size i = 0; i < n; i++) {
367 cpl_image * img = visir_imglist_get_img(list, i);
371 if (visir_data_is_drs(dtype)) {
372 double shift = get_grating_shift(base, img, xl, yl, xh, yh);
373 visir_spc_det_warp(&img, 1, 0., shift, phi, ksi, eps, delta);
376 overscan_correct(img);
381 return cpl_error_get_code();
385 static cpl_error_code
387 cpl_frameset * usedframes,
const cpl_propertylist * plist,
388 const cpl_parameterlist * parlist)
391 char * proname = cpl_sprintf(RECIPE_STRING
"_%03d" CPL_DFS_FITS, j++);
395 VISIR_UTIL_UNDISTORT_PROCATG,
397 visir_pipe_id, proname));
398 for (cpl_size i = 0; i < visir_imglist_get_size(imgs); i++) {
399 cpl_image * img = visir_imglist_get_img(imgs, i);
400 cpl_image_save(img, proname, CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_EXTEND);
406 return cpl_error_get_code();
410 comp_expno(cpl_frame * a, cpl_frame * b)
412 const char * fna = cpl_frame_get_filename(a);
413 const char * fnb = cpl_frame_get_filename(b);
414 cpl_propertylist * alist = cpl_propertylist_load(fna, 0);
415 cpl_propertylist * blist = cpl_propertylist_load(fnb, 0);
417 int expa = cpl_propertylist_get_int(alist,
"ESO TPL EXPNO");
418 int expb = cpl_propertylist_get_int(blist,
"ESO TPL EXPNO");
426 cpl_propertylist_delete(alist);
427 cpl_propertylist_delete(blist);
432 sort_framelist(irplib_framelist * allframes,
const char * tag)
434 irplib_framelist * on =
436 cx_list * frames = cx_list_new();
442 cx_list_sort(frames, (cx_compare_func)comp_expno);
451 check_rawframes(
const irplib_framelist * rawframes,
452 cpl_propertylist * plist)
454 cpl_errorstate cleanstate = cpl_errorstate_get();
455 const char * dit_key = VISIR_PFITS_DOUBLE_DIT;
456 if (cpl_propertylist_has(plist, VISIR_PFITS_DOUBLE_SEQ1_DIT))
457 dit_key = VISIR_PFITS_DOUBLE_SEQ1_DIT;
461 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
463 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5)) {
466 visir_error_reset(
"DIT differs by more than %g", 1e-5);
471 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
475 CPL_TYPE_DOUBLE, CPL_TRUE, 1.0));
478 CPL_TYPE_INT, CPL_TRUE, 0.0));
481 CPL_TYPE_INT, CPL_TRUE, 0.0));
484 CPL_TYPE_STRING, CPL_TRUE, 0.0)) {
485 visir_error_reset(
"Rawframe(s) missing standard star name");
490 double exptime = visir_utils_get_exptime(nnod, plist) / 2.;
493 cpl_propertylist_append_double(plist,
"ESO QC EXPTIME", exptime);
497 return cpl_error_get_code();
501 static void update_exectime(
const cpl_frame * frm,
double * t_min_obsstart,
502 double * t_max_filewrite)
504 cpl_propertylist * plist = cpl_propertylist_load(cpl_frame_get_filename(frm), 0);
505 if (plist == NULL || !cpl_propertylist_has(plist,
"ESO DRS DATE") ||
506 !cpl_propertylist_has(plist,
"ESO DRS DATE-OBS")) {
510 CX_MAX(cpl_propertylist_get_double(plist,
"ESO DRS DATE"),
513 CX_MIN(cpl_propertylist_get_double(plist,
"ESO DRS DATE-OBS"),
525 static int visir_util_undistort(cpl_frameset * framelist,
526 const cpl_parameterlist * parlist)
528 cpl_errorstate cleanstate = cpl_errorstate_get();
529 const cpl_frame * bpmframe = cpl_frameset_find_const
530 (framelist, VISIR_CALIB_STATIC_MASK);
531 irplib_framelist * allframes = NULL;
532 irplib_framelist * rawframes = NULL;
533 irplib_framelist * rawframes_a = NULL;
534 irplib_framelist * rawframes_b = NULL;
535 cpl_image * imbpm = NULL;
536 cpl_mask * bpm = NULL;
539 omp_set_num_threads(visir_get_num_threads(CPL_FALSE));
542 const cpl_boolean bkgcorrect =
543 irplib_parameterlist_get_bool(parlist, PACKAGE,
544 RECIPE_STRING,
"bkgcorrect");
549 VISIR_PARAM_SPECSKEW)
552 VISIR_PARAM_VERTARC);
554 VISIR_PARAM_HORIARC);
556 VISIR_PARAM_SLITSKEW)
559 const cpl_size xl = irplib_parameterlist_get_int(parlist, PACKAGE,
560 RECIPE_STRING,
"xl");
561 const cpl_size yl = irplib_parameterlist_get_int(parlist, PACKAGE,
562 RECIPE_STRING,
"yl");
563 const cpl_size xh = irplib_parameterlist_get_int(parlist, PACKAGE,
564 RECIPE_STRING,
"xh");
565 const cpl_size yh = irplib_parameterlist_get_int(parlist, PACKAGE,
566 RECIPE_STRING,
"yh");
573 cpl_frameset * usedframes = cpl_frameset_new();
574 cpl_image * base = NULL;
575 cpl_propertylist * plist = NULL;
576 visir_spc_resol resol;
577 visir_data_type data_type;
583 error_if(xl < 1 || yl < 1, CPL_ERROR_ILLEGAL_INPUT,
584 "Sky region %d/%d must be larger than 1", (
int)xl, (
int)yl);
588 skip_if(allframes == NULL);
591 VISIR_UTIL_REPACK_A_ON_PROCATG
"|"
592 VISIR_UTIL_REPACK_A_OFF_PROCATG
"|"
593 VISIR_UTIL_REPACK_B_ON_PROCATG
"|"
594 VISIR_UTIL_REPACK_B_OFF_PROCATG
598 skip_if(check_rawframes(rawframes, plist));
601 double pslitw, ptemp, pfwhm;
603 skip_if(visir_get_data_type(frm, plist, &data_type, NULL));
604 resol = visir_spc_get_res_wl(rawframes, &wlen, &pslitw, &ptemp, &pfwhm,
605 visir_data_is_aqu(data_type));
609 if (visir_data_is_drs(data_type)) {
611 const cpl_parameter * par =
612 cpl_parameterlist_find_const(parlist, PACKAGE
"." RECIPE_STRING
".ksi");
613 if (ksi == cpl_parameter_get_default_double(par) * CPL_MATH_RAD_DEG) {
614 ksi = VISIR_DRS_DIST_KSI;
616 par = cpl_parameterlist_find_const(parlist, PACKAGE
"." RECIPE_STRING
".eps");
617 if (eps == cpl_parameter_get_default_double(par)) {
618 eps = VISIR_DRS_DIST_EPS;
620 par = cpl_parameterlist_find_const(parlist, PACKAGE
"." RECIPE_STRING
".delta");
621 if (delta == cpl_parameter_get_default_double(par)) {
622 delta = VISIR_DRS_DIST_DELTA;
624 par = cpl_parameterlist_find_const(parlist, PACKAGE
"." RECIPE_STRING
".phi");
625 if (phi == cpl_parameter_get_default_double(par) * CPL_MATH_RAD_DEG) {
626 phi = VISIR_DRS_DIST_PHI;
631 VISIR_UTIL_REPACK_A_ON_PROCATG
"|"
632 VISIR_UTIL_REPACK_A_OFF_PROCATG
634 cpl_errorstate_set(cleanstate);
637 VISIR_UTIL_REPACK_B_ON_PROCATG
"|"
638 VISIR_UTIL_REPACK_B_OFF_PROCATG
640 cpl_errorstate_set(cleanstate);
642 error_if (rawframes_a == NULL && rawframes_b == NULL,
643 CPL_ERROR_DATA_NOT_FOUND,
"No frames with tags "
644 VISIR_UTIL_REPACK_A_ON_PROCATG
"|"
645 VISIR_UTIL_REPACK_A_OFF_PROCATG
"|"
646 VISIR_UTIL_REPACK_B_ON_PROCATG
"|"
647 VISIR_UTIL_REPACK_B_OFF_PROCATG
" found");
649 if (bpmframe != NULL) {
652 const char * badpix = cpl_frame_get_filename(bpmframe);
655 bpm = cpl_mask_load(badpix, 0, 0);
656 skip_if (bpm == NULL);
658 double t_min_obsstart = 1e300;
659 double t_max_filewrite = 0;
662 cx_list * on_frames = sort_framelist(rawframes_a,
"^("
663 VISIR_UTIL_REPACK_A_ON_PROCATG
665 cx_list * off_frames = sort_framelist(rawframes_a,
"^("
666 VISIR_UTIL_REPACK_A_OFF_PROCATG
668 FOR_EACH_T(cpl_frame * frm, on_frames) {
669 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
670 vimglist_append(aon, load_images(frm, bpm));
671 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
672 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
674 FOR_EACH_T(cpl_frame * frm, off_frames) {
675 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
676 vimglist_append(aoff, load_images(frm, bpm));
677 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
678 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
681 base = cpl_image_duplicate(visir_imglist_get_img(aoff, 0));
682 if (visir_data_is_aqu(data_type))
683 overscan_correct(base);
684 skip_if(handle_images(aon, base, xl, yl, xh, yh,
685 phi, ksi, eps, delta, data_type));
686 skip_if(handle_images(aoff, base, xl, yl, xh, yh,
687 phi, ksi, eps, delta, data_type));
690 cx_list * on_frames = sort_framelist(rawframes_b,
"^("
691 VISIR_UTIL_REPACK_B_ON_PROCATG
693 cx_list * off_frames = sort_framelist(rawframes_b,
"^("
694 VISIR_UTIL_REPACK_B_OFF_PROCATG
696 FOR_EACH_T(cpl_frame * frm, on_frames) {
697 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
698 vimglist_append(bon, load_images(frm, bpm));
699 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
700 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
702 FOR_EACH_T(cpl_frame * frm, off_frames) {
703 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
704 vimglist_append(boff, load_images(frm, bpm));
705 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
706 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
709 base = cpl_image_duplicate(visir_imglist_get_img(boff, 0));
710 if (visir_data_is_aqu(data_type))
711 overscan_correct(base);
714 skip_if(handle_images(bon, base, xl, yl, xh, yh,
715 phi, ksi, eps, delta, data_type));
716 skip_if(handle_images(boff, base, xl, yl, xh, yh,
717 phi, ksi, eps, delta, data_type));
720 if (bkgcorrect && rawframes_a && rawframes_b) {
721 cpl_imagelist * laon = visir_imglist_get_imglist(aon);
722 cpl_imagelist * laoff = visir_imglist_get_imglist(aoff);
723 cpl_imagelist_subtract(laon, laoff);
725 cpl_imagelist * lbon = visir_imglist_get_imglist(bon);
726 cpl_imagelist * lboff = visir_imglist_get_imglist(boff);
727 cpl_imagelist_subtract(lbon, lboff);
729 cpl_imagelist_subtract(laon, lbon);
734 cpl_image * img = cpl_imagelist_collapse_create(laon);
736 const cpl_size nx = cpl_image_get_size_x(img);
737 const cpl_size ny = cpl_image_get_size_y(img);
739 if (resol == VISIR_SPC_R_LRP) {
742 flipped = cpl_image_extract(img, 30, 25, nx - 30, ny - 25);
743 cpl_image_delete(img);
746 visir_spc_det_warp(&img, 1, 0., 0., phi, ksi, eps, delta);
748 flipped = visir_spc_flip(img, wlen, resol, data_type);
749 cpl_image_delete(img);
752 visir_imglist_append(l, img, NULL);
755 cpl_propertylist_append_double(plist,
"ESO QC EXECTIME",
756 (t_max_filewrite - t_min_obsstart) * 24 * 3600);
757 save_images(l, framelist, usedframes, plist, parlist);
758 visir_imglist_delete(l, NULL);
763 save_images(aon, framelist, usedframes, plist, parlist);
764 save_images(aoff, framelist, usedframes, plist, parlist);
765 save_images(bon, framelist, usedframes, plist, parlist);
766 save_images(boff, framelist, usedframes, plist, parlist);
773 const cpl_size nx = cpl_image_get_size_x(base);
774 const cpl_size ny = cpl_image_get_size_y(base);
776 if (resol == VISIR_SPC_R_LRP) {
777 flipped = cpl_image_extract(base, 30, 25, nx - 30, ny - 25);
778 cpl_image_delete(base);
781 skip_if(visir_spc_det_warp(&base, 1, 0., 0., phi, ksi, eps, delta));
782 flipped = visir_spc_flip(base, wlen, resol, data_type);
783 cpl_image_delete(base);
787 base, CPL_TYPE_UNSPECIFIED,
789 "SPEC_OBS_LMR_SKYFRAME", NULL, NULL,
790 visir_pipe_id,
"skyframe.fits"));
798 cpl_image_delete(imbpm);
799 cpl_mask_delete(bpm);
800 cpl_image_delete(base);
801 visir_imglist_delete(aon, NULL);
802 visir_imglist_delete(aoff, NULL);
803 visir_imglist_delete(bon, NULL);
804 visir_imglist_delete(boff, NULL);
805 cpl_frameset_delete(usedframes);
807 return cpl_error_get_code();
double visir_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR parameter of type double.
cpl_error_code visir_parameter_set(cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Define the specified parameters.
cpl_error_code irplib_dfs_save_propertylist(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save a propertylist as a DFS-compliant pipeline product.
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_frame * irplib_framelist_unset(irplib_framelist *self, int pos, cpl_propertylist **plist)
Erase a frame from a framelist and return it to the caller.
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
cpl_propertylist * irplib_framelist_get_propertylist(irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.