Response files come in two varieties: RMFs and ARFs. The former contain the response matrices describing the probability of a photon of a given energy being registered in a given channel of the spectrum. The latter describes the effictive area versus energy. The rmf class is used for manipulating RMFs and the arf and arfII classes for manipulating ARFs. The arfII class is an analog of the phaII class and is useful for the case where an ARF file contains many individual effective area curves. The rmft class handles the transposed response matrix and is of limited use at present.
The example code below shows a program to read in an RMF file, to compress the matrix to remove any element below 1.0e-6, to multiply the result by an ARF, and write a new RMF file.
#include "rmf.h" #ifndef HAVE_arf #include "arf.h" #endif using namespace std; int main(int argc, char* argv[]) { string rmffile("testin.rmf"); string arffile("testin.arf"); string outfile("testout.rmf"); rmf inputRMF, outputRMF; arf inputARF; Integer Status(0); // read in the RMF and the ARF Status = inputRMF.read(rmffile); Status = inputARF.read(arffile); // remove elements from the RMF with values < 1.0e-6 Real threshold(1.0e-6); inputRMF.compress(threshold); // multiply the compressed RMF and the ARF to make an output RMF if ( inputRMF.checkCompatibility(inputARF) ) { outputRMF = inputRMF * inputARF; // and write out the result copying any extra HDUs and keywords from // the input RMF Status = outputRMF.write(outfile, rmffile); } exit(0); }
The next example shows an example program to create an RMF file.
#include "rmf.h" using namespace std; int main(int argc, char* argv[]) { const size_t Nenergies(1024), Nchannels(1024); const Real responseThreshold(1.0e-6); rmf Response; Response.setAreaScaling(1.0); Response.setResponseThreshold(responseThreshold); Response.setEnergyUnits("keV"); Response.setRMFUnits("cm^2"); Response.setChannelType("PI"); Response.setTelescope("MyTelescope"); Response.setInstrument("MyInstrument"); Response.setDetector("NONE"); Response.setFilter("NONE"); Response.setRMFType("FULL"); Response.setRMFExtensionName("MATRIX"); Response.setEBDExtensionName("EBOUNDS"); // code to load the response energy ranges vector<Real> lowE(Nenergies), highE(Nenergies); for(size_t i=0; i<Nenergies; i++) { lowE[i] = 0.1 + i*0.01; highE[i] = 0.1 + (i+1)*0.01; } Response.setLowEnergy(lowE); Response.setHighEnergy(highE); // code to load the channel energy ranges. in this // case the channel energy ranges are identical to // the response energy ranges but they need not be vector<Real> chlowE(Nenergies), chhighE(Nenergies); for(size_t i=0; i<Nchannels; i++) { chlowE[i] = 0.1 + i*0.01; chhighE[i] = 0.1 + (i+1)*0.01; } Response.setChannelLowEnergy(chlowE); Response.setChannelHighEnergy(chhighE); // loop over the energy ranges creating the response. In this // example the response is assumed to be a simple gaussian for (size_t i=0; i<Nenergies; i++) { Real centroid = (lowE[i] + highE[i])/2.0; Real sigma = sqrt(centroid); vector<Real> work(Nchannels); calcGaussResp(sigma, centroid, responseThreshold, chlowE, chhighE, work); // add to the response matrix Response.addRow(work, lowE[i], highE[i]); } // Convert to correct units (not required in this particular example) Integer status = Response.convertUnits(); // Check for errors string diagnostic = Response.check(); // Write to an output FITS file status = Response.write("MyResponse.rsp"); return(0); }
The following example shows how to read in three type I ARFs and write out a single type II ARF.
#include "arf.h" int main(int argc, char* argv[]) { arf arf1, arf2, arf3; arfII outarf; int status(0); // Read in the ARFs status = arf1.read(“first.arf”); status = arf2.read(“second.arf”); status = arf3.read(“third.arf”); // Load into the output type II ARF outarf.push(arf1); outarf.push(arf2); outarf.push(arf3); // Write to an output FITS file. Include any extra keywords // or extensions from the first arf file. status = outarf.write("output.arf", "first.arf"); return(status); }