From 3b34ce3979540cbd8b073b99ac3c2206205ea1c6 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Sun, 16 Feb 2025 12:16:20 -0500 Subject: [PATCH] feat(utils/opatio): added print to ascii --- utils/opatio/src/opatio/opat/opat.py | 89 ++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/utils/opatio/src/opatio/opat/opat.py b/utils/opatio/src/opatio/opat/opat.py index ef091f7..81abd61 100644 --- a/utils/opatio/src/opatio/opat/opat.py +++ b/utils/opatio/src/opatio/opat/opat.py @@ -186,6 +186,87 @@ class OpatIO: return tableIndexBytes + def __repr__(self) -> str: + reprString = f"""OpatIO( + versoion: {self.header.version} + numTables: {self.header.numTables} + headerSize: {self.header.headerSize} + indexOffset: {self.header.indexOffset} + creationDate: {self.header.creationDate} + sourceInfo: {self.header.sourceInfo} + comment: {self.header.comment} + reserved: {self.header.reserved} +)""" + return reprString + + def _format_table_as_string(self, table: OPATTable, X: float, Z: float) -> str: + tableString: List[str] = [] + # fixed width X and Z header per table + tableString.append(f"X: {X:<10.4f} Z: {Z:<10.4f}") + tableString.append("-" * 80) + # write logR accross the top (reserving one col for where logT will be) + logRRow = f"{"":<10}" + logRRowTrue = "".join(f"{r:<10.4f}" for r in table.logR) + tableString.append(logRRow + logRRowTrue) + for i, logT in enumerate(table.logT): + row = f"{logT:<10.4f}" + for kappa in table.logKappa[i]: + row += f"{kappa:<10.4f}" + tableString.append(row) + tableString.append("=" * 80) + return '\n'.join(tableString) + + @staticmethod + def print_table_indexes(table_indexes: List[TableIndex]) -> str: + if not table_indexes: + print("No table indexes found.") + return + + tableRows: List[str] = [] + tableRows.append("\nTable Indexes in OPAT File:\n") + tableRows.append(f"{'X':<10} {'Z':<10} {'Byte Start':<15} {'Byte End':<15} {'Checksum (SHA-256)'}") + tableRows.append("=" * 80) + for entry in table_indexes: + tableRows.append(f"{entry.X:<10.4f} {entry.Z:<10.4f} {entry.byteStart:<15} {entry.byteEnd:<15} {entry.sha256[:16]}...") + return '\n'.join(tableRows) + + def save_as_ascii(self, filename: str) -> str: + numericFMT = "{:.18e}" + currentStartByte: int = 256 + tableIndexs: List[bytes] = [] + tableStrings: List[bytes] = [] + for (X, Z), table in self.tables: + checksum, tableBytes = self._table_bytes(table) + tableStrings.append(self._format_table_as_string(table, X, Z) + "\n") + tableIndex = TableIndex( + X = X, + Z = Z, + byteStart = currentStartByte, + byteEnd = currentStartByte + len(tableBytes), + sha256 = checksum + ) + tableIndexs.append(tableIndex) + + + currentStartByte += len(tableBytes) + self.header.indexOffset = currentStartByte + with open(filename, 'w') as f: + f.write(f"{self.header.magic}\n") + f.write(f"Version: {self.header.version}\n") + f.write(f"numTables: {self.header.numTables}\n") + f.write(f"headerSize (bytes): {self.header.headerSize}\n") + f.write(f"tableIndex Offset (bytes): {self.header.indexOffset}\n") + f.write(f"Creation Date: {self.header.creationDate}\n") + f.write(f"Source Info: {self.header.sourceInfo}\n") + f.write(f"Comment: {self.header.comment}\n") + f.write("="*80 + "\n") + f.write("="*80 + "\n") + for tableString in tableStrings: + f.write(tableString) + f.write("="*80 + "\n") + f.write("="*80 + "\n") + f.write(self.print_table_indexes(tableIndexs)) + def save(self, filename: str) -> str: tempHeaderBytes = self._header_bytes() @@ -229,14 +310,14 @@ def loadOpat(filename: str) -> OpatIO: headerBytes: bytes = f.read(256) unpackedHeader = struct.unpack("<4s H I I Q 16s 64s 128s 26s", headerBytes) loadedHeader = Header( - magic = unpackedHeader[0].decode(), + magic = unpackedHeader[0].decode().replace("\x00", ""), version = unpackedHeader[1], numTables = unpackedHeader[2], headerSize = unpackedHeader[3], indexOffset = unpackedHeader[4], - creationDate = unpackedHeader[5].decode(), - sourceInfo = unpackedHeader[6].decode(), - comment = unpackedHeader[7].decode(), + creationDate = unpackedHeader[5].decode().replace("\x00", ""), + sourceInfo = unpackedHeader[6].decode().replace("\x00", ""), + comment = unpackedHeader[7].decode().replace("\x00", ""), reserved = unpackedHeader[8] ) opat.header = loadedHeader