source: tags/release-1.1.11/src/Cubes/saveImage.cc @ 1441

Last change on this file since 1441 was 791, checked in by MatthewWhiting, 13 years ago

Making sure it works with the redesigned needBeamSize function (ie. not using it before reading beam from file). Also removing a lot of redundant code.

File size: 24.4 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(int 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(int 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(int 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.