Files
OpenSpace/modules/gaia/tasks/constructoctreetask.cpp
Alexander Bock 7004c02b86 Happy new year
2021-01-02 15:26:51 +01:00

817 lines
35 KiB
C++

/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* 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 <modules/gaia/tasks/constructoctreetask.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/fmt.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/directory.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionary.h>
#include <fstream>
#include <thread>
namespace {
constexpr const char* KeyInFileOrFolderPath = "InFileOrFolderPath";
constexpr const char* KeyOutFileOrFolderPath = "OutFileOrFolderPath";
constexpr const char* KeyMaxDist = "MaxDist";
constexpr const char* KeyMaxStarsPerNode = "MaxStarsPerNode";
constexpr const char* KeySingleFileInput = "SingleFileInput";
constexpr const char* KeyFilterPosX = "FilterPosX";
constexpr const char* KeyFilterPosY = "FilterPosY";
constexpr const char* KeyFilterPosZ = "FilterPosZ";
constexpr const char* KeyFilterGMag = "FilterGMag";
constexpr const char* KeyFilterBpRp = "FilterBpRp";
constexpr const char* KeyFilterVelX = "FilterVelX";
constexpr const char* KeyFilterVelY = "FilterVelY";
constexpr const char* KeyFilterVelZ = "FilterVelZ";
constexpr const char* KeyFilterBpMag = "FilterBpMag";
constexpr const char* KeyFilterRpMag = "FilterRpMag";
constexpr const char* KeyFilterBpG = "FilterBpG";
constexpr const char* KeyFilterGRp = "FilterGRp";
constexpr const char* KeyFilterRa = "FilterRa";
constexpr const char* KeyFilterRaError = "FilterRaError";
constexpr const char* KeyFilterDec = "FilterDec";
constexpr const char* KeyFilterDecError = "FilterDecError";
constexpr const char* KeyFilterParallax = "FilterParallax";
constexpr const char* KeyFilterParallaxError = "FilterParallaxError";
constexpr const char* KeyFilterPmra = "FilterPmra";
constexpr const char* KeyFilterPmraError = "FilterPmraError";
constexpr const char* KeyFilterPmdec = "FilterPmdec";
constexpr const char* KeyFilterPmdecError = "FilterPmdecError";
constexpr const char* KeyFilterRv = "FilterRv";
constexpr const char* KeyFilterRvError = "FilterRvError";
constexpr const char* _loggerCat = "ConstructOctreeTask";
} // namespace
namespace openspace {
ConstructOctreeTask::ConstructOctreeTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"ConstructOctreeTask"
);
_inFileOrFolderPath = absPath(dictionary.value<std::string>(KeyInFileOrFolderPath));
_outFileOrFolderPath = absPath(dictionary.value<std::string>(KeyOutFileOrFolderPath));
if (dictionary.hasKey(KeyMaxDist)) {
_maxDist = static_cast<int>(dictionary.value<double>(KeyMaxDist));
}
if (dictionary.hasKey(KeyMaxStarsPerNode)) {
_maxStarsPerNode = static_cast<int>(dictionary.value<double>(KeyMaxStarsPerNode));
}
if (dictionary.hasKey(KeySingleFileInput)) {
_singleFileInput = dictionary.value<bool>(KeySingleFileInput);
}
_octreeManager = std::make_shared<OctreeManager>();
_indexOctreeManager = std::make_shared<OctreeManager>();
// Check for filter params.
if (dictionary.hasKey(KeyFilterPosX)) {
_posX = dictionary.value<glm::dvec2>(KeyFilterPosX);
_filterPosX = true;
}
if (dictionary.hasKey(KeyFilterPosY)) {
_posY = dictionary.value<glm::dvec2>(KeyFilterPosY);
_filterPosY = true;
}
if (dictionary.hasKey(KeyFilterPosZ)) {
_posZ = dictionary.value<glm::dvec2>(KeyFilterPosZ);
_filterPosZ = true;
}
if (dictionary.hasKey(KeyFilterGMag)) {
_gMag = dictionary.value<glm::dvec2>(KeyFilterGMag);
_filterGMag = true;
}
if (dictionary.hasKey(KeyFilterBpRp)) {
_bpRp = dictionary.value<glm::dvec2>(KeyFilterBpRp);
_filterBpRp = true;
}
if (dictionary.hasKey(KeyFilterVelX)) {
_velX = dictionary.value<glm::dvec2>(KeyFilterVelX);
_filterVelX = true;
}
if (dictionary.hasKey(KeyFilterVelY)) {
_velY = dictionary.value<glm::dvec2>(KeyFilterVelY);
_filterVelY = true;
}
if (dictionary.hasKey(KeyFilterVelZ)) {
_velZ = dictionary.value<glm::dvec2>(KeyFilterVelZ);
_filterVelZ = true;
}
if (dictionary.hasKey(KeyFilterBpMag)) {
_bpMag = dictionary.value<glm::dvec2>(KeyFilterBpMag);
_filterBpMag = true;
}
if (dictionary.hasKey(KeyFilterRpMag)) {
_rpMag = dictionary.value<glm::dvec2>(KeyFilterRpMag);
_filterRpMag = true;
}
if (dictionary.hasKey(KeyFilterBpG)) {
_bpG = dictionary.value<glm::dvec2>(KeyFilterBpG);
_filterBpG = true;
}
if (dictionary.hasKey(KeyFilterGRp)) {
_gRp = dictionary.value<glm::dvec2>(KeyFilterGRp);
_filterGRp = true;
}
if (dictionary.hasKey(KeyFilterRa)) {
_ra = dictionary.value<glm::dvec2>(KeyFilterRa);
_filterRa = true;
}
if (dictionary.hasKey(KeyFilterRaError)) {
_raError = dictionary.value<glm::dvec2>(KeyFilterRaError);
_filterRaError = true;
}
if (dictionary.hasKey(KeyFilterDec)) {
_dec = dictionary.value<glm::dvec2>(KeyFilterDec);
_filterDec = true;
}
if (dictionary.hasKey(KeyFilterDecError)) {
_decError = dictionary.value<glm::dvec2>(KeyFilterDecError);
_filterDecError = true;
}
if (dictionary.hasKey(KeyFilterParallax)) {
_parallax = dictionary.value<glm::dvec2>(KeyFilterParallax);
_filterParallax = true;
}
if (dictionary.hasKey(KeyFilterParallaxError)) {
_parallaxError = dictionary.value<glm::dvec2>(KeyFilterParallaxError);
_filterParallaxError = true;
}
if (dictionary.hasKey(KeyFilterPmra)) {
_pmra = dictionary.value<glm::dvec2>(KeyFilterPmra);
_filterPmra = true;
}
if (dictionary.hasKey(KeyFilterPmraError)) {
_pmraError = dictionary.value<glm::dvec2>(KeyFilterPmraError);
_filterPmraError = true;
}
if (dictionary.hasKey(KeyFilterPmdec)) {
_pmdec = dictionary.value<glm::dvec2>(KeyFilterPmdec);
_filterPmdec = true;
}
if (dictionary.hasKey(KeyFilterPmdecError)) {
_pmdecError = dictionary.value<glm::dvec2>(KeyFilterPmdecError);
_filterPmdecError = true;
}
if (dictionary.hasKey(KeyFilterRv)) {
_rv = dictionary.value<glm::dvec2>(KeyFilterRv);
_filterRv = true;
}
if (dictionary.hasKey(KeyFilterRvError)) {
_rvError = dictionary.value<glm::dvec2>(KeyFilterRvError);
_filterRvError = true;
}
}
std::string ConstructOctreeTask::description() {
return "Read bin file (or files in folder): " + _inFileOrFolderPath + "\n "
"and write octree data file (or files) into: " + _outFileOrFolderPath + "\n";
}
void ConstructOctreeTask::perform(const Task::ProgressCallback& onProgress) {
onProgress(0.0f);
if (_singleFileInput) {
constructOctreeFromSingleFile(onProgress);
}
else {
constructOctreeFromFolder(onProgress);
}
onProgress(1.0f);
}
void ConstructOctreeTask::constructOctreeFromSingleFile(
const Task::ProgressCallback& progressCallback)
{
std::vector<float> fullData;
int32_t nValues = 0;
int32_t nValuesPerStar = 0;
size_t nFilteredStars = 0;
int nTotalStars = 0;
_octreeManager->initOctree(0, _maxDist, _maxStarsPerNode);
LINFO("Reading data file: " + _inFileOrFolderPath);
LINFO(fmt::format(
"MAX DIST: {} - MAX STARS PER NODE: {}",
_octreeManager->maxDist(), _octreeManager->maxStarsPerNode()
));
// Use to generate a synthetic dataset
/*for (float z = -1.0; z < 1.0; z += 0.05) {
for (float y = -1.0; y < 1.0; y += 0.05) {
for (float x = -1.0; x < 1.0; x += 0.05) {
float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
std::vector<float> renderValues(8);
renderValues[0] = x; // + x * r;
renderValues[2] = z; // + y * r;
renderValues[1] = y; // + z * r;
renderValues[3] = 5.0; // + 10 * r;
renderValues[4] = 2.0; // + 10 * r;
renderValues[5] = r;
renderValues[6] = r;
renderValues[7] = r;
_octreeManager->insert(renderValues);
nTotalStars++;
nValues+=8;
}
}
}
for (float phi = -180.0; phi < 180.0; phi += 10.0) {
for (float theta = -90.0; theta <= 90.0; theta += 10.0) {
float r = 1.0;
std::vector<float> renderValues(8);
renderValues[0] = r * sin(glm::radians(theta)) * cos(glm::radians(phi));
renderValues[2] = r * sin(glm::radians(theta)) * sin(glm::radians(phi));
renderValues[1] = r * cos(glm::radians(theta));
renderValues[3] = 5.0;
renderValues[4] = 2.0;
renderValues[5] = r;
renderValues[6] = r;
renderValues[7] = r;
_octreeManager->insert(renderValues);
nTotalStars++;
nValues += 8;
}
}*/
std::ifstream inFileStream(_inFileOrFolderPath, std::ifstream::binary);
if (inFileStream.good()) {
inFileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
inFileStream.read(reinterpret_cast<char*>(&nValuesPerStar), sizeof(int32_t));
fullData.resize(nValues);
inFileStream.read(
reinterpret_cast<char*>(fullData.data()),
nValues * sizeof(fullData[0])
);
nTotalStars = nValues / nValuesPerStar;
progressCallback(0.3f);
LINFO("Constructing Octree.");
// Insert star into octree. We assume the data already is in correct order.
for (size_t i = 0; i < fullData.size(); i += nValuesPerStar) {
auto first = fullData.begin() + i;
auto last = fullData.begin() + i + nValuesPerStar;
std::vector<float> filterValues(first, last);
std::vector<float> renderValues(first, first + RENDER_VALUES);
// Filter data by parameters.
if (checkAllFilters(filterValues)) {
nFilteredStars++;
continue;
}
// If all filters passed then insert render values into Octree.
_octreeManager->insert(renderValues);
}
inFileStream.close();
}
else {
LERROR(fmt::format(
"Error opening file '{}' for loading preprocessed file!",
_inFileOrFolderPath
));
}
LINFO(fmt::format("{} of {} read stars were filtered", nFilteredStars, nTotalStars));
// Slice LOD data before writing to files.
_octreeManager->sliceLodData();
LINFO("Writing octree to: " + _outFileOrFolderPath);
std::ofstream outFileStream(_outFileOrFolderPath, std::ofstream::binary);
if (outFileStream.good()) {
if (nValues == 0) {
LERROR("Error writing file - No values were read from file.");
}
_octreeManager->writeToFile(outFileStream, true);
outFileStream.close();
}
else {
LERROR(fmt::format(
"Error opening file: {} as output data file.", _outFileOrFolderPath
));
}
}
void ConstructOctreeTask::constructOctreeFromFolder(
const Task::ProgressCallback& progressCallback)
{
int32_t nStars = 0;
int32_t nValuesPerStar = 0;
size_t nFilteredStars = 0;
//float maxRadius = 0.0;
//int starsOutside10 = 0;
//int starsOutside25 = 0;
//int starsOutside50 = 0;
//int starsOutside75 = 0;
//int starsOutside100 = 0;
//int starsOutside200 = 0;
//int starsOutside300 = 0;
//int starsOutside400 = 0;
//int starsOutside500 = 0;
//int starsOutside750 = 0;
//int starsOutside1000 = 0;
//int starsOutside1500 = 0;
//int starsOutside2000 = 0;
//int starsOutside5000 = 0;
ghoul::filesystem::Directory currentDir(_inFileOrFolderPath);
std::vector<std::string> allInputFiles = currentDir.readFiles();
std::vector<float> filterValues;
auto writeThreads = std::vector<std::thread>(8);
_indexOctreeManager->initOctree(0, _maxDist, _maxStarsPerNode);
float processOneFile = 1.f / allInputFiles.size();
LINFO(fmt::format(
"MAX DIST: {} - MAX STARS PER NODE: {}",
_indexOctreeManager->maxDist(), _indexOctreeManager->maxStarsPerNode()
));
for (size_t idx = 0; idx < allInputFiles.size(); ++idx) {
std::string inFilePath = allInputFiles[idx];
int nStarsInfile = 0;
LINFO("Reading data file: " + inFilePath);
std::ifstream inFileStream(inFilePath, std::ifstream::binary);
if (inFileStream.good()) {
inFileStream.read(reinterpret_cast<char*>(&nValuesPerStar), sizeof(int32_t));
filterValues.resize(nValuesPerStar, 0.f);
while (inFileStream.read(
reinterpret_cast<char*>(filterValues.data()),
nValuesPerStar * sizeof(filterValues[0])
))
{
// Filter data by parameters.
if (checkAllFilters(filterValues)) {
nFilteredStars++;
continue;
}
// Generate a 50/12,5 dataset (gMag <=13/>13).
//if ((filterStar(glm::vec2(20.0), filterValues[3], 20.f)) ||
// (filterStar(glm::vec2(0.0), filterValues[16])) ||
// (filterValues[3] > 13.0 && filterValues[17] > 0.125) ||
// (filterValues[3] <= 13.0 && filterValues[17] > 0.5)) {
// nFilteredStars++;
// continue;
//}
// If all filters passed then insert render values into Octree.
std::vector<float> renderValues(
filterValues.begin(),
filterValues.begin() + RENDER_VALUES
);
_indexOctreeManager->insert(renderValues);
nStarsInfile++;
//float maxVal = fmax(fmax(fabs(renderValues[0]), fabs(renderValues[1])),
// fabs(renderValues[2]));
//if (maxVal > maxRadius) maxRadius = maxVal;
//// Calculate how many stars are outside of different thresholds.
//if (maxVal > 10) starsOutside10++;
//if (maxVal > 25) starsOutside25++;
//if (maxVal > 50) starsOutside50++;
//if (maxVal > 75) starsOutside75++;
//if (maxVal > 100) starsOutside100++;
//if (maxVal > 200) starsOutside200++;
//if (maxVal > 300) starsOutside300++;
//if (maxVal > 400) starsOutside400++;
//if (maxVal > 500) starsOutside500++;
//if (maxVal > 750) starsOutside750++;
//if (maxVal > 1000) starsOutside1000++;
//if (maxVal > 1500) starsOutside1500++;
//if (maxVal > 2000) starsOutside2000++;
//if (maxVal > 5000) starsOutside5000++;
}
inFileStream.close();
}
else {
LERROR(fmt::format(
"Error opening file '{}' for loading preprocessed file!", inFilePath
));
}
// Slice LOD data.
LINFO("Slicing LOD data!");
_indexOctreeManager->sliceLodData(idx);
progressCallback((idx + 1) * processOneFile);
nStars += nStarsInfile;
LINFO(fmt::format("Writing {} stars to octree files!", nStarsInfile));
LINFO(fmt::format(
"Number leaf nodes: {}\n Number inner nodes: {}\n Total depth of tree: {}",
_indexOctreeManager->numLeafNodes(),
_indexOctreeManager->numInnerNodes(),
_indexOctreeManager->totalDepth()
));
// Write to 8 separate files in a separate thread. Data will be cleared after it
// has been written. Store joinable thread for later sync.
std::thread t(
&OctreeManager::writeToMultipleFiles,
_indexOctreeManager,
_outFileOrFolderPath,
idx
);
writeThreads[idx] = std::move(t);
}
LINFO(fmt::format(
"A total of {} stars were read from files and distributed into {} total nodes",
nStars, _indexOctreeManager->totalNodes()
));
LINFO(std::to_string(nFilteredStars) + " stars were filtered");
//LINFO("Max radius of dataset is: " + std::to_string(maxRadius) +
// "\n Number of stars outside of:" +
// " - 10kPc is " + std::to_string(starsOutside10) + "\n" +
// " - 25kPc is " + std::to_string(starsOutside25) + "\n" +
// " - 50kPc is " + std::to_string(starsOutside50) + "\n" +
// " - 75kPc is " + std::to_string(starsOutside75) + "\n" +
// " - 100kPc is " + std::to_string(starsOutside100) + "\n" +
// " - 200kPc is " + std::to_string(starsOutside200) + "\n" +
// " - 300kPc is " + std::to_string(starsOutside300) + "\n" +
// " - 400kPc is " + std::to_string(starsOutside400) + "\n" +
// " - 500kPc is " + std::to_string(starsOutside500) + "\n" +
// " - 750kPc is " + std::to_string(starsOutside750) + "\n" +
// " - 1000kPc is " + std::to_string(starsOutside1000) + "\n" +
// " - 1500kPc is " + std::to_string(starsOutside1500) + "\n" +
// " - 2000kPc is " + std::to_string(starsOutside2000) + "\n" +
// " - 5000kPc is " + std::to_string(starsOutside5000));
// Write index file of Octree structure.
std::string indexFileOutPath = _outFileOrFolderPath + "index.bin";
std::ofstream outFileStream(indexFileOutPath, std::ofstream::binary);
if (outFileStream.good()) {
LINFO("Writing index file!");
_indexOctreeManager->writeToFile(outFileStream, false);
outFileStream.close();
}
else {
LERROR(fmt::format(
"Error opening file: {} as index output file.", indexFileOutPath
));
}
// Make sure all threads are done.
for (int i = 0; i < 8; ++i) {
writeThreads[i].join();
}
}
bool ConstructOctreeTask::checkAllFilters(const std::vector<float>& filterValues) {
// Return true if star is caught in any filter.
return (_filterPosX && filterStar(_posX, filterValues[0])) ||
(_filterPosY && filterStar(_posY, filterValues[1])) ||
(_filterPosZ && filterStar(_posZ, filterValues[2])) ||
(_filterGMag && filterStar(_gMag, filterValues[3], 20.f)) ||
(_filterBpRp && filterStar(_bpRp, filterValues[4])) ||
(_filterVelX && filterStar(_velX, filterValues[5])) ||
(_filterVelY && filterStar(_velY, filterValues[6])) ||
(_filterVelZ && filterStar(_velZ, filterValues[7])) ||
(_filterBpMag && filterStar(_bpMag, filterValues[8], 20.f)) ||
(_filterRpMag && filterStar(_rpMag, filterValues[9], 20.f)) ||
(_filterBpG && filterStar(_bpG, filterValues[10])) ||
(_filterGRp && filterStar(_gRp, filterValues[11])) ||
(_filterRa && filterStar(_ra, filterValues[12])) ||
(_filterRaError && filterStar(_raError, filterValues[13])) ||
(_filterDec && filterStar(_dec, filterValues[14])) ||
(_filterDecError && filterStar(_decError, filterValues[15])) ||
(_filterParallax && filterStar(_parallax, filterValues[16])) ||
(_filterParallaxError && filterStar(_parallaxError, filterValues[17])) ||
(_filterPmra && filterStar(_pmra, filterValues[18])) ||
(_filterPmraError && filterStar(_pmraError, filterValues[19])) ||
(_filterPmdec && filterStar(_pmdec, filterValues[20])) ||
(_filterPmdecError && filterStar(_pmdecError, filterValues[21])) ||
(_filterRv && filterStar(_rv, filterValues[22])) ||
(_filterRvError && filterStar(_rvError, filterValues[23]));
}
bool ConstructOctreeTask::filterStar(const glm::vec2& range, float filterValue,
float normValue)
{
// Return true if star should be filtered away, i.e. if min = max = filterValue or
// if filterValue < min (when min != 0.0) or filterValue > max (when max != 0.0).
return (fabs(range.x - range.y) < FLT_EPSILON &&
fabs(range.x - filterValue) < FLT_EPSILON) ||
(fabs(range.x - normValue) > FLT_EPSILON && filterValue < range.x) ||
(fabs(range.y - normValue) > FLT_EPSILON && filterValue > range.y);
}
documentation::Documentation ConstructOctreeTask::Documentation() {
using namespace documentation;
return {
"ConstructOctreeTask",
"gaiamission_constructoctreefrombin",
{
{
"Type",
new StringEqualVerifier("ConstructOctreeTask"),
Optional::No
},
{
KeyInFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileInput is set to true then this specifies the path to a "
"single BIN file containing a full dataset. Otherwise this specifies the "
"path to a folder with multiple BIN files containing subsets of sorted "
"star data.",
},
{
KeyOutFileOrFolderPath,
new StringVerifier,
Optional::No,
"If SingleFileInput is set to true then this specifies the output file "
"name (including full path). Otherwise this specifies the path to the "
"folder which to save all files.",
},
{
KeyMaxDist,
new IntVerifier,
Optional::Yes,
"If set it determines what MAX_DIST to use when creating Octree."
},
{
KeyMaxStarsPerNode,
new IntVerifier,
Optional::Yes,
"If set it determines what MAX_STAR_PER_NODE to use when creating Octree."
},
{
KeySingleFileInput,
new BoolVerifier,
Optional::Yes,
"If true then task will read from a single file and output a single "
"binary file with the full Octree. If false then task will read all "
"files in specified folder and output multiple files for the Octree."
},
{
KeyFilterPosX,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position X values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterPosY,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position Y values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterPosZ,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Position Z values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterGMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with G mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default "
"GMag = 20.0 if no value existed."
},
{
KeyFilterBpRp,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp-Rp color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelX,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity X values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelY,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity Y values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterVelZ,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Velocity Z values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterBpMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default "
"BpMag = 20.0 if no value existed."
},
{
KeyFilterRpMag,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Rp mean magnitude values between "
"[min, max] will be inserted into Octree (if min is set to 20.0 it is "
"read as -Inf, if max is set to 20.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away. Default RpMag = "
"20.0 if no value existed."
},
{
KeyFilterBpG,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Bp-G color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterGRp,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with G-Rp color values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterRa,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with RA values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterRaError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with RA Error values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterDec,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with DEC values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterDecError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with DEC Error values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterParallax,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Parallax values between [min, max] "
"will be inserted into Octree (if min is set to 0.0 it is read as -Inf, "
"if max is set to 0.0 it is read as +Inf). If min = max then all values "
"equal min|max will be filtered away."
},
{
KeyFilterParallaxError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Parallax Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmra,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion RA values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmraError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion RA Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmdec,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion DEC values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterPmdecError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Proper Motion DEC Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterRv,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Radial Velocity values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
{
KeyFilterRvError,
new Vector2Verifier<double>,
Optional::Yes,
"If defined then only stars with Radial Velocity Error values between "
"[min, max] will be inserted into Octree (if min is set to 0.0 it is "
"read as -Inf, if max is set to 0.0 it is read as +Inf). If min = max "
"then all values equal min|max will be filtered away."
},
}
};
}
} // namespace openspace