fixr 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fixr-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Joseph D. Long
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fixr-0.1.0/MANIFEST.in ADDED
@@ -0,0 +1,3 @@
1
+ include src/fixr/*.dylib
2
+ include src/fixr/*.so
3
+ include src/fixr/_xrif.py
fixr-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.1
2
+ Name: fixr
3
+ Version: 0.1.0
4
+ Summary: Python bindings to xrif, the extreme reordered image format
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+
9
+ # fiXr
10
+
11
+ Open xrif archives from Python directly using the [xrif](https://github.com/jaredmales/xrif) library.
12
+
13
+ ## Example
14
+
15
+ ```python
16
+ from fixr import xrif2numpy
17
+ fh = open('camwfs_20240315225750994842000.xrif', 'rb')
18
+ data = xrif2numpy(fh)
19
+ timings = xrif2numpy(fh)
20
+ ```
fixr-0.1.0/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # fiXr
2
+
3
+ Open xrif archives from Python directly using the [xrif](https://github.com/jaredmales/xrif) library.
4
+
5
+ ## Example
6
+
7
+ ```python
8
+ from fixr import xrif2numpy
9
+ fh = open('camwfs_20240315225750994842000.xrif', 'rb')
10
+ data = xrif2numpy(fh)
11
+ timings = xrif2numpy(fh)
12
+ ```
@@ -0,0 +1,22 @@
1
+ # pyproject.toml
2
+ [build-system]
3
+ requires = ["setuptools"]
4
+ build-backend = "setuptools.build_meta"
5
+
6
+ [project]
7
+ name = "fixr"
8
+ description = "Python bindings to xrif, the extreme reordered image format"
9
+ version = "0.1.0"
10
+ requires-python = ">=3.10"
11
+ readme = "README.md"
12
+
13
+ [tool.setuptools.packages.find]
14
+ where = ["src"]
15
+
16
+ [tool.cibuildwheel]
17
+ before-build = "bash build_xrif_and_generate_bindings.sh"
18
+ manylinux-x86_64-image = "quay.io/pypa/manylinux_2_28_x86_64"
19
+ manylinux-aarch64-image = "quay.io/pypa/manylinux_2_28_aarch64"
20
+
21
+ # skip pypi, 32bit windows, 32bit linux
22
+ skip = ["pp*", "*-win32", "*-manylinux_i686", "*-musllinux*"]
fixr-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
fixr-0.1.0/setup.py ADDED
@@ -0,0 +1,25 @@
1
+ from setuptools import setup, Extension
2
+ from setuptools.dist import Distribution
3
+
4
+ class BinaryDistribution(Distribution):
5
+ """Distribution which always forces a binary package with platform name"""
6
+ def has_ext_modules(foo):
7
+ return True
8
+
9
+ import sys
10
+
11
+ if sys.platform == 'darwin':
12
+ lib_extension = 'dylib'
13
+ else:
14
+ lib_extension = 'so'
15
+
16
+ setup(
17
+ ext_modules=[
18
+ Extension(
19
+ name="fixr._xrif",
20
+ sources=[], # empty list because we compile this separately
21
+ ),
22
+ ],
23
+ package_data={"fixr": [f"libxrif.{lib_extension}"]},
24
+ distclass=BinaryDistribution,
25
+ )
@@ -0,0 +1,165 @@
1
+ import typing
2
+ import ctypes
3
+ import numpy as np
4
+ from . import _xrif as xrif
5
+ import io
6
+
7
+
8
+ XRIF2NUMPY_DTYPE = {
9
+ xrif.XRIF_TYPECODE_UINT8: np.uint8,
10
+ xrif.XRIF_TYPECODE_INT8: np.int8,
11
+ xrif.XRIF_TYPECODE_UINT16: np.uint16,
12
+ xrif.XRIF_TYPECODE_INT16: np.int16,
13
+ xrif.XRIF_TYPECODE_UINT32: np.uint32,
14
+ xrif.XRIF_TYPECODE_INT32: np.int32,
15
+ xrif.XRIF_TYPECODE_UINT64: np.uint64,
16
+ xrif.XRIF_TYPECODE_INT64: np.int64,
17
+ }
18
+
19
+ class XrifReader:
20
+ def __init__(self, fh):
21
+ if 'b' not in fh.mode:
22
+ raise RuntimeError("File handle must be opened in binary mode")
23
+ self.fh = fh
24
+ # allocate and initialize xrif handle
25
+ self._reader = xrif.xrif_t()
26
+ xrif.xrif_new(self._reader)
27
+ self._decode_from_fh()
28
+
29
+ @property
30
+ def difference_method(self):
31
+ return xrif.string_cast((xrif.xrif_difference_method_string(self._reader.contents.difference_method)))
32
+
33
+ @property
34
+ def reorder_method(self):
35
+ return xrif.string_cast(xrif.xrif_reorder_method_string(self._reader.contents.reorder_method))
36
+
37
+ @property
38
+ def compress_method(self):
39
+ return xrif.string_cast(xrif.xrif_compress_method_string(self._reader.contents.compress_method))
40
+
41
+ @property
42
+ def lz4_acceleration(self):
43
+ return int(self._reader.contents.lz4_acceleration)
44
+
45
+ @property
46
+ def width(self):
47
+ return int(self._reader.contents.width)
48
+
49
+ @property
50
+ def height(self):
51
+ return int(self._reader.contents.height)
52
+
53
+ @property
54
+ def depth(self):
55
+ return int(self._reader.contents.depth)
56
+
57
+ @property
58
+ def frames(self):
59
+ return int(self._reader.contents.frames)
60
+
61
+ @property
62
+ def raw_size(self):
63
+ return self._reader.contents.width * self._reader.contents.height * self._reader.contents.depth * self._reader.contents.frames * self._reader.contents.data_size
64
+
65
+ @property
66
+ def shape(self):
67
+ return (
68
+ self._reader.contents.frames,
69
+ self._reader.contents.depth,
70
+ self._reader.contents.height,
71
+ self._reader.contents.width,
72
+ )
73
+
74
+ @property
75
+ def compressed_size(self):
76
+ return int(self._reader.contents.compressed_size)
77
+
78
+ @property
79
+ def ratio(self):
80
+ return self.compressed_size / self.raw_size
81
+
82
+ @property
83
+ def min_raw_size(self):
84
+ return xrif.xrif_min_raw_size(self._reader)
85
+
86
+ @property
87
+ def min_reordered_size(self):
88
+ return xrif.xrif_min_reordered_size(self._reader)
89
+
90
+ def describe(self):
91
+ # construct a report like xrif2fits has
92
+ s = 'xrif compression details:\n'
93
+ s += f" difference method: {self.difference_method}\n"
94
+ s += f" reorder method: {self.reorder_method}\n"
95
+ s += f" compression method: {self.compress_method}\n"
96
+ if self._reader.contents.compress_method == xrif.XRIF_COMPRESS_LZ4:
97
+ s += f" LZ4 acceleration: {self.lz4_acceleration}\n"
98
+ s += f" dimensions: {self.width} x {self.height} x {self.depth} x {self.frames}\n"
99
+
100
+ s += f" raw size: {self.raw_size} bytes\n"
101
+ s += f" encoded size: {self.compressed_size} bytes\n"
102
+ s += f" ratio: {self.ratio:.3f}\n"
103
+ return s
104
+
105
+ def __del__(self):
106
+ xrif.xrif_delete(self._reader)
107
+
108
+ def _decode_from_fh(self):
109
+ # read one header's worth of bytes
110
+ buf = self.fh.read(xrif.XRIF_HEADER_SIZE)
111
+ header_size_ptr = ctypes.c_uint32()
112
+ # populate header fields in reader
113
+ rv = xrif.xrif_read_header(self._reader, header_size_ptr, buf)
114
+ assert header_size_ptr.value == xrif.XRIF_HEADER_SIZE
115
+ if rv != xrif.XRIF_NOERROR:
116
+ raise RuntimeError("XRIF error reading header, check stderr")
117
+
118
+
119
+ rv = xrif.xrif_allocate_reordered(self._reader)
120
+ if rv != xrif.XRIF_NOERROR:
121
+ raise RuntimeError("XRIF error allocating reordered buffer")
122
+
123
+ # xrif can save you a buffer by decompressing into the raw buffer but that
124
+ # means it needs to be bigger than just `compressed_size`
125
+ min_buf_size = xrif.xrif_min_raw_size(self._reader)
126
+ # we need to own the raw (and then decompressed) buffer
127
+ buf = ctypes.c_buffer(min_buf_size)
128
+ # we're only filling the first `compressed_size` bytes
129
+ buf[:self._reader.contents.compressed_size] = self.fh.read(self._reader.contents.compressed_size)
130
+ # acquaint xrif with our arrangements
131
+ rv = xrif.xrif_set_raw(self._reader, buf, min_buf_size)
132
+
133
+ if rv != xrif.XRIF_NOERROR:
134
+ raise RuntimeError("XRIF error setting raw buffer, check stderr")
135
+
136
+ # do the business
137
+ xrif.xrif_decode(self._reader)
138
+
139
+ if rv != xrif.XRIF_NOERROR:
140
+ raise RuntimeError("XRIF decode error, check stderr")
141
+
142
+ # Now we need to make it intelligible to Python code.
143
+ # Fortunately xrif's data types are all available in NumPy
144
+ dtype = XRIF2NUMPY_DTYPE[self._reader.contents.type_code]
145
+
146
+ # figure out how many bytes it is now that it's decompressed
147
+ raw_size = self._reader.contents.width * self._reader.contents.height * self._reader.contents.depth * self._reader.contents.frames * self._reader.contents.data_size
148
+
149
+ # make a NumPy array from a buffer
150
+ self._decoded = np.frombuffer(buf[:raw_size], dtype).reshape(self.shape)
151
+ self._decoded.setflags(write=False)
152
+
153
+ @property
154
+ def array(self) -> np.ndarray:
155
+ return self._decoded
156
+
157
+ def copy_data(self) -> np.ndarray:
158
+ arr = self.array.copy()
159
+ arr.setflags(write=True)
160
+ return arr
161
+
162
+ def xrif2numpy(fh):
163
+ reader = XrifReader(fh)
164
+ print(reader.describe())
165
+ return reader.copy_data()
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.1
2
+ Name: fixr
3
+ Version: 0.1.0
4
+ Summary: Python bindings to xrif, the extreme reordered image format
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+
9
+ # fiXr
10
+
11
+ Open xrif archives from Python directly using the [xrif](https://github.com/jaredmales/xrif) library.
12
+
13
+ ## Example
14
+
15
+ ```python
16
+ from fixr import xrif2numpy
17
+ fh = open('camwfs_20240315225750994842000.xrif', 'rb')
18
+ data = xrif2numpy(fh)
19
+ timings = xrif2numpy(fh)
20
+ ```
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ src/fixr/__init__.py
7
+ src/fixr.egg-info/PKG-INFO
8
+ src/fixr.egg-info/SOURCES.txt
9
+ src/fixr.egg-info/dependency_links.txt
10
+ src/fixr.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ fixr