From cffec2f8d668d4914440e2ddaaa507cc694f8cef Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Fri, 14 Feb 2025 14:30:56 -0500 Subject: [PATCH] feat(opatIO): opat fileformat addedd --- src/opatIO/meson.build | 18 ++ src/opatIO/private/opatIO.cpp | 313 ++++++++++++++++++++++++++++++++++ src/opatIO/public/opatIO.h | 93 ++++++++++ 3 files changed, 424 insertions(+) create mode 100644 src/opatIO/meson.build create mode 100644 src/opatIO/private/opatIO.cpp create mode 100644 src/opatIO/public/opatIO.h diff --git a/src/opatIO/meson.build b/src/opatIO/meson.build new file mode 100644 index 0000000..ae5e73e --- /dev/null +++ b/src/opatIO/meson.build @@ -0,0 +1,18 @@ +# Define the library +opatIO_sources = files( + 'private/opatIO.cpp', +) + +opatIO_headers = files( + 'public/opatIO.h' +) + +# Define the libopatIO library so it can be linked against by other parts of the build system +libopatIO = library('opatIO', + opatIO_sources, + include_directories: include_directories('public'), + cpp_args: ['-fvisibility=default'], + install : true) + +# Make headers accessible +install_headers(opatIO_headers, subdir : '4DSSE/opatIO') \ No newline at end of file diff --git a/src/opatIO/private/opatIO.cpp b/src/opatIO/private/opatIO.cpp new file mode 100644 index 0000000..67900ba --- /dev/null +++ b/src/opatIO/private/opatIO.cpp @@ -0,0 +1,313 @@ +#include "opatIO.h" +#include +#include +#include +#include +#include +#include +#include + +// Constructor +OpatIO::OpatIO() {} + +OpatIO::OpatIO(std::string filename) : filename(filename) { + load(); +} + +// Destructor +OpatIO::~OpatIO() { + unload(); +} + +// Load the OPAT file +void OpatIO::load() { + if (loaded) return; + + std::ifstream file(filename, std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Could not open file: " + filename); + } + + readHeader(file); + readTableIndex(file); + + loaded = true; + file.close(); +} + +// // Unload the OPAT file +void OpatIO::unload() { + if (!loaded) return; + + tableIndex.clear(); + while (!tableQueue.empty()) { + tableQueue.pop(); + } + + loaded = false; +} + +// Read the header from the file +void OpatIO::readHeader(std::ifstream &file) { + file.read(reinterpret_cast(&header), sizeof(Header)); + if (file.gcount() != sizeof(Header)) { + throw std::runtime_error("Error reading header from file: " + filename); + } +} + +// Read the table index from the file +void OpatIO::readTableIndex(std::ifstream &file) { + file.seekg(header.indexOffset, std::ios::beg); + tableIndex.resize(header.numTables); + file.read(reinterpret_cast(tableIndex.data()), header.numTables * sizeof(TableIndex)); + if (file.gcount() != static_cast(header.numTables * sizeof(TableIndex))) { + throw std::runtime_error("Error reading table index from file: " + filename); + } +} + +// // Check if a table is in the queue +// bool OpatIO::isTableInQueue(double X, double Z) { +// for (const auto &table : tableQueue) { +// if (table.X == X && table.Z == Z) { +// return true; +// } +// } +// return false; +// } + +// // Get a table from the queue +// OPATTable OpatIO::getTableFromQueue(double X, double Z) { +// std::queue tempQueue; +// OPATTable result; + +// while (!tableQueue.empty()) { +// OPATTable table = tableQueue.front(); +// tableQueue.pop(); +// if (table.X == X && table.Z == Z) { +// result = table; +// } +// tempQueue.push(table); +// } + +// tableQueue = tempQueue; +// return result; +// } + +// // Add a table to the queue +// void OpatIO::addTableToQueue(OPATTable table) { +// if (tableQueue.size() >= maxQueueDepth) { +// removeTableFromQueue(); +// } +// tableQueue.push(table); +// } + +// // Remove a table from the queue +// void OpatIO::removeTableFromQueue() { +// if (!tableQueue.empty()) { +// tableQueue.pop(); +// } +// } + +// // Flush the queue +// void OpatIO::flushQueue() { +// while (!tableQueue.empty()) { +// tableQueue.pop(); +// } +// } + +// // Get the OPAT version +// uint16_t OpatIO::getOPATVersion() { +// return header.version; +// } + +// // Get the table ID for given X and Z +// uint16_t OpatIO::getTableID(double X, double Z) { +// for (const auto &index : tableIndex) { +// if (index.X == X && index.Z == Z) { +// 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 +// uint64_t OpatIO::getTableByteStart(uint16_t tableID) { +// for (const auto &index : tableIndex) { +// if (index.tableID == tableID) { +// return index.byteStart; +// } +// } +// throw std::runtime_error("Byte start not found for given table ID"); +// } + +// // Get the byte end for a given table ID +// uint64_t OpatIO::getTableByteEnd(uint16_t tableID) { +// for (const auto &index : tableIndex) { +// 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 +// OPATTable OpatIO::getTable(double X, double Z) { +// if (isTableInQueue(X, Z)) { +// return getTableFromQueue(X, Z); +// } + +// uint16_t tableID = getTableID(X, Z); +// return getTable(tableID); +// } + +// // Get a table for given table ID +// 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); +// uint64_t byteEnd = getTableByteEnd(tableID); +// uint64_t tableSize = byteEnd - byteStart; + +// file.seekg(byteStart, std::ios::beg); +// OPATTable table; +// file.read(reinterpret_cast(&table), tableSize); +// if (file.gcount() != tableSize) { +// throw std::runtime_error("Error reading table from file: " + filename); +// } + +// addTableToQueue(table); +// file.close(); +// return table; +// } + +// Set the maximum queue depth +void OpatIO::setMaxQDepth(int depth) { + maxQDepth = depth; +} + +int OpatIO::getMaxQDepth() { + return maxQDepth; +} + +// Set the filename +void OpatIO::setFilename(std::string filename) { + if (loaded) { + throw std::runtime_error("Cannot set filename while file is loaded"); + } + this->filename = filename; +} + +// Check if the file is loaded +bool OpatIO::isLoaded() { + return loaded; +} + +// Print the header +void OpatIO::printHeader() { + std::cout << "Version: " << header.version << std::endl; + std::cout << "Number of Tables: " << header.numTables << std::endl; + std::cout << "Header Size: " << header.headerSize << std::endl; + std::cout << "Index Offset: " << header.indexOffset << std::endl; + std::cout << "Creation Date: " << header.creationDate << std::endl; + std::cout << "Source Info: " << header.sourceInfo << std::endl; + std::cout << "Comment: " << header.comment << std::endl; +} + +// Print the table index +void OpatIO::printTableIndex() { + if (tableIndex.empty()) { + std::cout << "No table indexes found." << std::endl; + return; + } + + // Print table header + std::cout << std::left << std::setw(10) << "X" + << std::setw(10) << "Z" + << std::setw(15) << "Byte Start" + << std::setw(15) << "Byte End" + << "Checksum (SHA-256)" << std::endl; + + std::cout << std::string(80, '=') << std::endl; // Separator line + + // Print each entry in the table + for (const auto &index : tableIndex) { + std::cout << std::fixed << std::setprecision(4) + << std::setw(10) << index.X + << std::setw(10) << index.Z + << std::setw(15) << index.byteStart + << std::setw(15) << index.byteEnd + << std::hex; // Switch to hex mode for checksum + + for (int i = 0; i < 8; ++i) { // Print first 8 bytes of SHA-256 for brevity + std::cout << std::setw(2) << std::setfill('0') << (int)index.sha256[i]; + } + + std::cout << "..." << std::dec << std::setfill(' ') << std::endl; // Reset formatting + } +} + + +// // Print a table +// void OpatIO::printTable(OPATTable table) { +// std::cout << "Table ID: " << table.tableID << std::endl; +// std::cout << "N_R: " << table.N_R << std::endl; +// std::cout << "N_T: " << table.N_T << std::endl; +// std::cout << "LogR: "; +// for (uint32_t i = 0; i < table.N_R; ++i) { +// std::cout << table.logR[i] << " "; +// } +// std::cout << std::endl; +// std::cout << "LogT: "; +// for (uint32_t i = 0; i < table.N_T; ++i) { +// std::cout << table.logT[i] << " "; +// } +// std::cout << std::endl; +// std::cout << "LogKappa: "; +// for (uint32_t i = 0; i < table.N_R * table.N_T; ++i) { +// std::cout << table.logKappa[i] << " "; +// } +// std::cout << std::endl; +// } + +// // Get all tables +// std::vector OpatIO::getTables() { +// std::vector tables; +// for (const auto &index : tableIndex) { +// tables.push_back(getTable(index.tableID)); +// } +// return tables; +// } + +// Get the table index +std::vector OpatIO::getTableIndex() { + return tableIndex; +} + +// Get the header +Header OpatIO::getHeader() { + return header; +} + +// // Get the closest X tables +// std::vector OpatIO::getClosestXTables(double X, double ZExact, int numTables) { +// std::vector closestTables; +// // Implement logic to find closest X tables +// return closestTables; +// } + +// // Get the closest Z tables +// std::vector OpatIO::getClosestZTables(double XExact, double Z, int numTables) { +// std::vector closestTables; +// // Implement logic to find closest Z tables +// return closestTables; +// } + +// // Get the closest tables +// std::vector OpatIO::getClosestTables(double X, double Z, int numTables) { +// std::vector closestTables; +// // Implement logic to find closest tables +// return closestTables; +// } \ No newline at end of file diff --git a/src/opatIO/public/opatIO.h b/src/opatIO/public/opatIO.h new file mode 100644 index 0000000..30c4ba5 --- /dev/null +++ b/src/opatIO/public/opatIO.h @@ -0,0 +1,93 @@ +#ifndef OPATIO_H +#define OPATIO_H + +#include +#include +#include +#include +#include + +struct Header { + char magic[4]; + uint16_t version; + uint32_t numTables; + uint32_t headerSize; + uint64_t indexOffset; + char creationDate[16]; + char sourceInfo[64]; + char comment[128]; + char reserved[26]; +}; + +struct TableIndex { + double X; + double Z; + // double C; // For type 2 OPAL tables. When not set will be 0 + // double O; // For type 2 OPAL tables. When not set will be 0 + uint64_t byteStart; + uint64_t byteEnd; + char sha256[32]; +}; + +struct OPATTable { + uint32_t N_R; + uint32_t N_T; + std::vector logR; + std::vector logT; + std::vector> logKappa; +}; + +class OpatIO { +private: + Header header; + std::vector tableIndex; + std::queue tableQueue; + int maxQDepth = 10; + std::string filename; + bool loaded = false; + + void readHeader(std::ifstream &file); + void readTableIndex(std::ifstream &file); + + bool isTableInQueue(double X, double Z); + OPATTable getTableFromQueue(double X, double Z); + void addTableToQueue(OPATTable table); + void removeTableFromQueue(); + + void flushQueue(); + + uint16_t getOPATVersion(); + + uint16_t getTableID(double X, double Z); + uint64_t getTableByteStart(uint16_t tableID); + uint64_t getTableByteEnd(uint16_t tableID); + +public: + OpatIO(); + OpatIO(std::string filename); + ~OpatIO(); + + OPATTable getTable(double X, double, double C=0, double O=0); + OPATTable getTable(uint16_t tableID); + void setMaxQDepth(int depth); + int getMaxQDepth(); + void setFilename(std::string filename); + void load(); + void unload(); + bool isLoaded(); + + void printHeader(); + void printTableIndex(); + void printTable(OPATTable table); + + std::vector getTables(); + std::vector getTableIndex(); + Header getHeader(); + + std::vector getClosestXTables(double X, double ZExact, double C=0, double O=0, int numTables=1); + std::vector getClosestZTables(double XExact, double Z, double C=0, double O=0, int numTables=1); + std::vector getClosestTables(double X, double Z, double C=0, double O=0, int numTables=1); +}; + + +#endif \ No newline at end of file