SUBROUTINE wrtfak(phaobs, varobs, region, areasc, qbckfil) IMPLICIT NONE INCLUDE '../../inc/xspec.inc' REAL phaobs(*), varobs(*), region(*), areasc(*) LOGICAL qbckfil C c wrtfak burton 15 April 94 c XSPEC subroutine to write out the accumulated fake data c routines, using FITS format c 3.0 - rewritten to write out data into FITS files c phaobs r i: The count rate to be written out if counting statistics was set. c else an integer number of actual counts is written out. c varobs r i: The errors on the count rate if Poisson statistics were c not assumed for the background. c region r i: The BACKSCAL values c areasc r i: The AREASCAL values c qbckfil l i: If true then write out the background file c c 7/21/97 - correctly write the keywords in the case of POISSERR = .FALSE. c 4/30/99 - change handling for pre-existing files: now dealt with before this function c is called. B. Dorman c 4/29/02 - added option to write out background files c INTEGER icounts, ierror, ichannl, iqualty, igroup REAL grasp, backscal, areascal INTEGER istat, maxchn, iunit, ifile, i, bitpix, ichan, ibin INTEGER status, nrows, nfield, pcount, block, chan0, icol integer ridum character*20 rhdum character*3 rrchtyp real rrdum CHARACTER*11 cdate INTEGER yr,mo,day CHARACTER filenm*255, name*255 CHARACTER contxt*72, extens*10 CHARACTER cgroup*1 CHARACTER*20 tform(6), ttype(6), tunit(6), extnam LOGICAL simple, extend, qqual, qgroup, qpoiss, qback, qarea LOGICAL qexist REAL dgtime, dgbtme, dgcrnm INTEGER dgndst, lenact, dgungc, dgnbnb, dgnbne, dgchn0, ftgsdt CHARACTER fgflnm*255, dgtlsc*20 CHARACTER fgauxf*255, dginst*20, dggcrd*1 LOGICAL dgqnot, dgqfst, dgdtps EXTERNAL lenact, fgflnm, fgauxf, dgtlsc, dgdtps EXTERNAL dgtime, dgbtme, dgcrnm, dgndst, dgungc, dginst EXTERNAL dgnbnb, dgnbne, dgchn0, dggcrd, dgqnot, ftgsdt status = 0 c Find largest number of channels in a data set. maxchn = 0 DO ifile = 1, dgndst() maxchn = MAX(maxchn, dgungc(ifile)) ENDDO c Allocate memory for workspace arrays. CALL udmget( maxchn, 6, icounts, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmget( maxchn, 6, ierror, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmget( maxchn, 4, ichannl, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmget( maxchn, 4, iqualty, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmget( maxchn, 4, igroup, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) c c Define values that are constant c bitpix = 8 block = 2880 status = ftgsdt(day,mo,yr,status) write(cdate,'(i4,"-",i2.2,"-",i2.2)') yr,mo,day status = 0 c c Loop around files to be written c CALL getlun(iunit) DO ifile = 1, dgndst() IF ( qbckfil .AND. dgbtme(ifile) .EQ. 0. ) GOTO 300 qpoiss = .TRUE. IF ( dgbtme(ifile) .GT. 0. .AND. .NOT.dgdtps(ifile,'b') ) & qpoiss = .FALSE. c Create new file. fakeit has already checked whether the user c wishes to overwrite this file, so if it does already exist, delete C it. filenm = fgflnm(ifile) IF ( qbckfil ) THEN extens = filenm(index(filenm,'.')+1:) filenm = filenm(:index(filenm,'.')-1)//'_bkg.'//extens ENDIF INQUIRE(file=filenm, exist=qexist) IF ( qexist ) CALL xdelfil(filenm, status) CALL ftinit(iunit, filenm, block, status) contxt = 'WRTFAK : Failed to create '//filenm(:lenact(filenm)) IF( status.NE.0 )GOTO 100 c c simple = .TRUE. extend = .TRUE. c c Define primary header CALL ftpdef(iunit, bitpix, 0, 0, 0, 1, status) contxt = 'WRTFAK : Failed to define primary header' IF( status.NE.0 )GOTO 100 c c Write primary array keywords c CALL ftphpr(iunit, simple, bitpix, 0, 0, 0, 1, extend, status) contxt = 'WRTFAK : Failed to write primary array keywords' IF( status.NE.0 )GOTO 100 c c Create extension c CALL ftcrhd(iunit, status) contxt = 'WRTFAK : Failed to create extension' IF( status.NE.0 )GOTO 100 c Find out whether the quality and grouping columns need to be c written and if so set the arrays qqual = .FALSE. qgroup = .FALSE. DO 150 i = 1, dgungc(ifile) memi(iqualty+i-1) = 0 memi(igroup+i-1) = 1 cgroup = dggcrd(ifile, i) IF( cgroup.EQ.'-' )THEN memi(igroup+i-1) = -1 qgroup = .TRUE. ELSEIF( cgroup.EQ.'*' )THEN memi(iqualty+i-1) = 2 qqual = .TRUE. ELSEIF( cgroup.EQ.' ' )THEN memi(iqualty+i-1) = 1 qqual = .TRUE. ENDIF 150 CONTINUE c Find out whether the BACKSCAL array needs to be written or whether we can c get away with a scalar keyword qback = .FALSE. backscal = region(dgnbnb(ifile)) DO i = dgnbnb(ifile)+1, dgnbne(ifile) IF ( ABS(backscal-region(i))/backscal .GT. 1.e-6 ) THEN qback = .TRUE. ENDIF ENDDO c Do the same for the AREASCAL qarea = .FALSE. areascal = areasc(dgnbnb(ifile)) DO i = dgnbnb(ifile)+1, dgnbne(ifile) IF ( ABS(areascal-areasc(i))/areascal .GT. 1.e-6 ) THEN qarea = .TRUE. ENDIF ENDDO c Write required header keywords for extension nrows = dgungc(ifile) ttype(1) = 'CHANNEL' tform(1) = 'I' tunit(1) = ' ' IF(qpoiss)THEN ttype(2) = 'COUNTS' tunit(2) = 'COUNTS' tform(2) = 'E' nfield = 2 ELSE ttype(2) = 'RATE' tunit(2) = 'cts/s' tform(2) = 'E' ttype(3) = 'STAT_ERR' tunit(3) = 'cts/s' tform(3) = 'E' nfield = 3 ENDIF IF( qqual )THEN nfield = nfield + 1 ttype(nfield) = 'QUALITY' tform(nfield) = 'I' tunit(nfield) = ' ' ENDIF IF( qgroup )THEN nfield = nfield + 1 ttype(nfield) = 'GROUPING' tform(nfield) = 'I' tunit(nfield) = ' ' ENDIF IF( qback )THEN nfield = nfield + 1 ttype(nfield) = 'BACKSCAL' tform(nfield) = 'E' tunit(nfield) = ' ' ENDIF IF( qarea )THEN nfield = nfield + 1 ttype(nfield) = 'AREASCAL' tform(nfield) = 'E' tunit(nfield) = ' ' ENDIF extnam = 'SPECTRUM' pcount = 0 CALL ftphbn(iunit, nrows, nfield, ttype, tform, tunit, extnam, & pcount, status) contxt = 'WRTFAK : Failed to write extension header keywords' IF( status.NE.0 )GOTO 100 CALL rdrinf(fgauxf(ifile,'r'),ridum,rhdum,ridum,rhdum,rhdum, & rhdum,rrchtyp,ridum,ridum,ridum,rrdum, & ridum,rrdum,ridum,ridum,istat) c Write additional header keywords for extension CALL ftpkys(iunit, 'HDUCLASS', 'OGIP', & 'format conforms to OGIP/GSFC conventions', status) contxt = 'WRTFAK : Failed to write HDUCLASS keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'HDUCLAS1', 'SPECTRUM', & 'extension contains a spectrum', status) contxt = 'WRTFAK : Failed to write HDUCLAS1 keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'HDUCLAS2', 'TOTAL', & 'spectrum is gross PHA spectrum', status) contxt = 'WRTFAK : Failed to write HDUCLAS2 keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'HDUCLAS3', 'COUNT', 'spectrum is counts', & status) contxt = 'WRTFAK : Failed to write HDUCLAS3 keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'HDUVERS1', '1.1.0', & 'version number of the format', status) contxt = 'WRTFAK : Failed to write HDUCLAS3 keyword' IF( status.NE.0 )GOTO 100 name = 'XSPEC '//VERSION//' fakeit' CALL ftpkys(iunit, 'CREATOR', name, & 'program that created this file', status) contxt = 'WRTFAK : Failed to write CREATOR keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'FILENAME', filenm, 'source file for fit', & status) contxt = 'WRTFAK : Failed to write FILENAME keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'DATE ', cdate, & 'FITS creation date (dd/mm/yyyy)', status) contxt = 'WRTFAK : Failed to write DATE keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'TELESCOP', dgtlsc(ifile), & 'telescope (mission) name', status) contxt = 'WRTFAK : Failed to write TELESCOP keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'INSTRUME', dginst(ifile), & 'instrument name', status) contxt = 'WRTFAK : Failed to write INSTRUME keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'FILTER ', 'none ', & 'instrument filter used', status) contxt = 'WRTFAK : Failed to write FILTER keyword' IF( status.NE.0 )GOTO 100 IF ( qbckfil ) THEN CALL ftpkye(iunit, 'EXPOSURE', dgbtme(ifile), 4, & 'Exposure time', status) ELSE CALL ftpkye(iunit, 'EXPOSURE', dgtime(ifile), 4, & 'Exposure time', status) ENDIF contxt = 'WRTFAK : Failed to write EXPOSURE keyword' IF( status.NE.0 )GOTO 100 c If we aren't writing a backscal column then put it in the keyword IF ( .NOT.qback ) THEN CALL ftpkye(iunit, 'BACKSCAL', backscal, 4, & 'Background scale factor', status) contxt = 'WRTFAK : Failed to write BACKSCAL keyword' IF( status.NE.0 )GOTO 100 ENDIF c If we aren't writing a areascal column then put it in the keyword IF ( .NOT.qarea ) THEN CALL ftpkye(iunit, 'AREASCAL', areascal, 4, & 'Area scale factor', status) contxt = 'WRTFAK : Failed to write AREASCAL keyword' IF( status.NE.0 )GOTO 100 ENDIF CALL ftpkye(iunit, 'CORRSCAL', dgcrnm(ifile), 4, & 'Correction scale factor', status) contxt = 'WRTFAK : Failed to write CORRSCAL keyword' IF( status.NE.0 )GOTO 100 name = ' ' CALL ftpkys(iunit, 'OBJECT ', name, 'object observed', status) contxt = 'WRTFAK : Failed to write OBJECT keyword' IF( status.NE.0 )GOTO 100 IF ( qbckfil ) THEN CALL ftpkys(iunit, 'BACKFILE', 'NONE', & 'bgrd FITS file', status) ELSE filenm = fgflnm(ifile) extens = filenm(index(filenm,'.')+1:) IF ( index(filenm,'.') .GT. 0 .AND. & dgbtme(ifile) .NE. 0. ) THEN filenm = filenm(:index(filenm,'.')-1)//'_bkg.'//extens CALL ftpkys(iunit, 'BACKFILE', filenm, & 'bgrd FITS file', status) ELSE CALL ftpkys(iunit, 'BACKFILE', 'NONE', & 'bgrd FITS file', status) ENDIF ENDIF contxt = 'WRTFAK : Failed to write BACKFILE keyword' IF( status.NE.0 )GOTO 100 IF ( qbckfil ) THEN CALL ftpkys(iunit, 'CORRFILE', 'NONE', & 'Correction FITS file', status) ELSE CALL ftpkys(iunit, 'CORRFILE', fgauxf(ifile,'c'), & 'Correction FITS file', status) ENDIF contxt = 'WRTFAK : Failed to write CORFFILE keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'RESPFILE', fgauxf(ifile,'r'), & 'Redistribution matrix file (RMF)', status) contxt = 'WRTFAK : Failed to write RESPFILE keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'ANCRFILE', fgauxf(ifile,'a'), & 'Anc. Resp. file (ARF)', status) contxt = 'WRTFAK : Failed to write ANCRFILE keyword' IF( status.NE.0 )GOTO 100 CALL ftpkys(iunit, 'CHANTYPE', rrchtyp, & 'Chan. assigned by det. electronics', status) contxt = 'WRTFAK : Failed to write CHANTYPE keyword' IF( status.NE.0 )GOTO 100 CALL ftpkyj(iunit, 'DETCHANS', dgungc(ifile), & 'Total no. detector channels available', status) contxt = 'WRTFAK : Failed to write DETCHANS keyword' IF( status.NE.0 )GOTO 100 CALL ftpkyj(iunit, 'TLMIN1', dgchn0(ifile), & 'Minimum value legally allowed in column 1', & status) contxt = 'WRTFAK : Failed to write TLMIN1 keyword' IF( status.NE.0 )GOTO 100 CALL ftpkyj(iunit, 'TLMAX1', dgungc(ifile)-(1-dgchn0(ifile)), & 'Maximum value legally allowed in column 1', & status) contxt = 'WRTFAK : Failed to write TLMIN1 keyword' IF( status.NE.0 )GOTO 100 IF ( qpoiss ) THEN CALL ftpkyj(iunit, 'STAT_ERR', 0, 'No stat error spcf.', & status) contxt = 'WRTFAK : Failed to write STAT_ERR keyword' IF( status.NE.0 )GOTO 100 ENDIF CALL ftpkyl(iunit, 'POISSERR', qpoiss, 'Pois. err. assumed ?', & status) contxt = 'WRTFAK : Failed to write POISSERR keyword' IF( status.NE.0 )GOTO 100 CALL ftpkyj(iunit, 'SYS_ERR', 0, 'No sys. err spcf.', status) contxt = 'WRTFAK : Failed to write SYS_ERR keyword' IF( status.NE.0 )GOTO 100 IF( .NOT.qgroup )THEN CALL ftpkyj(iunit, 'GROUPING', 0, 'No grpng of data spcf.', & status) contxt = 'WRTFAK : Failed to write GROUPING keyword' IF( status.NE.0 )GOTO 100 ENDIF IF( .NOT.qqual )THEN CALL ftpkyj(iunit, 'QUALITY', 0, 'No data qual info spcf.', & status) contxt = 'WRTFAK : Failed to write QUALITY keyword' IF( status.NE.0 )GOTO 100 ENDIF c Define extension data structure CALL ftbdef(iunit, nfield, tform, pcount, nrows, status) contxt = 'WRTFAK : Failed to define extension data structure' IF( status.NE.0 )GOTO 100 c c Write data to extension c chan0 = dgchn0(ifile) DO 200 i = 1, nrows memi(ichannl+i-1) = (i - 1) + chan0 200 CONTINUE CALL ftpclj(iunit, 1, 1, 1, nrows, memi(ichannl), status) contxt = 'WRTFAK : Failed to write CHANNEL data to extension' IF( status.NE.0 )GOTO 100 c Set up the COUNTS/RATE&ERROR arrays with zero values included where a channel c was ignored or grouped up. IF ( qbckfil ) THEN grasp = dgbtme(ifile) ELSE grasp = dgtime(ifile) ENDIF ibin = dgnbnb(ifile) - 1 ichan = 0 DO 250 i = 1, nrows memr(icounts+i-1) = 0. memr(ierror+i-1) = 0. IF( (dggcrd(ifile,i).EQ.'+' .OR. dggcrd(ifile,i).EQ.'*') ) & THEN ichan = ichan + 1 IF( dgqnot(ifile,ichan) )THEN ibin = ibin + 1 IF ( qpoiss ) THEN memr(icounts+i-1) = NINT(grasp*areasc(ibin) & *phaobs(ibin)) ELSE memr(icounts+i-1) = areasc(ibin)*phaobs(ibin) memr(ierror+i-1) = areasc(ibin)*sqrt(varobs(ibin)) ENDIF ENDIF ENDIF 250 CONTINUE CALL ftpcle(iunit, 2, 1, 1, nrows, memr(icounts), status) IF(qpoiss)THEN contxt='WRTFAK : Failed to write COUNTS data to extension' ELSE contxt='WRTFAK : Failed to write RATE data to extension' ENDIF IF( status.NE.0 )GOTO 100 icol = 2 IF ( .NOT. qpoiss ) THEN icol = icol + 1 CALL ftpcle(iunit, icol, 1, 1, nrows, memr(ierror), status) contxt='WRTFAK : Failed to write STAT_ERR data to extension' IF( status.NE.0 )GOTO 100 ENDIF IF( qqual )THEN icol = icol + 1 CALL ftpclj(iunit, icol, 1, 1, nrows, memi(iqualty), status) contxt = & 'WRTFAK : Failed to write QUALITY data to extension' IF( status.NE.0 )GOTO 100 ENDIF IF ( qgroup )THEN icol = icol + 1 CALL ftpclj(iunit, icol, 1, 1, nrows, memi(igroup), status) contxt = & 'WRTFAK : Failed to write GROUPING data to extension' IF( status.NE.0 )GOTO 100 ENDIF c If we need to write BACKSCAL as a vector then do so. As with the actual c data we need to put values in for channels that have been ignored or c grouped up. For these channels we set the BACKSCAL to that for the last c valid bin. This is not perfect but will have to do. IF ( qback ) THEN icol = icol + 1 ibin = dgnbnb(ifile) - 1 ichan = 0 DO i = 1, nrows IF ( ibin .LT. dgnbnb(ifile) ) THEN memr(icounts+i-1) = region(dgnbnb(ifile)) ELSE memr(icounts+i-1) = region(ibin) ENDIF IF( (dggcrd(ifile,i).EQ.'+' .OR. & dggcrd(ifile,i).EQ.'*') ) THEN ichan = ichan + 1 IF( dgqnot(ifile,ichan) )THEN ibin = ibin + 1 memr(icounts+i-1) = region(ibin) ENDIF ENDIF ENDDO CALL ftpcle(iunit, icol, 1, 1, nrows, memr(icounts), & status) contxt = & 'WRTFAK : Failed to write BACKSCAL data to extension' IF( status.NE.0 )GOTO 100 ENDIF c If we need to write AREASCAL as a vector then do so. As with the actual c data we need to put values in for channels that have been ignored or c grouped up. For these channels we set the AREASCAL to that for the last c valid bin. This is not perfect but will have to do. IF ( qarea ) THEN icol = icol + 1 ibin = dgnbnb(ifile) - 1 ichan = 0 DO i = 1, nrows IF ( ibin .LT. dgnbnb(ifile) ) THEN memr(icounts+i-1) = areasc(dgnbnb(ifile)) ELSE memr(icounts+i-1) = areasc(ibin) ENDIF IF( (dggcrd(ifile,i).EQ.'+' .OR. & dggcrd(ifile,i).EQ.'*') ) THEN ichan = ichan + 1 IF( dgqnot(ifile,ichan) )THEN ibin = ibin + 1 memr(icounts+i-1) = areasc(ibin) ENDIF ENDIF ENDDO CALL ftpcle(iunit, icol, 1, 1, nrows, memr(icounts), & status) contxt = & 'WRTFAK : Failed to write AREASCAL data to extension' IF( status.NE.0 )GOTO 100 ENDIF c Write out error message if necessary 100 CONTINUE IF( status.NE.0 )THEN CALL xwrite(contxt, 10) WRITE(contxt, '(a, i4, a, i4)') 'FITSIO error = ', status, & 'for file number ', ifile CALL xwrite(contxt, 10) ENDIF c c Close file c CALL ftclos(iunit, status) 300 CONTINUE ENDDO CALL frelun(iunit) CALL udmfre(icounts, 6, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmfre(ierror, 6, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmfre(ichannl, 4, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmfre(iqualty, 4, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) CALL udmfre(igroup, 4, istat ) IF( istat .NE. 0 ) CALL xwrite( & ' WARNING: Memory allocation failed in WRTFAK.', 2) RETURN END