33 const char *
const fn =
"getError";
38 std::string tele0, tele, bandKey =
"BAND", teleKey =
"TELESCOP";
39 hdu.keyWord(teleKey).value(tele0);
42 for (
auto &file: files) {
43 std::unique_ptr<CCfits::FITS>
44 ferr{
new CCfits::FITS(file, CCfits::Read,
false, {bandKey, teleKey})};
45 auto &phdu = ferr->pHDU();
47 phdu.keyWord(teleKey).value(tele);
48 if (band == band0 && tele == tele0) {
51 "Error map '%s' size mismatch (%ud pixels, %ud in parent)",
52 file, err.size(), data.size());
54 MU_INFO(fn,
"Using error map '%s' for %ld micron band", file, band0);
60 double relerr = 0.01*cli.
getDouble(
'E', 3.0);
62 for (
auto &elem: err) { elem = fabs(elem * relerr); }
63 MU_INFO(fn,
"No error map found for %ld micron band, assuming %g%% of input",
84 const char *
const fn =
"process";
90 "Minimum of 2 input bands required (%lu given); try --help",
96 std::vector<std::unique_ptr<CCfits::FITS>> img;
97 std::vector<CCfits::PHDU*> bandHDU;
98 std::vector<mapDataType> bandData, bandError;
99 for (
auto &file: files) {
100 img.emplace_back(
new CCfits::FITS(file, CCfits::Read,
true));
101 bandHDU.push_back(&img.back()->pHDU());
105 auto &hd0 = *bandHDU.front(), &hd = *bandHDU.back();
106 int naxes = hd.axes();
107 MU_EXCEPTION_IF(naxes != 2, fn,
"%s has %ld axes (expected 2)", file,naxes);
108 MU_ERROR_IF(hd.axis(0) != hd0.axis(0) || hd.axis(1) != hd0.axis(1), fn,
109 "%s dimensions are %ldx%ld (fiducial is %ldx%ld)",
110 file, hd.axis(0), hd.axis(1), hd0.axis(0), hd0.axis(1));
113 std::string facility;
115 hd.read(bandData.back());
118 "Input maps too small for %ldx%ld model",
122 MU_INFO(fn,
"%s (%s): %ldx%ld @ %3ld microns (%s)", file,
123 hd.keyWord(
"OBJECT").value(name),
124 hd.axis(0), hd.axis(1),
getBand(hd),
125 hd.keyWord(
"TELESCOP").value(facility));
129 hd.readKey(
"BUNIT", units);
131 "%s map units are '%s' (need MJy/sr)", file, units);
135 for (
unsigned i=0; i != bandData.size(); i++) {
136 bandError.push_back(
getError(bandData[i], *bandHDU[i], cli));
141 auto mtfile = cli.
getString(
'o',
"mtcore.fits");
142 if (cli.
getOption(
'F')) { mtfile.insert(0, 1,
'!'); }
143 std::unique_ptr<CCfits::FITS>
144 outFITS(
new CCfits::FITS(mtfile, BYTE_IMG, 0,
nullptr));
147 std::vector<mapDataType> outMap;
148 std::vector<CCfits::ExtHDU*> outHDU;
149 solve(outMap, outHDU, outFITS.get(), bandData, bandError, bandHDU, cli);
152 for (
unsigned i=0, n=outMap.size(); i != n; i++) {
153 setKeys(*outHDU.at(i), *bandHDU[0]);
154 outHDU[i]->write(1, outMap[i].size(), outMap[i]);
159 for (
unsigned i=0, n=bandData.size(); i != n; i++) {
160 std::string name =
"BAND" + std::to_string(
getBand(*bandHDU[i]));
161 std::string bunit =
"BUNIT", units,
162 comm = bandHDU[i]->getComments();
163 bandHDU[i]->readKey(bunit, units);
165 std::vector<long> axes = {bandHDU[i]->axis(0), bandHDU[i]->axis(1)};
168 auto eHDU = outFITS->addImage(name,
mapDataCode, axes);
169 eHDU->addKey(bunit, units,
"Image flux units");
170 eHDU->copyAllKeys(bandHDU[i]);
171 eHDU->writeComment(comm);
172 eHDU->write(1, axes[0]*axes[1], bandData[i]);
176 eHDU->writeComment(
"ERROR map used for the associated parent image");
177 eHDU->addKey(bunit, units,
"Error flux units");
178 eHDU->copyAllKeys(bandHDU[i]);
179 eHDU->writeComment(comm);
180 eHDU->write(1, axes[0]*axes[1], bandError[i]);
196 void setKeys(CCfits::ExtHDU &hdu,
const CCfits::PHDU &hdu0)
198 const char *
const fn =
"setKeys";
201 hdu.addKey(
"CREATOR", std::string(
"Manticore v") +
version,
202 "FITS file creator");
209 auto name = hdu.name();
210 if (name[0] ==
'N' || name[1] ==
'N') {
211 hdu.addKey<std::string>(
"BUNIT",
"cm^-2",
"Gas column density units");
213 if (name[0] ==
'T' || name[1] ==
'T') {
214 hdu.addKey<std::string>(
"BUNIT",
"K",
"Gas temperature units");
216 if (name[0] ==
'C') {
217 hdu.addKey<std::string>(
"BUNIT",
"chi2/DOF",
"Goodness of fit units");
219 if (name[0] ==
'n') {
220 hdu.addKey<std::string>(
"BUNIT",
"counts",
"Fitter iterations");
227 auto &inKeys = hdu0.keyWord();
228 for (
auto &key: {
"OBJECT",
229 "CTYPE1",
"CRVAL1",
"CRPIX1",
"CDELT1",
230 "CTYPE2",
"CRVAL2",
"CRPIX2",
"CDELT2",
232 auto kp = inKeys.find(key);
233 if (kp != inKeys.end()) {
234 hdu.addKey(kp->second);
236 MU_EXCEPTION(fn,
"Fiducial image missing keyword '%s'", key);
void process(const mutils::CommandLine &cli)
Processes multi-wavelength maps into temperature/column density maps.
void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0)
Sets header keywords for an output map.
void solve(std::vector< mapDataType > &outMap, std::vector< CCfits::ExtHDU *> &outHDU, CCfits::FITS *outFITS, const std::vector< mapDataType > &bandData, const std::vector< mapDataType > &bandError, const std::vector< CCfits::PHDU *> &bandHDU, const mutils::CommandLine &cli)
Performs least-squares fitting of band SEDs.
unsigned getOption(const Option &option, Arguments *values=nullptr, unsigned nMax=-1) const
Retrieves all copies of a command line option.
const Arguments & arguments() const
Returns remaining arguments (read-only).
Command line options and arguments.
std::string getString(char shortName, const std::string &defValue) const
Retrieves unique string option.
std::vector< std::string > Arguments
Command line arguments type.
#define MU_EXCEPTION_IF(cond, src, msg,...)
Conditionally throws mutils::Exception.
std::map< std::string, manticore::tableType > modelMap
mapDataType getError(const mapDataType &data, CCfits::PHDU &hdu, const mutils::CommandLine &cli)
Generates image error map.
constexpr const char *const version
Version string.
#define MU_EXCEPTION(src, msg,...)
Throws mutils::Exception using uniform messaging.
#define MU_ERROR_IF(cond, src, msg,...)
Conditionally log a message at level Log::ERROR.
int getBand(const CCfits::HDU &hdu)
Returns nominal band center (microns) from an HDU.
#define MU_INFO(src, msg,...)
Log a message at level Log::INFO.
constexpr long modelMapLen
One-dimensional length of model map image.
constexpr int mapDataCode
Output FITS maps data code (cf. mapDataType).
double getDouble(char shortName, double defValue) const
Retrieves unique floating point option.
std::valarray< float > mapDataType
Output FITS maps data type (cf. mapDataCode).