[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/instamatic-dev/pyserialem/build)](https://github.com/instamatic-dev/pyserialem/actions)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyserialem)](https://pypi.org/project/pyserialem/)
[![PyPI](https://img.shields.io/pypi/v/pyserialem.svg?style=flat)](https://pypi.org/project/pyserialem/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/pyserialem)](https://pypi.org/project/pyserialem/)
# PySerialEM
A small Python library to read and write [SerialEM][serialem] navigator files (`.nav`), and process grid maps.
Install using `pip install pyserialem`.
# Usage
The main use of `pyserialem` is to manipulate coordinates in a `.nav` file written by SerialEM ([specification][serialem_nav]).
Reading a `.nav` file:
```python
import pyserialem
from pathlib import Path
p = Path('C:/path/to/data/') / 'nav.nav'
items = pyserialem.read_nav_file(p) # list
```
You can set the `acquire_only` toggle to return only the items with the `Acquire` tag set:
```python
items = pyserialem.read_nav_file(p, acquire_only=True) # list
```
This returns a `list` of `MapItem` and `NavItem`. A `MapItem` is associated with an image in the corresponding `.mrc` file, and a `NavItem` is a marker or point on that image.
```python
map_items = [item.kind == 'Map' for item in items]
nav_items = [item.kind == 'Marker' for item in items]
```
All of the tags associated with the `MapItem` or `NavItem` can be accessed as an attribute using the same name as in the `.nav` file, i.e. with the key defined [here][serialem_nav]. This is also how the values should be updated:
```python
nav_item = nav_items[0]
stage_position = nav_item.StageXYZ # tuple
map_item.StageXYZ = (100, 200, 0) # overwrite values
```
Alternatively, the stage position can be accessed directly through:
```python
x = map_item.stage_x
y = map_item.stage_y
z = map_item.stage_z
xy = map_item.stage_xy
```
## Map items
A `MapItem` has all the functions of a `NavItem`, and then some. Each `MapItem` can have a list of markers associated with it:
```python
map_item = map_items[0]
markers = map_item.markers # list
```
To visualize them, call:
```python
map_item.plot()
```
To just load the image associated with the `MapItem`:
```python
img = map_item.load() # np.array
```
They can be extracted as a dictionary:
```python
d = map_item.to_dict() # dict
```
...and restored:
```python
new_map_item = pysem.from_dict(d, tag='new_mapitem')
```
This is also the easiest way of constructing a new `MapItem`, because some keys can be autogenerated. Otherwise, all the required keys have to be specified to the `MapItem` constructor. The `tag` specifies the name of the item when displayed in `SerialEM`. If omitted, one will be generated.
It is easy to add new markers to a `MapItem`. As a pixel coordinate (i.e. from segmentation) is the default. `PySerialEM` calculates the corresponding stage position. The `acquire` argument sets the acquire flag (default=`True`):
```python
pixel_position = (0, 0)
new_nav_item = map_item.add_marker(
pixel_position,
tag='pixel_item',
acquire=True) # NavItem
```
You can also add a marker as a stage coordinate (although this is a bit more tricky to calculate the corresponding pixel coordinate):
```python
stage_positionion = (1000, 1000)
new_nav_item = map_item.add_marker(
pixel_position,
kind='stage',
tag='stage_item',
acquire=False) # NavItem
```
To add many markers:
```python
pixel_coordinates = ((0, 0), (100, 100), (200, 200))
nav_item_group = map_item.add_marker_group(pixel_coordinates) # tuple
```
Specify `replace=True` to replace the current list of markers associated with the `MapItem`.
If the `MapItem` has a set of markers associated with it `map_item.markers`, the coordinates be retrieved as followed:
```python
map_item.markers_as_pixel_coordinates() # np.array (Nx2)
map_item.markers_as_stage_coordinates() # np.array (Nx2)
```
To just convert between stage and pixel coordinates:
```python
pixel_coord = (1024, 1024)
stage_coord = map_item.pixel_to_stagecoords(pixel_coord) # tuple
new_pixel_coord = map_item.stage_to_pixelcoords(stagecoord) # tuple
assert new_pixel_coord == pixel_coord
```
To write a new file:
```python
pyserialem.write_nav_file('out.nav', map_item, *nav_item_group)
```
Note the `*`. This function captures arguments in a list (`*args`, so they must be unpacked when supplied.
## Stitching
A basic stitching algorithm is available to get an overview of the location of all map items:
```python
map_items = [item for item in items if item.kind == 'Map']
pyserialem.stitch_map_items(map_items)
```
For more advanced stitching and montaging, use the `pyserialem.montage` module. A [demo notebook](demos/montage_processing_serialem.ipynb) is available to demonstrate its usage.
## Mdoc files
There is also a simple function to read `.mdoc` files ([link][serialem_nav]). This returns a list of python objects where each key can be accessed as an attribute.
```python
p = Path('C:/path/to/data') / 'gm.mrc.mdoc'
mdoc = pyserialem.read_mdoc_file(p)
```
[src]: https://github.com/stefsmeets/pyserialem
[serialem]: https://bio3d.colorado.edu/SerialEM/
[serialem_nav]: https://bio3d.colorado.edu/SerialEM/hlp/html/about_formats.htm
Raw data
{
"_id": null,
"home_page": "http://github.com/stefsmeets/pyserialem",
"name": "pyserialem",
"maintainer": "Stef Smeets",
"docs_url": null,
"requires_python": ">=3.6.1",
"maintainer_email": "s.smeets@tudelft.nl",
"keywords": "serialem,electron-microscopy,navigator",
"author": "Stef Smeets",
"author_email": "s.smeets@tudelft.nl",
"download_url": "https://files.pythonhosted.org/packages/66/c7/11407149677d244d8f7fdcc9423f7b5e993bb06ae22ab0847438968e9e0d/pyserialem-0.3.2.tar.gz",
"platform": "",
"description": "[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/instamatic-dev/pyserialem/build)](https://github.com/instamatic-dev/pyserialem/actions)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyserialem)](https://pypi.org/project/pyserialem/)\n[![PyPI](https://img.shields.io/pypi/v/pyserialem.svg?style=flat)](https://pypi.org/project/pyserialem/)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/pyserialem)](https://pypi.org/project/pyserialem/)\n\n# PySerialEM\n\nA small Python library to read and write [SerialEM][serialem] navigator files (`.nav`), and process grid maps.\n\nInstall using `pip install pyserialem`.\n\n# Usage\n\nThe main use of `pyserialem` is to manipulate coordinates in a `.nav` file written by SerialEM ([specification][serialem_nav]).\n\nReading a `.nav` file:\n\n```python\nimport pyserialem\nfrom pathlib import Path\n\np = Path('C:/path/to/data/') / 'nav.nav'\nitems = pyserialem.read_nav_file(p) # list\n```\nYou can set the `acquire_only` toggle to return only the items with the `Acquire` tag set:\n\n```python\nitems = pyserialem.read_nav_file(p, acquire_only=True) # list\n```\n\nThis returns a `list` of `MapItem` and `NavItem`. A `MapItem` is associated with an image in the corresponding `.mrc` file, and a `NavItem` is a marker or point on that image.\n\n```python\nmap_items = [item.kind == 'Map' for item in items]\nnav_items = [item.kind == 'Marker' for item in items]\n```\n\nAll of the tags associated with the `MapItem` or `NavItem` can be accessed as an attribute using the same name as in the `.nav` file, i.e. with the key defined [here][serialem_nav]. This is also how the values should be updated:\n\n```python\nnav_item = nav_items[0]\nstage_position = nav_item.StageXYZ # tuple\nmap_item.StageXYZ = (100, 200, 0) # overwrite values\n```\n\nAlternatively, the stage position can be accessed directly through:\n\n```python\nx = map_item.stage_x\ny = map_item.stage_y\nz = map_item.stage_z\nxy = map_item.stage_xy\n```\n\n## Map items\n\nA `MapItem` has all the functions of a `NavItem`, and then some. Each `MapItem` can have a list of markers associated with it:\n\n```python\nmap_item = map_items[0]\nmarkers = map_item.markers # list\n```\n\nTo visualize them, call:\n\n```python\nmap_item.plot()\n```\n\nTo just load the image associated with the `MapItem`:\n\n```python\nimg = map_item.load() # np.array\n```\n\nThey can be extracted as a dictionary:\n\n```python\nd = map_item.to_dict() # dict\n```\n\n...and restored:\n\n```python\nnew_map_item = pysem.from_dict(d, tag='new_mapitem')\n```\n\nThis is also the easiest way of constructing a new `MapItem`, because some keys can be autogenerated. Otherwise, all the required keys have to be specified to the `MapItem` constructor. The `tag` specifies the name of the item when displayed in `SerialEM`. If omitted, one will be generated.\n\nIt is easy to add new markers to a `MapItem`. As a pixel coordinate (i.e. from segmentation) is the default. `PySerialEM` calculates the corresponding stage position. The `acquire` argument sets the acquire flag (default=`True`):\n\n```python\npixel_position = (0, 0)\nnew_nav_item = map_item.add_marker(\n pixel_position,\n tag='pixel_item',\n acquire=True) # NavItem\n```\n\nYou can also add a marker as a stage coordinate (although this is a bit more tricky to calculate the corresponding pixel coordinate):\n\n```python\nstage_positionion = (1000, 1000)\nnew_nav_item = map_item.add_marker(\n pixel_position,\n kind='stage',\n tag='stage_item',\n acquire=False) # NavItem\n```\n\nTo add many markers:\n\n```python\npixel_coordinates = ((0, 0), (100, 100), (200, 200))\nnav_item_group = map_item.add_marker_group(pixel_coordinates) # tuple\n```\n\nSpecify `replace=True` to replace the current list of markers associated with the `MapItem`.\n\nIf the `MapItem` has a set of markers associated with it `map_item.markers`, the coordinates be retrieved as followed:\n\n```python\nmap_item.markers_as_pixel_coordinates() # np.array (Nx2)\nmap_item.markers_as_stage_coordinates() # np.array (Nx2)\n```\n\nTo just convert between stage and pixel coordinates:\n\n```python\npixel_coord = (1024, 1024)\nstage_coord = map_item.pixel_to_stagecoords(pixel_coord) # tuple\nnew_pixel_coord = map_item.stage_to_pixelcoords(stagecoord) # tuple\nassert new_pixel_coord == pixel_coord\n```\n\nTo write a new file:\n\n```python\npyserialem.write_nav_file('out.nav', map_item, *nav_item_group)\n```\n\nNote the `*`. This function captures arguments in a list (`*args`, so they must be unpacked when supplied.\n\n## Stitching\n\nA basic stitching algorithm is available to get an overview of the location of all map items:\n\n```python\nmap_items = [item for item in items if item.kind == 'Map']\npyserialem.stitch_map_items(map_items)\n```\n\nFor more advanced stitching and montaging, use the `pyserialem.montage` module. A [demo notebook](demos/montage_processing_serialem.ipynb) is available to demonstrate its usage.\n\n## Mdoc files\n\nThere is also a simple function to read `.mdoc` files ([link][serialem_nav]). This returns a list of python objects where each key can be accessed as an attribute.\n\n```python\np = Path('C:/path/to/data') / 'gm.mrc.mdoc'\nmdoc = pyserialem.read_mdoc_file(p)\n```\n\n[src]: https://github.com/stefsmeets/pyserialem\n[serialem]: https://bio3d.colorado.edu/SerialEM/\n[serialem_nav]: https://bio3d.colorado.edu/SerialEM/hlp/html/about_formats.htm\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Python module to read/write SerialEM .nav files.",
"version": "0.3.2",
"project_urls": {
"Bug Reports": "https://github.com/stefsmeets/pyserialem/issues",
"Documentation": "http://github.com/stefsmeets/pyserialem",
"Homepage": "http://github.com/stefsmeets/pyserialem",
"Repository": "http://github.com/stefsmeets/pyserialem"
},
"split_keywords": [
"serialem",
"electron-microscopy",
"navigator"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "63f4c671c0fb39247bacd196d39f7032d58d067c2dffa18cf6316269362c7797",
"md5": "3c6860b27b697957fcaf87a54696b5cd",
"sha256": "263423acc9768f65c80bebd4c025f2a736cc7a73c4ba208e6803d1a4bae34d8e"
},
"downloads": -1,
"filename": "pyserialem-0.3.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3c6860b27b697957fcaf87a54696b5cd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6.1",
"size": 36088,
"upload_time": "2021-08-03T12:06:12",
"upload_time_iso_8601": "2021-08-03T12:06:12.940952Z",
"url": "https://files.pythonhosted.org/packages/63/f4/c671c0fb39247bacd196d39f7032d58d067c2dffa18cf6316269362c7797/pyserialem-0.3.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "66c711407149677d244d8f7fdcc9423f7b5e993bb06ae22ab0847438968e9e0d",
"md5": "c9f3dd3e97d43ecfcc7416ef295ca930",
"sha256": "9fd110ef4680a478f3dbcbfe46cec3514e8492cf86feb496ed6e58255e0ba286"
},
"downloads": -1,
"filename": "pyserialem-0.3.2.tar.gz",
"has_sig": false,
"md5_digest": "c9f3dd3e97d43ecfcc7416ef295ca930",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6.1",
"size": 32177,
"upload_time": "2021-08-03T12:06:14",
"upload_time_iso_8601": "2021-08-03T12:06:14.904296Z",
"url": "https://files.pythonhosted.org/packages/66/c7/11407149677d244d8f7fdcc9423f7b5e993bb06ae22ab0847438968e9e0d/pyserialem-0.3.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2021-08-03 12:06:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "stefsmeets",
"github_project": "pyserialem",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pyserialem"
}