source: trunk/src/Cubes/saveImage.cc @ 894

Last change on this file since 894 was 894, checked in by MatthewWhiting, 12 years ago

A large swathe of changes aimed at fixing compilation warnings. These mostly refer to size_t conversions, although there is at least one instance of adding a return value to a function that needed it. Note there are still a few warnings - I need to decide how best to reconcile the size_t variables with integral values that could conceivably be negative...

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