SDenseStationListXMLManager.cc
Go to the documentation of this file.
1 #include <fwk/CentralConfig.h>
2 #include <det/VManager.h>
3 #include <sdet/SManagerRegister.h> // needed for registration macro
4 
5 #include <utl/ErrorLogger.h>
6 #include <utl/Reader.h>
7 #include <utl/UTMPoint.h>
8 #include <utl/Point.h>
9 #include <utl/Vector.h>
10 #include <utl/Line.h>
11 #include <utl/Plane.h>
12 #include <utl/GeometryUtilities.h>
13 
14 #include <fwk/CoordinateSystemRegistry.h>
15 
16 #include <evt/Event.h>
17 #include <evt/ShowerSimData.h>
18 
19 #include <fwk/RunController.h>
20 #include <fwk/LocalCoordinateSystem.h>
21 
22 #include <det/Detector.h>
23 #include <sdet/SDetector.h>
24 #include <sdet/Station.h>
25 
26 #include <sdet/SDenseStationListXMLManager.h>
27 
28 #include <boost/range/iterator_range.hpp>
29 
30 using namespace std;
31 using namespace fwk;
32 using namespace utl;
33 using namespace det;
34 using namespace evt;
35 
36 
37 REGISTER_S_MANAGER("SDenseStationListXMLManager", sdet::SDenseStationListXMLManager);
38 
39 
40 namespace sdet {
41 
42  void
43  SDenseStationListXMLManager::Init(const string& configLink)
44  {
45  // call shadowed VManager::Init() first
46  VManager::Init(configLink);
47 
48  fDenseStationList.clear();
49 
50  const string stationString = "denseStation";
51 
52  for (auto cB = fBranch.GetFirstChild(); cB; cB = cB.GetNextSibling()) {
53  if (cB.GetName() != stationString)
54  continue;
55  const auto atts = cB.GetAttributes();
56  const auto id = FindComponent<int>("id", atts);
57  const auto it = fDenseStationList.find(id);
58  if (it == fDenseStationList.end())
59  fDenseStationList.insert(fDenseStationList.end(), id);
60  else {
61  ostringstream warn;
62  warn << "Found multiple instances of dense station " << id << ". "
63  "Only the first one will be used.";
64  WARNING(warn);
65  }
66  }
67  }
68 
69 
71  SDenseStationListXMLManager::GetData(int& returnData,
72  const string& componentProperty,
73  const string& componentName,
74  const IndexMap& componentIndex)
75  const
76  {
77  if (componentName != "stationList" || !IsDense(componentIndex))
78  return eNotFound;
79 
80  if (componentProperty == "isUUB") {
81  returnData = 0;
82  auto isUUBB = fBranch.GetChild("isUUB");
83  if (isUUBB)
84  isUUBB.GetData(returnData);
85  } else if (componentProperty == "hasSmallPMT") {
86  returnData = 0;
87  auto hasSmallPMTB = fBranch.GetChild("hasSmallPMT");
88  if (hasSmallPMTB)
89  hasSmallPMTB.GetData(returnData);
90  } else if (componentProperty == "hasScintillator") {
91  returnData = 0;
92  auto hasScintillatorB = fBranch.GetChild("hasScintillator");
93  if (hasScintillatorB)
94  hasScintillatorB.GetData(returnData);
95  } else if (componentProperty == "groupId")
96  returnData = 0;
97  else if (componentProperty == "zone")
98  fBranch.GetChild("UTMInfo").GetChild("zone").GetData(returnData);
99  else
100  return eNotFound;
101 
102  // final test: throw if "stationId" is not present in componentIndex
103  FindComponent<string>("stationId", componentIndex);
104  return eFound;
105  }
106 
107 
109  SDenseStationListXMLManager::GetData(double& returnData,
110  const string& componentProperty,
111  const string& componentName,
112  const IndexMap& componentIndex)
113  const
114  {
115  if (componentName != "stationList" || !IsDense(componentIndex))
116  return eNotFound;
117 
118  if (componentProperty == "northing" ||
119  componentProperty == "easting" ||
120  componentProperty == "altitude") {
121 
122  const auto& event = RunController::GetInstance().GetCurrentEvent();
123 
124  fDenseStations.Validate(event);
125 
126  const auto id = FindComponent<int>("stationId", componentIndex);
127 
128  if (!fDenseStations.HasStation(id)) {
129  // Dense station positions specified in (2-D) polar coordinates in the
130  // showerCS. Here we project coordinates onto the corsika observation
131  // level, and convert resulting coordinates into UTM so that that
132  // sdet::Station will interpret the data as though it were a regular
133  // (non-dense) station.
134 
135  double deltaPhi = 0;
136  if (GetData(deltaPhi, "deltaPhi", "stationList", componentIndex) == eNotFound)
137  return eNotFound;
138  double r = 0;
139  if (GetData(r, "r", "stationList", componentIndex) == eNotFound)
140  return eNotFound;
141 
142  fDenseStations.AddStation(id, r, deltaPhi);
143  }
144 
145  const auto& pos = fDenseStations.GetStation(id);
146  if (componentProperty == "northing")
147  returnData = pos.fNorthing;
148  else if (componentProperty == "easting")
149  returnData = pos.fEasting;
150  else if (componentProperty == "altitude")
151  returnData = pos.fHeight;
152  else
153  return eNotFound;
154 
155  return eFound;
156 
157  } else if (componentProperty == "axis1" || componentProperty == "axis2") {
158 
159  returnData = 0;
160  return eFound;
161 
162  } else {
163 
164  const auto it = componentIndex.find("stationId");
165 
166  if (it != componentIndex.end()) {
167 
168  const IndexMap atts({{ "id", it->second }});
169 
170  auto stationB = fBranch.GetChild("denseStation", atts);
171  if (!stationB)
172  return eNotFound;
173 
174  auto componentB = stationB.GetChild(componentProperty);
175  if (!componentB)
176  return eNotFound;
177 
178  componentB.GetData(returnData);
179  return eFound;
180 
181  } else {
182 
183  ostringstream info;
184  info << "Could not interpret the request with "
185  "component property = '" << componentProperty << "', "
186  "component name = '" << componentName << "', index ";
187  for (const auto& kv : componentIndex)
188  info << " (" << kv.first << ", " << kv.second << ')';
189  INFO(info);
190  return eNotFound;
191 
192  }
193 
194  }
195  }
196 
197 
199  SDenseStationListXMLManager::GetData(string& returnData,
200  const string& componentProperty,
201  const string& componentName,
202  const IndexMap& componentIndex)
203  const
204  {
205  if (componentName != "stationList" || !IsDense(componentIndex))
206  return eNotFound;
207 
208  if (componentProperty == "name")
209  returnData = "DenseStation" + FindComponent<string>("stationId", componentIndex);
210  else if (componentProperty == "commission")
211  returnData = "2000-01-01T00:00:00Z";
212  else if (componentProperty == "decommission")
213  returnData = "2030-01-01T00:00:00Z";
214  else {
215  auto componentB = fBranch.GetChild("UTMInfo").GetChild(componentProperty);
216  if (componentB)
217  componentB.GetData(returnData);
218  else
219  return eNotFound;
220  }
221 
222  return eFound;
223  }
224 
225 
227  SDenseStationListXMLManager::GetData(vector<int>& returnData,
228  const string& componentProperty,
229  const string& componentName,
230  const IndexMap& componentIndex)
231  const
232  {
233  if (componentName != "stationList")
234  return eNotFound;
235 
236  if (componentProperty == "denseStationList") {
237  GetFullStationList(returnData);
238  return eFound;
239  } else if (componentProperty == "stationGroup") {
240  if (IsDense(componentIndex)) {
241  returnData.clear();
242  return eFound;
243  }
244  } else if (componentProperty == "crown") {
245  if (IsDense(componentIndex)) {
246  returnData.clear();
247  return eFound;
248  }
249  }
250 
251  return eNotFound;
252  }
253 
254 
256  SDenseStationListXMLManager::GetData(vector<bool>& returnData,
257  const string& componentProperty,
258  const string& componentName,
259  const IndexMap& componentIndex)
260  const
261  {
262  if (componentName != "stationList" || !IsDense(componentIndex))
263  return eNotFound;
264 
265  if (componentProperty == "inGrid") {
266  returnData.clear();
267  return eFound;
268  }
269 
270  return eNotFound;
271  }
272 
273 
274  void
275  SDenseStationListXMLManager::GetFullStationList(vector<int>& returnList)
276  const
277  {
278  returnList.assign(fDenseStationList.begin(), fDenseStationList.end());
279  }
280 
281 
282  bool
283  SDenseStationListXMLManager::IsDense(const IndexMap& componentIndex)
284  const
285  {
286  const auto id = FindComponent<int>("stationId", componentIndex);
287  return fDenseStationList.find(id) != fDenseStationList.end();
288  }
289 
290 
291  //
292 
293 
294  void
295  SDenseStationListXMLManager::DenseStations::Validate(const Event& event)
296  {
297  Validate(event.GetHeader().GetId());
298  if (fEventId.empty())
299  Init(event);
300  }
301 
302 
303  void
305  {
306  // dense tank positions computed relative to sim shower. check
307  // that the sim shower has all the necessary ingredients.
308 
309  if (!event.HasSimShower())
311  "Attempt to generate a dense array failed because "
312  "no simulated shower is present in the event."
313  );
314 
315  const auto& simShower = event.GetSimShower();
316 
317  if (!simShower.HasGeometry())
319  "Attempt to generate a dense array failed because "
320  "the shower core position has not been set."
321  );
322 
323  const auto& showerCS = simShower.GetShowerCoordinateSystem();
324  const Point observationCore(0,0,0, showerCS);
325  fShowerDirection = simShower.GetDirection();
326 
327  // The core has to be projected from the corsika observation-level
328  // to the array ground. Since we do not know which array will be used
329  // (ideal or real), we simply find a station which is closest to the shower
330  // axis and take its height as the reference height.
331 
332  const Line showerAxis(observationCore, fShowerDirection);
333  const auto& sDet = det::Detector::GetInstance().GetSDetector();
334  const sdet::Station* closestStation = nullptr;
335  {
336  double minDistance = numeric_limits<double>::infinity();
337  for (const auto& s : sDet.StationsRange()) {
338  if (s.IsDense())
339  continue;
340  const double d = Distance(showerAxis, s.GetPosition());
341  if (d < minDistance) {
342  minDistance = d;
343  closestStation = &s;
344  }
345  }
346  }
347 
348  if (!closestStation)
349  throw MissingEventDataException("Could not find closest station!");
350  else {
351  ostringstream info;
352  info << "Reference height for dense stations taken from closest station "
353  "id = " << closestStation->GetId();
354  INFO(info);
355  }
356 
357  // project shower axis (line) to the ground plane at height of the closest station
358 
359  const auto& refPos = closestStation->GetPosition();
360  const auto& groundCS = LocalCoordinateSystem::Create(refPos);
361  const Vector groundNormal(0,0,1, groundCS);
362  fGroundPlane = Plane(refPos, groundNormal);
363  fGroundCore = Intersection(fGroundPlane, showerAxis);
364  fBaseX = Vector(1,0,0, showerCS);
365  fBaseY = Vector(0,1,0, showerCS);
366 
367 #if 0
368  const auto& pampaCS = det::Detector::GetInstance().GetReferenceCoordinateSystem();
369  ostringstream info;
370 #define DUMP(_x_) #_x_ " (" << _x_.GetX(pampaCS) << ", " << _x_.GetY(pampaCS) << ", " << _x_.GetZ(pampaCS) << ")\n"
371  info << "trigger calculation:\n"
372  << DUMP(observationCore)
373  << DUMP(fShowerDirection)
374  << DUMP(refPos)
375  << DUMP(groundNormal)
376  << DUMP(fGroundCore)
377  << DUMP(fBaseX)
378  << DUMP(fBaseY)
379  ;
380 #undef DUMP
381  INFO(info);
382 #endif
383 
384  fEventId = event.GetHeader().GetId();
385  }
386 
387 
388  void
389  SDenseStationListXMLManager::DenseStations::AddStation(const int id, const double r, const double deltaPhi)
390  {
391  // add the two unit vectors according to phi angle and stretch by r
392  const double x = r * cos(deltaPhi);
393  const double y = r * sin(deltaPhi);
394  const Vector rho = x * fBaseX + y * fBaseY;
395  const Point stationInShowerPlane = fGroundCore + rho;
396  const Point stationInGroundPlane =
397  Intersection(fGroundPlane, Line(stationInShowerPlane, fShowerDirection));
398  const UTMPoint utm(stationInGroundPlane, ReferenceEllipsoid::eWGS84);
399  const UTM neh{utm.GetNorthing(), utm.GetEasting(), utm.GetHeight()};
400  fStations.insert({id, neh});
401  }
402 
403 }
double Plane(const utl::Point &point, const utl::Vector &normal, const utl::Photon &photonIn, utl::Photon &photonOut)
Definition: RTFunctions.cc:41
Point object.
Definition: Point.h:32
Detector description interface for Station-related data.
evt::Header & GetHeader()
Class to hold and convert a point in geodetic coordinates.
Definition: UTMPoint.h:40
bool HasSimShower() const
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
Manager to return station positions for array defined in shower coordinates.
void Init()
Initialise the registry.
double GetNorthing() const
Get the northing.
Definition: UTMPoint.h:206
Line Intersection(const Plane &p1, const Plane &p2)
utl::Point GetPosition() const
Tank position.
constexpr double s
Definition: AugerUnits.h:163
double GetHeight() const
Get the height.
Definition: UTMPoint.h:212
#define REGISTER_S_MANAGER(_name_, _Type_)
double GetEasting() const
Get the easting.
Definition: UTMPoint.h:209
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
const std::string & GetId() const
Get the event identifier.
Definition: Event/Header.h:31
Base class for exceptions arising because required info not present in the Event. ...
double Distance(const Point &p, const sdet::Station &s)
std::map< std::string, std::string > IndexMap
Definition: VManager.h:133
Vector object.
Definition: Vector.h:30
#define DUMP(_x_)
int GetId() const
Station ID.
Status
Specifies success or (eventually) various possible failure modes.
Definition: VManager.h:127
Definition: Line.h:17

, generated on Tue Sep 26 2023.