mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 19:19:39 -06:00
Load CDFs and trace field lines using kameleon and store the info in FieldlinesState.
This commit is contained in:
@@ -149,6 +149,15 @@ private:
|
||||
void setModelDependentConstants();
|
||||
void setupProperties();
|
||||
bool prepareForOsflsStreaming();
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
// --- Initialization functions which require the kameleon module to be loaded! --- //
|
||||
bool extractCdfInfoFromDictionary(std::string& seedFilePath,
|
||||
std::string& tracingVar,
|
||||
std::vector<std::string>& extraVars);
|
||||
bool extractSeedPointsFromFile(const std::string& path,
|
||||
std::vector<glm::vec3>& outVec);
|
||||
bool getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER);
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
// ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ //
|
||||
inline bool isWithinSequenceInterval(const double CURRENT_TIME) const;
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
|
||||
#include <modules/fieldlinessequence/rendering/renderablefieldlinessequence.h>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
#include <ccmc/Kameleon.h>
|
||||
#include <modules/kameleon/include/kameleonhelper.h>
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/interaction/navigationhandler.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
@@ -33,6 +38,9 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
std::string _loggerCat = "RenderableFieldlinesSequence";
|
||||
|
||||
@@ -41,14 +49,21 @@ namespace {
|
||||
const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING]
|
||||
const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING]
|
||||
|
||||
// ---------------------- MANDATORY INPUT TYPE SPECIFIC KEYS ---------------------- //
|
||||
const char* KEY_CDF_SEED_POINT_FILE = "SeedPointFile"; // [STRING] Path to a .txt file containing seed points
|
||||
const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING] Currently supports: "batsrus", "enlil" & "pfss"
|
||||
|
||||
// ----------------------- OPTIONAL INPUT TYPE SPECIFIC KEYS ---------------------- //
|
||||
const char* KEY_CDF_EXTRA_VARIABLES = "ExtraVariables"; // [STRING ARRAY]
|
||||
const char* KEY_CDF_TRACING_VARIABLE = "TracingVariable"; // [STRING]
|
||||
const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING]
|
||||
const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM
|
||||
|
||||
// ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- //
|
||||
const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files
|
||||
const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers
|
||||
const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers
|
||||
const char* KEY_OUTPUT_FOLDER = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output)
|
||||
const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING]
|
||||
const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING]
|
||||
const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM
|
||||
|
||||
// ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- //
|
||||
const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf";
|
||||
@@ -209,7 +224,11 @@ void RenderableFieldlinesSequence::initialize() {
|
||||
// EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE
|
||||
switch (sourceFileType) {
|
||||
case SourceFileType::CDF:
|
||||
LERROR("CDF NOT YET IMPLEMENTED!"); return;
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
if (!getStatesFromCdfFiles(outputFolderPath)) {
|
||||
return;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
break;
|
||||
case SourceFileType::JSON:
|
||||
if (!loadJsonStatesIntoRAM(outputFolderPath)) {
|
||||
@@ -292,6 +311,10 @@ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary(
|
||||
// Verify that the input type is correct
|
||||
if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_CDF) {
|
||||
sourceFileType = SourceFileType::CDF;
|
||||
#ifndef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
LERROR(_name << ": CDF file inputs requires the 'Kameleon' module to be enabled!");
|
||||
return false;
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
} else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_JSON) {
|
||||
sourceFileType = SourceFileType::JSON;
|
||||
} else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_OSFLS) {
|
||||
@@ -688,4 +711,123 @@ void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) {
|
||||
_nStates++;
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER) {
|
||||
|
||||
std::string seedFilePath;
|
||||
std::string tracingVar;
|
||||
std::vector<std::string> extraVars;
|
||||
if (!extractCdfInfoFromDictionary(seedFilePath, tracingVar, extraVars)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<glm::vec3> seedPoints;
|
||||
if (!extractSeedPointsFromFile(seedFilePath, seedPoints)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load states into RAM!
|
||||
for (std::string filePath : _sourceFiles) {
|
||||
// Create Kameleon object and open CDF file!
|
||||
std::unique_ptr<ccmc::Kameleon> kameleon =
|
||||
kameleonHelper::createKameleonObject(filePath);
|
||||
|
||||
FieldlinesState newState;
|
||||
newState.setTriggerTime(kameleonHelper::getTime(kameleon.get()));
|
||||
|
||||
if (newState.addLinesFromKameleon(kameleon.get(), seedPoints, tracingVar)) {
|
||||
switch (newState.model()) {
|
||||
case fls::BATSRUS:
|
||||
newState.scalePositions(fls::R_E_TO_METER);
|
||||
break;
|
||||
case fls::ENLIL :
|
||||
newState.convertLatLonToCartesian(fls::A_U_TO_METER);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
addStateToSequence(newState);
|
||||
if (!OUTPUT_FOLDER.empty()) {
|
||||
newState.saveStateToOsfls(OUTPUT_FOLDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
/*
|
||||
* Returns false if it fails to extract mandatory information!
|
||||
*/
|
||||
bool RenderableFieldlinesSequence::extractCdfInfoFromDictionary(
|
||||
std::string& seedFilePath,
|
||||
std::string& tracingVar,
|
||||
std::vector<std::string>& extraVars) {
|
||||
|
||||
if (_dictionary->getValue(KEY_CDF_SEED_POINT_FILE, seedFilePath)) {
|
||||
ghoul::filesystem::File seedPointFile(seedFilePath);
|
||||
if (FileSys.fileExists(seedPointFile)) {
|
||||
seedFilePath = absPath(seedFilePath);
|
||||
} else {
|
||||
LERROR(_name << ": The specified seed point file: '" << seedFilePath
|
||||
<< "', does not exist!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LERROR(_name << ": Must specify '" << KEY_CDF_SEED_POINT_FILE << "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_dictionary->getValue(KEY_CDF_TRACING_VARIABLE, tracingVar)) {
|
||||
tracingVar = "b"; // Magnetic field variable as default
|
||||
LWARNING(_name << ": No '" << KEY_CDF_TRACING_VARIABLE << "', using default: "
|
||||
<< tracingVar);
|
||||
}
|
||||
|
||||
ghoul::Dictionary extraQuantityNamesDictionary;
|
||||
if (_dictionary->getValue(KEY_CDF_EXTRA_VARIABLES, extraQuantityNamesDictionary)) {
|
||||
const size_t N_PROVIDED_EXTRAS = extraQuantityNamesDictionary.size();
|
||||
for (size_t i = 1; i <= N_PROVIDED_EXTRAS; ++i) {
|
||||
extraVars.push_back(
|
||||
extraQuantityNamesDictionary.value<std::string>(std::to_string(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
bool RenderableFieldlinesSequence::extractSeedPointsFromFile(
|
||||
const std::string& path,
|
||||
std::vector<glm::vec3>& outVec) {
|
||||
|
||||
std::ifstream seedFile(FileSys.relativePath(path));
|
||||
if (!seedFile.good()) {
|
||||
LERROR("Could not open seed points file '" << path << "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
LDEBUG("Reading seed points from file '" << path << "'");
|
||||
std::string line;
|
||||
while (std::getline(seedFile, line)) {
|
||||
glm::vec3 point;
|
||||
std::stringstream ss(line);
|
||||
ss >> point.x;
|
||||
ss >> point.y;
|
||||
ss >> point.z;
|
||||
outVec.push_back(std::move(point));
|
||||
}
|
||||
|
||||
if (outVec.size() == 0) {
|
||||
LERROR("Found no seed points in: " << path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -25,16 +25,27 @@
|
||||
#include <modules/fieldlinessequence/util/fieldlinesstate.h>
|
||||
|
||||
#include <ext/json/json.hpp>
|
||||
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
#include <ccmc/Kameleon.h>
|
||||
#include <ccmc/KameleonInterpolator.h>
|
||||
#include <modules/kameleon/include/kameleonhelper.h>
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
namespace {
|
||||
std::string _loggerCat = "FieldlinesState";
|
||||
const int CURRENT_VERSION = 0;
|
||||
|
||||
const std::string T_AS_P_OVER_RHO = "T = p/rho";
|
||||
const std::string J_PARALLEL_B = "Current: mag(J||B)";
|
||||
const float TO_KELVIN = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * TO_KELVIN => Temperature in Kelvin
|
||||
|
||||
using json = nlohmann::json;
|
||||
}
|
||||
|
||||
@@ -45,6 +56,99 @@ FieldlinesState::FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& lo
|
||||
loadSucessful = loadStateFromOsfls(PATH_TO_OSFLS_FILE);
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
/**
|
||||
* Traces and adds line vertices to state. (Also sets the simulation model variable: _model!)
|
||||
* Vertices may need to be scaled to meters & converted from spherical into cartesian coordinates.
|
||||
* Note that extraQuantities will NOT be set!
|
||||
*/
|
||||
bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon,
|
||||
const std::vector<glm::vec3>& SEED_POINTS,
|
||||
const std::string TRACING_VAR) {
|
||||
|
||||
_model = fls::stringToModel(kameleon->getModelName());
|
||||
|
||||
float innerBoundaryLimit;
|
||||
|
||||
switch (_model) {
|
||||
case fls::Model::BATSRUS :
|
||||
innerBoundaryLimit = 2.5f; // TODO specify in Lua?
|
||||
break;
|
||||
case fls::Model::ENLIL :
|
||||
innerBoundaryLimit = 0.11f; // TODO specify in Lua?
|
||||
break;
|
||||
default:
|
||||
LERROR("OpenSpace's fieldlines sequence currently only supports CDFs from" <<
|
||||
"the BATSRUS and ENLIL models!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------- LOAD TRACING VARIABLE ---------------------------- //
|
||||
if (!kameleon->loadVariable(TRACING_VAR)) {
|
||||
LERROR("FAILED TO LOAD TRACING VARIABLE: " << TRACING_VAR);
|
||||
return false;
|
||||
}
|
||||
|
||||
LINFO("TRACING FIELD LINES!");
|
||||
// - LOOP THROUGH THE SEED POINTS, TRACE LINES AND CONVERT TO THE DESIRED FORMAT - //
|
||||
size_t lineStart = 0;
|
||||
for (glm::vec3 seed : SEED_POINTS) {
|
||||
//--------------------------------------------------------------------------//
|
||||
// We have to create a new tracer (or actually a new interpolator) for each //
|
||||
// new line, otherwise some issues occur //
|
||||
//--------------------------------------------------------------------------//
|
||||
std::unique_ptr<ccmc::Interpolator> interpolator =
|
||||
std::make_unique<ccmc::KameleonInterpolator>(kameleon->model);
|
||||
ccmc::Tracer tracer(kameleon, interpolator.get());
|
||||
tracer.setInnerBoundary(innerBoundaryLimit); // TODO specify in Lua?
|
||||
ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(TRACING_VAR,
|
||||
seed.x,
|
||||
seed.y,
|
||||
seed.z);
|
||||
const std::vector<ccmc::Point3f>& POSITIONS = ccmcFieldline.getPositions();
|
||||
|
||||
_lineStart.push_back(lineStart);
|
||||
const size_t N_LINE_POINTS = POSITIONS.size();
|
||||
_lineCount.push_back(static_cast<GLsizei>(N_LINE_POINTS));
|
||||
lineStart += static_cast<GLint>(N_LINE_POINTS);
|
||||
|
||||
for (const ccmc::Point3f& p : POSITIONS) {
|
||||
_vertexPositions.emplace_back(
|
||||
glm::vec3(p.component1, p.component2, p.component3));
|
||||
}
|
||||
}
|
||||
|
||||
return _vertexPositions.size() > 0;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
/**
|
||||
* Converts all glm::vec3 in _vertexPositions from spherical (radius, latitude, longitude)
|
||||
* coordinates into cartesian coordinates. The longitude and latitude coordinates are
|
||||
* expected to be in degrees. SCALE is an optional scaling factor.
|
||||
*/
|
||||
void FieldlinesState::convertLatLonToCartesian(const float SCALE /* = 1.f */) {
|
||||
for (glm::vec3& p : _vertexPositions) {
|
||||
|
||||
const float R = p.x * SCALE;
|
||||
const float LAT = glm::radians(p.y);
|
||||
const float LON = glm::radians(p.z);
|
||||
const float R_COS_LAT = R * cos(LAT);
|
||||
|
||||
p = glm::vec3(R_COS_LAT * cos(LON), R_COS_LAT* sin(LON), R * sin(LAT));
|
||||
}
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
void FieldlinesState::scalePositions(const float SCALE) {
|
||||
for (glm::vec3& p : _vertexPositions) {
|
||||
p *= SCALE;
|
||||
}
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) {
|
||||
std::ifstream ifs(PATH_TO_OSFLS_FILE, std::ifstream::binary);
|
||||
if (!ifs.is_open()) {
|
||||
|
||||
@@ -35,6 +35,12 @@
|
||||
|
||||
using std::vector;
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
namespace ccmc {
|
||||
class Kameleon;
|
||||
}
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class FieldlinesState {
|
||||
@@ -42,6 +48,14 @@ public:
|
||||
FieldlinesState();
|
||||
FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful);
|
||||
|
||||
#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
bool addLinesFromKameleon(ccmc::Kameleon* kameleon,
|
||||
const vector<glm::vec3>& SEED_POINTS,
|
||||
const std::string TRACING_VAR);
|
||||
void convertLatLonToCartesian(const float SCALE = 1.f);
|
||||
void scalePositions(const float SCALE);
|
||||
#endif // OPENSPACE_MODULE_KAMELEON_ENABLED
|
||||
|
||||
bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE);
|
||||
void saveStateToOsfls(const std::string& PATH_TO_OSFLS_FILE);
|
||||
|
||||
@@ -62,6 +76,8 @@ public:
|
||||
// Special getter. Returns extraQuantities[INDEX].
|
||||
const vector<float>& extraQuantity(const size_t INDEX, bool& isSuccesful) const;
|
||||
|
||||
void setTriggerTime(const double T) { _triggerTime = T; }
|
||||
|
||||
private:
|
||||
bool _isMorphable = false;
|
||||
double _triggerTime = -1.0;
|
||||
|
||||
Reference in New Issue
Block a user