Last active
April 22, 2024 16:06
Revisions
-
derrickturk revised this gist
Apr 22, 2024 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -36,13 +36,13 @@ class ZMapGrid(NamedTuple): cols: int grid: npt.NDArray[np.float64] def plot(self, pixel_is_point: bool = False) -> None: import matplotlib.pyplot as plt if pixel_is_point: extents = self.extents_pixel_is_point() else: extents = self.extents_pixel_is_area() plt.imshow(self.grid, extent=extents, origin='upper') plt.colorbar() plt.show() @@ -211,4 +211,4 @@ def load_zmap_grid(path: Path, check_nodes: bool = True) -> ZMapGrid: rows=rows, cols=cols, grid=grid ) -
derrickturk revised this gist
Apr 22, 2024 . 1 changed file with 27 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -46,6 +46,32 @@ def plot(self) -> None: plt.colorbar() plt.show() # (x, y) def pixel_size_pixel_is_area(self) -> tuple[float, float]: xsize = (self.xmax - self.xmin) / self.cols ysize = (self.ymax - self.ymin) / self.rows return xsize, ysize # (x, y) def pixel_size_pixel_is_point(self) -> tuple[float, float]: xsize = (self.xmax - self.xmin) / (self.cols - 1) ysize = (self.ymax - self.ymin) / (self.rows - 1) return xsize, ysize # (xmin, xmax, ymin, ymax) def extents_pixel_is_area(self) -> tuple[float, float, float, float]: return self.xmin, self.xmax, self.ymin, self.ymax # (xmin, xmax, ymin, ymax) def extents_pixel_is_point(self) -> tuple[float, float, float, float]: xsize, ysize = self.pixel_size_pixel_is_point() return ( self.xmin - 0.5 * xsize, self.xmax + 0.5 * xsize, self.ymin - 0.5 * ysize, self.ymax + 0.5 * ysize ) class ParseState(Enum): BEGIN = auto() @@ -185,4 +211,4 @@ def load_zmap_grid(path: Path, check_nodes: bool = True) -> ZMapGrid: rows=rows, cols=cols, grid=grid ) -
derrickturk revised this gist
Apr 22, 2024 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -131,10 +131,10 @@ def load_zmap_grid(path: Path, check_nodes: bool = True) -> ZMapGrid: ) rows = int(toks[0]) cols = int(toks[1]) xmin = float(toks[2]) xmax = float(toks[3]) ymin = float(toks[4]) ymax = float(toks[5]) expect_lens = [nodes] * (rows // nodes) if rows % nodes != 0: expect_lens += [rows % nodes] -
derrickturk revised this gist
Apr 19, 2024 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -55,7 +55,7 @@ class ParseState(Enum): HEADEREND = auto() DATA = auto() def load_zmap_grid(path: Path, check_nodes: bool = True) -> ZMapGrid: nodes = 0 missing = '' parse_float: Callable[[str], float] = float @@ -161,7 +161,7 @@ def load_zmap_grid(path: Path) -> ZMapGrid: ) case ParseState.DATA: if check_nodes and len(toks) != expect_lens[cyc]: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} had {len(toks)} entries;' @@ -185,4 +185,4 @@ def load_zmap_grid(path: Path) -> ZMapGrid: rows=rows, cols=cols, grid=grid ) -
derrickturk created this gist
Apr 18, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,188 @@ # Copyright (c) 2024 dwt | terminus, LLC # 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. from enum import Enum, auto from pathlib import Path from typing import Callable, NamedTuple import sys import numpy as np import numpy.typing as npt class ZMapGrid(NamedTuple): xmin: float xmax: float ymin: float ymax: float rows: int cols: int grid: npt.NDArray[np.float64] def plot(self) -> None: import matplotlib.pyplot as plt plt.imshow( self.grid, extent=(self.xmin, self.xmax, self.ymin, self.ymax), origin='upper' ) plt.colorbar() plt.show() class ParseState(Enum): BEGIN = auto() HEADER1 = auto() HEADER2 = auto() HEADER3 = auto() HEADEREND = auto() DATA = auto() def load_zmap_grid(path: Path) -> ZMapGrid: nodes = 0 missing = '' parse_float: Callable[[str], float] = float rows = 0 cols = 0 xmin = np.nan xmax = np.nan ymin = np.nan ymax = np.nan state = ParseState.BEGIN expect_lens: list[int] = [] cyc = 0 data: list[float] = [] with open(path, 'r') as f: # handle tagging with line #s, comment lines and line endings lines = ( (i + 1, line.rstrip()) for i, line in enumerate(f) if not line.startswith('!') ) for num, line in lines: # tokenize by , or whitespace depdending on file section if state == ParseState.DATA: toks = line.split() else: toks = [w.strip() for w in line.split(',')] match state: case ParseState.BEGIN: match toks: case [udf, 'GRID', s_nodes]: if not udf.startswith('@'): raise ValueError( f'invalid grid file {path}:\n' + f'line {num} does not begin with "@"' ) nodes = int(s_nodes) state = ParseState.HEADER1 case _: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} is not "@..., GRID, N"' ) case ParseState.HEADER1: if len(toks) != 5: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} does not contain 5 entries' ) _width = int(toks[0]) missing = toks[1] if missing == '': missing = toks[2] elif toks[2] != '': raise ValueError( f'invalid grid file {path}:\n' + f'line {num} specifies missing number ' + 'AND text' ) ndec = int(toks[3]) parse_float = lambda s: float(s) if '.' in s else float(s[:len(s) - ndec] + '.' + s[-ndec:]) _startcol = int(toks[4]) state = ParseState.HEADER2 case ParseState.HEADER2: if len(toks) != 6: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} does not contain 6 entries' ) rows = int(toks[0]) cols = int(toks[1]) xmin = parse_float(toks[2]) xmax = parse_float(toks[3]) ymin = parse_float(toks[4]) ymax = parse_float(toks[5]) expect_lens = [nodes] * (rows // nodes) if rows % nodes != 0: expect_lens += [rows % nodes] state = ParseState.HEADER3 case ParseState.HEADER3: match toks: case ['0.0', '0.0', '0.0']: state = ParseState.HEADEREND case _: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} was not "0.0, 0.0, 0.0"' ) case ParseState.HEADEREND: match toks: case ['@']: state = ParseState.DATA case _: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} was not "@"' ) case ParseState.DATA: if len(toks) != expect_lens[cyc]: raise ValueError( f'invalid grid file {path}:\n' + f'line {num} had {len(toks)} entries;' + f' expected {expect_lens[cyc]}' ) for tok in toks: if tok == missing: data.append(np.nan) else: data.append(parse_float(tok)) cyc = (cyc + 1) % len(expect_lens) grid = np.array(data, dtype=np.float64, order='F' ).reshape((rows, cols), order='F') return ZMapGrid( xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, rows=rows, cols=cols, grid=grid )