casa  5.7.0-16
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SynthesisImagerMixin.h
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 //# SynthesisImagerMixin.h: Mixin for using SynthesisImager class in parallel
3 //# imaging framework (ParallelImagerMixin)
4 //# Copyright (C) 2016
5 //# Associated Universities, Inc. Washington DC, USA.
6 //#
7 //# This library is free software; you can redistribute it and/or modify it
8 //# under the terms of the GNU Library General Public License as published by
9 //# the Free Software Foundation; either version 2 of the License, or (at your
10 //# option) any later version.
11 //#
12 //# This library is distributed in the hope that it will be useful, but WITHOUT
13 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 //# License for more details.
16 //#
17 //# You should have received a copy of the GNU Library General Public License
18 //# along with this library; if not, write to the Free Software Foundation,
19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20 //#
21 //# Correspondence concerning AIPS++ should be addressed as follows:
22 //# Internet email: aips2-request@nrao.edu.
23 //# Postal address: AIPS++ Project Office
24 //# National Radio Astronomy Observatory
25 //# 520 Edgemont Road
26 //# Charlottesville, VA 22903-2475 USA
27 //#
28 #ifndef SYNTHESIS_IMAGER_MIXIN_H_
29 #define SYNTHESIS_IMAGER_MIXIN_H_
30 
31 #include <casa/Containers/Record.h>
32 #include <casa/Arrays/Array.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <algorithm>
38 #include <memory>
39 #include <vector>
40 #include <unistd.h>
41 #include <cerrno>
42 #include <cstring>
43 #include <string>
44 #include <dirent.h>
45 #include <system_error>
46 
47 namespace casa {
48 
52 template <class T>
54  : public T {
55 
56 private:
57  std::unique_ptr<SynthesisImager> si;
58 
59  static casacore::Quantity asQuantity(const casacore::Record &rec, const char *field_name);
60 
61  static casacore::Quantity asQuantity(const casacore::String &field_name);
62 
63  static bool haveCFCache(const std::string &dirname);
64 
65  static int isCFS(const struct dirent *d);
66 
67  static std::vector<std::string> getCFCacheList(
68  const SynthesisParamsGrid &grid_pars, int size, int rank);
69 
70  void
71  set_weighting(const casacore::Record &weight_pars,
72  const std::vector<SynthesisParamsImage> &image_pars) {
74  ((weight_pars.fieldNumber("type") != -1)
75  ? weight_pars.asString("type")
76  : casacore::String("natural"));
77  casacore::String rmode =
78  ((weight_pars.fieldNumber("rmode") != -1)
79  ? weight_pars.asString("rmode")
80  : casacore::String("norm"));
81  casacore::Double robust =
82  ((weight_pars.fieldNumber("robust") != -1)
83  ? weight_pars.asDouble("robust")
84  : 0.0);
85  casacore::Int npixels =
86  ((weight_pars.fieldNumber("npixels") != -1)
87  ? weight_pars.asInt("npixels")
88  : 0);
89  casacore::Bool multifield =
90  ((weight_pars.fieldNumber("multifield") != -1)
91  ? weight_pars.asBool("multifield")
92  : false);
93  casacore::Bool usecubebriggs =
94  ((weight_pars.fieldNumber("usecubebrigss") != -1)
95  ? weight_pars.asBool("usecubebriggs")
96  : false);
97  casacore::Quantity noise =
98  ((weight_pars.fieldNumber("noise") != -1)
99  ? asQuantity(weight_pars, "noise")
100  : casacore::Quantity(0.0, "Jy"));
101  casacore::Quantity field_of_view =
102  ((weight_pars.fieldNumber("fieldofview") != -1)
103  ? asQuantity(weight_pars, "fieldofview")
104  : casacore::Quantity(0.0, "arcsec"));
105  const casacore::Array<casacore::String> &uv_taper_pars =
106  ((weight_pars.fieldNumber("uvtaper") != -1)
107  ? weight_pars.asArrayString("uvtaper")
109  casacore::Quantity bmaj(0.0, "deg"), bmin(0.0, "deg"), bpa(0.0, "deg");
110  casacore::String filter_type("");
111  if (uv_taper_pars.nelements() > 0) {
112  bmaj = asQuantity(uv_taper_pars(casacore::IPosition(1, 0)));
113  filter_type = casacore::String("gaussian");
114  if (uv_taper_pars.nelements() > 1) {
115  bmin = asQuantity(uv_taper_pars(casacore::IPosition(1, 1)));
116  if (uv_taper_pars.nelements() > 2)
117  bpa = asQuantity(uv_taper_pars(casacore::IPosition(1, 2)));
118  } else /* uv_taper_pars.nelements() == 1 */ {
119  bmin = bmaj;
120  }
121  }
122  // TODO: the following is the logic for setting 'filter_type' in
123  // synthesisimager_cmpt.cc...verify that the check on uv_taper_pars[0]
124  // length is not required here
125  //
126  // if (uv_taper_pars.nelements() > 0 && uv_taper_pars[0].length() > 0)
127  // filter_type = casacore::String("gaussian");
128  si->weight(type, rmode, noise, robust, field_of_view, npixels,
129  multifield, usecubebriggs, filter_type, bmaj, bmin, bpa);
130  if (image_pars.size() == 1
131  && image_pars[0].stokes == casacore::String("I")
132  && weight_pars.asString("type") != casacore::String("natural")) {
133  si->getWeightDensity();
134  T::reduce_weight_density();
135  si->setWeightDensity();
136  }
137  };
138 
139 protected:
140  void
142  std::vector<SynthesisParamsSelect> &select_pars,
143  std::vector<SynthesisParamsImage> &image_pars,
144  std::vector<SynthesisParamsGrid> &grid_pars,
145  casacore::Record &weight_pars) {
146  // Create a single imager component for every rank in comm.
147 
148  teardown_imager();
149  int imaging_rank = T::effective_rank(comm);
150  if (imaging_rank == 0) {
151  si = std::unique_ptr<SynthesisImager>(new SynthesisImager());
152  for (auto s : select_pars)
153  si->selectData(s);
154  for (size_t i = 0;
155  i < std::min(image_pars.size(), grid_pars.size());
156  ++i)
157  si->defineImage(image_pars[i], grid_pars[i]);
158  }
159  int imaging_size = T::effective_size(comm);
160  if (imaging_rank >= 0 && imaging_size > 1) {
161  SynthesisParamsGrid &grid_pars0 = grid_pars.at(0);
162  if (!haveCFCache(grid_pars0.cfCache)) {
163  if (imaging_rank == 0) {
164  std::vector<std::string> empty;
165  si->dryGridding(empty);
166  }
167  std::vector<std::string> cf_list =
168  getCFCacheList(grid_pars0, imaging_size, imaging_rank);
169  if (cf_list.size() > 0) {
170  if (si == nullptr)
171  si = std::unique_ptr<SynthesisImager>(
172  new SynthesisImager());
173  si->fillCFCache(
174  cf_list, grid_pars0.ftmachine, grid_pars0.cfCache,
175  grid_pars0.psTermOn, grid_pars0.aTermOn,grid_pars0.conjBeams);
176  }
177  }
178  // create new imager instance, scrapping any that already exists
179  si = std::unique_ptr<SynthesisImager>(new SynthesisImager());
180  si->selectData(select_pars.at(imaging_rank));
181  si->defineImage(image_pars.at(imaging_rank),
182  grid_pars.at(imaging_rank));
183  }
184  if (imaging_rank >= 0)
185  set_weighting(weight_pars, image_pars);
186  };
187 
189  si.reset();
190  };
191 
192 public:
193  void
195  // TODO: verify this is correct for all ranks
196  if (si != nullptr) si->makePSF();
197  };
198 
199  void
201  casacore::Record rec;
202  rec.define("lastcycle", T::is_clean_complete());
203  // TODO: verify this is correct for all ranks
204  if (si != nullptr) si->executeMajorCycle(rec);
205  T::end_major_cycle();
206  };
207 
208  void
210  // TODO: verify this is correct for all ranks
211  if (si != nullptr) si->predictModel();
212  };
213 };
214 
215 // TODO: this method is a utility function...move it into another module?
216 template <class T>
219  const casacore::Record &rec, const char *field_name) {
220  casacore::Bool success = false;
222  casacore::String err_str;
223  switch (rec.dataType(field_name)) {
224  case casacore::DataType::TpRecord:
225  success = qh.fromRecord(err_str, rec.subRecord(field_name));
226  break;
227  case casacore::DataType::TpString:
228  success = qh.fromString(err_str, rec.asString(field_name));
229  break;
230  default:
231  break;
232  }
233  if (!(success && qh.isQuantity())) {
234  ostringstream oss;
235  oss << "Error in converting quantity: " << err_str;
236  throw (casacore::AipsError(oss.str()));
237  }
238  return qh.asQuantity();
239 };
240 
241 // TODO: this method is a utility function...move it into another module?
242 template <class T>
246  casacore::String err_str;
247  casacore::Bool success = qh.fromString(err_str, field_name);
248  if (!(success && qh.isQuantity())) {
249  ostringstream oss;
250  oss << "Error in converting quantity: " << err_str;
251  throw (casacore::AipsError(oss.str()));
252  }
253  return qh.asQuantity();
254 };
255 
256 template <class T>
257 bool
258 SynthesisImagerMixin<T>::haveCFCache(const std::string &dirname) {
259  struct stat stat_buf;
260  return (stat(dirname.c_str(), &stat_buf) == 0
261  && S_ISDIR(stat_buf.st_mode));
262 };
263 
264 template <class T>
265 int
266 SynthesisImagerMixin<T>::isCFS(const struct dirent *d) {
267  std::string name(d->d_name);
268  return name.find("CFS") == 0;
269 };
270 
271 template <class T>
272 std::vector<std::string>
274  const SynthesisParamsGrid &grid_pars, int size, int rank) {
275  // return vector for all ranks, even if it's empty
276  std::vector<std::string> result;
277  struct dirent **namelist;
278  int nCFS = scandir(grid_pars.cfCache.c_str(), &namelist,
279  SynthesisImagerMixin::isCFS, alphasort);
280  if (nCFS >= 0) {
281  size = std::min(size, nCFS);
282  // Note that with size having been redefined as the minimum of the
283  // original size value and nCFS, if rank >= size, then no strings
284  // are added to the result vector in the following loop.
285  for (int n = rank; n < nCFS; n += size) {
286  std::string name(namelist[n]->d_name);
287  result.push_back(name);
288  }
289  free(namelist);
290  } else {
291  // errno == ENOMEM
292  std::error_condition ec(errno, std::generic_category());
293  throw casacore::AipsError(casacore::String("Failed to scan cf cache directory '")
294  + grid_pars.cfCache + casacore::String("': ")
295  + casacore::String(ec.message()));
296  }
297  return result;
298 };
299 
300 } // namespace casa
301 
302 #endif // SYNTHESIS_IMAGER_MIXIN_H_
const Record & subRecord(const RecordFieldId &) const
Get the subrecord from the given field.
Bool asBool(const RecordFieldId &) const
The following functions get the value based on field name or number.
A Vector of integers, for indexing into Array&lt;T&gt; objects.
Definition: IPosition.h:119
int Int
Definition: aipstype.h:50
virtual Bool fromRecord(String &error, const RecordInterface &in)
Create a Quantum from a record or a string.
int MPI_Comm
Definition: MPIGlue.h:59
const Array< String > & asArrayString(const RecordFieldId &) const
size_t nelements() const
How many elements does this array have? Product of all axis lengths.
Definition: ArrayBase.h:99
void setup_imager(MPI_Comm comm, std::vector< SynthesisParamsSelect > &select_pars, std::vector< SynthesisParamsImage > &image_pars, std::vector< SynthesisParamsGrid > &grid_pars, casacore::Record &weight_pars)
#define min(a, b)
Definition: hio.h:45
Quantum< Double > Quantity
Definition: Quantum.h:38
virtual Type type()
Return the type enum.
std::unique_ptr< SynthesisImager > si
Class that contains functions needed for imager.
A holder for Quantums to enable record conversions.
ABSTRACT CLASSES Abstract class for colors Any implementation of color should be able to provide a hexadecimal form of the if a human readable name(i.e."black").In many places throughout the plotter
casacore::Bool aTermOn
For wb-aprojection ftm.
size_t size() const
Simple mixin class to put SynthesisImager into ParallelImagerMixin framework.
DataType dataType(const RecordFieldId &) const
virtual Int fieldNumber(const String &fieldName) const
Get the field number from the field name.
static bool haveCFCache(const std::string &dirname)
double Double
Definition: aipstype.h:55
const Char * c_str() const
Get char array.
Definition: String.h:555
const Quantum< Double > & asQuantity()
Double asDouble(const RecordFieldId &) const
A hierarchical collection of named fields of various types.
Definition: Record.h:180
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
static int isCFS(const struct dirent *d)
static casacore::Quantity asQuantity(const casacore::Record &rec, const char *field_name)
TODO: this method is a utility function...move it into another module?
casacore::Bool empty() const
void set_weighting(const casacore::Record &weight_pars, const std::vector< SynthesisParamsImage > &image_pars)
free(pool)
virtual Bool fromString(String &error, const String &in)
Initialise the class from a String representation.
Int asInt(const RecordFieldId &) const
Bool isQuantity() const
Base class for all Casacore library errors.
Definition: Error.h:134
const String & asString(const RecordFieldId &) const
String: the storage and methods of handling collections of characters.
Definition: String.h:223
void define(const RecordFieldId &, Bool value)
Define a value for the given field.
static std::vector< std::string > getCFCacheList(const SynthesisParamsGrid &grid_pars, int size, int rank)