gsystem
Loading...
Searching...
No Matches
loadMirrors.cc
Go to the documentation of this file.
1
10
11// gsystem
12#include "systemCadFactory.h"
13#include "gsystemConventions.h"
14
15// gemc
16#include "gutilities.h"
17
18// sqlite
19#include "sqlite3.h"
20
21// c++
22#include <vector>
23
24using namespace std;
25
26namespace {
28 bool table_exists(sqlite3* db, const char* name) {
29 sqlite3_stmt* stmt = nullptr;
30 if (sqlite3_prepare_v2(db, "SELECT 1 FROM sqlite_master WHERE type='table' AND name=?",
31 -1, &stmt, nullptr) != SQLITE_OK) {
32 return false;
33 }
34 sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
35 bool exists = (sqlite3_step(stmt) == SQLITE_ROW);
36 sqlite3_finalize(stmt);
37 return exists;
38 }
39
41 bool mirrors_column_exists(sqlite3* db, const std::string& column_name) {
42 sqlite3_stmt* stmt = nullptr;
43 if (sqlite3_prepare_v2(db, "SELECT name FROM PRAGMA_TABLE_INFO('mirrors')", -1, &stmt, nullptr) != SQLITE_OK) {
44 return false;
45 }
46 bool exists = false;
47 while (sqlite3_step(stmt) == SQLITE_ROW) {
48 const unsigned char* colText = sqlite3_column_text(stmt, 0);
49 if (colText != nullptr && column_name == reinterpret_cast<const char*>(colText)) {
50 exists = true;
51 break;
52 }
53 }
54 sqlite3_finalize(stmt);
55 return exists;
56 }
57}
58
59void GSystemCADFactory::loadMirrors(GSystem* s) {
60 // skip ROOT system
61 if (s->getName() == ROOTWORLDGVOLUMENAME) { return; }
62
63 // The mirror definitions come from the sqlite database (same file as the geometry).
64 string dbhost = s->get_dbhost();
65 if (dbhost.empty() || dbhost == "na") { dbhost = GSYSTEMSQLITETDEFAULTFILE; }
66
67 vector<string> dirs = {
68 ".",
69 gutilities::gemc_root().string(),
70 (gutilities::gemc_root() / "examples").string()
71 };
72 auto dbPath = gutilities::searchForFileInLocations(dirs, dbhost);
73 if (!dbPath) {
74 log->error(ERR_GSQLITEERROR, "CAD factory: sqlite database <" + dbhost + "> not found.");
75 return;
76 }
77
78 sqlite3* db = nullptr;
79 if (sqlite3_open_v2(dbPath.value().c_str(), &db, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) {
80 sqlite3_close(db);
81 log->error(ERR_GSQLITEERROR, "CAD factory: failed to open sqlite database <" + dbhost + ">.");
82 return;
83 }
84
85 // Mirrors are optional: databases created before mirror support may lack the table, and systems
86 // that define no mirrors carry a bare table with only the id column.
87 if (!table_exists(db, "mirrors") || !mirrors_column_exists(db, "name")) {
88 log->info(2, "CAD factory: no usable 'mirrors' table (ok if the system defines no mirrors).");
89 sqlite3_close(db);
90 return;
91 }
92
93 // Columns are selected explicitly by name (canonical GMirror parameter order) so the loader does
94 // not depend on the table column order.
95 const string transmittance_column = mirrors_column_exists(db, "transmittance")
96 ? "transmittance"
97 : "NULL AS transmittance";
98 const string sql_query =
99 "SELECT name, description, type, finish, model, border, matOptProps, photonEnergy, "
100 "indexOfRefraction, reflectivity, efficiency, specularlobe, specularspike, backscatter, "
101 + transmittance_column +
102 ", sigmaAlpha FROM mirrors WHERE experiment = ? AND system = ? AND variation = ? AND run = ?";
103
104 sqlite3_stmt* stmt = nullptr;
105 if (sqlite3_prepare_v2(db, sql_query.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
106 log->error(ERR_GSQLITEERROR, "CAD factory: error preparing mirrors query: ", sqlite3_errmsg(db));
107 sqlite3_close(db);
108 return;
109 }
110
111 string experiment = s->getExperiment();
112 string system_name = s->getName();
113 string variation = s->getVariation();
114 int runno = s->getRunno();
115
116 sqlite3_bind_text(stmt, 1, experiment.c_str(), -1, SQLITE_TRANSIENT);
117 sqlite3_bind_text(stmt, 2, system_name.c_str(), -1, SQLITE_TRANSIENT);
118 sqlite3_bind_text(stmt, 3, variation.c_str(), -1, SQLITE_TRANSIENT);
119 sqlite3_bind_int(stmt, 4, runno);
120
121 int rc;
122 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
123 vector<string> gmirrorPars;
124 const int ncols = sqlite3_column_count(stmt);
125 for (int i = 0; i < ncols; ++i) {
126 const char* ctext =
127 (sqlite3_column_type(stmt, i) == SQLITE_NULL)
128 ? "NULL"
129 : reinterpret_cast<const char*>(sqlite3_column_text(stmt, i));
130 gmirrorPars.emplace_back(ctext);
131 }
132 s->addGMirror(gmirrorPars);
133 }
134
135 if (rc != SQLITE_DONE) {
136 log->error(ERR_GSQLITEERROR, "CAD factory: sqlite error while reading mirrors: ", sqlite3_errmsg(db));
137 }
138
139 sqlite3_finalize(stmt);
140 sqlite3_close(db);
141}
std::shared_ptr< GLogger > log
Represents a single detector system (e.g., calorimeter, tracker).
Definition gsystem.h:33
int getRunno() const
Definition gsystem.h:127
std::string getExperiment() const
Definition gsystem.h:125
std::string getVariation() const
Definition gsystem.h:124
std::string getName() const
Definition gsystem.h:122
void addGMirror(std::vector< std::string > pars)
Build and add a mirror (optical surface) from a serialized parameter list.
Definition gsystem.cc:194
std::string get_dbhost() const
Definition gsystem.h:128
Conventions and shared constants for the detector-system module.
#define GSYSTEMSQLITETDEFAULTFILE
Default sqlite DB filename used when the user does not specify one.
#define ROOTWORLDGVOLUMENAME
Canonical name for the ROOT/world gvolume entry.
#define ERR_GSQLITEERROR
std::filesystem::path gemc_root()
std::optional< std::string > searchForFileInLocations(const std::vector< std::string > &locations, std::string_view filename)