source: trunk/external/atnf/PKSIO/SDFITSwriter.cc@ 1721

Last change on this file since 1721 was 1720, checked in by Malte Marquarding, 15 years ago

Update from livedata CVS repository

File size: 25.8 KB
Line 
1//#---------------------------------------------------------------------------
2//# SDFITSwriter.cc: ATNF CFITSIO interface class for SDFITS output.
3//#---------------------------------------------------------------------------
4//# livedata - processing pipeline for single-dish, multibeam spectral data.
5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
6//#
7//# This file is part of livedata.
8//#
9//# livedata is free software: you can redistribute it and/or modify it under
10//# the terms of the GNU General Public License as published by the Free
11//# Software Foundation, either version 3 of the License, or (at your option)
12//# any later version.
13//#
14//# livedata is distributed in the hope that it will be useful, but WITHOUT
15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17//# more details.
18//#
19//# You should have received a copy of the GNU General Public License along
20//# with livedata. If not, see <http://www.gnu.org/licenses/>.
21//#
22//# Correspondence concerning livedata may be directed to:
23//# Internet email: mcalabre@atnf.csiro.au
24//# Postal address: Dr. Mark Calabretta
25//# Australia Telescope National Facility, CSIRO
26//# PO Box 76
27//# Epping NSW 1710
28//# AUSTRALIA
29//#
30//# http://www.atnf.csiro.au/computing/software/livedata.html
31//# $Id: SDFITSwriter.cc,v 19.18 2009-09-29 07:33:39 cal103 Exp $
32//#---------------------------------------------------------------------------
33//# Original: 2000/07/24, Mark Calabretta, ATNF
34//#---------------------------------------------------------------------------
35
36#include <atnf/PKSIO/MBrecord.h>
37#include <atnf/PKSIO/PKSmsg.h>
38#include <atnf/PKSIO/SDFITSwriter.h>
39
40#include <casa/iostream.h>
41
42#include <algorithm>
43#include <math.h>
44
45using namespace std;
46
47// Numerical constants.
48const double PI = 3.141592653589793238462643;
49
50// Factor to convert radians to degrees.
51const double R2D = 180.0 / PI;
52
53//------------------------------------------------- SDFITSwriter::SDFITSwriter
54
55SDFITSwriter::SDFITSwriter()
56{
57 // Default constructor.
58 cSDptr = 0x0;
59
60 // By default, messages are written to stderr.
61 initMsg();
62}
63
64//------------------------------------------------ SDFITSwriter::~SDFITSwriter
65
66SDFITSwriter::~SDFITSwriter()
67{
68 close();
69}
70
71//------------------------------------------------------- SDFITSwriter::create
72
73// Create the output SDFITS file.
74
75int SDFITSwriter::create(
76 char* sdName,
77 char* observer,
78 char* project,
79 char* telescope,
80 double antPos[3],
81 char* obsMode,
82 char* bunit,
83 float equinox,
84 char* dopplerFrame,
85 int nIF,
86 int* nChan,
87 int* nPol,
88 int* haveXPol,
89 int haveBase,
90 int extraSysCal)
91{
92 if (cSDptr) {
93 logMsg("ERROR: Output file already open, close it first.");
94 return 1;
95 }
96
97 // Clear the message stack.
98 clearMsg();
99
100 // Prepend an '!' to the output name to force it to be overwritten.
101 char sdname[80];
102 sdname[0] = '!';
103 strcpy(sdname+1, sdName);
104
105 // Create a new SDFITS file.
106 cStatus = 0;
107 if (fits_create_file(&cSDptr, sdname, &cStatus)) {
108 sprintf(cMsg, "ERROR: Failed to create SDFITS file\n %s", sdName);
109 logMsg(cMsg);
110 return cStatus;
111 }
112
113 cIsMX = strstr(obsMode, "MX") != 0;
114 cNIF = nIF;
115 cNChan = nChan;
116 cNPol = nPol;
117 cHaveXPol = haveXPol;
118 cHaveBase = haveBase;
119 cExtraSysCal = extraSysCal;
120
121 // Do all IFs have the same number of channels and polarizations?
122 cDoTDIM = 0;
123 int nprod = cNChan[0] * cNPol[0];
124 for (int iIF = 0; iIF < nIF; iIF++) {
125 if (cNChan[iIF]*cNPol[iIF] != nprod) {
126 // Need variable-length arrays as well as a TDIM column.
127 cDoTDIM = 2;
128 break;
129 }
130
131 if (cNChan[iIF] != cNChan[0] || cNPol[iIF] != cNPol[0]) {
132 // Varying channels and/or polarizations, need a TDIM column at least.
133 cDoTDIM = 1;
134 }
135 }
136
137 // Find the maximum number of polarizations in any IF.
138 int maxNPol = 0;
139 for (int iIF = 0; iIF < nIF; iIF++) {
140 if (cNPol[iIF] > maxNPol) maxNPol = cNPol[iIF];
141 }
142
143 // Do any IFs have cross-polarizations?
144 cDoXPol = 0;
145 for (int iIF = 0; iIF < nIF; iIF++) {
146 if (cHaveXPol[iIF]) {
147 cDoXPol = 1;
148 break;
149 }
150 }
151
152
153 cRow = 0;
154
155 // Write required primary header keywords.
156 if (fits_write_imghdr(cSDptr, 8, 0, 0, &cStatus)) {
157 logMsg("ERROR: Failed to write required primary header keywords.");
158 return cStatus;
159 }
160
161 // Identify the origin of the data.
162 fits_write_comment(cSDptr, " ", &cStatus);
163 fits_write_comment(cSDptr,
164 "This single dish FITS (SDFITS) file has a binary table extension which",
165 &cStatus);
166 fits_write_comment(cSDptr,
167 "contains data obtained from a telescope run by the Australia Telescope",
168 &cStatus);
169 fits_write_comment(cSDptr, "National Facility (ATNF).", &cStatus);
170 fits_write_comment(cSDptr, " ", &cStatus);
171
172 fits_write_date(cSDptr, &cStatus);
173
174 char text[72];
175 char version[7];
176 char date[11];
177 sscanf("$Revision: 19.18 $", "%*s%s", version);
178 sscanf("$Date: 2009-09-29 07:33:39 $", "%*s%s", date);
179 sprintf(text, "SDFITSwriter (v%s, %s)", version, date);
180 fits_write_key_str(cSDptr, "ORIGIN", text, "output class", &cStatus);
181
182 float cfvers;
183 fits_write_comment(cSDptr, "Written by Mark Calabretta "
184 "(mcalabre@atnf.csiro.au)", &cStatus);
185 sprintf(text, "using cfitsio v%.3f.", fits_get_version(&cfvers));
186 fits_write_comment(cSDptr, text, &cStatus);
187
188 if (cStatus) {
189 logMsg("ERROR: Failed in writing primary header.");
190 return cStatus;
191 }
192
193
194 // Create an SDFITS extension.
195 long nrow = 0;
196 int ncol = 0;
197 if (fits_create_tbl(cSDptr, BINARY_TBL, nrow, ncol, NULL, NULL, NULL,
198 "SINGLE DISH", &cStatus)) {
199 logMsg("ERROR: Failed to create a binary table extension.");
200 return 1;
201 }
202
203 char ttype[16];
204 char tform[9];
205 char tunit[9];
206
207 // NMATRIX (core, virtual).
208 fits_write_key_lng(cSDptr, "NMATRIX", 1l, "Number of DATA arrays",
209 &cStatus);
210
211 // OBSERVER (shared, virtual).
212 fits_write_key_str(cSDptr, "OBSERVER", observer, "Observer name(s)",
213 &cStatus);
214
215 // PROJID (shared, virtual).
216 fits_write_key_str(cSDptr, "PROJID", project, "Project name", &cStatus);
217
218 // TELESCOP (core, virtual).
219 fits_write_key_str(cSDptr, "TELESCOP", telescope, "Telescope name",
220 &cStatus);
221
222 // OBSGEO-X/Y/Z (additional, virtual).
223 fits_write_key_dbl(cSDptr, "OBSGEO-X", antPos[0], 9,
224 "[m] Antenna ITRF X-coordinate", &cStatus);
225 fits_write_key_dbl(cSDptr, "OBSGEO-Y", antPos[1], 9,
226 "[m] Antenna ITRF Y-coordinate", &cStatus);
227 fits_write_key_dbl(cSDptr, "OBSGEO-Z", antPos[2], 9,
228 "[m] Antenna ITRF Z-coordinate", &cStatus);
229
230 // SCAN (shared, real).
231 fits_insert_col(cSDptr, ++ncol, "SCAN", "1I", &cStatus);
232
233 // CYCLE (additional, real).
234 fits_insert_col(cSDptr, ++ncol, "CYCLE", "1J", &cStatus);
235
236 // DATE-OBS (core, real).
237 fits_insert_col(cSDptr, ++ncol, "DATE-OBS", "10A", &cStatus);
238
239 // TIME (core, real).
240 fits_insert_col(cSDptr, ++ncol, "TIME", "1D", &cStatus);
241 sprintf(tunit, "TUNIT%d", ncol);
242 fits_write_key_str(cSDptr, tunit, "s", "units of field", &cStatus);
243
244 // EXPOSURE (core, real).
245 fits_insert_col(cSDptr, ++ncol, "EXPOSURE", "1E", &cStatus);
246 sprintf(tunit, "TUNIT%d", ncol);
247 fits_write_key_str(cSDptr, tunit, "s", "units of field", &cStatus);
248
249 // OBJECT (core, real).
250 fits_insert_col(cSDptr, ++ncol, "OBJECT", "16A", &cStatus);
251
252 // OBJ-RA (additional, real).
253 fits_insert_col(cSDptr, ++ncol, "OBJ-RA", "1D", &cStatus);
254 sprintf(tunit, "TUNIT%d", ncol);
255 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
256
257 // OBJ-DEC (additional, real).
258 fits_insert_col(cSDptr, ++ncol, "OBJ-DEC", "1D", &cStatus);
259 sprintf(tunit, "TUNIT%d", ncol);
260 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
261
262 // RESTFRQ (additional, real).
263 fits_insert_col(cSDptr, ++ncol, "RESTFRQ", "1D", &cStatus);
264 sprintf(tunit, "TUNIT%d", ncol);
265 fits_write_key_str(cSDptr, tunit, "Hz", "units of field", &cStatus);
266
267 // OBSMODE (shared, real).
268 fits_insert_col(cSDptr, ++ncol, "OBSMODE", "16A", &cStatus);
269
270 // BEAM (additional, real).
271 fits_insert_col(cSDptr, ++ncol, "BEAM", "1I", &cStatus);
272
273 // IF (additional, real).
274 fits_insert_col(cSDptr, ++ncol, "IF", "1I", &cStatus);
275
276 // FREQRES (core, real).
277 fits_insert_col(cSDptr, ++ncol, "FREQRES", "1D", &cStatus);
278 sprintf(tunit, "TUNIT%d", ncol);
279 fits_write_key_str(cSDptr, tunit, "Hz", "units of field", &cStatus);
280
281 // BANDWID (core, real).
282 fits_insert_col(cSDptr, ++ncol, "BANDWID", "1D", &cStatus);
283 sprintf(tunit, "TUNIT%d", ncol);
284 fits_write_key_str(cSDptr, tunit, "Hz", "units of field", &cStatus);
285
286 // CTYPE1 (core, virtual).
287 fits_write_key_str(cSDptr, "CTYPE1", "FREQ",
288 "DATA array axis 1: frequency in Hz.", &cStatus);
289
290 // CRPIX1 (core, real).
291 fits_insert_col(cSDptr, ++ncol, "CRPIX1", "1E", &cStatus);
292
293 // CRVAL1 (core, real).
294 fits_insert_col(cSDptr, ++ncol, "CRVAL1", "1D", &cStatus);
295 sprintf(tunit, "TUNIT%d", ncol);
296 fits_write_key_str(cSDptr, tunit, "Hz", "units of field", &cStatus);
297
298 // CDELT1 (core, real).
299 fits_insert_col(cSDptr, ++ncol, "CDELT1", "1D", &cStatus);
300 sprintf(tunit, "TUNIT%d", ncol);
301 fits_write_key_str(cSDptr, tunit, "Hz", "units of field", &cStatus);
302
303
304 // CTYPE2 (core, virtual).
305 fits_write_key_str(cSDptr, "CTYPE2", "STOKES",
306 "DATA array axis 2: polarization code", &cStatus);
307
308 // CRPIX2 (core, virtual).
309 fits_write_key_flt(cSDptr, "CRPIX2", 1.0f, 1,
310 "Polarization code reference pixel", &cStatus);
311
312 // CRVAL2 (core, virtual).
313 fits_write_key_dbl(cSDptr, "CRVAL2", -5.0, 1,
314 "Polarization code at reference pixel (XX)", &cStatus);
315
316 // CDELT2 (core, virtual).
317 fits_write_key_dbl(cSDptr, "CDELT2", -1.0, 1,
318 "Polarization code axis increment", &cStatus);
319
320
321 // CTYPE3 (core, virtual).
322 fits_write_key_str(cSDptr, "CTYPE3", "RA",
323 "DATA array axis 3 (degenerate): RA (mid-int)",
324 &cStatus);
325
326 // CRPIX3 (core, virtual).
327 fits_write_key_flt(cSDptr, "CRPIX3", 1.0f, 1, "RA reference pixel",
328 &cStatus);
329
330 // CRVAL3 (core, real).
331 fits_insert_col(cSDptr, ++ncol, "CRVAL3", "1D", &cStatus);
332 sprintf(tunit, "TUNIT%d", ncol);
333 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
334
335 // CDELT3 (core, virtual).
336 fits_write_key_dbl(cSDptr, "CDELT3", -1.0, 1, "RA axis increment", &cStatus);
337
338 // CTYPE4 (core, virtual).
339 fits_write_key_str(cSDptr, "CTYPE4", "DEC",
340 "DATA array axis 4 (degenerate): Dec (mid-int)",
341 &cStatus);
342
343 // CRPIX4 (core, virtual).
344 fits_write_key_flt(cSDptr, "CRPIX4", 1.0f, 1, "Dec reference pixel",
345 &cStatus);
346
347 // CRVAL4 (core, real).
348 fits_insert_col(cSDptr, ++ncol, "CRVAL4", "1D", &cStatus);
349 sprintf(tunit, "TUNIT%d", ncol);
350 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
351
352 // CDELT4 (core, virtual).
353 fits_write_key_dbl(cSDptr, "CDELT4", 1.0, 1, "Dec axis increment", &cStatus);
354
355 // SCANRATE (additional, real).
356 fits_insert_col(cSDptr, ++ncol, "SCANRATE", "2E", &cStatus);
357 sprintf(tunit, "TUNIT%d", ncol);
358 fits_write_key_str(cSDptr, tunit, "deg/s", "units of field", &cStatus);
359
360 // SPECSYS (additional, virtual).
361 fits_write_key_str(cSDptr, "SPECSYS", dopplerFrame,
362 "Doppler reference frame (transformed)", &cStatus);
363
364 // SSYSOBS (additional, virtual).
365 fits_write_key_str(cSDptr, "SSYSOBS", "TOPOCENT",
366 "Doppler reference frame of observation", &cStatus);
367
368 // EQUINOX (shared, virtual).
369 fits_write_key_flt(cSDptr, "EQUINOX", equinox, 1,
370 "Equinox of equatorial coordinates", &cStatus);
371
372 // RADESYS (additional, virtual).
373 fits_write_key_str(cSDptr, "RADESYS", "FK5", "Equatorial coordinate frame",
374 &cStatus);
375
376 // TSYS (core, real).
377 sprintf(tform, "%dE", maxNPol);
378 fits_insert_col(cSDptr, ++ncol, "TSYS", tform, &cStatus);
379 sprintf(tunit, "TUNIT%d", ncol);
380 fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
381
382 // CALFCTR (additional, real).
383 sprintf(tform, "%dE", maxNPol);
384 fits_insert_col(cSDptr, ++ncol, "CALFCTR", tform, &cStatus);
385
386 if (cHaveBase) {
387 // BASELIN (additional, real).
388 sprintf(tform, "%dE", 2*maxNPol);
389 fits_insert_col(cSDptr, ++ncol, "BASELIN", tform, &cStatus);
390 long tdim[] = {2, maxNPol};
391 fits_write_tdim(cSDptr, ncol, 2, tdim, &cStatus);
392
393 // BASESUB (additional, real).
394 sprintf(tform, "%dE", 24*maxNPol);
395 fits_insert_col(cSDptr, ++ncol, "BASESUB", tform, &cStatus);
396 tdim[0] = 24;
397 fits_write_tdim(cSDptr, ncol, 2, tdim, &cStatus);
398 }
399
400 // DATA (core, real).
401 if (cDoTDIM < 2) {
402 // IFs all have the same number of products, use fixed-length arrays.
403 sprintf(tform, "%dE", cNChan[0]*cNPol[0]);
404 } else {
405 // IFs have a differing number of products, use variable-length arrays.
406 strcpy(tform, "1PE");
407 }
408 fits_insert_col(cSDptr, ++ncol, "DATA", tform, &cStatus);
409
410 if (cDoTDIM) {
411 // TDIMn varies with IF, write a TDIM column.
412 sprintf(ttype, "TDIM%d", ncol);
413 fits_insert_col(cSDptr, ++ncol, ttype, "16A", &cStatus);
414 } else {
415 // TDIMn fixed for each IF, write a TDIM keyword.
416 long tdim[] = {cNChan[0], cNPol[0], 1, 1};
417 fits_write_tdim(cSDptr, ncol, 4, tdim, &cStatus);
418 }
419
420 sprintf(tunit, "TUNIT%d", ncol);
421 fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
422
423 // FLAGGED (additional, logical).
424 if (cDoTDIM < 2) {
425 // IFs all have the same number of products, use fixed-length arrays.
426 sprintf(tform, "%dB", cNChan[0]*cNPol[0]);
427 } else {
428 // IFs have a differing number of products, use variable-length arrays.
429 strcpy(tform, "1PB");
430 }
431 fits_insert_col(cSDptr, ++ncol, "FLAGGED", tform, &cStatus);
432
433 if (cDoTDIM) {
434 // TDIMn varies with IF, write a TDIM column.
435 sprintf(ttype, "TDIM%d", ncol);
436 fits_insert_col(cSDptr, ++ncol, ttype, "16A", &cStatus);
437 } else {
438 // TDIMn fixed for each IF, write a TDIM keyword.
439 long tdim[] = {cNChan[0], cNPol[0], 1, 1};
440 fits_write_tdim(cSDptr, ncol, 4, tdim, &cStatus);
441 }
442
443 if (cDoXPol) {
444 // XCALFCTR (additional, real).
445 sprintf(tform, "%dE", 2);
446 fits_insert_col(cSDptr, ++ncol, "XCALFCTR", tform, &cStatus);
447
448 // XPOLDATA (additional, real).
449 if (cDoTDIM < 2) {
450 // IFs all have the same number of products, use fixed-length arrays.
451 sprintf(tform, "%dE", 2*cNChan[0]);
452 } else {
453 // IFs have a differing number of products, use variable-length arrays.
454 strcpy(tform, "1PE");
455 }
456 fits_insert_col(cSDptr, ++ncol, "XPOLDATA", tform, &cStatus);
457
458 if (cDoTDIM) {
459 // TDIMn varies with IF, write a TDIM column.
460 sprintf(ttype, "TDIM%d", ncol);
461 fits_insert_col(cSDptr, ++ncol, ttype, "16A", &cStatus);
462 } else {
463 // TDIMn fixed for each IF, write a TDIM keyword.
464 long tdim[] = {2, cNChan[0]};
465 fits_write_tdim(cSDptr, ncol, 2, tdim, &cStatus);
466 }
467
468 sprintf(tunit, "TUNIT%d", ncol);
469 fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
470 }
471
472 if (cExtraSysCal) {
473 if (cIsMX) {
474 // REFBEAM (additional, real).
475 fits_insert_col(cSDptr, ++ncol, "REFBEAM", "1I", &cStatus);
476 }
477
478 // TCAL (shared, real).
479 sprintf(tform, "%dE", min(maxNPol,2));
480 fits_insert_col(cSDptr, ++ncol, "TCAL", tform, &cStatus);
481 sprintf(tunit, "TUNIT%d", ncol);
482 fits_write_key_str(cSDptr, tunit, "Jy", "units of field", &cStatus);
483
484 // TCALTIME (additional, real).
485 fits_insert_col(cSDptr, ++ncol, "TCALTIME", "16A", &cStatus);
486
487 // AZIMUTH (shared, real).
488 fits_insert_col(cSDptr, ++ncol, "AZIMUTH", "1E", &cStatus);
489 sprintf(tunit, "TUNIT%d", ncol);
490 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
491
492 // ELEVATIO (shared, real).
493 fits_insert_col(cSDptr, ++ncol, "ELEVATIO", "1E", &cStatus);
494 sprintf(tunit, "TUNIT%d", ncol);
495 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
496
497 // PARANGLE (additional, real).
498 fits_insert_col(cSDptr, ++ncol, "PARANGLE", "1E", &cStatus);
499 sprintf(tunit, "TUNIT%d", ncol);
500 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
501
502 // FOCUSAXI (additional, real).
503 fits_insert_col(cSDptr, ++ncol, "FOCUSAXI", "1E", &cStatus);
504 sprintf(tunit, "TUNIT%d", ncol);
505 fits_write_key_str(cSDptr, tunit, "m", "units of field", &cStatus);
506
507 // FOCUSTAN (additional, real).
508 fits_insert_col(cSDptr, ++ncol, "FOCUSTAN", "1E", &cStatus);
509 sprintf(tunit, "TUNIT%d", ncol);
510 fits_write_key_str(cSDptr, tunit, "m", "units of field", &cStatus);
511
512 // FOCUSROT (additional, real).
513 fits_insert_col(cSDptr, ++ncol, "FOCUSROT", "1E", &cStatus);
514 sprintf(tunit, "TUNIT%d", ncol);
515 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
516
517 // TAMBIENT (shared, real).
518 fits_insert_col(cSDptr, ++ncol, "TAMBIENT", "1E", &cStatus);
519 sprintf(tunit, "TUNIT%d", ncol);
520 fits_write_key_str(cSDptr, tunit, "C", "units of field", &cStatus);
521
522 // PRESSURE (shared, real).
523 fits_insert_col(cSDptr, ++ncol, "PRESSURE", "1E", &cStatus);
524 sprintf(tunit, "TUNIT%d", ncol);
525 fits_write_key_str(cSDptr, tunit, "Pa", "units of field", &cStatus);
526
527 // HUMIDITY (shared, real).
528 fits_insert_col(cSDptr, ++ncol, "HUMIDITY", "1E", &cStatus);
529 sprintf(tunit, "TUNIT%d", ncol);
530 fits_write_key_str(cSDptr, tunit, "%", "units of field", &cStatus);
531
532 // WINDSPEE (shared, real).
533 fits_insert_col(cSDptr, ++ncol, "WINDSPEE", "1E", &cStatus);
534 sprintf(tunit, "TUNIT%d", ncol);
535 fits_write_key_str(cSDptr, tunit, "m/s", "units of field", &cStatus);
536
537 // WINDDIRE (shared, real).
538 fits_insert_col(cSDptr, ++ncol, "WINDDIRE", "1E", &cStatus);
539 sprintf(tunit, "TUNIT%d", ncol);
540 fits_write_key_str(cSDptr, tunit, "deg", "units of field", &cStatus);
541 }
542
543 // Set scaling parameters.
544 for (int j = 1; j <= ncol; j++) {
545 fits_set_tscale(cSDptr, j, 1.0, 0.0, &cStatus);
546 }
547
548 if (cStatus) {
549 logMsg("ERROR: Failed in writing binary table header.");
550 }
551
552 return cStatus;
553}
554
555//-------------------------------------------------------- SDFITSwriter::write
556
557// Write a record to the SDFITS file.
558
559int SDFITSwriter::write(MBrecord &mbrec)
560{
561 char *cptr;
562
563 // Check parameters.
564 int IFno = mbrec.IFno[0];
565 if (IFno < 1 || cNIF < IFno) {
566 cerr << "SDFITSwriter::write: "
567 << "Invalid IF number " << IFno
568 << " (maximum " << cNIF << ")." << endl;
569 return 1;
570 }
571
572 int iIF = IFno - 1;
573 int nChan = cNChan[iIF];
574 if (mbrec.nChan[0] != nChan) {
575 cerr << "SDFITSriter::write: "
576 << "Wrong number of channels for IF " << IFno << "," << endl
577 << " "
578 << "got " << nChan << " should be " << mbrec.nChan[0] << "." << endl;
579 return 1;
580 }
581
582 int nPol = cNPol[iIF];
583 if (mbrec.nPol[0] != nPol) {
584 cerr << "SDFITSriter::write: "
585 << "Wrong number of polarizations for IF " << IFno << "," << endl
586 << " "
587 << "got " << nPol << " should be " << mbrec.nPol[0] << "." << endl;
588 return 1;
589 }
590
591
592 // Next row.
593 cRow++;
594
595 int icol = 0;
596
597 // SCAN.
598 fits_write_col_int(cSDptr, ++icol, cRow, 1, 1, &mbrec.scanNo, &cStatus);
599
600 // CYCLE.
601 fits_write_col_int(cSDptr, ++icol, cRow, 1, 1, &mbrec.cycleNo, &cStatus);
602
603 // DATE-OBS.
604 cptr = mbrec.datobs;
605 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
606
607 // TIME.
608 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &mbrec.utc, &cStatus);
609
610 // EXPOSURE.
611 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.exposure, &cStatus);
612
613 // OBJECT.
614 cptr = mbrec.srcName;
615 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
616
617 // OBJ-RA.
618 double srcRA = mbrec.srcRA * R2D;
619 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &srcRA, &cStatus);
620
621 // OBJ-DEC.
622 double srcDec = mbrec.srcDec * R2D;
623 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &srcDec, &cStatus);
624
625 // RESTFRQ.
626 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &mbrec.restFreq, &cStatus);
627
628 // OBJECT.
629 cptr = mbrec.obsType;
630 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
631
632 // BEAM.
633 fits_write_col_sht(cSDptr, ++icol, cRow, 1, 1, &mbrec.beamNo, &cStatus);
634
635 // IF.
636 fits_write_col_sht(cSDptr, ++icol, cRow, 1, 1, &mbrec.IFno[0], &cStatus);
637
638 // FREQRES.
639 double freqRes = fabs(mbrec.fqDelt[0]);
640 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &freqRes, &cStatus);
641
642 // BANDWID.
643 double bandwidth = freqRes * nChan;
644 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &bandwidth, &cStatus);
645
646 // CRPIX1.
647 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.fqRefPix[0],
648 &cStatus);
649
650 // CRVAL1.
651 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &mbrec.fqRefVal[0],
652 &cStatus);
653
654 // CDELT1.
655 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &mbrec.fqDelt[0], &cStatus);
656
657 // CRVAL3.
658 double ra = mbrec.ra * R2D;
659 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &ra, &cStatus);
660
661 // CRVAL4.
662 double dec = mbrec.dec * R2D;
663 fits_write_col_dbl(cSDptr, ++icol, cRow, 1, 1, &dec, &cStatus);
664
665 // SCANRATE.
666 float scanrate[2];
667 scanrate[0] = mbrec.raRate * R2D;
668 scanrate[1] = mbrec.decRate * R2D;
669 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 2, scanrate, &cStatus);
670
671 // TSYS.
672 fits_write_col_flt(cSDptr, ++icol, cRow, 1, nPol, mbrec.tsys[0], &cStatus);
673
674 // CALFCTR.
675 fits_write_col_flt(cSDptr, ++icol, cRow, 1, nPol, mbrec.calfctr[0],
676 &cStatus);
677
678 if (cHaveBase) {
679 // BASELIN.
680 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 2*nPol, mbrec.baseLin[0][0],
681 &cStatus);
682
683 // BASESUB.
684 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 24*nPol, mbrec.baseSub[0][0],
685 &cStatus);
686 }
687
688 // DATA.
689 fits_write_col_flt(cSDptr, ++icol, cRow, 1, nChan*nPol, mbrec.spectra[0],
690 &cStatus);
691
692 if (cDoTDIM) {
693 // TDIM(DATA).
694 char tdim[16];
695 sprintf(tdim, "(%d,%d,1,1)", nChan, nPol);
696 cptr = tdim;
697 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
698 }
699
700 // FLAGGED.
701 fits_write_col_byt(cSDptr, ++icol, cRow, 1, nChan*nPol, mbrec.flagged[0],
702 &cStatus);
703
704 if (cDoTDIM) {
705 // TDIM(FLAGGED).
706 char tdim[16];
707 sprintf(tdim, "(%d,%d,1,1)", nChan, nPol);
708 cptr = tdim;
709 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
710 }
711
712 if (cDoXPol) {
713 if (cHaveXPol[iIF] && mbrec.xpol[0]) {
714 // XCALFCTR.
715 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 2, mbrec.xcalfctr[0],
716 &cStatus);
717
718 // XPOLDATA.
719 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 2*nChan, mbrec.xpol[0],
720 &cStatus);
721
722 if (cDoTDIM) {
723 // TDIM(XPOLDATA).
724 char tdim[16];
725 sprintf(tdim, "(2,%d)", nChan);
726 cptr = tdim;
727 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
728 }
729
730 } else {
731 // Skip columns.
732 icol += cDoTDIM ? 3 : 2;
733 }
734 }
735
736
737 // Extra system calibration quantities from Parkes.
738 if (cExtraSysCal) {
739 if (cIsMX) {
740 fits_write_col_sht(cSDptr, ++icol, cRow, 1, 1, &mbrec.refBeam, &cStatus);
741 }
742
743 fits_write_col_flt(cSDptr, ++icol, cRow, 1, min(nPol,2), mbrec.tcal[0],
744 &cStatus);
745 cptr = mbrec.tcalTime;
746 fits_write_col_str(cSDptr, ++icol, cRow, 1, 1, &cptr, &cStatus);
747
748 float azimuth = mbrec.azimuth * R2D;
749 float elevation = mbrec.elevation * R2D;
750 float parAngle = mbrec.parAngle * R2D;
751 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &azimuth, &cStatus);
752 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &elevation, &cStatus);
753 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &parAngle, &cStatus);
754
755 float focusRot = mbrec.focusRot * R2D;
756 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.focusAxi, &cStatus);
757 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.focusTan, &cStatus);
758 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &focusRot, &cStatus);
759
760 float windAz = mbrec.windAz * R2D;
761 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.temp, &cStatus);
762 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.pressure, &cStatus);
763 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.humidity, &cStatus);
764 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &mbrec.windSpeed, &cStatus);
765 fits_write_col_flt(cSDptr, ++icol, cRow, 1, 1, &windAz, &cStatus);
766 }
767
768 if (cStatus) {
769 logMsg("ERROR: Failed in writing binary table entry.");
770 }
771
772 return cStatus;
773}
774
775
776//------------------------------------------------------ SDFITSwriter::history
777
778// Write a history record.
779
780int SDFITSwriter::history(char *text)
781
782{
783 if (!cSDptr) {
784 return 1;
785 }
786
787 if (fits_write_history(cSDptr, text, &cStatus)) {
788 logMsg("ERROR: Failed in writing HISTORY records.");
789 }
790
791 return cStatus;
792}
793
794//-------------------------------------------------------- SDFITSwriter::close
795
796// Close the SDFITS file.
797
798void SDFITSwriter::close()
799{
800 if (cSDptr) {
801 cStatus = 0;
802 if (fits_close_file(cSDptr, &cStatus)) {
803 logMsg("ERROR: Failed to close file.");
804 }
805
806 cSDptr = 0;
807 }
808}
809
810//--------------------------------------------------- SDFITSwriter::deleteFile
811
812// Delete the SDFITS file.
813
814void SDFITSwriter::deleteFile()
815{
816 if (cSDptr) {
817 cStatus = 0;
818 if (fits_delete_file(cSDptr, &cStatus)) {
819 logMsg("ERROR: Failed to close and delete file.");
820 }
821
822 cSDptr = 0;
823 }
824}
825
826//------------------------------------------------------- SDFITSwriter::logMsg
827
828// Log a message. If the current CFITSIO status value is non-zero, also log
829// the corresponding error message and dump the CFITSIO message stack.
830
831void SDFITSwriter::logMsg(const char *msg)
832{
833 PKSmsg::logMsg(msg);
834
835 if (cStatus) {
836 fits_get_errstatus(cStatus, cMsg);
837 PKSmsg::logMsg(cMsg);
838
839 while (fits_read_errmsg(cMsg)) {
840 PKSmsg::logMsg(cMsg);
841 }
842 }
843}
Note: See TracBrowser for help on using the repository browser.