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:
2025-02-15 07:27:47 -05:00
parent eda61c6889
commit 3fc2651730
4 changed files with 169 additions and 117 deletions

View File

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

View File

@@ -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();
}; };