Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
CameraFactory.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7
8#include <csm/Plugin.h>
9#include <QDir>
10#include <QDirIterator>
11#include <QFileInfo>
12#include <QLibrary>
13
14#include "CameraFactory.h"
15
16#include "Camera.h"
17#include "CSMCamera.h"
18#include "FileName.h"
19#include "IException.h"
20#include "Plugin.h"
21#include "Preference.h"
22
23#include "csm/csm.h"
24#include "csm/GeometricModel.h"
25#include "csm/Isd.h"
26#include "csm/Model.h"
27#include "csm/NitfIsd.h"
28#include "csm/Plugin.h"
29
30using namespace csm;
31using namespace std;
32
33namespace Isis {
36
49 // Try to load a plugin file in the current working directory and then
50 // load the system file
51
52 initPlugin();
53
54 try {
55 // Is there a CSM blob on the cube?
56 if (cube.hasBlob("CSMState", "String")) {
57 // Create ISIS CSM Camera Model
58 try {
59 return new CSMCamera(cube);
60 }
61 catch (IException &e) {
62 QString msg = "Unable to create CSM camera using CSMState Cube blob.";
63 throw IException(e, IException::Unknown, msg, _FILEINFO_);
64 }
65 }
66 else {
67 // First get the spacecraft and instrument and combine them
68 Pvl &lab = *cube.label();
69 PvlGroup &inst = lab.findGroup("Instrument", Isis::Pvl::Traverse);
70 QString spacecraft = (QString) inst["SpacecraftName"];
71 QString name = (QString) inst["InstrumentId"];
72 spacecraft = spacecraft.toUpper();
73 name = name.toUpper();
74 QString group = spacecraft + "/" + name;
75 group = group.remove(" ");
76
77 PvlGroup &kerns = lab.findGroup("Kernels", Isis::Pvl::Traverse);
78 // Default version 1 for backwards compatibility (spiceinit'd cubes before camera model versioning)
79 if (!kerns.hasKeyword("CameraVersion")) {
80 kerns.addKeyword(PvlKeyword("CameraVersion", "1"));
81 }
82
83 int cameraOriginalVersion = (int)kerns["CameraVersion"];
84 int cameraNewestVersion = CameraVersion(cube);
85
86 if (cameraOriginalVersion != cameraNewestVersion) {
87 string msg = "The camera model used to create a camera for this cube is out of date, " \
88 "please re-run spiceinit on the file or process with an old Isis version " \
89 "that has the correct camera model.";
90 throw IException(IException::Unknown, msg, _FILEINFO_);
91 }
92
93 // See if we have a camera model plugin
94 QFunctionPointer ptr;
95 try {
96 ptr = m_cameraPlugin.GetPlugin(group);
97 }
98 catch(IException &e) {
99 QString msg = "Unsupported camera model, unable to find plugin for ";
100 msg += "SpacecraftName [" + spacecraft + "] with InstrumentId [";
101 msg += name + "]";
102 throw IException(e, IException::Unknown, msg, _FILEINFO_);
103 }
104
105 // Now cast that pointer in the proper way
106 Camera * (*plugin)(Isis::Cube &cube);
107 plugin = (Camera * ( *)(Isis::Cube &cube)) ptr;
108
109 // Create the camera as requested
110 return (*plugin)(cube);
111 }
112 }
113 catch(IException &e) {
114 string message = "Unable to initialize camera model in Camera Factory.";
115 throw IException(e, IException::Unknown, message, _FILEINFO_);
116 }
117 }
118
119
125 if (!m_initialized) {
126 // Handle the ISIS camera plugins
127 if (m_cameraPlugin.fileName() == "") {
128 FileName localFile("Camera.plugin");
129 if (localFile.fileExists())
130 m_cameraPlugin.read(localFile.expanded());
131
132 FileName systemFile("$ISISROOT/lib/Camera.plugin");
133 if (systemFile.fileExists())
134 m_cameraPlugin.read(systemFile.expanded());
135 }
136
137 // Find the CSM plugins by searching the directories identified in the Preferences.
138 // Load the found libraries. This causes the static instance(s) to be constructed,
139 // and thus registering the model with the csm Plugin class.
140 Preference &p = Preference::Preferences();
141 PvlGroup &grp = p.findGroup("Plugins", Isis::Pvl::Traverse);
142 for (int i = 0; i<grp["CSMDirectory"].size(); i++) {
143 FileName csmDir = grp["CSMDirectory"][i];
144
145 QDirIterator csmLib(csmDir.expanded(), {"*.so", "*.dylib"}, QDir::Files);
146 while (csmLib.hasNext()) {
147 QString csmLibName = csmLib.next();
148 QLibrary csmDynamicLib(csmLibName);
149 csmDynamicLib.load();
150 }
151 }
152 }
153 m_initialized = true;
154 }
155
156
165 return CameraVersion(*cube.label());
166 }
167
168
177 // Try to load a plugin file in the current working directory and then
178 // load the system file
179 initPlugin();
180
181 try {
182 // First get the spacecraft and instrument and combine them
183 PvlGroup &inst = lab.findGroup("Instrument", Isis::Pvl::Traverse);
184 QString spacecraft = (QString) inst["SpacecraftName"];
185 QString name = (QString) inst["InstrumentId"];
186 spacecraft = spacecraft.toUpper();
187 name = name.toUpper();
188 QString group = spacecraft + "/" + name;
189 group = group.remove(" ");
190
191 PvlGroup plugin;
192 try {
193 bool found = false;
194 // Find the most recent (last) version of the camera model
195 for (int i = m_cameraPlugin.groups() - 1; i >= 0; i--) {
196 if (m_cameraPlugin.group(i) == group) {
197 plugin = m_cameraPlugin.group(i);
198 found = true;
199 break;
200 }
201 }
202 if (!found) {
203 QString msg = "Unable to find PVL group [" + group + "].";
204 throw IException(IException::Unknown, msg, _FILEINFO_);
205 }
206 }
207 catch(IException &e) {
208 QString msg = "Unsupported camera model, unable to find plugin for ";
209 msg += "SpacecraftName [" + spacecraft + "] with InstrumentId [";
210 msg += name + "]";
211 throw IException(e, IException::Unknown, msg, _FILEINFO_);
212 }
213
214 if (!plugin.hasKeyword("Version")) {
215 QString msg = "Camera model identified by [" + group + "] does not have a version number";
216 throw IException(IException::Programmer, msg, _FILEINFO_);
217 }
218
219 return (int)plugin["Version"];
220 }
221 catch(IException &e) {
222 string msg = "Unable to locate latest camera model version number from group [Instrument]";
223 throw IException(e, IException::Unknown, msg, _FILEINFO_);
224 }
225 }
226
236 csm::Model *CameraFactory::constructModelFromIsd(QString isdFilePath, QString pluginName, QString modelName, QString isdFormat) {
237
238 // Get model spec if any of these params are not passed in
239 if (pluginName.isEmpty() || modelName.isEmpty() || isdFormat.isEmpty()) {
240 QStringList modelSpec = getModelSpecFromIsd(isdFilePath);
241 pluginName = modelSpec[0];
242 modelName = modelSpec[1];
243 isdFormat = modelSpec[2];
244 }
245
246 csm::Model *model = nullptr;
247
248 const csm::Plugin *plugin = csm::Plugin::findPlugin(pluginName.toStdString());
249 if (plugin == NULL) {
250 QString message = "Cannot find requested Plugin: [" + pluginName + "].";
251 throw IException(IException::User, message, _FILEINFO_);
252 }
253
254 csm::Isd fileIsd(isdFilePath.toStdString());
255 csm::Nitf21Isd nitf21Isd(isdFilePath.toStdString());
256 if (isdFormat == QString::fromStdString(fileIsd.format())) {
257 model = plugin->constructModelFromISD(fileIsd, modelName.toStdString());
258 }
259 else if (isdFormat == QString::fromStdString(nitf21Isd.format())) {
260 model = plugin->constructModelFromISD(nitf21Isd, modelName.toStdString());
261 }
262 else {
263 QString message = "Invalid ISD format specifications [" + isdFormat + "].";
264 throw IException(IException::Programmer, message, _FILEINFO_);
265 }
266
267 return model;
268 }
269
277 QStringList CameraFactory::getModelSpecFromIsd(QString isdFilePath, QString pluginName, QString modelName) {
278 QList<QStringList> possibleModels;
279 for (const csm::Plugin * plugin : csm::Plugin::getList()) {
280 QString currentPluginName = QString::fromStdString(plugin->getPluginName());
281
282 if (!pluginName.isEmpty() && pluginName != pluginName) {
283 continue;
284 }
285
286 for (size_t modelIndex = 0; modelIndex < plugin->getNumModels(); modelIndex++) {
287 QString currentModelName = QString::fromStdString(plugin->getModelName(modelIndex));
288
289 if (!modelName.isEmpty() && currentModelName != modelName) {
290 continue;
291 }
292
293 csm::Isd fileIsd(isdFilePath.toStdString());
294 if (plugin->canModelBeConstructedFromISD(fileIsd, currentModelName.toStdString())) {
295 QStringList modelSpec = {
296 currentPluginName,
297 currentModelName,
298 QString::fromStdString(fileIsd.format())};
299 possibleModels.append(modelSpec);
300 continue; // If the file ISD works, don't check the other ISD formats
301 }
302
303 csm::Nitf21Isd nitf21Isd(isdFilePath.toStdString());
304 if (plugin->canModelBeConstructedFromISD(nitf21Isd, currentModelName.toStdString())) {
305 QStringList modelSpec = {
306 currentPluginName,
307 currentModelName,
308 QString::fromStdString(nitf21Isd.format())};
309 possibleModels.append(modelSpec);
310 continue; // If the NITF 2.1 ISD works, don't check the other ISD formats
311 }
312 }
313 }
314
315 if (possibleModels.size() > 1) {
316 QString message = "Multiple models can be created from the ISD [" + isdFilePath + "]. "
317 "Re-run with the PLUGINNAME and MODELNAME parameters. "
318 "Possible plugin & model names:\n";
319 for (const QStringList &modelSpec : possibleModels) {
320 message += "Plugin [" + modelSpec[0] + "], Model [" + modelSpec[1] + "]\n";
321 }
322 throw IException(IException::User, message, _FILEINFO_);
323 }
324
325 if (possibleModels.empty()) {
326 QString message = "No loaded model could be created from the ISD [" + isdFilePath + "]."
327 "Loaded plugin & model names:\n";
328 for (const csm::Plugin * plugin : csm::Plugin::getList()) {
329 QString currentPluginName = QString::fromStdString(plugin->getPluginName());
330 for (size_t modelIndex = 0; modelIndex < plugin->getNumModels(); modelIndex++) {
331 QString modelName = QString::fromStdString(plugin->getModelName(modelIndex));
332 message += "Plugin [" + currentPluginName + "], Model [" + modelName + "]\n";
333 }
334 }
335 throw IException(IException::User, message, _FILEINFO_);
336 }
337
338 // If we are here, then we have exactly 1 model
339 QStringList modelSpec = possibleModels.front();
340
341 if (modelSpec.size() != 3) {
342 QString message = "Model specification [" + modelSpec.join(" ") + "] has [" + QString::number(modelSpec.size()) + "] elements "
343 "when it should have 3 elements.";
344 throw IException(IException::Programmer, message, _FILEINFO_);
345 }
346
347 return modelSpec;
348 }
349} // end namespace isis
static QStringList getModelSpecFromIsd(QString isdFilePath, QString pluginName="", QString modelName="")
Generate CSM Model specs from ISD.
static bool m_initialized
Has the plugin list been initialized.
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
static void initPlugin()
Reads the appropriate plugin file for the ISIS cameras, and scans the directories specified in IsisPr...
static int CameraVersion(Cube &cube)
This looks up the current camera model version from the cube.
static csm::Model * constructModelFromIsd(QString isdFilePath, QString pluginName="", QString modelName="", QString isdFormat="")
Constructs CSM Model from ISD.
static Plugin m_cameraPlugin
The plugin file for the camera.
IO Handler for Isis Cubes.
Definition Cube.h:168
bool hasBlob(const QString &name, const QString &type)
Check to see if the cube contains a BLOB.
Definition Cube.cpp:2305
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1975
Loads plugins from a shared library.
Definition Plugin.h:55
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.