Manticore  Version 2.0alpha
Physics of Molecular Clouds
process.cc
Go to the documentation of this file.
1 
8 #include "manticore.h"
9 #include "version.h"
10 
11 namespace mu = mutils;
12 
14 namespace manticore {
15 
30 mapDataType getError(const mapDataType &data, CCfits::PHDU &hdu,
31  const mu::CommandLine &cli)
32 {
33  const char *const fn = "getError";
34  mapDataType err;
36 
37  int band0 = getBand(hdu), band;
38  std::string tele0, tele, bandKey = "BAND", teleKey = "TELESCOP";
39  hdu.keyWord(teleKey).value(tele0);
40 
41  if (cli.getOption('e', &files)) {
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();
46  band = getBand(phdu);
47  phdu.keyWord(teleKey).value(tele);
48  if (band == band0 && tele == tele0) {
49  phdu.read(err);
50  MU_EXCEPTION_IF(err.size() != data.size(), fn,
51  "Error map '%s' size mismatch (%ud pixels, %ud in parent)",
52  file, err.size(), data.size());
53 
54  MU_INFO(fn, "Using error map '%s' for %ld micron band", file, band0);
55  return err;
56  }
57  }
58  }
59 
60  double relerr = 0.01*cli.getDouble('E', 3.0);
61  err = data;
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",
64  band0, 100*relerr);
65  return err;
66 }
67 
68 
82 void process(const mu::CommandLine &cli)
83 {
84  const char *const fn = "process";
85  auto &files = cli.arguments();
86  bool modelMap = cli.getOption('M');
87 
88  // Sanity check.
89  MU_EXCEPTION_IF(files.size() < 2, fn,
90  "Minimum of 2 input bands required (%lu given); try --help",
91  files.size());
92 
93  // Read the FITS images.
94  // It is assumed ALL images have the same pixel scale and dimensions,
95  // even if the beams are mismatched.
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());
102 
103  // Axis check.
104  std::string name;
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));
111 
112  // Get image data and keywords.
113  std::string facility;
114  bandData.push_back(mapDataType());
115  hd.read(bandData.back());
117  bandData.back().size() < modelMapLen*modelMapLen, fn,
118  "Input maps too small for %ldx%ld model",
120 
121  hd.readAllKeys();
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));
126 
127  // Unit check.
128  std::string units;
129  hd.readKey("BUNIT", units);
130  MU_EXCEPTION_IF(units != "MJy/sr", fn,
131  "%s map units are '%s' (need MJy/sr)", file, units);
132  }
133 
134  // Find or create associated error maps.
135  for (unsigned i=0; i != bandData.size(); i++) {
136  bandError.push_back(getError(bandData[i], *bandHDU[i], cli));
137  }
138 
139  //
140  // Output maps (one image extension per map).
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));
145 
146  // Fit the mass and temperature maps.
147  std::vector<mapDataType> outMap;
148  std::vector<CCfits::ExtHDU*> outHDU;
149  solve(outMap, outHDU, outFITS.get(), bandData, bandError, bandHDU, cli);
150 
151  // Populate header keywords and write data.
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]);
155  }
156 
157  if (!cli.getOption('B')) {
158  // Append input band data to FITS output.
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);
164 
165  std::vector<long> axes = {bandHDU[i]->axis(0), bandHDU[i]->axis(1)};
166  if (modelMap) { axes = {modelMapLen, modelMapLen}; }
167 
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]);
173 
174  name.insert(0, "d");
175  eHDU = outFITS->addImage(name, mapDataCode, axes);
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]);
181  }
182  }
183 }
184 
185 
196 void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0)
197 {
198  const char *const fn = "setKeys";
199 
200  // Local keywords.
201  hdu.addKey("CREATOR", std::string("Manticore v") + version,
202  "FITS file creator");
203  //
204  // Units are determined from the extension name:
205  // - N/dN: 1/cm^2
206  // - T/dT: K
207  // - Chi2: chi2/DOF
208  // - nIter: counts
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");
212  }
213  if (name[0] == 'T' || name[1] == 'T') {
214  hdu.addKey<std::string>("BUNIT", "K", "Gas temperature units");
215  }
216  if (name[0] == 'C') {
217  hdu.addKey<std::string>("BUNIT", "chi2/DOF", "Goodness of fit units");
218  }
219  if (name[0] == 'n') {
220  hdu.addKey<std::string>("BUNIT", "counts", "Fitter iterations");
221  }
222 // if (name == 'C') {
223 // hdu.addKey<std::string>("BUNIT", "chi2/DOF", "Goodness of fit units");
224 // }
225 
226  // Copy select keywords from fiducial image.
227  auto &inKeys = hdu0.keyWord();
228  for (auto &key: {"OBJECT",
229  "CTYPE1", "CRVAL1", "CRPIX1", "CDELT1",
230  "CTYPE2", "CRVAL2", "CRPIX2", "CDELT2",
231  }) {
232  auto kp = inKeys.find(key);
233  if (kp != inKeys.end()) {
234  hdu.addKey(kp->second);
235  } else {
236  MU_EXCEPTION(fn, "Fiducial image missing keyword '%s'", key);
237  }
238  }
239 }
240 
241 } // namespace manticore
void process(const mutils::CommandLine &cli)
Processes multi-wavelength maps into temperature/column density maps.
Definition: process.cc:82
void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0)
Sets header keywords for an output map.
Definition: process.cc:196
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.
Definition: solve.cc:635
unsigned getOption(const Option &option, Arguments *values=nullptr, unsigned nMax=-1) const
Retrieves all copies of a command line option.
Definition: CommandLine.cc:197
const Arguments & arguments() const
Returns remaining arguments (read-only).
Definition: CommandLine.h:132
Command line options and arguments.
Definition: CommandLine.h:47
std::string getString(char shortName, const std::string &defValue) const
Retrieves unique string option.
Definition: CommandLine.cc:392
std::vector< std::string > Arguments
Command line arguments type.
Definition: CommandLine.h:51
#define MU_EXCEPTION_IF(cond, src, msg,...)
Conditionally throws mutils::Exception.
Definition: Exception.h:101
Package namespace.
Definition: Detector.cc:13
std::map< std::string, manticore::tableType > modelMap
Definition: Dust.cc:137
mapDataType getError(const mapDataType &data, CCfits::PHDU &hdu, const mutils::CommandLine &cli)
Generates image error map.
Definition: process.cc:30
constexpr const char *const version
Version string.
Definition: version.h:6
MathUtils package.
Definition: CommandLine.cc:10
#define MU_EXCEPTION(src, msg,...)
Throws mutils::Exception using uniform messaging.
Definition: Exception.h:90
#define MU_ERROR_IF(cond, src, msg,...)
Conditionally log a message at level Log::ERROR.
Definition: Log.h:174
int getBand(const CCfits::HDU &hdu)
Returns nominal band center (microns) from an HDU.
Definition: manticore.cc:97
#define MU_INFO(src, msg,...)
Log a message at level Log::INFO.
Definition: Log.h:100
constexpr long modelMapLen
One-dimensional length of model map image.
Definition: manticore.h:17
constexpr int mapDataCode
Output FITS maps data code (cf. mapDataType).
Definition: manticore.h:14
double getDouble(char shortName, double defValue) const
Retrieves unique floating point option.
Definition: CommandLine.cc:376
std::valarray< float > mapDataType
Output FITS maps data type (cf. mapDataCode).
Definition: manticore.h:11