39 const char *
const fn =
"getError";
44 std::string tele0, tele, bandKey =
"BAND", teleKey =
"TELESCOP";
45 hdu.keyWord(teleKey).value(tele0);
48 for (
auto &file: files) {
50 ferr{
new CCfits::FITS(file, CCfits::Read,
false, {bandKey, teleKey})};
51 auto &phdu = ferr->pHDU();
53 phdu.keyWord(teleKey).value(tele);
54 if (band == band0 && tele == tele0) {
55 if (st[0]) { phdu.read(err, ll, ur, st); }
56 else { phdu.read(err); }
58 phdu.axis(1) != hdu.axis(1), fn,
59 "Error map '%s' size mismatch (%lux%lu pixels, %lux%lu in parent)",
60 file, phdu.axis(0), phdu.axis(1), hdu.axis(0), hdu.axis(1));
62 MU_INFO(fn,
"Using error map '%s' for %ld micron band", file, band0);
68 double relerr = 0.01*cli.
getDouble(
'E', 3.0);
70 for (
auto &elem: err) { elem = fabs(elem * relerr); }
71 MU_INFO(fn,
"No error map found for %ld micron band, assuming %g%% of input",
86 hdu.keyWord(
"CRPIX1").setValue(1+hdu.keyWord(
"CRPIX1").value(pix)-ll[0]);
87 hdu.keyWord(
"CRPIX2").setValue(1+hdu.keyWord(
"CRPIX2").value(pix)-ll[1]);
106 const char *
const fn =
"process";
112 "Minimum of 2 input bands required (%lu given); try --help",
119 unsigned nc, nr, r0, c0;
121 &nc, &nr, &c0, &r0), fn,
122 "Invalid syntax '--cutout %s'; try --help", cutout);
123 MU_INFO(fn,
"Processing %lux%lu cutout at (%lu,%lu)",
125 ll[0] = c0, ll[1] = r0;
126 ur[0] = c0+nc-1, ur[1] = r0+nr-1;
136 for (
auto &file: files) {
137 img.
emplace_back(
new CCfits::FITS(file, CCfits::Read,
true));
142 auto &hd0 = *bandHDU.
front(), &hd = *bandHDU.
back();
143 int naxes = hd.axes();
144 MU_EXCEPTION_IF(naxes != 2, fn,
"%s has %ld axes (expected 2)", file,naxes);
149 if (st[0]) { hd.read(bandData.
back(), ll, ur, st); }
150 else { hd.read(bandData.
back()); }
153 "Input maps too small for %ldx%ld model",
155 MU_ERROR_IF(hd.axis(0) != hd0.axis(0) || hd.axis(1) != hd0.axis(1), fn,
156 "%s dimensions are %ldx%ld (fiducial is %ldx%ld)",
157 file, hd.axis(0), hd.axis(1), hd0.axis(0), hd0.axis(1));
160 MU_INFO(fn,
"%s (%s): %ldx%ld @ %3ld microns (%s)", file,
161 hd.keyWord(
"OBJECT").value(name),
162 hd.axis(0), hd.axis(1),
getBand(hd),
163 hd.keyWord(
"TELESCOP").value(facility));
167 hd.readKey(
"BUNIT", units);
169 "%s map units are '%s' (need MJy/sr)", file, units);
173 for (
unsigned i=0; i != bandData.
size(); i++) {
179 auto mtfile = cli.
getString(
'o',
"mtcore.fits");
182 outFITS(
new CCfits::FITS(mtfile, BYTE_IMG, 0,
nullptr));
191 solve(outMap, outHDU, outFITS.
get(), bandData, bandError, bandHDU, axis,
195 for (
unsigned i=0, n=outMap.
size(); i != n; i++) {
196 setKeys(*outHDU.
at(i), *bandHDU[0], cli, ll);
197 outHDU[i]->write(1, outMap[i].size(), outMap[i]);
200 if (!cli.getOption(
'B')) {
202 for (
unsigned i=0, n=bandData.
size(); i != n; i++) {
205 comm = bandHDU[i]->getComments();
206 bandHDU[i]->readKey(bunit, units);
210 auto eHDU = outFITS->addImage(name,
mapDataCode, axis);
211 eHDU->addKey(bunit, units,
"Image flux units");
212 eHDU->copyAllKeys(bandHDU[i]);
213 eHDU->writeComment(comm);
214 eHDU->write(1, axis[0]*axis[1], bandData[i]);
219 eHDU->writeComment(
"ERROR map used for the associated parent image");
220 eHDU->addKey(bunit, units,
"Error flux units");
221 eHDU->copyAllKeys(bandHDU[i]);
222 eHDU->writeComment(comm);
223 eHDU->write(1, axis[0]*axis[1], bandError[i]);
241 void setKeys(CCfits::ExtHDU &hdu,
const CCfits::PHDU &hdu0,
244 const char *
const fn =
"setKeys";
248 "FITS file creator");
257 auto name = hdu.name();
258 if (name[0] ==
'N' || name[1] ==
'N') {
259 hdu.addKey<
std::string>(
"BUNIT",
"cm^-2",
"Gas column density units");
261 if (name[0] ==
'T' || name[1] ==
'T') {
262 hdu.addKey<
std::string>(
"BUNIT",
"K",
"Gas temperature units");
264 if (name[0] ==
'C' || ! name.compare(0, 4,
"dChi")) {
265 hdu.addKey<
std::string>(
"BUNIT",
"chi2/DOF",
"Goodness of fit units");
267 if (name[0] ==
'n') {
268 hdu.addKey<
std::string>(
"BUNIT",
"counts",
"Fitter iterations");
270 if (! name.compare(0, 4,
"diff")) {
273 "Absolute differential flux units");
276 "Relative differential flux units");
279 if (! name.compare(0, 4,
"frac")) {
280 hdu.addKey<
std::string>(
"BUNIT",
"ratio",
"Cold flux fraction");
284 auto &inKeys = hdu0.keyWord();
285 for (
auto &key: {
"OBJECT",
"RADESYS",
286 "CTYPE1",
"CRVAL1",
"CRPIX1",
"CDELT1",
287 "CTYPE2",
"CRVAL2",
"CRPIX2",
"CDELT2",
289 auto kp = inKeys.
find(key);
290 if (kp != inKeys.end()) {
291 hdu.addKey(kp->second);
293 MU_EXCEPTION(fn,
"Fiducial image missing keyword '%s'", key);
void process(const mutils::CommandLine &cli)
Processes multi-wavelength maps into temperature/column density maps.
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
void resetRefPix(CCfits::HDU &hdu, const std::vector< long > &ll)
Reset cutout header coordinates.
constexpr const char *const version
Version string.
mapDataType getError(const mapDataType &data, CCfits::PHDU &hdu, const mutils::CommandLine &cli)
#define MU_EXCEPTION(src, msg,...)
Throws mutils::Exception using uniform messaging.
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 std::vector< long > &axis, const mutils::CommandLine &cli, const std::vector< long > &ll, const std::vector< long > &ur, const std::vector< long > &st)
Performs least-squares fitting of band SEDs.
#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.
const std::string nullStr(1, 0)
constexpr int mapDataCode
Output FITS maps data code (cf. mapDataType).
double getDouble(char shortName, double defValue) const
Retrieves unique floating point option.
void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0, const mutils::CommandLine &cli, const std::vector< long > &ll)
Sets header keywords for an output map.
std::valarray< float > mapDataType
Output FITS maps data type (cf. mapDataCode).
T emplace_back(T... args)