Load CDFs and trace field lines using kameleon and store the info in FieldlinesState.

This commit is contained in:
Oskar Carlbaum
2017-10-09 21:56:47 +02:00
parent bf83073120
commit 4fc88c595f
4 changed files with 275 additions and 4 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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()) {

View File

@@ -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;