Skip to content

Commit

Permalink
Improve docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
manthey committed Jan 28, 2022
1 parent 40503a9 commit 34a4a33
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Features
- Initial implementation of multi-source tile source ([#764](../../pull/764))

### Improvements
- Add more opacity support for image overlays ([#761](../../pull/761))
- Make annotation schema more uniform ([#763](../../pull/763))
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
_build/large_image_source_gdal/modules
_build/large_image_source_mapnik/modules
_build/large_image_source_multi/modules
multi_source_specification
_build/large_image_source_nd2/modules
_build/large_image_source_ometiff/modules
_build/large_image_source_openjpeg/modules
Expand Down
1 change: 1 addition & 0 deletions docs/make_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ln -s ../build/docs-work _build

large_image_converter --help > _build/large_image_converter.txt
python -c 'from girder_large_image_annotation.models import annotation;import json;print(json.dumps(annotation.AnnotationSchema.annotationSchema, indent=2))' > _build/annotation_schema.json
python -c 'import large_image_source_multi, json;print(json.dumps(large_image_source_multi.MultiSourceSchema, indent=2))' > _build/multi_source_schema.json

sphinx-apidoc -f -o _build/large_image ../large_image
sphinx-apidoc -f -o _build/large_image_source_bioformats ../sources/bioformats/large_image_source_bioformats
Expand Down
6 changes: 6 additions & 0 deletions docs/multi_source_specification.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. include:: ../sources/multi/docs/specification.rst

This returns the following:

.. include:: ../build/docs-work/multi_source_schema.json
:literal:
136 changes: 136 additions & 0 deletions sources/multi/docs/specification.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
Multi Source Schema
===================

A multi-source tile source is used to composite multiple other sources into a
single conceptual tile source. It is specified by a yaml or json file that
conforms to the appropriate schema.

Examples
--------

All of the examples presented here are in yaml; json works just as well.

Multi Z-position
~~~~~~~~~~~~~~~~

For example, if you have a set of individual files that you wish to treat as
multiple z slices in a single file, you can do something like:

::

---
sources:
- path: ./test_orient1.tif
z: 0
- path: ./test_orient2.tif
z: 1
- path: ./test_orient3.tif
z: 2
- path: ./test_orient4.tif
z: 3
- path: ./test_orient5.tif
z: 4
- path: ./test_orient6.tif
z: 5
- path: ./test_orient7.tif
z: 6
- path: ./test_orient8.tif
z: 7

Here, each of the files is explicitly listed with a specific ``z`` value.
Since these files are ordered, this could equivalently be done in a simpler
manner using a ``pathPattern``, which is a regular expression that can match
multiple files.

::

---
sources:
- path: .
pathPattern: 'test_orient[1-8]\.tif'
zStep: 1

Since the ``z`` value will default to 0, this works. The files are sorted in
C-sort order (lexically using the ASCII or UTF code points). This sorting will
break down if you have files with variable length numbers (e.g., ``file10.tif``
will appear before ``file9.tiff``. You can instead assign values from the
file name using named expressions:

::

---
sources:
- path: .
pathPattern: 'test_orient(?P<z1>[1-8])\.tif'

Note that the name in the expression (``z1`` in this example) is the name of
the value in the schema. If a ``1`` is added, then it is assumed to be 1-based
indexed. Without the ``1``, it is assumed to be zero-indexed.

Composite To A Single Frame
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Multiple sources can be made to appear as a single frame. For instance:

::

---
width: 360
height: 360
sources:
- path: ./test_orient1.tif
position:
x: 0
y: 0
- path: ./test_orient2.tif
position:
x: 180
y: 0
- path: ./test_orient3.tif
position:
x: 0
y: 180
- path: ./test_orient4.tif
position:
x: 180
y: 180

Here, the total width and height of the final image is specified, along with
the upper-left position of each image in the frame.

Composite With Scaling
~~~~~~~~~~~~~~~~~~~~~~

Transforms can be applied to scale the individual sources:

::

---
width: 720
height: 720
sources:
- path: ./test_orient1.tif
position:
scale: 2
- path: ./test_orient2.tif
position:
scale: 2
x: 360
- path: ./test_orient3.tif
position:
scale: 2
y: 360
- path: ./test_orient4.tif
position:
scale: 360
x: 180
y: 180

Note that the zero values from the previous example have been omitted as they
are unnecessary.

Full Schema
-----------

The full schema (jsonschema Draft6 standard) can be obtained by referencing the
Python at ``large_image_source_multi.MultiSourceSchema``.
14 changes: 11 additions & 3 deletions sources/multi/large_image_source_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,14 @@ def _collectFrames(self, checkAll=False):
self.levels = int(max(1, math.ceil(math.log(
max(self.sizeX / self.tileWidth, self.sizeY / self.tileHeight)) / math.log(2)) + 1))

def getNativeMagnification(self):
"""
Get the magnification at a particular level.
:return: magnification, width of a pixel in mm, height of a pixel in mm.
"""
return self._nativeMagnification.copy()

def getAssociatedImage(self, imageKey, *args, **kwargs):
"""
Return an associated image.
Expand Down Expand Up @@ -835,10 +843,10 @@ def _addSourceToTile(self, tile, sourceEntry, corners, scale):
# Otherwise, get an area twice as big as needed and use
# scipy.ndimage.affine_transform to transform it
else:
# ##DWM::
# TODO
raise TileSourceError('Not implemented')
# Crop
# ##DWM::
# TODO
tile = self._mergeTiles(tile, sourceTile, x, y)
return tile

Expand Down Expand Up @@ -885,7 +893,7 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs):
for sourceEntry in sourceList:
tile = self._addSourceToTile(tile, sourceEntry, corners, scale)
if tile is None:
# ##DWM:: number of channels?
# TODO number of channels?
colors = self._info.get('backgroundColor', [0])
if colors:
tile = numpy.full((self.tileWidth, self.tileHeight, len(colors)), colors)
Expand Down

0 comments on commit 34a4a33

Please sign in to comment.