You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e4e61b2
Browse filesBrowse the repository at this point in the historyBrowse files
AGENTS.md lists what _binding.em.image holds and what the package adds to
it, and states three rules the update settled: only what the functions of
image_read.hpp and image_write.hpp need is bound, a collaborator the
package defaults moves behind the arguments it does not, and the helpers
that assemble collaborators are nouns. Every call that reaches a file
releases the GIL, not the batch read alone.
DECISIONS.md renames the batch source section to the sources and sinks it
now covers, and records that centres are an IndexTable in the binding and
any sequence in the package. A file's own data type can be asked for
after all, through query_descriptor, so the entry saying no such query
exists is corrected.
BACKLOG.md drops the patch source, which is bound, names the error types
rexlib has now in the item on translating them, and says why the image
tests never assert a value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|`_binding.concurrency`|`src/core/concurrency/`|`Executor` and its two kinds, `Completion`|
73
73
|`_binding.functional`|`src/functional/`| The operations, each taking an explicit context |
74
-
|`_binding.em.image`|`src/em/image/`|`ImageLocation`, the format managers and reader providers, the sources, `read`, `write`and the shape queries|
74
+
|`_binding.em.image`|`src/em/image/`|`ImageLocation`, `ImageDescriptor`, `IndexTable`, the format managers, the reader and writer providers, the source and the sink, and the functions of `image_read.hpp` and `image_write.hpp`|
75
75
76
76
A submodule is created by the `main.cpp` above it, which then hands it to the
77
77
`bind_` function of the directory it stands for: `src/main.cpp` creates `em`
@@ -89,7 +89,7 @@ the order the declarations need.
89
89
|`_device.py`|`rexlib.device(...)`, the `with` block that activates one |
90
90
|`_functional.py`| The operations again, with `context` defaulting to the active one |
91
91
|`_ndarray.py`| Installs the Python operators onto `Array`|
92
-
|`em/`| The electron microscopy areas, one module each; `em/image/` defaults the format manager and the context |
92
+
|`em/`| The electron microscopy areas, one module each; `em/image/` defaults the formats, the reader provider and the context, and assembles sources and sinks|
93
93
94
94
`_paths` is imported first in `__init__.py`, and the order matters: on Windows
95
95
nothing else imports until the bundled library is findable. `_ndarray` is
@@ -99,13 +99,30 @@ imported for its side effect, before anything can hand out an `Array`.
99
99
than carrying one of its own, so `read` asks for an active device exactly as
100
100
`zeros` does and there is one place to change if that ever stops being the
101
101
rule. Two things about those functions are rexlib's and not this package's:
102
-
`em::read` allocates on the host whatever device is active, and `em::write`
103
-
refuses storage the host cannot reach instead of transferring it. Both are
102
+
`em::read` allocates on the host whatever device is active, and the writes
103
+
refuse storage the host cannot reach instead of transferring it. Both are
104
104
stated in their docstrings, since a caller has no other way to find out.
105
105
106
+
Only what the functions of `image_read.hpp` and `image_write.hpp` need is
107
+
bound. A reader, a writer, a format, a transfer plan and a sanitizer have no
108
+
Python counterpart, so `ImageSource` and `ImageSink` are bound without the
109
+
`read` and `write` that take them, and `ManagedImageWriterProvider` without
110
+
`acquire`.
111
+
112
+
A collaborator the package defaults moves behind the arguments it does not:
113
+
`em::write(arr, path, manager, descriptor)` is
114
+
`write(array, path, descriptor, manager=None)`. A function with nothing to
115
+
default is re-exported as the binding has it, which is how
116
+
`read_batch_async` and `write_batch_async` arrive.
117
+
118
+
The helpers that assemble collaborators are nouns: `reader_provider`,
119
+
`writer_provider`, `source` and `sink`. `sink` takes its writer provider
120
+
rather than assembling one, since whoever writes keeps it to declare the
121
+
files and to close them.
122
+
106
123
`image_metadata` is not bound. rexlib declares it empty, so the parameter is
107
-
left off `write` until the type has fields; adding it later is compatible,
108
-
and publishing an empty class now would not be.
124
+
left off the writes and off `declare` until the type has fields; adding it
125
+
later is compatible, and publishing an empty class now would not be.
109
126
110
127
## Building
111
128
@@ -249,16 +266,16 @@ written, which is rexlib's to do rather than this binding's;
and `ImageBatchSource.read` all do: held through a read, the GIL would freeze
253
-
every other Python thread for its duration and there would be nothing
254
-
asynchronous left about the interface. pybind11 converts the arguments before
269
+
and everything in `em.image` that reaches a file all do: held through a
270
+
read, the GIL would freeze every other Python thread for its duration and
271
+
there would be nothing asynchronous left about the interface. pybind11 converts the arguments before
255
272
the guard is constructed and the return value after it is destroyed, so
256
273
nothing touches Python without it.
257
274
258
275
`rexlib::array` is move-only, and anything taking one by value has to be given
259
-
`destination.share()` rather than the caller's own. Bound plainly, pybind11
260
-
would move the array out of the Python object and hand the caller back an
261
-
empty one.
276
+
`destination.share()` rather than the caller's own, or `source.share_const()`
277
+
where it takes a `const_array`. Bound plainly, pybind11 would move the array
278
+
out of the Python object and hand the caller back an empty one.
262
279
263
280
A type rexlib parses from a string carries a `from_string` static method and
264
281
no constructor that parses. `DeviceIndex` and `ImageLocation` both do, and
@@ -350,7 +367,7 @@ Tests for what `_binding` exposes at its top level stay at the root.
350
367
| `tests/hardware/` | Devices, sessions, events, memory resources, the session pool |
351
368
| `tests/dispatch/` | `ExecutionContext`, the active context, `rexlib.device(...)` |
352
369
| `tests/functional/` | The operations |
353
-
| `tests/em/image/` | `ImageLocation`, parsing, the format managers, `read` and `write` |
370
+
| `tests/em/image/` | `ImageLocation`, `ImageDescriptor`, `IndexTable`, the format managers, the providers, the synchronous reads and writes and the asynchronous ones |
354
371
355
372
There are no `__init__.py` files and no `conftest.py`. Test module names are
356
373
therefore unique across the whole tree, and a fixture belongs to the file that
0 commit comments