OMEGA Pipeline Reference Manual  1.0.5
omega_wcscor.c
1 /* $Id: omega_wcscor.c,v 1.38 2011-12-21 14:53:55 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: 2011-12-21 14:53:55 $
24  * $Revision: 1.38 $
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 <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <math.h>
40 #include <cpl.h>
41 
42 #include "omega_wcscor.h"
43 #include "omega_catalog.h"
44 #include "omega_dfs.h"
45 #include "omega_pfits.h"
46 #include "omega_trim.h"
47 #include "omega_utils.h"
48 
49 /*-----------------------------------------------------------------------------
50  Function prototypes
51  -----------------------------------------------------------------------------*/
52 static char *my_strchr(char *, char);
53 
54 /* Search for a char in a string and return its position*/
55 static char * my_strchr(char *string, char find)
56 {
57  while(*string != find)
58  {
59  if(*string == '\0')
60  return NULL;
61 
62  ++string;
63  }
64 
65  return (string);
66 }
67 
68 /*----------------------------------------------------------------------------*/
97 int omega_shift_refpix(const cpl_frame *frame, int xn, cpl_propertylist *xlist)
98 {
99  int xoffset = 0;
100  int yoffset = 0;
101  double crpix1 = 0.0;
102  double crpix2 = 0.0;
103  cpl_vector *region_vec;
104  cpl_propertylist *plist;
105 
106 
107  if(omega_pfits_check_instrume(frame) == 1){
108  /* It's a WFI image */
109  plist = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
110  omega_wfi_correct_wcs(plist, xlist);
111  freeplist(plist);
112  }
113 
114  region_vec = get_trim_region(frame, xn);
115 
116  if(region_vec != NULL){
117  /*
118  * Shift reference pixels of trimmed image
119  */
120  xoffset = (int)cpl_vector_get(region_vec, 0);
121  xoffset = xoffset -1;
122  yoffset = (int)cpl_vector_get(region_vec, 1);
123  yoffset = yoffset -1;
124 
125  crpix1 = cpl_propertylist_get_double(xlist, "CRPIX1");
126  crpix2 = cpl_propertylist_get_double(xlist, "CRPIX2");
127  crpix1 = crpix1 - xoffset;
128  crpix2 = crpix2 - yoffset;
129 
130  cpl_propertylist_update_double(xlist, "CRPIX1", crpix1);
131  cpl_propertylist_update_double(xlist, "CRPIX2", crpix2);
132 
133  cpl_vector_delete(region_vec);
134  }
135 
136  return 0;
137 }
138 
139 
163 cpl_propertylist *omega_match_points(const char *reduced, const char *reduced_weight, const cpl_frame *catalog, cpl_parameterlist *pars,
164  int ext, int *nmatches, double *mratio)
165 {
166 
167  int i, nsources=0, nsources_flag0=0, nstds, nstars, npattern;
168  int mode = 0;
169  int niter = 1;
170  int npars = 0;
171  int SextractorFlagLimit=0;
172  int imsizex=0;
173  int imsizey=0;
174  //int shiftvalue=0;
175  int nsources_firstpass=0;
176  double matchlimit=0.;
177  double zp = 0.0;
178  double gain = 1.0;
179  double x1,x2,y1,y2;
180  double pradius = 0.0;
181  double maxpradius = 0.0;
182  double tol = 0.0;
183  double astrom_thre = 0.0;
184  double scale = 0.0;
185  double angle = 0.0;
186  double SextractorClassStar=0.0;
187  double centralwl=0.0;
188  char *cmd = NULL;
189  const char *text = NULL;
190  const char *path;
191  const char *sex_conf = NULL;
192  const char *sex_conv = NULL;
193  const char *sex_par = NULL;
194  const char *sex_nnw = NULL;
195  const char *srcs = "omega_cat_astrom_sources.fits";
196  cpl_parameter *par;
197  cpl_array *status, *matches;
198  cpl_table *sources=NULL, *sources_flag0=NULL, *stds, *extracted, *data;
199  cpl_table *dummy_table1=NULL;
200  cpl_table * dummy_table=NULL;
201  //cpl_table * tshift1=NULL;
202  //cpl_table * tshift2=NULL;
203  cpl_matrix *from, *to, *xymat, *rdmat, *stars, *pattern;
204  cpl_wcs *wcs;
205  cpl_vector *coords;
206  cpl_wcs_platesol_fitmode fitmode = CPL_WCS_PLATESOL_4;
207  cpl_propertylist *xlist = NULL;
208  cpl_propertylist *plist = NULL;
209  cpl_propertylist *filterlist = NULL;
210 
211  cpl_propertylist *aplist = NULL;
212  cpl_propertylist *p;
213 
214  /* Get parameters */
215  npars = cpl_parameterlist_get_size(pars);
216  par = cpl_parameterlist_get_first(pars);
217 
218  for(i=0; i<npars; i++) {
219  text = cpl_parameter_get_alias(par, CPL_PARAMETER_MODE_CLI);
220  if(strcmp("bin-path", text) == 0) {
221  path = cpl_parameter_get_string(par) ;
222  }
223  else if(strcmp("sex-config", text) == 0) {
224  sex_conf = cpl_parameter_get_string(par) ;
225  }
226  else if(strcmp("sex-conv", text) == 0) {
227  sex_conv = cpl_parameter_get_string(par) ;
228  }
229  else if(strcmp("sex-param", text) == 0) {
230  sex_par = cpl_parameter_get_string(par) ;
231  }
232  else if(strcmp("sex-nnw", text) == 0) {
233  sex_nnw = cpl_parameter_get_string(par) ;
234  }
235  else if(strcmp("astrom-thre", text) == 0){
236  astrom_thre = cpl_parameter_get_double(par);
237  }
238  else if(strcmp("nstars", text) == 0){
239  nstars = cpl_parameter_get_int(par);
240  }
241  else if(strcmp("npattern", text) == 0){
242  npattern = cpl_parameter_get_int(par);
243  }
244  else if(strcmp("pradius", text) == 0){
245  pradius = cpl_parameter_get_double(par);
246  }
247  else if(strcmp("maxpradius", text) == 0){
248  maxpradius = cpl_parameter_get_double(par);
249  }
250  else if(strcmp("tol", text) == 0){
251  tol = cpl_parameter_get_double(par);
252  }
253  else if(strcmp("platesol", text) == 0){
254  mode = cpl_parameter_get_int(par);
255  if(mode == 6) fitmode = CPL_WCS_PLATESOL_6;
256  }
257  else if(strcmp("niter", text) == 0){
258  niter = cpl_parameter_get_int(par);
259  }
260  else if(strcmp("SextractorFlagLimit", text) == 0){
261  SextractorFlagLimit = cpl_parameter_get_int(par);
262  }
263  else if(strcmp("SextractorClassStar", text) == 0){
264  SextractorClassStar= cpl_parameter_get_double(par);
265  }
266 
267  par = cpl_parameterlist_get_next(pars);
268 
269  }
270 
271 
272  /*
273  * Get Zeropoint for science frames. For STD,
274  * this will be calculated later.
275  */
276  xlist = cpl_propertylist_load(reduced, 1);
277  if(cpl_propertylist_has(xlist,"ESO QC SCI ZEROPNT"))
278  zp = cpl_propertylist_get_double(xlist,"ESO QC SCI ZEROPNT");
279 
280  if(cpl_propertylist_has(xlist,"NAXIS1"))
281  imsizex = cpl_propertylist_get_int(xlist,"NAXIS1");
282  if(cpl_propertylist_has(xlist,"NAXIS2"))
283  imsizey = cpl_propertylist_get_int(xlist,"NAXIS2");
284 
285  /*Get filter info - used to sort the right filter in the USNO table*/
286  plist = cpl_propertylist_load(reduced, 0);
287  if(cpl_propertylist_has(xlist,"EXTNAME") &&
288  !cpl_propertylist_has(plist,"EXTNAME"))
289  cpl_propertylist_copy_property(plist,xlist,"EXTNAME");
290 
291  filterlist=omega_pfits_get_filter_info(plist);
292 
293  if(cpl_propertylist_has(filterlist,"CWL")){
294  centralwl=cpl_propertylist_get_double(filterlist, "CWL");
295  }
296  else{
297  centralwl=0.;
298  }
299  freeplist(plist);
300  freeplist(filterlist);
301 
302  /*
303  * Get the gain for this extension.
304  */
305 
306  omega_pfits_get_conad(xlist, &gain);
307  cpl_msg_debug(cpl_func,"gain: %f",gain);
308 
309 
310  sources = NULL;
311 
312  for(i = 0; i < 15; i++) {
313  /* Create catalog of sources from image */
314 
315  if(reduced_weight != NULL){
316  cmd = cpl_sprintf("%s/sex %s -WEIGHT_TYPE MAP_WEIGHT -WEIGHT_IMAGE %s "
317  "-c %s -PARAMETERS_NAME %s -FILTER_NAME %s -STARNNW_NAME %s "
318  "-FILTER Y -DETECT_THRESH %g -ANALYSIS_THRESH %g -GAIN %g -MAG_ZEROPOINT %f "
319  "-CATALOG_TYPE FITS_1.0 -CATALOG_NAME %s -CHECKIMAGE_NAME %s "
320  "-CHECKIMAGE_TYPE OBJECTS -DEBLEND_NTHRESH 1 2>/dev/null",
321  path, reduced, reduced_weight, sex_conf, sex_par, sex_conv, sex_nnw, astrom_thre, astrom_thre,
322  gain, zp, srcs, "omega_ima_detected_astrom_srcs.fits");
323  }
324  else
325  {
326  cmd = cpl_sprintf("%s/sex %s -c %s -PARAMETERS_NAME %s -FILTER_NAME %s -STARNNW_NAME %s "
327  "-FILTER Y -DETECT_THRESH %g -ANALYSIS_THRESH %g -GAIN %g -MAG_ZEROPOINT %f "
328  "-CATALOG_TYPE FITS_1.0 -CATALOG_NAME %s -CHECKIMAGE_NAME %s "
329  "-CHECKIMAGE_TYPE OBJECTS -DEBLEND_NTHRESH 1 2>/dev/null",
330  path, reduced, sex_conf, sex_par, sex_conv, sex_nnw, astrom_thre, astrom_thre,
331  gain, zp, srcs, "omega_ima_detected_astrom_srcs.fits");
332  }
333 
334  cpl_msg_debug(cpl_func,"cmd: %s", cmd);
335  if (system(cmd) != 0) {
336  cpl_msg_error(cpl_func,"Failed to detect sources in image using Sextractor");
337  freespace(cmd);
338  freeplist(xlist);
339  return NULL;
340  }
341  freespace(cmd);
342 
343  data = cpl_table_load(srcs, 1, 0);
344  if (data == NULL) {
345  cpl_msg_error(cpl_func,"Sources table is NULL");
346  freeplist(xlist);
347  return NULL;
348  }
349 
350  freetable(sources);
351  sources_flag0 = omega_filter_table_int(data, "FLAGS",
352  CPL_NOT_GREATER_THAN, SextractorFlagLimit, &nsources_flag0);
353  sources = omega_filter_table_float(sources_flag0, "CLASS_STAR",
354  CPL_NOT_LESS_THAN, SextractorClassStar, &nsources);
355  freetable(data);
356  freetable(sources_flag0);
357 
358  if (i==0){
359  nsources_firstpass=nsources;
360  }
361 
362  if(nsources > 1000) {
363  /* Detect again with greater threshold */
364  astrom_thre = astrom_thre + 30;
365  }
366  else
367  break;
368  }
369 
370 
371  /* Sort sources table by magnitude */
372  p = cpl_propertylist_new();
373  cpl_propertylist_append_bool(p,"MAG_AUTO",0);
374  if (cpl_table_sort(sources, p) != CPL_ERROR_NONE) {
375  cpl_msg_error(cpl_func,"Cannot sort sources table");
376  freeplist(p);
377  freeplist(xlist);
378  freetable(sources);
379  return NULL;
380  }
381  freeplist(p);
382 
383 
384  /*If there are too many sources in the image, pattern matching will very
385  * likely fail. In this case for the pattern-matching-first-guess only
386  * objects in a smaller spatial region are used*/
387 
388  if(nsources_firstpass>500)
389  {
390  /*cpl_msg_info(cpl_func,"There are too many sources for pattern matching,"
391  " shrinking the field size ... ");*/
392  dummy_table=cpl_table_duplicate(sources);
393  freetable(sources);
394  cpl_table_and_selected_float(dummy_table,"X_IMAGE",CPL_NOT_LESS_THAN,1.+500.);
395  cpl_table_and_selected_float(dummy_table,"Y_IMAGE",CPL_NOT_LESS_THAN,1.+500.);
396  cpl_table_and_selected_float(dummy_table,"X_IMAGE",CPL_NOT_GREATER_THAN,(float)imsizex-500.);
397  cpl_table_and_selected_float(dummy_table,"Y_IMAGE",CPL_NOT_GREATER_THAN,(float)imsizey-500.);
398 
399  sources= cpl_table_extract_selected(dummy_table);
400 
401  cpl_table_not_selected(dummy_table);
402  dummy_table1=cpl_table_extract_selected(dummy_table);
403 
404  cpl_table_insert(sources, dummy_table1, cpl_table_get_nrow(sources));
405  freetable(dummy_table);
406  freetable(dummy_table1);
407  nsources=cpl_table_get_nrow(sources);
408  }
409 
410  cpl_msg_info(cpl_func,"Number of sources in image: %d", nsources);
411  if(nsources < nstars){
412  nstars = nsources -1;
413  }
414 
415 
416  if(pradius > maxpradius)
417  pradius = maxpradius;
418 
419 
420  /* Create matrix of X,Y coordinates */
421  from = cpl_matrix_new(nsources, 2);
422  for (i=0; i<nsources; i++){
423  float xim = cpl_table_get_float(sources, "X_IMAGE", i, NULL);
424  float yim = cpl_table_get_float(sources, "Y_IMAGE", i, NULL);
425  cpl_matrix_set(from, i, 0, xim);
426  cpl_matrix_set(from, i, 1, yim);
427  }
428 
429  /* Create matrix to be used in PPM */
430  stars = cpl_matrix_transpose_create(from);
431 
432  /* Get coverage of image */
433  if(omega_get_coverage(xlist, 0, from, &x1, &x2, &y1, &y2) != 0){
434  cpl_msg_error(cpl_func,"Cannot get coverage of image");
435  freematrix(from);
436  freematrix(stars);
437  freeplist(xlist);
438  freetable(sources);
439  return NULL;
440  }
441  freematrix(from);
442 
443  /* Get USNOA stars that fall in region of image */
444  /* ramin = x1 ramax = x2 decmin = y1 decmax = y2;*/
445  /* Write in 'nstds' the number of sources in the table */
446  coords = cpl_vector_new(4);
447  cpl_vector_set(coords, 0, x1);
448  cpl_vector_set(coords, 1, x2);
449  cpl_vector_set(coords, 2, y1);
450  cpl_vector_set(coords, 3, y2);
451 
452  stds = omega_get_usnoa_table(catalog, coords, &nstds);
453  if (stds == NULL) {
454  cpl_msg_warning(cpl_func,"Cannot find USNOA2 stars in this region: {RA-RA:DEC-DEC}={%g-%g:%g=%g}",
455  x1,x2,y1,y2);
456  freeplist(xlist);
457  freematrix(stars);
458  freetable(sources);
459  freevector(coords);
460  return NULL;
461  }
462  freevector(coords);
463 
464 
465  cpl_msg_info(cpl_func,"Number of USNOA2 stars in this region: %d", nstds);
466  cpl_msg_debug(cpl_func,"%d USNOA2 stars fall in region: {RA-RA:DEC-DEC}={%g--%g:%g--%g}", nstds,x1,x2,y1,y2);
467 
468  /* Convert Ra, Dec to X,Y using the WCS information from image */
469  from = cpl_matrix_new(nstds, 2);
470  for (i=0; i<nstds; i++){
471  cpl_matrix_set(from, i, 0, cpl_table_get_double(stds, "RA2000", i, NULL));
472  cpl_matrix_set(from, i, 1, cpl_table_get_double(stds, "Dec2000", i, NULL));
473  }
474 
475  to = NULL;
476  status = NULL;
477  wcs = cpl_wcs_new_from_propertylist(xlist);
478  if(cpl_wcs_convert(wcs, from, &to, &status, CPL_WCS_WORLD2PHYS) != CPL_ERROR_NONE){
479  freewcs(wcs);
480  freearray(status);
481  freematrix(from);
482  freematrix(stars);
483  freematrix(to);
484  freeplist(xlist);
485  freetable(sources);
486  freetable(stds);
487  cpl_msg_error(cpl_func,"Error in cpl_wcs conversion. %s",cpl_error_get_message());
488  return NULL;
489  }
490  freewcs(wcs);
491  freematrix(from);
492  freearray(status);
493 
494  /* Add the predicted x,y coordinate columns to the usnoa table */
495  cpl_table_new_column(stds,"xpredict",CPL_TYPE_FLOAT);
496  cpl_table_set_column_unit(stds,"xpredict","pixels");
497  cpl_table_new_column(stds,"ypredict",CPL_TYPE_FLOAT);
498  cpl_table_set_column_unit(stds,"ypredict","pixels");
499 
500 
501 
502  for(i=0; i< nstds; i++){
503  float xp = (float)cpl_matrix_get(to, i, 0);
504  float yp = (float)cpl_matrix_get(to, i, 1);
505  cpl_table_set_float(stds,"xpredict", i, xp);
506  cpl_table_set_float(stds,"ypredict", i, yp);
507  }
508  freematrix(to);
509 
510  //cpl_table_dump(stds,0,1000,NULL);
511 
512  /*Unselect objects falling outside the image borders +- fudge*/
513 
514 
515 
516  /* Sort stds table by magnitude */
517  p = cpl_propertylist_new();
518 
519  if (centralwl>6000){
520  cpl_propertylist_append_bool(p,"MagR",0);
521  cpl_msg_info(cpl_func,"Sorting standard star catalogue by R-band mag");
522  }
523  else{
524  cpl_propertylist_append_bool(p,"MagB",0);
525  cpl_msg_info(cpl_func,"Sorting standard star catalogue by B-band mag");
526  }
527 
528  if (cpl_table_sort(stds, p) != CPL_ERROR_NONE) {
529  cpl_msg_error(cpl_func,"Cannot sort stds table");
530  freeplist(p);
531  freetable(sources);
532  freematrix(stars);
533  freetable(stds);
534  freeplist(xlist);
535  return NULL;
536  }
537  freeplist(p);
538 
539 
540  /* If there are too many objects in the catalog, pattern matching will very
541  * likely fail. In this case for the pattern-matching-first-guess only
542  * objects in a smaller spatial region are used */
543 
544  dummy_table=cpl_table_duplicate(stds);
545  freetable(stds);
546 
547  if(nsources_firstpass>500){
548  cpl_table_and_selected_float(dummy_table,"xpredict",CPL_NOT_LESS_THAN,1.+600.);
549  cpl_table_and_selected_float(dummy_table,"ypredict",CPL_NOT_LESS_THAN,1.+600.);
550  cpl_table_and_selected_float(dummy_table,"xpredict",CPL_NOT_GREATER_THAN,(float)imsizex-600.);
551  cpl_table_and_selected_float(dummy_table,"ypredict",CPL_NOT_GREATER_THAN,(float)imsizey-600.);
552  }
553  else {
554  cpl_table_and_selected_float(dummy_table,"xpredict",CPL_NOT_LESS_THAN,1.+100.);
555  cpl_table_and_selected_float(dummy_table,"ypredict",CPL_NOT_LESS_THAN,1.+100.);
556  cpl_table_and_selected_float(dummy_table,"xpredict",CPL_NOT_GREATER_THAN,(float)imsizex-100.);
557  cpl_table_and_selected_float(dummy_table,"ypredict",CPL_NOT_GREATER_THAN,(float)imsizey-100.);
558  }
559 
560  stds= cpl_table_extract_selected(dummy_table);
561  cpl_table_not_selected(dummy_table);
562  dummy_table1=cpl_table_extract_selected(dummy_table);
563 
564  cpl_table_insert(stds, dummy_table1, cpl_table_get_nrow(stds));
565  freetable(dummy_table);
566  freetable(dummy_table1);
567 
568  if (stds == NULL) {
569  cpl_msg_warning(cpl_func,"Cannot find USNOA2 stars within the image "
570  "borders");
571  freewcs(wcs);
572  freearray(status);
573  freematrix(from);
574  freematrix(stars);
575  freematrix(to);
576  freeplist(xlist);
577  freetable(sources);
578  return NULL;
579  }
580 
581 
582 
583 
584 
585 
586  nstds=cpl_table_get_nrow(stds);
587  cpl_msg_info(cpl_func,"Number of USNOA2 stars falling on the image: %d", nstds);
588 
589 
590  /* Prepare the matrices for the pattern matching */
591  pattern = cpl_matrix_new(2, nstds);
592  for(i=0; i<nstds; i++){
593  float x = cpl_table_get_float(stds, "xpredict", i, NULL);
594  float y = cpl_table_get_float(stds, "ypredict", i, NULL);
595  cpl_matrix_set(pattern, 0, i, x);
596  cpl_matrix_set(pattern, 1, i, y);
597  }
598 
599 
600  if(nstds < npattern){
601  npattern = nstds -1;
602  }
603 
604  cpl_msg_debug(cpl_func,"stars: % " CPL_SIZE_FORMAT " , nstars: %d pattern: % " CPL_SIZE_FORMAT " npattern: %d",
605  cpl_matrix_get_ncol(stars), nstars, cpl_matrix_get_ncol(pattern),
606  npattern);
607 
608 
609 /*
610 
611 
612  Define the number of (bright)objects that should not be used for the
613  * first guess in the pattern matching as they might be saturated, ...
614 
615 
616 
617  shift the matrix
618 
619  if(nsources_firstpass>1000){
620  shiftvalue = nstds < nsources ? (int)nstds*0.0 : (int)nsources*0.0;
621  }
622  else{
623  shiftvalue = nstds < nsources ? (int)nstds*0.0 : (int)nsources*0.0;
624  }
625 
626 
627  cpl_matrix_shift(stars, 0,0 - shiftvalue);
628  cpl_matrix_shift(pattern,0,0 - shiftvalue);
629  cpl_msg_debug(cpl_func,"shift_value: %d",shiftvalue);
630 
631  Shift the tables to keep them in sync with the matrix
632  tshift1 = cpl_table_extract(sources,0,shiftvalue);
633  tshift2 = cpl_table_extract(sources,shiftvalue,cpl_table_get_nrow(sources)-shiftvalue);
634  freetable(sources);
635  sources=cpl_table_duplicate(tshift2);
636  cpl_table_insert(sources,tshift1,cpl_table_get_nrow(sources));
637  freetable(tshift1);
638  freetable(tshift2);
639  //cpl_table_dump_structure(sources,NULL);
640 
641  tshift1 = cpl_table_extract(stds,0,shiftvalue);
642  tshift2 = cpl_table_extract(stds,shiftvalue,cpl_table_get_nrow(stds)-shiftvalue);
643  freetable(stds);
644  stds=cpl_table_duplicate(tshift2);
645  cpl_table_insert(stds,tshift1,cpl_table_get_nrow(stds));
646  freetable(tshift1);
647  freetable(tshift2);
648  //cpl_table_dump_structure(sources,NULL);
649 
650 */
651 
652  /* Call the PPM routine
653  * If no matches, less than 25%, or less then 5 are found, change nstar and
654  * try again
655  */
656  matchlimit = nstds < nsources ? (double)nstds*0.25 : (double)nsources*0.25;
657  if(matchlimit < 5) matchlimit=5;
658  cpl_msg_debug(cpl_func,"Match limit: %f", matchlimit);
659  for (i = 0; i < 4; i++) {
660 
661  *nmatches = 0;
662  matches = NULL;
663  cpl_msg_debug(cpl_func,"nstars: %d - npattern: %d ", nstars, npattern);
664  matches = cpl_ppm_match_points(stars, nstars, 0.5, pattern, npattern,
665  15, tol, pradius, NULL, NULL, &scale, &angle);
666  if(matches != NULL){
667  *nmatches = cpl_array_get_size(matches) - cpl_array_count_invalid(matches);
668  }
669  if((matches == NULL) || (*nmatches < matchlimit )) {
670  cpl_msg_debug(cpl_func,"nstars: %d npattern: %d i: %d",nstars,npattern,i );
671 
672  if (i==1){
673  npattern=20;
674  nstars=35;
675  }
676 
677  if (i==2){
678  npattern=25;
679  nstars=50;
680  }
681 
682  if (i==3){
683  freearray(matches);
684  break;
685  }
686 
687  cpl_msg_debug(cpl_func,"Increasing number of stars in PPM; scale=%g angle=%g "
688  "nstars=%d npattern=%d nmatches=%d",scale,angle,nstars,npattern,*nmatches);
689 
690  freearray(matches);
691  continue;
692  }
693  else
694  break;
695 
696  }
697  *mratio = (double )(*nmatches / (double)nsources);
698 
699  if((matches == NULL) || (*nmatches < matchlimit)){
700  cpl_msg_error(cpl_func,"Error in PPM module: Not enough matches found");
701  freematrix(stars);
702  freematrix(pattern);
703  freetable(sources);
704  freetable(stds);
705  freeplist(xlist);
706  freearray(matches);
707  return NULL;
708  }
709  freematrix(stars);
710 
711  cpl_msg_info(cpl_func, "There are %d matches between USNOA2 and image", *nmatches);
712 
713  /* Get the RA and DEC from the pattern identifications */
714  cpl_table_new_column(sources, "RA2000", CPL_TYPE_DOUBLE);
715  cpl_table_new_column(sources, "Dec2000", CPL_TYPE_DOUBLE);
716  cpl_table_unselect_all(stds);
717  cpl_table_unselect_all(sources);
718  for(i=0; i<cpl_matrix_get_ncol(pattern); i++){
719  int null;
720  int index = cpl_array_get_int(matches,i, &null);
721  if(!null){
722  double ra = cpl_table_get_double(stds, "RA2000", i, NULL);
723  double dec = cpl_table_get_double(stds, "Dec2000", i, NULL);
724  cpl_table_set(sources, "RA2000", index, ra);
725  cpl_table_set(sources, "Dec2000", index, dec);
726  cpl_table_select_row(sources, index);
727  }
728  }
729 
730  freearray(matches);
731  freematrix(pattern);
732 
733  /* Create two matrices for plate solution fitting */
734  extracted = cpl_table_extract_selected(sources);
735  rdmat = cpl_matrix_new(cpl_table_get_nrow(extracted), 2);
736  xymat = cpl_matrix_new(cpl_table_get_nrow(extracted), 2);
737  for (i=0; i<cpl_table_get_nrow(extracted); i++){
738  double ra = cpl_table_get_double(extracted, "RA2000", i, NULL);
739  double dec = cpl_table_get_double(extracted, "Dec2000", i, NULL);
740  cpl_matrix_set(rdmat, i, 0, ra);
741  cpl_matrix_set(rdmat, i, 1, dec);
742  float x = cpl_table_get_float(extracted, "X_IMAGE", i, NULL);
743  float y = cpl_table_get_float(extracted, "Y_IMAGE", i, NULL);
744  cpl_matrix_set(xymat, i, 0, x);
745  cpl_matrix_set(xymat, i, 1, y);
746  }
747  freetable(extracted);
748  freetable(stds);
749  freetable(sources);
750 
751  if(cpl_wcs_platesol(xlist, rdmat, xymat, niter, 3.0, fitmode,
752  CPL_WCS_MV_CRPIX, &aplist) != CPL_ERROR_NONE) {
753  cpl_msg_error(cpl_func,"Cannot calculate plate solution. %s", cpl_error_get_message());
754  freematrix(xymat);
755  freematrix(rdmat);
756  freeplist(xlist);
757  return NULL;
758  }
759  freematrix(xymat);
760  freematrix(rdmat);
761  freeplist(xlist);
762 
763  /* Return updated WCS in header */
764 
765  return aplist;
766 
767 }
768 
769 /*----------------------------------------------------------------
770 
771  This function will read the WCS information from a WFI header
772  and correct it using CASU initwcsimage functions
773 
774 ------------------------------------------------------------------*/
775 
776 void omega_wfi_correct_wcs(cpl_propertylist *mplist, cpl_propertylist *xplist)
777 {
778  int i = 0;
779  double xoff = 0.;
780  double yoff = 0.;
781  double tpa = 0.;
782  double tpd = 0;
783  double pixsca = 0.238;
784  double rotskypa = 0.0;
785  double angle = 0.0;
786  double xapoff = 0.0;
787  double yapoff = 0.0;
788  double secd = 0.0;
789  double aa = 0.0;
790  double aap = 0.0;
791  double bb = 0.0;
792  double bbp = 0.0;
793  double dd = 0.0;
794  double ddp = 0.0;
795  double eep = 0.0;
796  double ee = 0.0;
797  double cc = 0.0;
798  double ff = 0.0;
799  char key[80]= "";
800  char ccdstr[80] = "";
801  const char *ccd = NULL;
802 
803 /*Get the CCD index*/
804  if(cpl_propertylist_has(xplist, "ESO DET CHIP ID") == 1){
805  ccd = cpl_propertylist_get_string(xplist, "ESO DET CHIP ID");
806  }
807  else {
808  for(i=1; i<=8; i++){
809  sprintf(key,"ESO DET CHIP%d ID", i);
810  if(cpl_propertylist_has(xplist,key)==1){
811  break;
812  }
813  }
814  sprintf(ccdstr,"ESO DET CHIP%d ID", i);
815  ccd = cpl_propertylist_get_string(xplist, ccdstr);
816  }
817 
818  /*Identify wich CCD is in use and set the correct X Y offset */
819  if(strcmp(ccd, "ccd50")==0){
820  xoff = 4127.;
821  yoff = -240.;
822  }
823  else if(strcmp(ccd, "ccd51")==0){
824  xoff = 1990.;
825  yoff = -233.;
826  }
827  else if(strcmp(ccd, "ccd52")==0){
828  xoff = -154.;
829  yoff = -233.;
830  }
831  else if(strcmp(ccd, "ccd53")==0){
832  xoff = -2295.;
833  yoff = -233.;
834  }
835  else if(strcmp(ccd, "ccd54")==0){
836  xoff = -2294.;
837  yoff = 3917.;
838  }
839  else if(strcmp(ccd, "ccd55")==0){
840  xoff = -151.;
841  yoff = 3919.;
842  }
843  else if(strcmp(ccd, "ccd56")==0){
844  xoff = 1988.;
845  yoff = 3920.;
846  }
847  else if(strcmp(ccd, "ccd57")==0){
848  xoff = 4131.;
849  yoff = 3912.;
850  }
851 
852 /* Get RA and DEC from main header*/
853  tpa = cpl_propertylist_get_double(mplist, "RA");
854  tpd = cpl_propertylist_get_double(mplist, "DEC");
855 
856  rotskypa = 180.0;
857  angle = (rotskypa-180.0)*PI/180.0;
858  xapoff = 0.0;
859  yapoff = 0.0;
860 
861  /* tangent points of optical axis/rotator centre*/
862  secd = 1.0/cos(tpd*PI/180.0);
863  tpa = tpa - yapoff * secd * cos(angle) + xapoff *secd * sin(angle);
864  tpd = tpd + yapoff * sin(angle) + xapoff * cos(angle);
865  /* printf (" %10.5f %10.5f %8.4f %6.3f %6.3f \n",tpa,tpd,angle,xapoff,yapoff);*/
866 
867  /* transformation matrix*/
868  aap = -pixsca/3600.0;
869  bbp = 0.0;
870  ddp = 0.0;
871  eep = pixsca/3600.0;
872 
873  /* apply rotation matrix to all constants to allow for different sky pa
874  since n = A x ; x = R x'; o = R o'
875  where A = aa bb; R = c -s;
876  cc dd s c */
877 
878  aa = aap * cos(angle) + bbp * sin(angle);
879  bb =-aap * sin(angle) + bbp * cos(angle);
880  dd = ddp * cos(angle) + eep * sin(angle);
881  ee =-ddp * sin(angle) + eep * cos(angle);
882 
883  cc = xoff;
884  ff = yoff;
885  /* printf (" %10.5f %10.5f %10.5f %10.5f %10.5f %10.5f \n",aa,bb,cc,dd,ee,ff);*/
886 
887 
888  /* Update extension header */
889  cpl_propertylist_update_double(xplist,"CRPIX1",cc);
890  cpl_propertylist_update_double(xplist,"CRPIX2",ff);
891  cpl_propertylist_update_double(xplist,"CRVAL1",tpa);
892  cpl_propertylist_update_double(xplist,"CRVAL2",tpd);
893  cpl_propertylist_erase(xplist,"CDELT1");
894  cpl_propertylist_erase(xplist,"CDELT2");
895  cpl_propertylist_update_double(xplist,"CD1_1",aa);
896  cpl_propertylist_update_double(xplist,"CD1_2",bb);
897  cpl_propertylist_update_double(xplist,"CD2_1",dd);
898  cpl_propertylist_update_double(xplist,"CD2_2",ee);
899  /* cpl_propertylist_update_double(xplist,"PROJP1",1.0);
900  cpl_propertylist_update_double(xplist,"PROJP3",0.0);*/
901  cpl_propertylist_update_string(xplist,"CTYPE1", "RA---TAN");
902  cpl_propertylist_update_string(xplist,"CTYPE2","DEC--TAN");
903 
904 }
905