/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2015 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "iswamanager_lua.inl"; namespace { using json = nlohmann::json; const std::string _loggerCat = "IswaManager"; std::string baseUrl = "https://iswa-demo-server.herokuapp.com/"; //const std::string baseUrl = "http://128.183.168.116:3000/"; } namespace openspace{ IswaManager::IswaManager() : _iswaEvent() { _month["JAN"] = "01"; _month["FEB"] = "02"; _month["MAR"] = "03"; _month["APR"] = "04"; _month["MAY"] = "05"; _month["JUN"] = "06"; _month["JUL"] = "07"; _month["AUG"] = "08"; _month["SEP"] = "09"; _month["OCT"] = "10"; _month["NOV"] = "11"; _month["DEC"] = "12"; _type[CygnetType::Texture] = "Texture"; _type[CygnetType::Data] = "Data"; _type[CygnetType::Kameleon] = "Kameleon"; // _type[CygnetType::TexturePlane] = "TexturePlane"; // _type[CygnetType::DataPlane] = "DataPlane"; // _type[CygnetType::KameleonPlane] = "KameleonPlane"; // _type[CygnetType::Kameleon] = "DataSphere"; _geom[CygnetGeometry::Plane] = "Plane"; _geom[CygnetGeometry::Sphere] = "Sphere"; OsEng.downloadManager().fetchFile( "http://iswa3.ccmc.gsfc.nasa.gov/IswaSystemWebApp/CygnetHealthServlet", [this](const DownloadManager::MemoryFile& file){ fillCygnetInfo(std::string(file.buffer)); }, [](const std::string& err){ LWARNING("Download to memory was aborted: " + err); } ); } IswaManager::~IswaManager(){ _groups.clear(); _cygnetInformation.clear(); } void IswaManager::addIswaCygnet(int id, std::string type, std::string group){ if(id > 0){ createScreenSpace(id); }else if(id < 0){ // create metadata object and assign group and id std::shared_ptr metaFuture = std::make_shared(); metaFuture->id = id; metaFuture->group = group; // Assign type of cygnet Texture/Data if(type == _type[CygnetType::Texture]){ metaFuture->type = CygnetType::Texture; } else if (type == _type[CygnetType::Data]) { metaFuture->type = CygnetType::Data; } else { LERROR("\""+ type + "\" is not a valid type"); return; } // This callback determines what geometry should be used and creates the right cygbet auto metadataCallback = [this, metaFuture](const DownloadManager::MemoryFile& file){ //Create a string from downloaded file std::string res; res.append(file.buffer, file.size); //add it to the metafuture object metaFuture->json = res; //convert to json json j = json::parse(res); // Check what kind of geometry here if(j["Coordinate Type"].is_null()){ metaFuture->geom = CygnetGeometry::Sphere; createSphere(metaFuture); } else if (j["Coordinate Type"] == "Cartesian"){ metaFuture->geom = CygnetGeometry::Plane; createPlane(metaFuture); } LDEBUG("Download to memory finished"); }; // Download metadata OsEng.downloadManager().fetchFile( baseUrl + std::to_string(-id), metadataCallback, [id](const std::string& err){ LDEBUG("Download to memory was aborted for data cygnet with id "+ std::to_string(id)+": " + err); } ); } } void IswaManager::addKameleonCdf(std::string groupName, int pos){ // auto info = _cdfInformation[group][pos]; auto group = iswaGroup(groupName); if(group){ std::dynamic_pointer_cast(group)->changeCdf(_cdfInformation[groupName][pos].path); return; } createKameleonPlane(_cdfInformation[groupName][pos], "z"); createKameleonPlane(_cdfInformation[groupName][pos], "y"); createKameleonPlane(_cdfInformation[groupName][pos], "x"); } std::future IswaManager::fetchImageCygnet(int id, double timestamp){ return std::move(OsEng.downloadManager().fetchFile( iswaUrl(id, timestamp, "image"), [id](const DownloadManager::MemoryFile& file){ LDEBUG("Download to memory finished for image cygnet with id: " + std::to_string(id)); }, [id](const std::string& err){ LDEBUG("Download to memory was aborted for image cygnet with id "+ std::to_string(id)+": " + err); } ) ); } std::future IswaManager::fetchDataCygnet(int id, double timestamp){ return std::move(OsEng.downloadManager().fetchFile( iswaUrl(id, timestamp, "data"), [id](const DownloadManager::MemoryFile& file){ LDEBUG("Download to memory finished for data cygnet with id: " + std::to_string(id)); }, [id](const std::string& err){ LDEBUG("Download to memory was aborted for data cygnet with id "+ std::to_string(id)+": " + err); } ) ); } std::string IswaManager::iswaUrl(int id, double timestamp, std::string type){ std::string url; if(id < 0){ url = baseUrl+type+"/" + std::to_string(-id) + "/"; } else{ url = "http://iswa3.ccmc.gsfc.nasa.gov/IswaSystemWebApp/iSWACygnetStreamer?window=-1&cygnetId="+ std::to_string(id) +"×tamp="; } //std::string t = Time::ref().currentTimeUTC(); std::string t = SpiceManager::ref().dateFromEphemerisTime(timestamp); std::stringstream ss(t); std::string token; std::getline(ss, token, ' '); url += token + "-"; std::getline(ss, token, ' '); url += _month[token] + "-"; std::getline(ss, token, 'T'); url += token + "%20"; std::getline(ss, token, '.'); url += token; return url; } void IswaManager::registerGroup(std::string groupName, std::string type){ if(_groups.find(groupName) == _groups.end()){ bool dataGroup = (type == typeid(DataPlane).name()) || (type == typeid(DataSphere).name()); bool kameleonGroup = (type == typeid(KameleonPlane).name()); if(dataGroup){ _groups.insert(std::pair>(groupName, std::make_shared(groupName, type))); }else if(kameleonGroup){ _groups.insert(std::pair>(groupName, std::make_shared(groupName, type))); }else{ _groups.insert(std::pair>(groupName, std::make_shared(groupName, type))); } } else if(!_groups[groupName]->isType(type)){ LWARNING("Can't add cygnet to groups with diffent type"); } } std::shared_ptr IswaManager::iswaGroup(std::string name){ if(_groups.find(name) != _groups.end()){ return _groups[name]; } return nullptr; } std::map>& IswaManager::cygnetInformation(){ return _cygnetInformation; } std::map>& IswaManager::groups(){ return _groups; } std::map>& IswaManager::cdfInformation(){ return _cdfInformation; } std::shared_ptr IswaManager::downloadMetadata(int id){ std::shared_ptr metaFuture = std::make_shared(); metaFuture->id = id; OsEng.downloadManager().fetchFile( baseUrl + std::to_string(-id), [&metaFuture](const DownloadManager::MemoryFile& file){ metaFuture->json = std::string(file.buffer, file.size); metaFuture->isFinished = true; }, [](const std::string& err){ LWARNING("Download Metadata to memory was aborted: " + err); } ); return metaFuture; } std::string IswaManager::jsonPlaneToLuaTable(std::shared_ptr data){ if(data->json != ""){ json j = json::parse(data->json); std::string parent = j["Central Body"]; std::string frame = j["Coordinates"]; std::string coordinateType = j["Coordinate Type"]; int updateTime = j["ISWA_UPDATE_SECONDS"]; glm::vec3 max( j["Plot XMAX"], j["Plot YMAX"], j["Plot ZMAX"] ); glm::vec3 min( j["Plot XMIN"], j["Plot YMIN"], j["Plot ZMIN"] ); glm::vec4 spatialScale(1, 1, 1, 10); std::string spatial = j["Spatial Scale (Custom)"]; if(spatial == "R_E"){ spatialScale.x = 6.371f; spatialScale.y = 6.371f; spatialScale.z = 6.371f; spatialScale.w = 6; } float xOffset = 0.0f; if(data->id == -7) xOffset = -10.0f; if(data->id == -8) xOffset = -20.0f; if(data->id == -9) xOffset = -30.0f; std::string table = "{" "Name = '" + data->name +"' , " "Parent = '" + parent + "', " "Renderable = {" "Type = '" + _type[data->type] + _geom[data->geom] + "', " "Id = " + std::to_string(data->id) + ", " "Frame = '" + frame + "' , " "GridMin = " + std::to_string(min) + ", " "GridMax = " + std::to_string(max) + ", " "SpatialScale = " + std::to_string(spatialScale) + ", " "UpdateTime = " + std::to_string(updateTime) + ", " "CoordinateType = '" + coordinateType + "', " "Group = '"+ data->group + "'," "XOffset = "+ std::to_string(xOffset) + "," "}" "}"; return table; } return ""; } std::string IswaManager::parseKWToLuaTable(CdfInfo info, std::string cut){ if(info.path != ""){ const std::string& extension = ghoul::filesystem::File(absPath(info.path)).fileExtension(); if(extension == "cdf"){ KameleonWrapper kw = KameleonWrapper(absPath(info.path)); std::string parent = kw.getParent(); std::string frame = kw.getFrame(); glm::vec3 min = kw.getGridMin(); glm::vec3 max = kw.getGridMax(); glm::vec4 spatialScale; std::string coordinateType; std::tuple < std::string, std::string, std::string > gridUnits = kw.getGridUnits(); if (std::get<0>(gridUnits) == "R" && std::get<1>(gridUnits) == "R" && std::get<2>(gridUnits) == "R") { spatialScale.x = 6.371f; spatialScale.y = 6.371f; spatialScale.z = 6.371f; spatialScale.w = 6; coordinateType = "Cartesian"; }else{ spatialScale = glm::vec4(1.0); spatialScale.w = 1; //-log10(1.0f/max.x); coordinateType = "Polar"; } std::string table = "{" "Name = '" +info.name+ "'," "Parent = '" + parent + "', " "Renderable = {" "Type = 'KameleonPlane', " "Id = 0 ," "Frame = '" + frame + "' , " "GridMin = " + std::to_string(min) + ", " "GridMax = " + std::to_string(max) + ", " "SpatialScale = " + std::to_string(spatialScale) + ", " "UpdateTime = 0, " "kwPath = '" + info.path + "' ," "axisCut = '"+cut+"'," "CoordinateType = '" + coordinateType + "', " "Group = '"+ info.group + "'," // "Group = ''," "fieldlineSeedsIndexFile = '"+info.fieldlineSeedsIndexFile+"'" "}" "}" ; return table; } } return ""; } std::string IswaManager::jsonSphereToLuaTable(std::shared_ptr data){ if(data->json == ""){ LWARNING("jsonSphereToLuaTable: no content in metadata json"); return ""; } json j = json::parse(data->json); j = j["metadata"]; std::string parent = j["central_body"]; parent[0] = toupper(parent[0]); std::string frame = j["standard_grid_target"]; std::string coordinateType = j["grid_1_type"]; float updateTime = j["output_time_interval"]; float radius = j["radius"]; glm::vec4 spatialScale(6.371f, 6.371f, 6.371f, 6); glm::vec3 max( j["x"]["actual_max"], j["y"]["actual_max"], j["z"]["actual_max"] ); glm::vec3 min( j["x"]["actual_min"], j["y"]["actual_min"], j["z"]["actual_min"] ); std::string table = "{" "Name = '" + data->name +"' , " "Parent = '" + parent + "', " "Renderable = {" "Type = '" + _type[data->type] + _geom[data->geom] + "', " "Id = " + std::to_string(data->id) + ", " "Frame = '" + frame + "' , " "GridMin = " + std::to_string(min) + ", " "GridMax = " + std::to_string(max) + ", " "UpdateTime = " + std::to_string(updateTime) + ", " "Radius = " + std::to_string(radius) + ", " "CoordinateType = '" + coordinateType + "', " "Group = '"+ data->group + "'," "}" "}"; return table; } void IswaManager::createScreenSpace(int id){ std::string script = "openspace.iswa.addScreenSpaceCygnet(" "{CygnetId =" + std::to_string(id) + "});"; OsEng.scriptEngine().queueScript(script); } void IswaManager::createPlane(std::shared_ptr data){ // check if this plane already exist std::string name = _type[data->type] + _geom[data->geom] + std::to_string(data->id); if(!data->group.empty()){ std::string type; if(data->type == CygnetType::Data){ type = typeid(DataPlane).name(); }else{ type = typeid(TexturePlane).name(); } registerGroup(data->group, type); auto it = _groups.find(data->group); if(it == _groups.end() || (*it).second->isType(type)){ name = data->group +"_"+ name; }else{ data->group=""; } } data->name = name; if( OsEng.renderEngine().scene()->sceneGraphNode(name) ){ LERROR("A node with name \"" + name +"\" already exist"); return; } std::string luaTable = jsonPlaneToLuaTable(data); if(luaTable != ""){ std::string script = "openspace.addSceneGraphNode(" + luaTable + ");"; OsEng.scriptEngine().queueScript(script); } } void IswaManager::createSphere(std::shared_ptr data){ // check if this sphere already exist std::string name = _type[data->type] + _geom[data->geom] + std::to_string(data->id); if(!data->group.empty()){ std::string type = typeid(DataSphere).name(); registerGroup(data->group, type); auto it = _groups.find(data->group); if(it == _groups.end() || (*it).second->isType(type)){ name = data->group +"_"+name; }else{ data->group=""; } } data->name = name; if( OsEng.renderEngine().scene()->sceneGraphNode(name) ){ LERROR("A node with name \"" + name +"\" already exist"); return; } std::string luaTable = jsonSphereToLuaTable(data); if(luaTable != ""){ std::string script = "openspace.addSceneGraphNode(" + luaTable + ");"; OsEng.scriptEngine().queueScript(script); } } void IswaManager::createKameleonPlane(CdfInfo info, std::string cut){ const std::string& extension = ghoul::filesystem::File(absPath(info.path)).fileExtension(); if(FileSys.fileExists(absPath(info.path)) && extension == "cdf"){ if(!info.group.empty()){ std::string type = typeid(KameleonPlane).name(); registerGroup(info.group, type); auto it = _groups.find(info.group); if(it == _groups.end() || (*it).second->isType(type)){ info.name = info.group +"_"+info.name; }else{ info.group=""; } } info.name = info.name+"-"+cut; if( OsEng.renderEngine().scene()->sceneGraphNode(info.name) ){ LERROR("A node with name \"" + info.name +"\" already exist"); return; } std::string luaTable = parseKWToLuaTable(info, cut); if(!luaTable.empty()){ std::string script = "openspace.addSceneGraphNode(" + luaTable + ");"; OsEng.scriptEngine().queueScript(script); } }else{ LWARNING( absPath(info.path) + " is not a cdf file or can't be found."); } } void IswaManager::createFieldline(std::string name, std::string cdfPath, std::string seedPath){ const std::string& extension = ghoul::filesystem::File(absPath(cdfPath)).fileExtension(); if(FileSys.fileExists(absPath(cdfPath)) && extension == "cdf"){ std::string luaTable = "{" "Name = '" + name + "'," "Parent = 'Earth'," "Renderable = {" "Type = 'RenderableFieldlines'," "VectorField = {" "Type = 'VolumeKameleon'," "File = '" + cdfPath + "'," "Model = 'BATSRUS'," "Variables = {'bx', 'by', 'bz'}" "}," "Fieldlines = {" "Stepsize = 1," "Classification = true" "}," "SeedPoints = {" "Type = 'File'," "File = '" + seedPath + "'" "}" "}" "}"; if(!luaTable.empty()){ std::string script = "openspace.addSceneGraphNode(" + luaTable + ");"; OsEng.scriptEngine().queueScript(script); } }else{ LWARNING( cdfPath + " is not a cdf file or can't be found."); } } void IswaManager::fillCygnetInfo(std::string jsonString){ if(jsonString != ""){ json j = json::parse(jsonString); std::set lists = {"listOfPriorityCygnets", "listOfOKCygnets" // ,"listOfStaleCygnets", "listOfInactiveCygnets", }; for(auto list : lists){ json jsonList = j[list]; for(int i=0; i(info); } } } } void IswaManager::addCdfFiles(std::string path){ path = absPath(path); if(FileSys.fileExists(path)){ //std::string basePath = path.substr(0, path.find_last_of("/\\")); std::ifstream jsonFile(path); if (jsonFile.is_open()){ json cdfGroups = json::parse(jsonFile); for(int i=0; i(); json cdfs = cdfGroup["cdfs"]; for(int j=0; j