source: tags/release-1.1.9/src/Cubes/saveImage.cc

Last change on this file was 695, checked in by MatthewWhiting, 14 years ago

Tidying up error reporting in the save-to-fits functions, and giving them return status values.

File size: 23.9 KB
Line 
1// -----------------------------------------------------------------------
2// saveImage.cc: Write a wavelet-reconstructed or smoothed array to a
3//               FITS file.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29#include <iostream>
30#include <sstream>
31#include <string>
32#include <string.h>
33#include <wcslib/wcs.h>
34#include <wcslib/wcshdr.h>
35#define WCSLIB_GETWCSTAB
36// define this so that we don't try and redefine wtbarr
37// (this is a problem when using cfitsio v.3 and g++ v.4)
38
39#include <fitsio.h>
40#include <duchamp/duchamp.hh>
41#include <duchamp/Cubes/cubes.hh>
42#include <duchamp/PixelMap/Voxel.hh>
43#include <duchamp/PixelMap/Object3D.hh>
44
45namespace duchamp
46{
47
48  /// @brief Write FITS headers in correct format for reconstructed array output
49  void writeReconHeaderInfo(fitsfile *fptr, Param &par, std::string nature);
50
51  /// @brief Write FITS headers in correct format for smoothed array output
52  void writeSmoothHeaderInfo(fitsfile *fptr, Param &par);
53
54  /// @brief Write FITS headers in correct format for mask array output
55  void writeMaskHeaderInfo(fitsfile *fptr, Param &par);
56
57  /// @brief Write FITS headers in correct format for moment-0 array output
58  void writeMomentMapHeaderInfo(fitsfile *fptr, Param &par);
59
60  //---------------------------------------------------------------------------
61
62  char *numerateKeyword(std::string key, int num)
63  {
64    /// @details A utility function to combine a keyword and a
65    /// value, to produce a relevant FITS keyword for a given
66    /// axis. For example numerateKeyword(CRPIX,1) returns CRPIX1.
67    std::stringstream ss;
68    ss << key << num;
69    return (char *)ss.str().c_str();
70  }
71
72  void duchampFITSerror(int status, std::string subroutine, std::string error)
73  {
74    if(status){
75      duchampError(subroutine,error);
76      fits_report_error(stderr, status);
77    }
78  }
79
80
81  OUTCOME Cube::saveMomentMapImage()
82  {
83    /// @details
84    ///  A function to save the moment-0 map to a FITS file.
85   
86    int newbitpix = FLOAT_IMG;
87    char *comment = new char[FLEN_COMMENT];
88    strcpy(comment,"");
89    long *fpixel = new long[2];
90    for(int i=0;i<2;i++) fpixel[i]=1;
91    int status = 0;  /* MUST initialize status */
92    fitsfile *fptr;         
93
94    std::string fileout = "!" + this->par.outputMomentMapFile();
95    // the ! is there so that it writes over an existing file.
96    char *keyword = new char[FLEN_KEYWORD];
97
98    status = 0;
99    if(fits_create_file(&fptr,fileout.c_str(),&status)){
100      duchampFITSerror(status,"saveMomentMapImage","Error creating file:");
101      return FAILURE;
102    }
103    else {
104      status = 0;
105      long *dim = new long[2];
106      for (uint i = 0; i < 2; i++) dim[i] = this->axisDim[i];
107      if (fits_create_img(fptr, newbitpix, 2, dim, &status)) {
108        duchampFITSerror(status,"saveMomentMapImage","Error creating image:");
109      }
110
111      if(!this->par.getFlagUsingBeam()){   // if the cube has beam info, copy it
112        float bmaj=this->head.getBmajKeyword(), bmin=this->head.getBminKeyword(), bpa=this->head.getBpaKeyword();
113        status = 0;
114        strcpy(keyword,"BMAJ");
115        if (fits_update_key(fptr, TFLOAT, keyword, &bmaj, NULL, &status)){
116          duchampFITSerror(status,"saveMomentMapImage","Error saving beam info:");
117        }
118        status = 0;
119        strcpy(keyword,"BMIN");
120        if (fits_update_key(fptr, TFLOAT, keyword, &bmin, NULL, &status)){
121          duchampFITSerror(status,"saveMomentMapImage","Error saving beam info:");
122        }
123        status = 0;
124        strcpy(keyword,"BPA");
125        if (fits_update_key(fptr, TFLOAT, keyword, &bpa, NULL, &status)){
126          duchampFITSerror(status,"saveMomentMapImage","Error saving beam info:");
127        }
128      }                 
129      status = 0;
130      strcpy(keyword,"EQUINOX");
131      if (fits_update_key(fptr, TFLOAT, keyword, &this->head.WCS().equinox, NULL, &status)){
132        duchampFITSerror(status,"saveMomentMapImage","Error saving equinox:");
133      }
134      status = 0;
135      strcpy(keyword,"BUNIT");
136      if (fits_update_key(fptr, TSTRING, keyword, (char *)this->head.getIntFluxUnits().c_str(),  NULL, &status)){
137        duchampFITSerror(status,"saveMomentMapImage","Error saving BUNIT:");
138      }
139      float val;
140      int axisNumbers[2];
141      axisNumbers[0] = this->head.WCS().lng;
142      axisNumbers[1] = this->head.WCS().lat;
143      for (uint d = 0; d < 2; d++) {
144        int i = axisNumbers[d];
145        status = 0;
146        if (fits_update_key(fptr, TSTRING, numerateKeyword("CTYPE", d + 1), this->head.WCS().ctype[i],  NULL, &status)){
147          duchampFITSerror(status,"saveMomentMapImage","Error saving CTYPE:");
148        }
149        status = 0;
150        if (fits_update_key(fptr, TSTRING, numerateKeyword("CUNIT", d + 1), this->head.WCS().cunit[i],  NULL, &status)){
151          duchampFITSerror(status,"saveMomentMapImage","Error saving CUNIT:");
152        }
153        status = 0;
154        val = this->head.WCS().crval[i];
155        if (fits_update_key(fptr, TFLOAT, numerateKeyword("CRVAL", d + 1), &val, NULL, &status)){
156          duchampFITSerror(status,"saveMomentMapImage","Error saving CRVAL:");
157        }
158        val = this->head.WCS().cdelt[i];
159        status = 0;
160        if (fits_update_key(fptr, TFLOAT, numerateKeyword("CDELT", d + 1), &val, NULL, &status)){
161          duchampFITSerror(status,"saveMomentMapImage","Error saving CDELT:");
162        }
163        val = this->head.WCS().crpix[i];
164        status = 0;
165        if (fits_update_key(fptr, TFLOAT, numerateKeyword("CRPIX", d + 1), &val, NULL, &status)){
166          duchampFITSerror(status,"saveMomentMapImage","Error saving CRPIX:");
167        }
168        val = this->head.WCS().crota[i];
169        status = 0;
170        if (fits_update_key(fptr, TFLOAT, numerateKeyword("CROTA", d + 1), &val, NULL, &status)){
171          duchampFITSerror(status,"saveMomentMapImage","Error saving CROTA:");
172        }
173      }
174
175      delete [] comment;
176      delete [] keyword;
177
178      writeMomentMapHeaderInfo(fptr, this->par);
179       
180      long size = this->axisDim[0] * this->axisDim[1];
181      float *momentMap = new float[size];
182      std::vector<bool> detectionMap;
183      this->getMomentMap(momentMap,detectionMap);
184      status=0;
185      if(fits_write_pix(fptr, TFLOAT, fpixel, size, momentMap, &status)){
186        duchampFITSerror(status,"saveMomentMapImage","Error writing data");
187      }
188      status = 0;
189      if(fits_close_file(fptr, &status)){
190        duchampFITSerror(status,"saveMomentMapImage","Error closing file");
191      }
192
193      delete [] momentMap;
194
195    }
196
197    delete [] fpixel;
198
199    return SUCCESS;
200
201  }
202
203  OUTCOME Cube::saveMaskCube()
204  {
205    /// @details
206    ///  A function to save a mask to a FITS file, indicating where the
207    ///  detections where made. The value of the detected pixels is
208    ///  determined by the flagMaskWithObjectNum parameter: if true,
209    ///  the value of the pixels is given by the corresponding object
210    ///  ID number; if false, they take the value 1 for all
211    ///  objects. Pixels not in a detected object have the value 0.
212
213    int newbitpix = SHORT_IMG;
214    char *comment = new char[FLEN_COMMENT];
215    strcpy(comment,"");
216    long *fpixel = new long[this->header().WCS().naxis];
217    for(int i=0;i<this->header().WCS().naxis;i++) fpixel[i]=1;
218    int status = 0;  /* MUST initialize status */
219    fitsfile *fptrOld, *fptrNew;         
220    if(fits_open_file(&fptrOld,this->par.getImageFile().c_str(),READONLY,&status)){
221      duchampFITSerror(status,"saveMask","Error opening existing file:");
222      return FAILURE;
223    }
224
225    std::string fileout = "!" + this->par.outputMaskFile();
226    // the ! is there so that it writes over an existing file.
227
228    status = 0;
229    if(fits_create_file(&fptrNew,fileout.c_str(),&status)){
230      duchampFITSerror(status,"saveMask","Error creating file:");
231      return FAILURE;
232    }
233    else {
234      status = 0;
235      if(fits_movabs_hdu(fptrOld, 1, NULL, &status)){
236        duchampFITSerror(status,"saveMask","Error accessing existing file's header:");
237        return FAILURE;
238      }
239      status = 0;
240      fits_copy_header(fptrOld, fptrNew, &status);
241      if (status){
242        duchampFITSerror(status,"saveMask","Error copying header to new file:");
243        fits_report_error(stderr, status);
244        return FAILURE;
245      }
246      status = 0;
247      char *keyword = new char[FLEN_KEYWORD];
248      strcpy(keyword,"BITPIX");
249      strcpy(comment,"number of bits per data pixel");
250      if(fits_update_key(fptrNew, TINT, keyword, &newbitpix, comment, &status)){
251        duchampFITSerror(status,"saveMask","Error writing BITPIX header:");
252      }
253      float bscale=1., bzero=0.;
254      strcpy(comment,"");
255      strcpy(keyword,"BSCALE");
256      if(fits_update_key(fptrNew, TFLOAT, keyword, &bscale, comment, &status)){
257        duchampFITSerror(status,"saveMask","Error writing BSCALE header:");
258      }
259      strcpy(keyword,"BZERO");
260      if(fits_update_key(fptrNew, TFLOAT, keyword, &bzero, comment, &status)){
261        duchampFITSerror(status,"saveMask","Error writing BZERO header:");
262      }
263      if(fits_set_bscale(fptrNew, 1, 0, &status)){
264        duchampFITSerror(status,"saveMask","Error setting scale:");
265      }
266      std::string newunits;
267      if(this->par.getFlagMaskWithObjectNum())
268        newunits = "Object ID";
269      else
270        newunits = "Detection flag";
271      strcpy(keyword,"BUNIT");
272      if(fits_update_key(fptrNew, TSTRING, keyword, (char *)newunits.c_str(), comment, &status)){
273        duchampFITSerror(status,"saveMask","Error writing BUNIT header:");
274      }
275      long dud;
276      // Need to correct the dimensions, if we have subsectioned the image
277      if(this->par.getFlagSubsection()){
278        std::stringstream naxis;
279        fits_read_key(fptrOld, TLONG, (char *)naxis.str().c_str(), &dud, comment, &status);
280        fits_update_key(fptrNew, TLONG, (char *)naxis.str().c_str(),
281                        &(this->axisDim[0]), comment, &status);
282        naxis.str("");
283        naxis << "NAXIS" << this->head.WCS().lat;
284        fits_read_key(fptrOld, TLONG, (char *)naxis.str().c_str(), &dud, comment, &status);
285        fits_update_key(fptrNew, TLONG, (char *)naxis.str().c_str(),
286                        &(this->axisDim[1]), comment, &status);
287        naxis.str("");
288        naxis << "NAXIS" << this->head.WCS().spec;
289        fits_read_key(fptrOld, TLONG, (char *)naxis.str().c_str(), &dud, comment, &status);
290        fits_update_key(fptrNew, TLONG, (char *)naxis.str().c_str(),
291                        &(this->axisDim[2]), comment, &status);
292      }
293
294      delete [] comment;
295      delete [] keyword;
296
297      writeMaskHeaderInfo(fptrNew, this->par);
298       
299      short *mask = new short[this->numPixels];
300      for(int i=0;i<this->numPixels;i++) mask[i]=0;
301      std::vector<Detection>::iterator obj;
302      for(obj=this->objectList->begin();obj<this->objectList->end();obj++){
303        std::vector<PixelInfo::Voxel> voxlist = obj->getPixelSet();
304        std::vector<PixelInfo::Voxel>::iterator vox;
305        for(vox=voxlist.begin();vox<voxlist.end();vox++){
306          int pixelpos = vox->getX() + this->axisDim[0]*vox->getY() +
307            this->axisDim[0]*this->axisDim[1]*vox->getZ();
308          if(this->par.getFlagMaskWithObjectNum()) mask[pixelpos] = obj->getID();
309          else mask[pixelpos] = 1;
310        }
311      }
312      status=0;
313      if(fits_write_pix(fptrNew, TSHORT, fpixel, this->numPixels, mask, &status)){
314        duchampFITSerror(status,"saveMask","Error writing mask array:");
315      }
316      status = 0;
317      if(fits_close_file(fptrNew, &status)){
318        duchampFITSerror(status,"saveMask","Error closing file:");
319      }
320
321      delete [] mask;
322
323    }
324
325    delete [] fpixel;
326
327    return SUCCESS;
328  }
329 
330  //---------------------------------------------------------------------------
331
332  OUTCOME Cube::saveSmoothedCube()
333  {
334    /// @brief
335    ///   A function to save the smoothed arrays to a FITS file.
336    ///   Additional header keywords are written as well, indicating the
337    ///   width of the Hanning filter or the dimensions of the Gaussian
338    ///   kernel.
339    ///   The file is always written -- if the filename (as calculated
340    ///    based on the parameters) exists, then it is overwritten.
341 
342    float blankval = this->par.getBlankPixVal();
343
344    int status = 0;  /* MUST initialize status */
345    fitsfile *fptrOld, *fptrNew;         
346    if(fits_open_file(&fptrOld,this->par.getFullImageFile().c_str(),READONLY,&status)){
347      duchampFITSerror(status,"saveSmoothedCube", "Error opening existing file:");
348      return FAILURE;
349    }
350
351    if(this->par.getFlagOutputSmooth()){
352      std::string fileout = "!" + this->par.outputSmoothFile();
353      // the ! is there so that it writes over an existing file.
354
355      status = 0;
356      if(fits_create_file(&fptrNew,fileout.c_str(),&status)){
357        duchampFITSerror(status,"saveSmoothedCube","Error creating smoothed FITS file:");
358        return FAILURE;
359      }
360      else {
361        status = 0;
362        if(fits_movabs_hdu(fptrOld, 1, NULL, &status)){
363          duchampFITSerror(status,"saveSmoothedCube","Error accessing existing file's header:");
364          return FAILURE;
365        }
366        status = 0;
367        if(fits_copy_header(fptrOld, fptrNew, &status)){
368          duchampFITSerror(status,"saveSmoothedCube","Error copying header info:");
369          return FAILURE;
370        }
371
372        writeSmoothHeaderInfo(fptrNew, this->par);
373
374        if(this->par.getFlagBlankPix())
375          fits_write_imgnull(fptrNew, TFLOAT, 1, this->numPixels, this->recon, &blankval, &status);
376        else
377          fits_write_img(fptrNew, TFLOAT, 1, this->numPixels, this->recon, &status);
378        if(status){
379          duchampFITSerror(status,"saveSmothedCube","Error writing smoothed array:");
380          return FAILURE;
381        }
382
383        status = 0;
384        if(fits_close_file(fptrNew, &status)){
385          duchampFITSerror(status,"saveSmoothedCube","Error closing file:");
386        }
387      }
388    }
389
390    return SUCCESS;
391
392  }
393
394  //---------------------------------------------------------------------------
395
396  OUTCOME Cube::saveReconstructedCube()
397  {
398    /// @details
399    ///  A function to save the reconstructed and/or residual arrays.
400    ///   A number of header keywords are written as well, indicating the
401    ///    nature of the reconstruction that has been done.
402    ///   The file is always written -- if the filename (as calculated
403    ///    based on the recon parameters) exists, then it is overwritten.
404 
405    float blankval = this->par.getBlankPixVal();
406
407    int status = 0;  /* MUST initialize status */
408    fitsfile *fptrOld, *fptrNew;         
409    if(fits_open_file(&fptrOld,this->par.getFullImageFile().c_str(),READONLY,&status)){
410      duchampFITSerror(status,"saveReconCube","Error opening existing file:");
411      return FAILURE;
412    }
413 
414    if(this->par.getFlagOutputRecon()){
415      std::string fileout = "!" + this->par.outputReconFile();
416      // the ! is there so that it writes over an existing file.
417
418      status = 0;
419      if(fits_create_file(&fptrNew,fileout.c_str(),&status)){
420        duchampFITSerror(status,"saveReconCube","Error creating file:");
421        return FAILURE;
422      }
423      else
424        {
425          status = 0;
426          if(fits_movabs_hdu(fptrOld, 1, NULL, &status)){
427            duchampFITSerror(status,"saveReconCube","Error accessing existing file's header:");
428            return FAILURE;
429          }
430          status = 0;
431          if(fits_copy_header(fptrOld, fptrNew, &status)){
432            duchampFITSerror(status,"saveReconCube","Error copying header:");
433            return FAILURE;
434          }
435
436          writeReconHeaderInfo(fptrNew, this->par, "recon");
437
438          if(this->par.getFlagBlankPix())
439            fits_write_imgnull(fptrNew, TFLOAT, 1, this->numPixels, this->recon, &blankval, &status);
440          else 
441            fits_write_img(fptrNew, TFLOAT, 1, this->numPixels, this->recon, &status);
442          if(status){
443            duchampFITSerror(status,"saveReconCube","Error writing reconstructed array:");
444            return FAILURE;
445          }
446
447          status = 0;
448          if(fits_close_file(fptrNew, &status)){
449            duchampFITSerror(status,"saveReconCube","Error closing file:");
450          }
451        }
452    }
453
454
455    if(this->par.getFlagOutputResid()){
456      float *resid = new float[this->numPixels];
457      for(int i=0;i<this->numPixels;i++)
458        resid[i] = this->array[i] - this->recon[i];
459
460      std::string fileout = "!" + this->par.outputResidFile();
461      // the ! is there so that it writes over an existing file.
462      status = 0;
463      if(fits_create_file(&fptrNew,fileout.c_str(),&status)){
464        duchampFITSerror(status,"saveResidualCube","Error creating new file:");
465        return FAILURE;
466      }
467      else
468        {
469          status = 0;
470          if(fits_movabs_hdu(fptrOld, 1, NULL, &status)){
471            duchampFITSerror(status,"saveResidualCube","Error accessing existing file's header:");
472            return FAILURE;
473          }
474          status = 0;
475          if(fits_copy_header(fptrOld, fptrNew, &status)){
476            duchampFITSerror(status,"saveResidualCube","Error copying header:");
477            return FAILURE;
478          }
479          writeReconHeaderInfo(fptrNew, this->par, "resid");
480
481          if(this->par.getFlagBlankPix())
482            fits_write_imgnull(fptrNew, TFLOAT, 1, this->numPixels, resid, &blankval, &status);
483          else 
484            fits_write_img(fptrNew, TFLOAT, 1, this->numPixels, resid, &status);
485          if(status){
486            duchampFITSerror(status,"saveResidualCube","Error writing reconstructed array:");
487            return FAILURE;
488          }
489
490          status=0;
491          if(fits_close_file(fptrNew, &status)){
492            duchampFITSerror(status,"saveResidualCube","Error closing file:");
493          }
494        }
495      delete [] resid;
496    }
497
498    return SUCCESS;
499  }
500
501  //---------------------------------------------------------------------------
502
503  void writeReconHeaderInfo(fitsfile *fptr, Param &par, std::string nature)
504  {
505    /// @details
506    ///   A simple function that writes all the necessary keywords and comments
507    ///    to the FITS header pointed to by fptr.
508    ///   The keyword names and comments are taken from duchamp.hh
509    ///   The parameter "nature" indicates what type of file is being written:
510    ///    should be either "recon" or "resid".
511
512    int status = 0;
513    std::string explanation = "",ReconResid="";
514
515    fits_write_history(fptr, (char *)header_reconHistory1.c_str(), &status);
516                                   
517    fits_write_history(fptr, (char *)header_reconHistory2.c_str(), &status);
518
519    fits_write_history(fptr, (char *)header_reconHistory_input.c_str(), &status);
520
521    fits_write_history(fptr, (char *)par.getImageFile().c_str(), &status);
522
523    if(par.getFlagSubsection()){
524      fits_write_comment(fptr,(char *)header_reconSubsection_comment.c_str(),
525                         &status);
526      fits_write_key(fptr, TSTRING, (char *)keyword_subsection.c_str(),
527                     (char *)par.getSubsection().c_str(),
528                     (char *)comment_subsection.c_str(), &status);
529    }
530   
531    fits_write_comment(fptr, (char *)header_atrous_comment.c_str(), &status);
532
533    float valf = par.getAtrousCut();
534    fits_write_key(fptr, TFLOAT, (char *)keyword_snrRecon.c_str(), &valf,
535                   (char *)comment_snrRecon.c_str(), &status);
536
537    int vali = par.getReconDim();
538    fits_write_key(fptr, TINT, (char *)keyword_reconDim.c_str(), &vali,
539                   (char *)comment_reconDim.c_str(), &status);
540
541    vali = par.getMinScale();
542    fits_write_key(fptr, TINT, (char *)keyword_scaleMin.c_str(), &vali,
543                   (char *)comment_scaleMin.c_str(), &status);
544
545    vali = par.getFilterCode();
546    fits_write_key(fptr, TINT, (char *)keyword_filterCode.c_str(), &vali,
547                   (char *)comment_filterCode.c_str(), &status);
548
549    if(nature == "recon"){
550      explanation = "Duchamp: This is the RECONSTRUCTED cube";
551      ReconResid = "RECON";
552    }
553    else if(nature == "resid"){
554      explanation = "Duchamp: This is the RESIDUAL cube";
555      ReconResid = "RESID";
556    }
557    else duchampWarning("write_header_info","explanation not present!\n");
558    fits_write_comment(fptr, (char *)explanation.c_str(), &status);
559    fits_write_key(fptr, TSTRING, (char *)keyword_ReconResid.c_str(),
560                   (char *)ReconResid.c_str(),
561                   (char *)comment_ReconResid.c_str(), &status);
562
563  }
564
565  //---------------------------------------------------------------------------
566
567  void writeSmoothHeaderInfo(fitsfile *fptr, Param &par)
568  {
569    /// @details
570    ///   A simple function that writes all the necessary keywords and comments
571    ///    to the FITS header pointed to by fptr.
572    ///   The keyword names and comments are taken from duchamp.hh
573
574    int status = 0;
575
576    fits_write_history(fptr, (char *)header_smoothHistory.c_str(), &status);
577    status = 0;
578    fits_write_history(fptr, (char *)header_smoothHistory_input.c_str(),&status);
579    status = 0;
580    fits_write_history(fptr, (char *)par.getImageFile().c_str(), &status);
581
582    if(par.getFlagSubsection()){
583      status = 0;
584      fits_write_comment(fptr,(char *)header_smoothSubsection_comment.c_str(),
585                         &status);
586      status = 0;
587      fits_write_key(fptr, TSTRING, (char *)keyword_subsection.c_str(),
588                     (char *)par.getSubsection().c_str(),
589                     (char *)comment_subsection.c_str(), &status);
590    }
591   
592    if(par.getSmoothType()=="spatial"){
593      // if kernMin is negative (not defined), make it equal to kernMaj
594      if(par.getKernMin() < 0) par.setKernMin(par.getKernMaj());
595
596      fits_write_key(fptr, TSTRING, (char *)keyword_smoothtype.c_str(),
597                     (char *)header_smoothSpatial.c_str(),
598                     (char *)comment_smoothtype.c_str(), &status);
599      float valf = par.getKernMaj();
600      fits_write_key(fptr, TFLOAT, (char *)keyword_kernmaj.c_str(), &valf,
601                     (char *)comment_kernmaj.c_str(), &status);
602      valf = par.getKernMin();
603      fits_write_key(fptr, TFLOAT, (char *)keyword_kernmin.c_str(), &valf,
604                     (char *)comment_kernmin.c_str(), &status);
605      valf = par.getKernPA();
606      fits_write_key(fptr, TFLOAT, (char *)keyword_kernpa.c_str(), &valf,
607                     (char *)comment_kernpa.c_str(), &status);
608    }
609    else if(par.getSmoothType()=="spectral"){
610      fits_write_key(fptr, TSTRING, (char *)keyword_smoothtype.c_str(),
611                     (char *)header_smoothSpectral.c_str(),
612                     (char *)comment_smoothtype.c_str(), &status);
613      int vali = par.getHanningWidth();
614      fits_write_key(fptr, TINT, (char *)keyword_hanningwidth.c_str(), &vali,
615                     (char *)comment_hanningwidth.c_str(), &status);
616    }
617  }
618
619  //---------------------------------------------------------------------------
620
621  void writeMaskHeaderInfo(fitsfile *fptr, Param &par)
622  {
623    /// @details
624    ///   A simple function that writes all the necessary keywords and comments
625    ///    to the FITS header pointed to by fptr.
626    ///   The keyword names and comments are taken from duchamp.hh
627
628    int status = 0;
629
630    fits_write_history(fptr, (char *)header_maskHistory.c_str(), &status);
631    status = 0;
632    fits_write_history(fptr, (char *)header_maskHistory_input.c_str(),&status);
633    status = 0;
634    fits_write_history(fptr, (char *)par.getImageFile().c_str(), &status);
635
636    if(par.getFlagSubsection()){
637      status = 0;
638      fits_write_comment(fptr,(char *)header_maskSubsection_comment.c_str(),
639                         &status);
640      status = 0;
641      fits_write_key(fptr, TSTRING, (char *)keyword_subsection.c_str(),
642                     (char *)par.getSubsection().c_str(),
643                     (char *)comment_subsection.c_str(), &status);
644    }
645  }
646
647  //---------------------------------------------------------------------------
648
649  void writeMomentMapHeaderInfo(fitsfile *fptr, Param &par)
650  {
651    /// @details
652    ///   A simple function that writes all the necessary keywords and comments
653    ///    to the FITS header pointed to by fptr.
654    ///   The keyword names and comments are taken from duchamp.hh
655
656    int status = 0;
657
658    fits_write_history(fptr, (char *)header_moment0History.c_str(), &status);
659    status = 0;
660    fits_write_history(fptr, (char *)header_moment0History_input.c_str(),&status);
661    status = 0;
662    fits_write_history(fptr, (char *)par.getImageFile().c_str(), &status);
663
664    if(par.getFlagSubsection()){
665      status = 0;
666      fits_write_comment(fptr,(char *)header_moment0Subsection_comment.c_str(),
667                         &status);
668      status = 0;
669      fits_write_key(fptr, TSTRING, (char *)keyword_subsection.c_str(),
670                     (char *)par.getSubsection().c_str(),
671                     (char *)comment_subsection.c_str(), &status);
672    }
673  }
674
675}
Note: See TracBrowser for help on using the repository browser.