Manticore  Version 1.0
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, band;
38  std::string tele0, tele;
39  std::vector<std::string> keys = {"BAND", "TELESCOP"};
40  hdu.keyWord(keys[0]).value(band0);
41  hdu.keyWord(keys[1]).value(tele0);
42 
43  if (cli.getOption('e', &files)) {
44  for (auto &file: files) {
45  std::unique_ptr<CCfits::FITS>
46  ferr{new CCfits::FITS(file, CCfits::Read, false, keys)};
47  auto &phdu = ferr->pHDU();
48  phdu.keyWord(keys[0]).value(band);
49  phdu.keyWord(keys[1]).value(tele);
50  if (band == band0 && tele == tele0) {
51  phdu.read(err);
52  MU_EXCEPTION_IF(err.size() != data.size(), fn,
53  "Error map '%s' size mismatch (%ud pixels, %ud in parent)",
54  file, err.size(), data.size());
55 
56  MU_INFO(fn, "Using error map '%s' for %ld micron band", file, band0);
57  return err;
58  }
59  }
60  }
61 
62  double relerr = 0.01*cli.getDouble('E', 3.0);
63  err = data;
64  for (auto &elem: err) { elem *= relerr; }
65  MU_INFO(fn, "No error map found for %ld micron band, assuming %g%% of input",
66  band0, 100*relerr);
67  return err;
68 }
69 
70 
84 void process(const mu::CommandLine &cli)
85 {
86  const char *const fn = "process";
87  auto &files = cli.arguments();
88 
89  // Sanity check.
90  MU_EXCEPTION_IF(files.size() < 2, fn,
91  "Minimum of 2 input bands required (%lu given); try --help",
92  files.size());
93 
94  // Read the FITS images.
95  // It is assumed ALL images have the same pixel scale and dimensions,
96  // even if the beams are mismatched.
97  std::vector<std::unique_ptr<CCfits::FITS>> img;
98  std::vector<CCfits::PHDU*> bandHDU;
99  std::vector<mapDataType> bandData, bandError;
100  for (auto &file: files) {
101  img.emplace_back(new CCfits::FITS(file, CCfits::Read, true));
102  bandHDU.push_back(&img.back()->pHDU());
103 
104  // Axis check.
105  std::string name;
106  auto &hd0 = *bandHDU.front(), &hd = *bandHDU.back();
107  int naxes = hd.axes();
108  MU_EXCEPTION_IF(naxes != 2, fn, "%s has %ld axes (expected 2)", file,naxes);
109  MU_ERROR_IF(hd.axis(0) != hd0.axis(0) || hd.axis(1) != hd0.axis(1), fn,
110  "%s dimensions are %ldx%ld (fiducial is %ldx%ld)",
111  file, hd.axis(0), hd.axis(1), hd0.axis(0), hd0.axis(1));
112 
113  // Get image data and keywords.
114  int band;
115  std::string facility;
116  bandData.push_back(mapDataType());
117  hd.read(bandData.back());
118  hd.readAllKeys();
119  MU_INFO(fn, "%s (%s): %ldx%ld @ %3ld microns (%s)", file,
120  hd.keyWord("OBJECT").value(name),
121  hd.axis(0), hd.axis(1), hd.keyWord("BAND").value(band),
122  hd.keyWord("TELESCOP").value(facility));
123 
124  // Unit check.
125  std::string units;
126  hd.readKey("BUNIT", units);
127  MU_EXCEPTION_IF(units != "MJy/sr", fn,
128  "%s map units are '%s' (need MJy/sr)", file, units);
129  }
130 
131  // Find or create associated error maps.
132  for (unsigned i=0; i != bandData.size(); i++) {
133  bandError.push_back(getError(bandData[i], *bandHDU[i], cli));
134  }
135 
136  // Output maps (one image extension per map).
137  auto mtfile = cli.getString('o', "mtcore.fits");
138  if (cli.getOption('F')) { mtfile.insert(0, 1, '!'); }
139  std::unique_ptr<CCfits::FITS>
140  outFITS(new CCfits::FITS(mtfile, BYTE_IMG, 0, nullptr));
141 
142  // Fit the mass and temperature maps.
143  std::vector<mapDataType> outMap;
144  std::vector<CCfits::ExtHDU*> outHDU;
145  solve(outMap, outHDU, outFITS.get(), bandData, bandError, bandHDU, cli);
146 
147  // Populate header keywords and write data.
148  for (unsigned i=0, n=outMap.size(); i != n; i++) {
149  setKeys(*outHDU.at(i), *bandHDU[0]);
150  outHDU[i]->write(1, outMap[i].size(), outMap[i]);
151  }
152 
153  if (!cli.getOption('B')) {
154  // Append input band data to FITS output.
155  for (unsigned i=0, n=bandData.size(); i != n; i++) {
156  int band;
157  std::string bunit = "BUNIT", units,
158  comm = bandHDU[i]->getComments(),
159  hist = bandHDU[i]->getHistory();
160  bandHDU[i]->readKey(bunit, units);
161  bandHDU[i]->keyWord("BAND").value(band);
162  std::string name = "BAND" + std::to_string(band);
163 
164  std::vector<long> axes = {bandHDU[i]->axis(0), bandHDU[i]->axis(1)};
165  auto eHDU = outFITS->addImage(name, mapDataCode, axes);
166  eHDU->addKey(bunit, units, "Image flux units");
167  eHDU->copyAllKeys(bandHDU[i]);
168  eHDU->writeComment(comm);
169  eHDU->writeHistory(hist);
170  eHDU->write(1, bandData[i].size(), bandData[i]);
171 
172  name.insert(0, "d");
173  eHDU = outFITS->addImage(name, mapDataCode, axes);
174  eHDU->writeComment("ERROR map used for the associated parent image");
175  eHDU->addKey(bunit, units, "Error flux units");
176  eHDU->copyAllKeys(bandHDU[i]);
177  eHDU->writeComment(comm);
178  eHDU->writeHistory(hist);
179  eHDU->write(1, bandError[i].size(), bandError[i]);
180  }
181  }
182 }
183 
184 
195 void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0)
196 {
197  const char *const fn = "setKeys";
198 
199  // Local keywords.
200  hdu.addKey("CREATOR", std::string("Manticore v") + version,
201  "FITS file creator");
202  //
203  // Units are determined from the extension name:
204  // - N/dN: 1/cm^2
205  // - T/dT: K
206  // - Chi2: chi2/DOF
207  auto name = hdu.name().c_str();
208  if (name[0] == 'N' || name[1] == 'N') {
209  hdu.addKey<std::string>("BUNIT", "cm^-2", "Gas column density units");
210  }
211  if (name[0] == 'T' || name[1] == 'T') {
212  hdu.addKey<std::string>("BUNIT", "K", "Gas temperature units");
213  }
214  if (name[0] == 'C') {
215  hdu.addKey<std::string>("BUNIT", "chi2/DOF", "Goodness of fit units");
216  }
217 
218  // Copy select keywords from fiducial image.
219  auto &inKeys = hdu0.keyWord();
220  for (auto &key: {"OBJECT",
221  "CTYPE1", "CRVAL1", "CRPIX1", "CDELT1",
222  "CTYPE2", "CRVAL2", "CRPIX2", "CDELT2",
223  }) {
224  auto kp = inKeys.find(key);
225  if (kp != inKeys.end()) {
226  hdu.addKey(kp->second);
227  } else {
228  MU_EXCEPTION(fn, "Fiducial image missing keyword '%s'", key);
229  }
230  }
231 }
232 
233 } // namespace manticore
void process(const mutils::CommandLine &cli)
Processes multi-wavelength maps into temperature/column density maps.
Definition: process.cc:84
void setKeys(CCfits::ExtHDU &hdu, const CCfits::PHDU &hdu0)
Sets header keywords for an output map.
Definition: process.cc:195
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:286
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
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
#define MU_INFO(src, msg,...)
Log a message at level Log::INFO.
Definition: Log.h:100
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