OMEGA Pipeline Reference Manual  1.0.5
omega_utils.c
1 /* $Id: omega_utils.c,v 1.5 2012-01-12 12:05:09 agabasch Exp $
2  *
3  * This file is part of the OMEGA Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: agabasch $
23  * $Date: 2012-01-12 12:05:09 $
24  * $Revision: 1.5 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <string.h>
37 #include <math.h>
38 #include "omega_utils.h"
39 #include "omega_dfs.h"
40 #include "omega_pfits.h"
41 
42 #define MAXNAMESZ 4096
43 
58 /*----------------------------------------------------------------------------*/
66 /*----------------------------------------------------------------------------*/
67 const char * omega_get_license(void)
68 {
69  const char * omega_license =
70  "This file is part of the OMEGA Instrument Pipeline\n"
71  "Copyright (C) 2002,2003 European Southern Observatory\n"
72  "\n"
73  "This program is free software; you can redistribute it and/or modify\n"
74  "it under the terms of the GNU General Public License as published by\n"
75  "the Free Software Foundation; either version 2 of the License, or\n"
76  "(at your option) any later version.\n"
77  "\n"
78  "This program is distributed in the hope that it will be useful,\n"
79  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
80  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
81  "GNU General Public License for more details.\n"
82  "\n"
83  "You should have received a copy of the GNU General Public License\n"
84  "along with this program; if not, write to the Free Software\n"
85  "Foundation, Inc., 59 Temple Place, Suite 330, Boston, \n"
86  "MA 02111-1307 USA" ;
87  return omega_license ;
88 }
89 
90 /*----------------------------------------------------------------------------*/
105 /*----------------------------------------------------------------------------*/
107  char * filename,
108  char * paf_id,
109  char * paf_desc)
110 {
111  FILE * paf ;
112 
113  if ((paf=fopen(filename, "w"))==NULL) return NULL ;
114  fprintf(paf, "PAF.HDR.START ;# start of header\n");
115  fprintf(paf, "PAF.TYPE \"pipeline product\" ;\n");
116  fprintf(paf, "PAF.ID \"%s\"\n", paf_id);
117  fprintf(paf, "PAF.NAME \"%s\"\n", filename);
118  fprintf(paf, "PAF.DESC \"%s\"\n", paf_desc);
119  fprintf(paf, "PAF.CHCK.CHECKSUM \"\"\n");
120  fprintf(paf, "PAF.HDR.END ;# end of header\n");
121  fprintf(paf, "\n");
122  return paf ;
123 }
124 
125 /*----------------------------------------------------------------------------*/
157 /*----------------------------------------------------------------------------*/
158 char * omega_get_root_name(const char * filename)
159 {
160  static char path[MAXNAMESZ+1];
161  char * lastdot ;
162 
163  if (strlen(filename)>MAXNAMESZ) return NULL ;
164  memset(path, MAXNAMESZ, 0);
165  strcpy(path, filename);
166  lastdot = strrchr(path, '.');
167  if (lastdot == NULL) return path ;
168  if ((!strcmp(lastdot, ".fits")) || (!strcmp(lastdot, ".FITS")) ||
169  (!strcmp(lastdot, ".paf")) || (!strcmp(lastdot, ".PAF")) ||
170  (!strcmp(lastdot, ".dat")) || (!strcmp(lastdot, ".DAT")) ||
171  (!strcmp(lastdot, ".txt")) || (!strcmp(lastdot, ".TXT")) ||
172  (!strcmp(lastdot, ".tfits")) || (!strcmp(lastdot, ".TFITS")) ||
173  (!strcmp(lastdot, ".ascii")) || (!strcmp(lastdot, ".ASCII")))
174  {
175  lastdot[0] = (char)0;
176  }
177  return path ;
178 }
179 
180 /*---------------------------------------------------------------------------*/
204 /*---------------------------------------------------------------------------*/
205 
206 extern int omega_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2) {
207  char *v1,*v2;
208 
209  /* Test entries */
210 
211  if (frame1 == NULL || frame2 == NULL)
212  return(-1);
213 
214  /* Get the tags */
215 
216  if ((v1 = (char *)cpl_frame_get_tag(frame1)) == NULL)
217  return(-1);
218  if ((v2 = (char *)cpl_frame_get_tag(frame2)) == NULL)
219  return(-1);
220 
221  /* Compare the tags */
222 
223  if (strcmp(v1,v2))
224  return(0);
225  else
226  return(1);
227 }
228 
229 /*---------------------------------------------------------------------------*/
255 /*---------------------------------------------------------------------------*/
256 
257 extern cpl_frameset *omega_frameset_subgroup(cpl_frameset *frameset,
258  cpl_size *labels, cpl_size nlab,
259  const char *tag) {
260  cpl_size i;
261  cpl_frameset *cur_set,*ret_set;
262  cpl_frame *cur_frame;
263  char *cur_tag;
264 
265  ret_set = NULL;
266  for (i = 0; i < nlab; i++) {
267  cur_set = cpl_frameset_extract(frameset,labels,i);
268  if (cur_set == NULL)
269  break;
270  cur_frame = cpl_frameset_get_frame(cur_set,0);
271  cur_tag = (char *)cpl_frame_get_tag(cur_frame);
272  if (!strcmp(cur_tag,tag)) {
273  ret_set = cur_set;
274  break;
275  }
276  cpl_frameset_delete(cur_set);
277  }
278  return(ret_set);
279 }
280 
281 /*---------------------------------------------------------------------------*/
303 /*---------------------------------------------------------------------------*/
304 
305 extern void omega_exten_range(int inexten, int *out1, int *out2) {
306 
307  if(inexten == -1){
308  *out1 = 1;
309  *out2 = 32;
310  }
311  else if (inexten == 0) {
312  *out1 = 0;
313  *out2 = 0;
314  } else {
315  *out1 = inexten;
316  *out2 = inexten;
317  }
318 
319  return;
320 }
321 
322 /*---------------------------------------------------------------------------*/
346 /*---------------------------------------------------------------------------*/
347 
348 extern void omega_extensions(const cpl_frame *frame, int inexten, int *out1,
349  int *out2)
350 {
351 
352  int maxextension=0;
353  if(inexten == -1){
354  /* All extensions */
355  *out1 = 1;
356  //*out2 = 32;
357  maxextension = cpl_fits_count_extensions(cpl_frame_get_filename(frame));
358  if(maxextension==32){
359  *out2 = maxextension;
360  }
361  else{
362  cpl_msg_warning(cpl_func,"Number of extension is %d and not 32. "
363  "The pipeline will still try to reduce all 32 "
364  "expected extensions", maxextension);
365  *out2 = 32;
366  }
367  }
368  else if (inexten == 0) {
369  /* Unsupported */
370  *out1 = 0;
371  *out2 = 0;
372  } else {
373  /* One specific extension */
374  *out1 = inexten;
375  *out2 = inexten;
376  }
377 
378  return;
379 }
380 
381 
382 /*---------------------------------------------------------------------------*/
403 /*---------------------------------------------------------------------------*/
404 int omega_compare_reference(const cpl_image *master, const cpl_frame *refframe,
405  int ext, cpl_stats **diffstats)
406 {
407 
408  cpl_image *refimage = NULL;
409  cpl_image *diff = NULL;
410 
411  if ((master == NULL) || (refframe == NULL)){
412  cpl_msg_warning(cpl_func,"NULL input");
413  return -1;
414  }
415 
416  refimage = cpl_image_load(cpl_frame_get_filename(refframe),CPL_TYPE_FLOAT,0, ext);
417  if (refimage == NULL){
418  cpl_msg_warning(cpl_func,"Cannot load reference image");
419  return -1;
420  }
421 
422  diff = cpl_image_subtract_create(master, refimage);
423  *diffstats = cpl_stats_new_from_image(diff,CPL_STATS_ALL);
424  if (*diffstats == NULL){
425  freeimage(diff);
426  freeimage(refimage);
427  cpl_msg_warning(cpl_func,"Cannot calculate statistics of difference image");
428  return -1;
429  }
430 
431 
432  return 0;
433 }
434 
435 /*---------------------------------------------------------------------------*/
457 char * omega_get_pathname(const char * filename)
458 {
459 
460  static char path[MAXNAMESZ];
461  char *last_slash;
462 
463  if (strlen(filename)>MAXNAMESZ) return NULL ;
464  strcpy(path, filename);
465  /* Find last '/'. */
466  last_slash = path != NULL ? strrchr (path, '/') : NULL;
467 
468  if (last_slash == path)
469  /* The last slash is the first character in the string. We have to
470  return "/". */
471  ++last_slash;
472  else if (last_slash != NULL && last_slash[1] == '\0')
473  /* The '/' is the last character, we have to look further. */
474  last_slash = memchr (path, last_slash - path, '/');
475 
476  if (last_slash != NULL)
477  /* Terminate the path. */
478  last_slash[0] = '\0';
479  else
480  /* This assignment is ill-designed but the XPG specs require to
481  return a string containing "." in any case no directory part is
482  found and so a static and constant string is required. */
483  strcpy(path, ".");
484 
485  return path;
486 
487 
488 }
489 
490 /*---------------------------------------------------------------------------*/
498 /*---------------------------------------------------------------------------*/
499 cpl_frame *omega_product_frame(const char *filename, const char *tag, cpl_frame_type type)
500 {
501  cpl_frame *frame;
502 
503  if ((filename == NULL) || (tag == NULL)){
504  return NULL;
505  }
506 
507  frame = cpl_frame_new();
508  cpl_frame_set_filename(frame, filename);
509  cpl_frame_set_tag(frame, tag);
510  cpl_frame_set_type(frame, type);
511  cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
512  cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL);
513 
514  return frame;
515 
516 }
517 
518 /*---------------------------------------------------------------------------*/
532 /*---------------------------------------------------------------------------*/
533 int omega_save_dummy(cpl_frameset *set, cpl_parameterlist *parlist, cpl_frame_type type,
534  cpl_type_bpp bitpix, const char *outfile, const cpl_propertylist *plist,
535  const char *recipe, cpl_frame *product_frame)
536 {
537  int naxis1 = 2046;
538  int naxis2 = 4098;
539  const char delkeys[] = "^(ORIGIN|TELESCOPE|INSTRUME|OBJECT|RA|DEC|EPOCH|EQUINOX|RADECSYS|DATE-OBS|" \
540  "MJD-OBS|UTC|LST|PI-COI|OBSERVER|PIPEFILE)$";
541  cpl_image *image = NULL;
542  cpl_table *table = NULL;
543  cpl_propertylist *list = NULL;
544 
545 
546  /* Setup the extension */
547  /* Add DataFlow keywords in extension header */
548  list = cpl_propertylist_duplicate(plist);
549 
550  if (cpl_dfs_setup_product_header(list, product_frame, set, parlist,
551  recipe,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
552 
553  cpl_msg_warning(cpl_func, "Problem in the extension header of product DFS-compliance") ;
554  }
555 
556  /*Remove undesired keywords from extension header*/
557  cpl_propertylist_erase_regexp(list, delkeys, 0);
558 
559  /* Save the product */
560  if(type == CPL_FRAME_TYPE_IMAGE){
561  image = cpl_image_new(naxis1, naxis2, CPL_TYPE_FLOAT);
562  if (cpl_image_save(image,outfile,bitpix,list,
563  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
564  cpl_msg_error(cpl_func,"Cannot save product %s", cpl_error_get_message());
565  freeimage(image);
566  freeplist(list);
567  return -1;
568  }
569  freeimage(image);
570  }
571  else {
572  table = cpl_table_new(1);
573  if (cpl_table_save(table, NULL, list,outfile, CPL_IO_EXTEND) != CPL_ERROR_NONE) {
574  cpl_msg_error(cpl_func, "Cannot save the extension table");
575  freetable(table);
576  freeplist(list);
577  return -1;
578  }
579  freetable(table);
580  }
581 
582  freeplist(list);
583 
584  return 0;
585 }
586 
587 /*---------------------------------------------------------------------------*/
600 /*---------------------------------------------------------------------------*/
601 int omega_save_primary(cpl_frameset *set, const cpl_parameterlist *parlist,
602  const char *outfile, const char *recipe, const cpl_propertylist *plist,
603  cpl_frame *product_frame, const cpl_frame *inherit)
604 {
605 
606  cpl_propertylist *pplist;
607 
608  /* Create an empty primary header */
609  if(plist == NULL)
610  pplist = cpl_propertylist_new();
611  else
612  pplist = cpl_propertylist_duplicate(plist);
613 
614  /* Add DataFlow keywords in primary header */
615  if (cpl_dfs_setup_product_header(pplist, product_frame, set, parlist,
616  recipe,PIPEID,DICID,inherit) != CPL_ERROR_NONE) {
617 
618  cpl_msg_debug(cpl_func, "Problem in the main header of product DFS-compliance") ;
619  }
620 
621  /*Remove undesired keywords from main header*/
622  /* Once CPL recalculates these values, the following
623  * line should be removed
624  */
625  cpl_propertylist_erase_regexp(pplist,REM_PRIM_KEYS,0);
626 
627  /* Save the empty primary unit */
628  if (cpl_propertylist_save(pplist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
629  freeplist(pplist);
630  return -1;
631  }
632 
633  freeplist(pplist);
634  cpl_frameset_insert(set,product_frame);
635 
636  return 0;
637 }
638 
639 /*---------------------------------------------------------------------------*/
647 /*---------------------------------------------------------------------------*/
648 cpl_image *omega_smooth_image(cpl_image *in, int size)
649 {
650 
651  int i,nx, ny, type;
652  cpl_matrix *kernel;
653  cpl_mask *mask;
654  cpl_image *out;
655 
656  if (in == NULL)
657  return NULL;
658 
659 // if(size < 3)
660 // return NULL;
661 
662  nx = cpl_image_get_size_x(in);
663  ny = cpl_image_get_size_y(in);
664  type = cpl_image_get_type(in);
665 
666  kernel = cpl_matrix_new(size, size);
667 // cpl_matrix_fill(kernel, 1.0);
668 // out = cpl_image_filter_median(in, kernel);
669  cpl_matrix_delete(kernel);
670 
671  /* new code */
672 
673  mask = cpl_mask_new(size, size);
674  for (i = 0; i < size; ++i) {
675  int j = 0;
676  for (j = 0; j < size; j++)
677  {
678  cpl_mask_set(mask, i + 1, j + 1, CPL_BINARY_1);
679  }
680 
681  }
682 
683  out = cpl_image_new(nx, ny, type);
684  if(cpl_image_filter_mask(out, in, mask, CPL_FILTER_AVERAGE, CPL_BORDER_FILTER)
685  != CPL_ERROR_NONE){
686  cpl_msg_debug(cpl_func,"Cannot filter image. %s", cpl_error_get_message());
687  freeimage(out);
688  freemask(mask);
689  return NULL;
690  }
691 
692 
693  freemask(mask);
694  return (out);
695 
696 }
697 
698 /*---------------------------------------------------------------------------*/
710 /*---------------------------------------------------------------------------*/
711 char *omega_create_name(const char *instrument, const char *name, const char *suffix)
712 {
713  char *outname;
714  const char *end = "fits";
715 
716  if(instrument == NULL || name == NULL){
717  return NULL;
718  }
719  if(suffix == NULL)
720  suffix = end;
721 
722  sprintf(outname, "%s_%s.%s", instrument, name, suffix);
723 
724  return outname;
725 }
726 
737 int omega_biascor(cpl_image *image, const cpl_image *bias)
738 {
739 
740  if((image == NULL) || (bias == NULL))
741  return -1;
742 
743 
744  if(cpl_image_subtract(image, bias) != CPL_ERROR_NONE){
745  return -1;
746  }
747 
748 
749  return 0;
750 }
751 
762 const char * omega_get_extension_chipid(int ext)
763 {
764 
765  const char *chipid;
766 
767  switch (ext){
768  case 1:
769  chipid = "ESO_CCD_#65";
770  break;
771  case 2:
772  chipid = "ESO_CCD_#66";
773  break;
774  case 3:
775  chipid = "ESO_CCD_#67";
776  break;
777  case 4:
778  chipid = "ESO_CCD_#68";
779  break;
780  case 5:
781  chipid = "ESO_CCD_#73";
782  break;
783  case 6:
784  chipid = "ESO_CCD_#74";
785  break;
786  case 7:
787  chipid = "ESO_CCD_#75";
788  break;
789  case 8:
790  chipid = "ESO_CCD_#76";
791  break;
792  case 9:
793  chipid = "ESO_CCD_#81";
794  break;
795  case 10:
796  chipid = "ESO_CCD_#82";
797  break;
798  case 11:
799  chipid = "ESO_CCD_#83";
800  break;
801  case 12:
802  chipid = "ESO_CCD_#84";
803  break;
804  case 13:
805  chipid = "ESO_CCD_#89";
806  break;
807  case 14:
808  chipid = "ESO_CCD_#90";
809  break;
810  case 15:
811  chipid = "ESO_CCD_#91";
812  break;
813  case 16:
814  chipid = "ESO_CCD_#92";
815  break;
816  case 17:
817  chipid = "ESO_CCD_#69";
818  break;
819  case 18:
820  chipid = "ESO_CCD_#70";
821  break;
822  case 19:
823  chipid = "ESO_CCD_#71";
824  break;
825  case 20:
826  chipid = "ESO_CCD_#72";
827  break;
828  case 21:
829  chipid = "ESO_CCD_#77";
830  break;
831  case 22:
832  chipid = "ESO_CCD_#78";
833  break;
834  case 23:
835  chipid = "ESO_CCD_#79";
836  break;
837  case 24:
838  chipid = "ESO_CCD_#80";
839  break;
840  case 25:
841  chipid = "ESO_CCD_#85";
842  break;
843  case 26:
844  chipid = "ESO_CCD_#86";
845  break;
846  case 27:
847  chipid = "ESO_CCD_#87";
848  break;
849  case 28:
850  chipid = "ESO_CCD_#88";
851  break;
852  case 29:
853  chipid = "ESO_CCD_#93";
854  break;
855  case 30:
856  chipid = "ESO_CCD_#94";
857  break;
858  case 31:
859  chipid = "ESO_CCD_#95";
860  break;
861  case 32:
862  chipid = "ESO_CCD_#96";
863  break;
864  default:
865  cpl_msg_warning(cpl_func,"Unable to find CHIP ID for extension %d",ext);
866  chipid = NULL;
867  break;
868  }
869 
870  return chipid;
871 }
872 
883 {
884 
885  int orient = 1;
886 
887  if(((ext >= 1) && (ext <= 8)) || ((ext >=17) && (ext <= 24)))
888  orient = 1;
889  else if(((ext >= 9) && (ext <=16)) || ((ext >= 25) && (ext <= 32)))
890  orient = 2;
891  else
892  cpl_msg_warning(cpl_func,"Unable to get chip orientation. Using default 1");
893 
894 
895  return orient;
896 }
897 
916 int omega_save_image(const cpl_image *img,cpl_frameset *set,const cpl_parameterlist *pars,
917  cpl_propertylist *alist, const cpl_propertylist *qclist,cpl_type_bpp bpp,
918  const char *name, const char *recipe, cpl_frame *frame,
919  const cpl_frame *inherit, int isfirst)
920 {
921 
922  cpl_propertylist *plist;
923 
924  if((img == NULL) || (set == NULL) || (pars == NULL) ||
925  (name == NULL) || (frame == NULL))
926  return -1;
927 
928  if(isfirst){
929  /* Save primary header */
930  if(omega_save_primary(set,pars,name,recipe,NULL,frame,inherit) == -1){
931  cpl_msg_error(cpl_func,"Cannot save primary header of product");
932  return -1;
933  }
934  }
935 
936  /* Save extension */
937  plist = cpl_propertylist_new();
938 
939  if(alist != NULL)
940  omega_pfits_update_header(plist,alist);
941 
942  /* Add DataFlow keywords in extension header */
943  if (cpl_dfs_setup_product_header(plist, frame, set, pars,
944  recipe,PIPEID,DICID,inherit) != CPL_ERROR_NONE) {
945  cpl_msg_warning(cpl_func, "Unable to setup extension header of %s. %s",name,
946  cpl_error_get_message()) ;
947  }
948 
949  /*Remove undesired keywords from extension header*/
950  cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
951 
952  /* Append QC list to the extension header */
953  if(qclist != NULL)
954  cpl_propertylist_append(plist, qclist);
955 
956  /* Save the product */
957  if (cpl_image_save(img,name,bpp,plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
958  cpl_msg_error(cpl_func,"Cannot save product. %s", cpl_error_get_message());
959  freeplist(plist);
960  return -1;
961  }
962 
963  freeplist(plist);
964 
965  return 0;
966 
967 }
968 
987 int omega_save_table(const cpl_table *tbl,cpl_frameset *set,const cpl_parameterlist *pars,
988  cpl_propertylist *alist, const cpl_propertylist *qclist,const char *name,
989  const char *recipe, cpl_frame *frame,const cpl_frame *inherit, int isfirst)
990 {
991 
992  cpl_propertylist *plist;
993 
994  if((tbl == NULL) || (set == NULL) || (pars == NULL) ||
995  (name == NULL) || (frame == NULL))
996  return -1;
997 
998  if(isfirst){
999  /* Save primary header */
1000  if(omega_save_primary(set,pars,name,recipe,NULL,frame,inherit) == -1){
1001  cpl_msg_error(cpl_func,"Cannot save primary header of product");
1002  return -1;
1003  }
1004  }
1005 
1006  /* Save the extension */
1007  plist = cpl_propertylist_new();
1008 
1009  if(alist != NULL)
1010  omega_pfits_update_header(plist,alist);
1011 
1012  /* Add DataFlow keywords in extension header */
1013  if (cpl_dfs_setup_product_header(plist, frame, set, pars,
1014  recipe,PIPEID,DICID,inherit) != CPL_ERROR_NONE) {
1015 
1016  cpl_msg_warning(cpl_func, "Unable to setup extension header of %s. %s",name,
1017  cpl_error_get_message()) ;
1018  }
1019 
1020  /*Remove undesired keywords from extension header*/
1021  cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
1022 
1023  /* Append QC list to the extension header */
1024  if(qclist != NULL)
1025  cpl_propertylist_append(plist, qclist);
1026 
1027  /* Save the product */
1028  if (cpl_table_save(tbl,NULL,plist,name,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
1029  cpl_msg_error(cpl_func,"Cannot save product. %s", cpl_error_get_message());
1030  freeplist(plist);
1031  return -1;
1032  }
1033 
1034  freeplist(plist);
1035 
1036  return 0;
1037 }
1038 
1056 int omega_save_fits(omega_fits *scifits,cpl_frameset *set, const cpl_parameterlist *pars,
1057  const cpl_propertylist *qclist, cpl_type_bpp bpp,const char *name,
1058  const char *recipe,cpl_frame *product_frame, const cpl_frame *inherit,
1059  const int isfirst)
1060 {
1061 
1062  cpl_propertylist *plist;
1063 
1064  if((scifits == NULL) || (set == NULL) || (pars == NULL) ||
1065  (name == NULL) || (product_frame == NULL))
1066  return -1;
1067 
1068 
1069  if(isfirst){
1070 
1071  plist = cpl_propertylist_duplicate(omega_fits_get_phu(scifits));
1072 
1073  if(omega_save_primary(set,pars,name,recipe,plist,product_frame,inherit) == -1){
1074  cpl_msg_error(cpl_func,"Cannot save primary header of product");
1075  freeplist(plist);
1076  return -1;
1077  }
1078 
1079  freeplist(plist);
1080  }
1081 
1082  /* Save the extension */
1083  plist = cpl_propertylist_duplicate(omega_fits_get_ehu(scifits));
1084 
1085  /* Add DataFlow keywords in extension header */
1086  if (cpl_dfs_setup_product_header(plist, product_frame, set, pars,
1087  recipe,PIPEID,DICID,inherit) != CPL_ERROR_NONE) {
1088 
1089  cpl_msg_warning(cpl_func, "Unable to setup extension header of %s. %s",name,
1090  cpl_error_get_message()) ;
1091  }
1092 
1093  /*Remove undesired keywords from extension header*/
1094  cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
1095 
1096  /* Append QC list to the extension header */
1097  if(qclist != NULL)
1098  cpl_propertylist_append(plist, qclist);
1099 
1100  /* Save the product */
1101  if (cpl_image_save(omega_fits_get_image(scifits),name,bpp,
1102  plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
1103  cpl_msg_error(cpl_func,"Cannot save product %s. %s", name, cpl_error_get_message());
1104  freeplist(plist);
1105  return -1;
1106  }
1107 
1108  freeplist(plist);
1109 
1110  return 0;
1111 }
1112 
1113 cpl_error_code omega_get_pixelscale(cpl_propertylist *plist,
1114  double * pixscale_x, double * pixscale_y){
1115 
1116  double cd11= 0.;
1117  double cd12= 0.;
1118  double cd21= 0.;
1119  double cd22= 0.;
1120 
1121  if(cpl_propertylist_has(plist,"CD1_1") &&
1122  cpl_propertylist_has(plist,"CD1_2") &&
1123  cpl_propertylist_has(plist,"CD2_1") &&
1124  cpl_propertylist_has(plist,"CD2_2")){
1125  cd11= cpl_propertylist_get_double(plist, "CD1_1");
1126  cd12= cpl_propertylist_get_double(plist, "CD1_2");
1127  cd21= cpl_propertylist_get_double(plist, "CD2_1");
1128  cd22= cpl_propertylist_get_double(plist, "CD2_2");
1129  }
1130  else{
1131  cpl_error_set_message(cpl_func,CPL_ERROR_DATA_NOT_FOUND, "CD matrix not"
1132  " complete. Pixel scale can not be computed");
1133  return cpl_error_get_code();
1134  }
1135 
1136  *pixscale_x = sqrt (cd11*cd11 + cd21*cd21);
1137  *pixscale_y = sqrt (cd12*cd12 + cd22*cd22);
1138 
1139  cpl_msg_debug(cpl_func,"Pixelscale "
1140  "x: %g y: %g",*pixscale_x, *pixscale_y);
1141 
1142  return cpl_error_get_code();
1143 
1144 }
1145 
1157 cpl_error_code omega_get_wcsshift(cpl_propertylist * wcslist1,
1158  cpl_propertylist * wcslist2, double * xshift, double * yshift){
1159 
1160  cpl_wcs * wcs1=NULL;
1161  cpl_wcs * wcs2=NULL;
1162 
1163  wcs1=cpl_wcs_new_from_propertylist(wcslist1);
1164  wcs2=cpl_wcs_new_from_propertylist(wcslist2);
1165 
1166  if(wcs1 == NULL || wcs2 == NULL )
1167  {
1168  cpl_msg_warning(cpl_func, "WCS informations missing - assuming no shift "
1169  "of the x and y coordinate");
1170  *xshift=0;
1171  *yshift=0;
1172  cpl_msg_debug(cpl_func, "Coordinateshift: xshif=%g, yshift=%g",
1173  *xshift,*yshift);
1174  cpl_wcs_delete(wcs1);
1175  cpl_wcs_delete(wcs2);
1176  return cpl_error_get_code();
1177  }
1178  else{
1179  *xshift=cpl_array_get(cpl_wcs_get_crpix(wcs1),0,NULL) -
1180  cpl_array_get(cpl_wcs_get_crpix(wcs2),0,NULL);
1181  *yshift=cpl_array_get(cpl_wcs_get_crpix(wcs1),1,NULL) -
1182  cpl_array_get(cpl_wcs_get_crpix(wcs2),1,NULL);
1183  }
1184 
1185  cpl_wcs_delete(wcs1);
1186  cpl_wcs_delete(wcs2);
1187 
1188  cpl_msg_debug(cpl_func, "Coordinateshift: xshif=%g, yshift=%g",
1189  *xshift,*yshift);
1190 
1191  return cpl_error_get_code();
1192 }
1193