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
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <cpl.h>
00039
00040 #include "irplib_plugin.h"
00041 #include "irplib_utils.h"
00042
00043 #include "sofi_utils.h"
00044 #include "sofi_pfits.h"
00045 #include "sofi_dfs.h"
00046
00047
00048
00049
00050
00051 #define RECIPE_STRING "sofi_spc_flat"
00052
00053 #define MEDIAN_XSIZE 200
00054 #define MEDIAN_YSIZE 200
00055
00056
00057
00058
00059
00060 static cpl_image * sofi_spc_flat_reduce(cpl_frameset *);
00061 static cpl_imagelist * sofi_spc_flat_diffs(cpl_frameset *);
00062 static cpl_image * sofi_spc_flat_divide_fit(cpl_image *, int, int, int);
00063 static cpl_error_code sofi_spc_flat_save(cpl_frameset *, int, const cpl_image *,
00064 const cpl_frameset *,
00065 const cpl_parameterlist *);
00066 static int sofi_spc_flat_compare(const cpl_frame *, const cpl_frame *);
00067
00068 cpl_recipe_define(sofi_spc_flat, SOFI_BINARY_VERSION,
00069 "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003,2009",
00070 "SOFI spectro flat-field creation",
00071 RECIPE_STRING " -- SOFI spectro flat-field creation.\n"
00072 "The files listed in the Set Of Frames (sof-file) "
00073 "must be tagged:\n"
00074 "raw-file.fits "SOFI_SPC_FLAT_RAW"\n");
00075
00076
00077
00078
00079
00080 static struct {
00081
00082 double low_thresh;
00083 double high_thresh;
00084 int fit_order;
00085 int fit_size;
00086 int offset;
00087 int llx;
00088 int lly;
00089 int urx;
00090 int ury;
00091
00092 double med_stdev;
00093 double med_avg;
00094 } sofi_spc_flat_config;
00095
00096
00097
00098
00099
00100
00101
00109
00110 static
00111 cpl_error_code sofi_spc_flat_fill_parameterlist(cpl_parameterlist * self)
00112 {
00113 const char * context = PACKAGE "." RECIPE_STRING;
00114 cpl_error_code err;
00115
00116 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00117
00118
00119
00120
00121 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00122 "thresholds", "0.01,3.0", NULL,
00123 context, "Low and high thresholds");
00124 cpl_ensure_code(!err, err);
00125
00126
00127 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "fit_order",
00128 3, NULL, context, "Order of the fit");
00129 cpl_ensure_code(!err, err);
00130
00131
00132 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "fit_size",
00133 200, NULL, context, "Size of the fit");
00134 cpl_ensure_code(!err, err);
00135
00136
00137 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "offset",
00138 40, NULL, context, "Offset");
00139 cpl_ensure_code(!err, err);
00140
00141
00142 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00143 "zone", "256,256,768,768", NULL,
00144 context, "Zone to process [pixel]");
00145 cpl_ensure_code(!err, err);
00146
00147 return CPL_ERROR_NONE;
00148 }
00149
00150
00151
00159
00160 static int sofi_spc_flat(cpl_frameset * framelist,
00161 const cpl_parameterlist * parlist)
00162 {
00163 const int nframes = cpl_frameset_get_size(framelist);
00164 const char * sval;
00165 cpl_frameset * flatframes = NULL;
00166 cpl_size * labels = NULL;
00167 cpl_size nlabels;
00168 int nflats;
00169 int i;
00170
00171
00172 sofi_spc_flat_config.med_stdev = 0.0;
00173 sofi_spc_flat_config.med_avg = 0.0;
00174
00175
00176
00177 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00178 "thresholds");
00179 bug_if(sval == NULL);
00180 skip_if (sscanf(sval, "%lg,%lg",
00181 &sofi_spc_flat_config.low_thresh,
00182 &sofi_spc_flat_config.high_thresh) != 2);
00183
00184
00185 sofi_spc_flat_config.fit_order
00186 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00187 "fit_order");
00188
00189 sofi_spc_flat_config.fit_size
00190 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00191 "fit_size");
00192
00193 sofi_spc_flat_config.offset
00194 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00195 "offset");
00196
00197 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00198 "zone");
00199 bug_if(sval == NULL);
00200 skip_if (sscanf(sval, "%d,%d,%d,%d",
00201 &sofi_spc_flat_config.llx,
00202 &sofi_spc_flat_config.lly,
00203 &sofi_spc_flat_config.urx,
00204 &sofi_spc_flat_config.ury) != 4);
00205
00206
00207
00208 skip_if (sofi_dfs_set_groups(framelist));
00209
00210
00211 flatframes = sofi_extract_frameset(framelist, SOFI_SPC_FLAT_RAW);
00212 error_if (flatframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00213 "Cannot find flat frames in the input frame list");
00214
00215 nflats = cpl_frameset_get_size(flatframes);
00216
00217
00218 error_if (cpl_frameset_get_size(flatframes) % 2, CPL_ERROR_ILLEGAL_INPUT,
00219 "The number of flat frames must be even, not %d", nflats);
00220
00221
00222 labels = cpl_frameset_labelise(flatframes, sofi_spc_flat_compare, &nlabels);
00223 error_if (labels == NULL, cpl_error_get_code(),
00224 "Cannot labelise input frames");
00225
00226
00227 for (i=0; i < nlabels; i++) {
00228
00229 cpl_errorstate prestate = cpl_errorstate_get();
00230 cpl_frameset * flat_one = cpl_frameset_extract(flatframes, labels, i);
00231 cpl_image * spflat;
00232
00233 cpl_msg_info(cpl_func, "Reducing set %d/%d", i+1, (int)nlabels);
00234
00235 spflat = sofi_spc_flat_reduce(flat_one);
00236
00237 if (spflat == NULL) {
00238 cpl_msg_warning(cpl_func, "Could not reduce set %d:", i+1);
00239 cpl_errorstate_dump(prestate, CPL_FALSE,
00240 irplib_errorstate_dump_warning);
00241 cpl_errorstate_set(prestate);
00242 } else {
00243 sofi_spc_flat_save(framelist, i+1, spflat, flat_one, parlist);
00244 cpl_image_delete(spflat);
00245 }
00246 cpl_frameset_delete(flat_one);
00247 if (!cpl_errorstate_is_equal(prestate)) break;
00248 }
00249 skip_if(i != nlabels);
00250
00251 error_if (cpl_frameset_get_size(framelist) == nframes,
00252 CPL_ERROR_ILLEGAL_INPUT, "No products produced from %d flat "
00253 "frames grouped into %d set(s)", nflats, (int)nlabels);
00254
00255 end_skip;
00256
00257 cpl_frameset_delete(flatframes);
00258 cpl_free(labels);
00259 return cpl_error_get_code();
00260 }
00261
00262
00269
00270 static cpl_image * sofi_spc_flat_reduce(cpl_frameset * flatframes)
00271 {
00272 cpl_imagelist * diffs;
00273 cpl_vector * medians;
00274 double med, mean;
00275 cpl_image * avg_ima;
00276 cpl_image * fitted;
00277 int nima, nx, ny;
00278 int nframes;
00279 int i;
00280
00281
00282 if (flatframes == NULL) return NULL;
00283 nframes = cpl_frameset_get_size(flatframes);
00284 if (nframes != 4) {
00285 cpl_msg_error(cpl_func, "Expect 4 frames in input, not %d", nframes);
00286 return NULL;
00287 }
00288
00289
00290 cpl_msg_info(cpl_func, "Compute the difference images");
00291 if ((diffs = sofi_spc_flat_diffs(flatframes)) == NULL) {
00292 cpl_msg_error(cpl_func, "Cannot create the difference images");
00293 return NULL;
00294 }
00295 nima = cpl_imagelist_get_size(diffs);
00296 nx = cpl_image_get_size_x(cpl_imagelist_get(diffs, 0));
00297 ny = cpl_image_get_size_y(cpl_imagelist_get(diffs, 0));
00298
00299
00300 cpl_msg_info(cpl_func, "Compute statistics on images");
00301 cpl_msg_indent_more();
00302 medians = cpl_vector_new(nima);
00303
00304
00305 for (i=0; i<nima; i++) {
00306 med = cpl_image_get_median_window(cpl_imagelist_get(diffs, i),
00307 (nx-MEDIAN_XSIZE)/2.0, (ny-MEDIAN_YSIZE)/2.0,
00308 (nx+MEDIAN_XSIZE)/2.0, (ny+MEDIAN_YSIZE)/2.0);
00309 if (cpl_vector_set(medians, i, med) != CPL_ERROR_NONE) {
00310 cpl_msg_error(cpl_func, "Cannot compute the medians");
00311 cpl_vector_delete(medians);
00312 cpl_imagelist_delete(diffs);
00313 cpl_msg_indent_less();
00314 return NULL;
00315 }
00316 }
00317
00318
00319 sofi_spc_flat_config.med_avg = cpl_vector_get_mean(medians);
00320 if (nima >= 2)
00321 sofi_spc_flat_config.med_stdev=cpl_vector_get_stdev(medians);
00322 cpl_vector_delete(medians);
00323 cpl_msg_info(cpl_func, "Average of the medians: %g",
00324 sofi_spc_flat_config.med_avg);
00325 cpl_msg_info(cpl_func, "Standard deviation of the medians: %g",
00326 sofi_spc_flat_config.med_stdev);
00327 cpl_msg_indent_less();
00328
00329
00330 cpl_msg_info(cpl_func, "Normalise the images");
00331 for (i=0; i<nima; i++) {
00332 mean = cpl_image_get_mean_window(cpl_imagelist_get(diffs, i),
00333 sofi_spc_flat_config.llx, sofi_spc_flat_config.lly,
00334 sofi_spc_flat_config.urx, sofi_spc_flat_config.ury);
00335 if (cpl_image_divide_scalar(cpl_imagelist_get(diffs, i), mean) !=
00336 CPL_ERROR_NONE) {
00337 cpl_msg_error(cpl_func, "Cannot normalise the image");
00338 cpl_imagelist_delete(diffs);
00339 return NULL;
00340 }
00341 }
00342
00343
00344 for (i=0; i<nima; i++) {
00345 if (cpl_image_threshold(cpl_imagelist_get(diffs, i),
00346 sofi_spc_flat_config.low_thresh,
00347 sofi_spc_flat_config.high_thresh,
00348 0.0, 0.0) != CPL_ERROR_NONE) {
00349 cpl_msg_error(cpl_func, "Cannot threshold the image");
00350 cpl_imagelist_delete(diffs);
00351 return NULL;
00352 }
00353 }
00354
00355
00356 cpl_msg_info(cpl_func, "Stack the images");
00357 if ((avg_ima = cpl_imagelist_collapse_create(diffs)) == NULL) {
00358 cpl_msg_error(cpl_func, "Cannot collapse the image list");
00359 cpl_imagelist_delete(diffs);
00360 return NULL;
00361 }
00362 cpl_imagelist_delete(diffs);
00363
00364
00365 cpl_msg_info(cpl_func, "Divide by a fit");
00366 if ((fitted = sofi_spc_flat_divide_fit(avg_ima,
00367 sofi_spc_flat_config.fit_order,
00368 sofi_spc_flat_config.fit_size,
00369 sofi_spc_flat_config.offset)) == NULL) {
00370 cpl_msg_error(cpl_func, "Cannot collapse the image list");
00371 cpl_image_delete(avg_ima);
00372 return NULL;
00373 }
00374 cpl_image_delete(avg_ima);
00375
00376 return fitted;
00377 }
00378
00379
00385
00386 static cpl_imagelist * sofi_spc_flat_diffs(cpl_frameset * in)
00387 {
00388 int nima;
00389 cpl_imagelist * out;
00390 cpl_image * in1;
00391 cpl_image * in2;
00392 cpl_frame * cur_frame;
00393 int i;
00394
00395
00396 nima = cpl_frameset_get_size(in);
00397
00398
00399 if ((nima % 2) || (nima != 4)) {
00400 cpl_msg_error(cpl_func, "Wrong nb of frames");
00401 return NULL;
00402 }
00403
00404
00405 out = cpl_imagelist_new();
00406
00407
00408 for (i=0; i<nima/2; i++) {
00409 cur_frame = cpl_frameset_get_frame(in, 2*i);
00410 if ((in1 = cpl_image_load(cpl_frame_get_filename(cur_frame),
00411 CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00412 cpl_msg_error(cpl_func, "Cannot load the image %d", 2*i);
00413 cpl_imagelist_delete(out);
00414 return NULL;
00415 }
00416 cur_frame = cpl_frameset_get_frame(in, 2*i+1);
00417 if ((in2 = cpl_image_load(cpl_frame_get_filename(cur_frame),
00418 CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00419 cpl_msg_error(cpl_func, "Cannot load the image %d", 2*i+1);
00420 cpl_image_delete(in1);
00421 cpl_imagelist_delete(out);
00422 return NULL;
00423 }
00424
00425
00426 if (i==0) {
00427 cpl_image_subtract(in2, in1);
00428 cpl_image_delete(in1);
00429 cpl_imagelist_set(out, in2, i);
00430 } else {
00431 cpl_image_subtract(in1, in2);
00432 cpl_image_delete(in2);
00433 cpl_imagelist_set(out, in1, i);
00434 }
00435 }
00436 return out;
00437 }
00438
00439
00445
00446 static cpl_image * sofi_spc_flat_divide_fit(
00447 cpl_image * in,
00448 int order,
00449 int xsize,
00450 int offset)
00451 {
00452 const cpl_size degree = order - 1;
00453 int nx, ny;
00454 int xstart, xend, ystart, yend;
00455 cpl_image * collapsed;
00456 float * pcollapsed;
00457 cpl_image * extracted;
00458 float * pextracted;
00459 int nb_samples;
00460 cpl_matrix * xvec;
00461 cpl_vector * yvec;
00462 cpl_polynomial * poly_fit;
00463 cpl_polynomial * poly_2d;
00464 cpl_image * fit_image;
00465 cpl_image * out;
00466 cpl_size power[2];
00467 int i;
00468
00469
00470 if (in == NULL) return NULL;
00471
00472
00473 nx = cpl_image_get_size_x(in);
00474 ny = cpl_image_get_size_y(in);
00475
00476
00477 xstart = (int)((nx - xsize)/2) + 1;
00478 xend = xstart + xsize - 1;
00479 if ((xstart<1) || (xend>nx)) {
00480 cpl_msg_error(cpl_func, "bad X size specified");
00481 return NULL;
00482 }
00483
00484
00485 if ((collapsed = cpl_image_collapse_window_create(in, xstart, 1, xend, ny,
00486 1)) == NULL) {
00487 cpl_msg_error(cpl_func, "Cannot collpase a part of the image");
00488 return NULL;
00489 }
00490 pcollapsed = cpl_image_get_data_float(collapsed);
00491
00492
00493 ystart = 1;
00494 while ((fabs(pcollapsed[ystart-1]) < 1e-4) && (ystart < nx)) ystart++;
00495 ystart += offset;
00496
00497 yend = ny;
00498 while ((fabs(pcollapsed[yend-1]) <1e-4) && (yend > 1)) yend--;
00499 yend -= offset;
00500
00501 if (ystart > yend) {
00502 cpl_msg_error(cpl_func, "invalid coordinates of the zone to extract");
00503 cpl_image_delete(collapsed);
00504 return NULL;
00505 }
00506
00507
00508 if ((extracted = cpl_image_extract(collapsed, 1, ystart, 1, yend))==NULL) {
00509 cpl_msg_error(cpl_func, "cannot extract 1D image");
00510 cpl_image_delete(collapsed);
00511 return NULL;
00512 }
00513 cpl_image_delete(collapsed);
00514 pextracted = cpl_image_get_data_float(extracted);
00515
00516
00517 nb_samples = cpl_image_get_size_y(extracted);
00518 xvec = cpl_matrix_new(1, nb_samples);
00519 yvec = cpl_vector_new(nb_samples);
00520 for (i=0; i<nb_samples; i++) {
00521 cpl_matrix_set(xvec, 0, i, (double)(ystart + i));
00522 cpl_vector_set(yvec, i, (double)(pextracted[i] / xsize));
00523 }
00524 cpl_image_delete(extracted);
00525 poly_fit = cpl_polynomial_new(1);
00526 if (cpl_polynomial_fit(poly_fit, xvec, NULL, yvec, NULL, CPL_FALSE,
00527 NULL, °ree)) {
00528 cpl_msg_error(cpl_func, "cannot fit the 1D signal");
00529 cpl_polynomial_delete(poly_fit);
00530 cpl_matrix_delete(xvec);
00531 cpl_vector_delete(yvec);
00532 return NULL;
00533 }
00534 cpl_matrix_delete(xvec);
00535 cpl_vector_delete(yvec);
00536
00537
00538 poly_2d = cpl_polynomial_new(2);
00539 power[0] = 0; power[1] = 0;
00540 cpl_polynomial_set_coeff(poly_2d, power,
00541 cpl_polynomial_get_coeff(poly_fit, power + 1));
00542 power[0] = 0; power[1] = 1;
00543 cpl_polynomial_set_coeff(poly_2d, power,
00544 cpl_polynomial_get_coeff(poly_fit, power + 1));
00545 power[0] = 0; power[1] = 2;
00546 cpl_polynomial_set_coeff(poly_2d, power,
00547 cpl_polynomial_get_coeff(poly_fit, power + 1));
00548 cpl_polynomial_delete(poly_fit);
00549
00550
00551 fit_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00552 cpl_image_fill_polynomial(fit_image, poly_2d, 1.0, 1.0, 1.0, 1.0);
00553 cpl_polynomial_delete(poly_2d);
00554
00555
00556 if ((out = cpl_image_divide_create(in, fit_image)) == NULL) {
00557 cpl_msg_error(cpl_func, "cannot divide the images");
00558 cpl_image_delete(fit_image);
00559 return NULL;
00560 }
00561 cpl_image_delete(fit_image);
00562
00563 return out;
00564 }
00565
00566
00576
00577 static cpl_error_code sofi_spc_flat_save(cpl_frameset * set_tot,
00578 int set_nb,
00579 const cpl_image * flat,
00580 const cpl_frameset * set,
00581 const cpl_parameterlist * parlist)
00582 {
00583 #define SOFI_SPC_FLAT_PAF \
00584 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG" \
00585 "|ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME" \
00586 "|ESO INS GRAT WLEN|ESO INS OPTI1 ID|ESO DET DIT|ESO INS LAMP3 SET)$"
00587
00588 cpl_errorstate prestate = cpl_errorstate_get();
00589
00590 const cpl_frame * ref_frame
00591 = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00592
00593 cpl_propertylist * qclist = cpl_propertylist_new();
00594 cpl_propertylist * plist = cpl_propertylist_load_regexp
00595 (cpl_frame_get_filename(ref_frame), 0, SOFI_SPC_FLAT_PAF
00596 "|^ESO INS FILT[12] ID$", 0);
00597 const char * sval;
00598 char * filename;
00599
00600 skip_if(0);
00601
00602 sval = sofi_pfits_get_filter(plist);
00603 if (sval == NULL) {
00604 cpl_msg_warning(cpl_func, "Could not get filter for set %d:", set_nb);
00605 cpl_errorstate_dump(prestate, CPL_FALSE,
00606 irplib_errorstate_dump_warning);
00607 cpl_errorstate_set(prestate);
00608 } else {
00609 cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
00610 }
00611
00612 cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT NCOUNTS",
00613 sofi_spc_flat_config.med_avg);
00614 cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT STDEV",
00615 sofi_spc_flat_config.med_stdev);
00616
00617
00618 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00619 irplib_dfs_save_image(set_tot, parlist, set, flat, CPL_BPP_IEEE_FLOAT,
00620 RECIPE_STRING, SOFI_SPC_FLAT_RES, qclist, NULL,
00621 PACKAGE "/" PACKAGE_VERSION, filename);
00622 cpl_free(filename);
00623 skip_if(0);
00624
00625 cpl_propertylist_copy_property_regexp(qclist, plist,
00626 SOFI_SPC_FLAT_PAF, 0);
00627 cpl_propertylist_empty(plist);
00628
00629
00630 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00631 cpl_dfs_save_paf("SOFI", RECIPE_STRING, qclist, filename);
00632 cpl_free(filename);
00633
00634 skip_if(0);
00635
00636 end_skip;
00637
00638 cpl_propertylist_delete(qclist);
00639 cpl_propertylist_delete(plist);
00640
00641 return cpl_error_get_code();
00642 }
00643
00644
00651
00652 static int sofi_spc_flat_compare(
00653 const cpl_frame * frame1,
00654 const cpl_frame * frame2)
00655 {
00656 int comparison;
00657 cpl_propertylist * plist1;
00658 cpl_propertylist * plist2;
00659 const char * sval1,
00660 * sval2;
00661
00662
00663 if (frame1==NULL || frame2==NULL) return -1;
00664
00665
00666 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
00667 0)) == NULL) {
00668 cpl_msg_error(cpl_func, "getting header from reference frame");
00669 return -1;
00670 }
00671 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
00672 0)) == NULL) {
00673 cpl_msg_error(cpl_func, "getting header from reference frame");
00674 cpl_propertylist_delete(plist1);
00675 return -1;
00676 }
00677
00678
00679 if (cpl_error_get_code()) {
00680 cpl_propertylist_delete(plist1);
00681 cpl_propertylist_delete(plist2);
00682 return -1;
00683 }
00684
00685 comparison = 1;
00686
00687
00688 sval1 = sofi_pfits_get_opti1_id(plist1);
00689 sval2 = sofi_pfits_get_opti1_id(plist2);
00690 if (cpl_error_get_code()) {
00691 cpl_msg_error(cpl_func, "cannot get the slit used");
00692 cpl_propertylist_delete(plist1);
00693 cpl_propertylist_delete(plist2);
00694 return -1;
00695 }
00696 if (strcmp(sval1, sval2)) comparison = 0;
00697
00698
00699 sval1 = sofi_pfits_get_filter(plist1);
00700 sval2 = sofi_pfits_get_filter(plist2);
00701 if (cpl_error_get_code()) {
00702 cpl_msg_error(cpl_func, "cannot get the filter");
00703 cpl_propertylist_delete(plist1);
00704 cpl_propertylist_delete(plist2);
00705 return -1;
00706 }
00707 if (strcmp(sval1, sval2)) comparison = 0;
00708
00709 cpl_propertylist_delete(plist1);
00710 cpl_propertylist_delete(plist2);
00711 return comparison;
00712 }
00713
00714