feat(opatIO): added min viable version of opatIO
opatIO can now read tables properly and retreive them in a useful manner. Future aditions will be the ability to lookup "closest" tables and a pretty printer for tables.
This commit is contained in:
@@ -4,8 +4,12 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include<cstring>
|
#include <iomanip>
|
||||||
#include<iomanip>
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
OpatIO::OpatIO() {}
|
OpatIO::OpatIO() {}
|
||||||
@@ -41,7 +45,7 @@ void OpatIO::unload() {
|
|||||||
|
|
||||||
tableIndex.clear();
|
tableIndex.clear();
|
||||||
while (!tableQueue.empty()) {
|
while (!tableQueue.empty()) {
|
||||||
tableQueue.pop();
|
tableQueue.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
@@ -63,125 +67,168 @@ void OpatIO::readTableIndex(std::ifstream &file) {
|
|||||||
if (file.gcount() != static_cast<std::streamsize>(header.numTables * sizeof(TableIndex))) {
|
if (file.gcount() != static_cast<std::streamsize>(header.numTables * sizeof(TableIndex))) {
|
||||||
throw std::runtime_error("Error reading table index from file: " + filename);
|
throw std::runtime_error("Error reading table index from file: " + filename);
|
||||||
}
|
}
|
||||||
|
buildTableIDToComposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Check if a table is in the queue
|
void OpatIO::buildTableIDToComposition(){
|
||||||
// bool OpatIO::isTableInQueue(double X, double Z) {
|
tableIDToComposition.clear();
|
||||||
// for (const auto &table : tableQueue) {
|
int tableID = 0;
|
||||||
// if (table.X == X && table.Z == Z) {
|
std::pair<double, double> comp;
|
||||||
// return true;
|
for (const auto &index : tableIndex) {
|
||||||
// }
|
comp.first = index.X;
|
||||||
// }
|
comp.second = index.Z;
|
||||||
// return false;
|
tableIDToComposition.emplace(tableID, comp);
|
||||||
// }
|
tableID++;
|
||||||
|
}
|
||||||
|
XZLookupEpsilon();
|
||||||
|
}
|
||||||
|
|
||||||
// // Get a table from the queue
|
void OpatIO::XZLookupEpsilon() {
|
||||||
// OPATTable OpatIO::getTableFromQueue(double X, double Z) {
|
/*
|
||||||
// std::queue<OPATTable> tempQueue;
|
Get 10% of the minimum spacing between XZ values
|
||||||
// OPATTable result;
|
in the tableIDToComposition map. This can be used
|
||||||
|
to set the comparison distance when doing a reverse
|
||||||
|
lookup (composition -> tableID)
|
||||||
|
*/
|
||||||
|
std::vector<double> Xvalues, Zvalues;
|
||||||
|
double epsilonX, epsilonZ, xgap, zgap;
|
||||||
|
|
||||||
// while (!tableQueue.empty()) {
|
// Start these out as larger than they will ever be
|
||||||
// OPATTable table = tableQueue.front();
|
epsilonX = 1;
|
||||||
// tableQueue.pop();
|
epsilonZ = 1;
|
||||||
// if (table.X == X && table.Z == Z) {
|
for (const auto& pair : tableIDToComposition) {
|
||||||
// result = table;
|
Xvalues.push_back(pair.second.first);
|
||||||
// }
|
Zvalues.push_back(pair.second.second);
|
||||||
// tempQueue.push(table);
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// tableQueue = tempQueue;
|
// Sorting is required for this algorithm.
|
||||||
// return result;
|
std::sort(Xvalues.begin(), Xvalues.end());
|
||||||
// }
|
std::sort(Zvalues.begin(), Zvalues.end());
|
||||||
|
|
||||||
// // Add a table to the queue
|
for (size_t i = 1; i < Xvalues.size(); ++i) {
|
||||||
// void OpatIO::addTableToQueue(OPATTable table) {
|
xgap = Xvalues[i] - Xvalues[i - 1];
|
||||||
// if (tableQueue.size() >= maxQueueDepth) {
|
zgap = Zvalues[i] - Zvalues[i - 1];
|
||||||
// removeTableFromQueue();
|
if (xgap > 0 && xgap < epsilonX) {
|
||||||
// }
|
epsilonX = xgap;
|
||||||
// tableQueue.push(table);
|
}
|
||||||
// }
|
if (zgap > 0 && zgap < epsilonZ) {
|
||||||
|
epsilonZ = zgap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 0.1 to extract 10% of min distance.
|
||||||
|
XZepsilon = {0.1*epsilonX, 0.1*epsilonZ};
|
||||||
|
}
|
||||||
|
|
||||||
// // Remove a table from the queue
|
int OpatIO::lookupTableID(double X, double Z){
|
||||||
// void OpatIO::removeTableFromQueue() {
|
bool XOkay;
|
||||||
// if (!tableQueue.empty()) {
|
bool ZOkay;
|
||||||
// tableQueue.pop();
|
int tableID = 0;
|
||||||
// }
|
for (const auto &tableMap : tableIDToComposition){
|
||||||
// }
|
XOkay = std::fabs(tableMap.second.first - X) < XZepsilon.first;
|
||||||
|
ZOkay = std::fabs(tableMap.second.second - Z) < XZepsilon.second;
|
||||||
|
if (XOkay and ZOkay){
|
||||||
|
return tableID;
|
||||||
|
}
|
||||||
|
tableID++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// // Flush the queue
|
// Get a table from the queue
|
||||||
// void OpatIO::flushQueue() {
|
OPATTable OpatIO::getTableFromQueue(int tableID) {
|
||||||
// while (!tableQueue.empty()) {
|
for (const auto &table : tableQueue) {
|
||||||
// tableQueue.pop();
|
if (table.first == tableID) {
|
||||||
// }
|
return table.second;
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
throw std::out_of_range("Table not found!");
|
||||||
|
}
|
||||||
|
|
||||||
// // Get the OPAT version
|
// Add a table to the queue
|
||||||
// uint16_t OpatIO::getOPATVersion() {
|
void OpatIO::addTableToQueue(int tableID, OPATTable table) {
|
||||||
// return header.version;
|
if (static_cast<int>(tableQueue.size()) >= maxQDepth) {
|
||||||
// }
|
removeTableFromQueue();
|
||||||
|
}
|
||||||
|
std::pair<int, OPATTable> IDTablePair = {tableID, table};
|
||||||
|
tableQueue.push_back(IDTablePair);
|
||||||
|
}
|
||||||
|
|
||||||
// // Get the table ID for given X and Z
|
// Remove a table from the queue
|
||||||
// uint16_t OpatIO::getTableID(double X, double Z) {
|
void OpatIO::removeTableFromQueue() {
|
||||||
// for (const auto &index : tableIndex) {
|
if (!tableQueue.empty()) {
|
||||||
// if (index.X == X && index.Z == Z) {
|
tableQueue.pop_front();
|
||||||
// return index.tableID;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// throw std::runtime_error("Table ID not found for given X and Z");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get the byte start for a given table ID
|
// Flush the queue
|
||||||
// uint64_t OpatIO::getTableByteStart(uint16_t tableID) {
|
void OpatIO::flushQueue() {
|
||||||
// for (const auto &index : tableIndex) {
|
while (!tableQueue.empty()) {
|
||||||
// if (index.tableID == tableID) {
|
tableQueue.pop_back();
|
||||||
// return index.byteStart;
|
tableQueue.pop_front();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// throw std::runtime_error("Byte start not found for given table ID");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get the byte end for a given table ID
|
// Get the OPAT version
|
||||||
// uint64_t OpatIO::getTableByteEnd(uint16_t tableID) {
|
uint16_t OpatIO::getOPATVersion() {
|
||||||
// for (const auto &index : tableIndex) {
|
return header.version;
|
||||||
// if (index.tableID == tableID) {
|
}
|
||||||
// return index.byteEnd;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// throw std::runtime_error("Byte end not found for given table ID");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get a table for given X and Z
|
// Get a table for given X and Z
|
||||||
// OPATTable OpatIO::getTable(double X, double Z) {
|
OPATTable OpatIO::getTable(double X, double Z) {
|
||||||
// if (isTableInQueue(X, Z)) {
|
int tableID = lookupTableID(X, Z);
|
||||||
// return getTableFromQueue(X, Z);
|
if (tableID == -1) {
|
||||||
// }
|
throw std::out_of_range("X Z Pair Not found!");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return getTableFromQueue(tableID);
|
||||||
|
}
|
||||||
|
catch(const std::out_of_range &e) {
|
||||||
|
return getTable(tableID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// uint16_t tableID = getTableID(X, Z);
|
OPATTable OpatIO::getTable(int tableID) {
|
||||||
// return getTable(tableID);
|
std::ifstream file(filename, std::ios::binary);
|
||||||
// }
|
if (!file.is_open()) {
|
||||||
|
throw std::runtime_error("Could not open file: " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
// // Get a table for given table ID
|
uint64_t byteStart = tableIndex[tableID].byteStart;
|
||||||
// OPATTable OpatIO::getTable(uint16_t tableID) {
|
|
||||||
// std::ifstream file(filename, std::ios::binary);
|
|
||||||
// if (!file.is_open()) {
|
|
||||||
// throw std::runtime_error("Could not open file: " + filename);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// uint64_t byteStart = getTableByteStart(tableID);
|
file.seekg(byteStart, std::ios::beg);
|
||||||
// uint64_t byteEnd = getTableByteEnd(tableID);
|
|
||||||
// uint64_t tableSize = byteEnd - byteStart;
|
|
||||||
|
|
||||||
// file.seekg(byteStart, std::ios::beg);
|
OPATTable table;
|
||||||
// OPATTable table;
|
|
||||||
// file.read(reinterpret_cast<char*>(&table), tableSize);
|
|
||||||
// if (file.gcount() != tableSize) {
|
|
||||||
// throw std::runtime_error("Error reading table from file: " + filename);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// addTableToQueue(table);
|
// Step 1: Read N_R and N_T
|
||||||
// file.close();
|
file.read(reinterpret_cast<char*>(&table.N_R), sizeof(uint32_t));
|
||||||
// return table;
|
file.read(reinterpret_cast<char*>(&table.N_T), sizeof(uint32_t));
|
||||||
// }
|
|
||||||
|
|
||||||
|
// Resize vectors to hold the correct number of elements
|
||||||
|
table.logR.resize(table.N_R);
|
||||||
|
table.logT.resize(table.N_T);
|
||||||
|
table.logKappa.resize(table.N_R, std::vector<double>(table.N_T));
|
||||||
|
|
||||||
|
// Step 2: Read logR values
|
||||||
|
file.read(reinterpret_cast<char*>(table.logR.data()), table.N_R * sizeof(double));
|
||||||
|
|
||||||
|
// Step 3: Read logT values
|
||||||
|
file.read(reinterpret_cast<char*>(table.logT.data()), table.N_T * sizeof(double));
|
||||||
|
|
||||||
|
// Step 4: Read logKappa values (flattened row-major order)
|
||||||
|
for (size_t i = 0; i < table.N_R; ++i) {
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(table.logKappa[i].data()), table.N_T * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
throw std::runtime_error("Error reading table from file: " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
addTableToQueue(tableID, table);
|
||||||
|
file.close();
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the maximum queue depth
|
// Set the maximum queue depth
|
||||||
void OpatIO::setMaxQDepth(int depth) {
|
void OpatIO::setMaxQDepth(int depth) {
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
@@ -37,11 +39,15 @@ struct OPATTable {
|
|||||||
std::vector<std::vector<double>> logKappa;
|
std::vector<std::vector<double>> logKappa;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class opatIOTest; // Friend for gtest
|
||||||
|
|
||||||
class OpatIO {
|
class OpatIO {
|
||||||
private:
|
private:
|
||||||
Header header;
|
Header header;
|
||||||
std::vector<TableIndex> tableIndex;
|
std::vector<TableIndex> tableIndex;
|
||||||
std::queue<OPATTable> tableQueue;
|
std::deque<std::pair<int, OPATTable>> tableQueue;
|
||||||
|
std::map<int, std::pair<double, double>> tableIDToComposition;
|
||||||
|
std::pair<double, double> XZepsilon;
|
||||||
int maxQDepth = 10;
|
int maxQDepth = 10;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
@@ -49,26 +55,21 @@ private:
|
|||||||
void readHeader(std::ifstream &file);
|
void readHeader(std::ifstream &file);
|
||||||
void readTableIndex(std::ifstream &file);
|
void readTableIndex(std::ifstream &file);
|
||||||
|
|
||||||
bool isTableInQueue(double X, double Z);
|
OPATTable getTableFromQueue(int tableID);
|
||||||
OPATTable getTableFromQueue(double X, double Z);
|
void addTableToQueue(int tableID, OPATTable table);
|
||||||
void addTableToQueue(OPATTable table);
|
|
||||||
void removeTableFromQueue();
|
void removeTableFromQueue();
|
||||||
|
|
||||||
void flushQueue();
|
void flushQueue();
|
||||||
|
|
||||||
uint16_t getOPATVersion();
|
OPATTable getTable(int tableID);
|
||||||
|
|
||||||
uint16_t getTableID(double X, double Z);
|
|
||||||
uint64_t getTableByteStart(uint16_t tableID);
|
|
||||||
uint64_t getTableByteEnd(uint16_t tableID);
|
|
||||||
|
|
||||||
|
void XZLookupEpsilon();
|
||||||
|
void buildTableIDToComposition();
|
||||||
public:
|
public:
|
||||||
OpatIO();
|
OpatIO();
|
||||||
OpatIO(std::string filename);
|
OpatIO(std::string filename);
|
||||||
~OpatIO();
|
~OpatIO();
|
||||||
|
|
||||||
OPATTable getTable(double X, double, double C=0, double O=0);
|
OPATTable getTable(double X, double Z);
|
||||||
OPATTable getTable(uint16_t tableID);
|
|
||||||
void setMaxQDepth(int depth);
|
void setMaxQDepth(int depth);
|
||||||
int getMaxQDepth();
|
int getMaxQDepth();
|
||||||
void setFilename(std::string filename);
|
void setFilename(std::string filename);
|
||||||
@@ -87,6 +88,10 @@ public:
|
|||||||
std::vector<OPATTable> getClosestXTables(double X, double ZExact, double C=0, double O=0, int numTables=1);
|
std::vector<OPATTable> getClosestXTables(double X, double ZExact, double C=0, double O=0, int numTables=1);
|
||||||
std::vector<OPATTable> getClosestZTables(double XExact, double Z, double C=0, double O=0, int numTables=1);
|
std::vector<OPATTable> getClosestZTables(double XExact, double Z, double C=0, double O=0, int numTables=1);
|
||||||
std::vector<OPATTable> getClosestTables(double X, double Z, double C=0, double O=0, int numTables=1);
|
std::vector<OPATTable> getClosestTables(double X, double Z, double C=0, double O=0, int numTables=1);
|
||||||
|
|
||||||
|
int lookupTableID(double X, double Z);
|
||||||
|
int lookupClosestTableID(double X, double Z);
|
||||||
|
uint16_t getOPATVersion();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user